Skip to content

Commit

Permalink
[chrome-remote-control] Simplifications to page_runner preparing for …
Browse files Browse the repository at this point in the history
…interactions

My last megachange to crc, I promise.
- Rename replay_server to wpr_server because replay implied replaying mode
- Move WebPageReplay to be more core to the Browser object, splitting up
  "boot up the browser in a replay or record mode" from "what archive
  is being used for record" state.
- Make browser_backend track its options object
- Centralize argument handling on browser_backend.GetBrowserStartupArgs()
- Make temporary http server handling more browser-centric in order
  to simplify page runner
- Move some credentials logistics to the browser credentials object, also
  to simplify page_runner
- Add some testability hooks to credentials object for tests. Not used,
  yet, but used in followup patch.
- Pull page out of page_set. Its getting bigger.
- Fix cyclic dependency on browser_gone_exception

R=tonyg@chromium.org
NOTRY=True

Review URL: https://codereview.chromium.org/11115006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162318 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
nduca@chromium.org committed Oct 17, 2012
1 parent a844983 commit 918091f
Show file tree
Hide file tree
Showing 27 changed files with 375 additions and 277 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
"""A library for chrome-based tests.
"""
from chrome_remote_control.browser import Browser
from chrome_remote_control.browser_finder import FindBrowser
from chrome_remote_control.browser_finder import GetAllAvailableBrowserTypes
from chrome_remote_control.browser_gone_exception import BrowserGoneException
from chrome_remote_control.browser_options import BrowserOptions
from chrome_remote_control.browser import Browser
from chrome_remote_control.tab import Tab
from chrome_remote_control.tab_crash_exception import TabCrashException
from chrome_remote_control.util import TimeoutException, WaitFor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@

from chrome_remote_control import adb_commands
from chrome_remote_control import browser_backend
from chrome_remote_control import browser_gone_exception

class AndroidBrowserBackend(browser_backend.BrowserBackend):
"""The backend for controlling a browser instance running on Android.
"""
def __init__(self, options, extra_browser_args, adb, package,
def __init__(self, options, adb, package,
is_content_shell, cmdline_file, activity, devtools_remote_port):
super(AndroidBrowserBackend, self).__init__(is_content_shell)
super(AndroidBrowserBackend, self).__init__(is_content_shell, options)
# Initialize fields so that an explosion during init doesn't break in Close.
self._options = options
self._adb = adb
Expand All @@ -23,13 +24,6 @@ def __init__(self, options, extra_browser_args, adb, package,
self._port = 9222
self._devtools_remote_port = devtools_remote_port

# Beginnings of a basic command line.
if is_content_shell:
pseudo_exec_name = 'content_shell'
else:
pseudo_exec_name = 'chrome'
args = [pseudo_exec_name, '--disable-fre']

# Kill old browser.
self._adb.KillAll(self._package)
self._adb.KillAll('forwarder')
Expand All @@ -46,10 +40,14 @@ def __init__(self, options, extra_browser_args, adb, package,
pass

# Set up the command line.
if extra_browser_args:
args.extend(extra_browser_args)
args.extend(options.extra_browser_args)
args.extend(self._common_chrome_browser_args)
if is_content_shell:
pseudo_exec_name = 'content_shell'
else:
pseudo_exec_name = 'chrome'

args = [pseudo_exec_name]
args.extend(self.GetBrowserStartupArgs())

with tempfile.NamedTemporaryFile() as f:
def EscapeIfNeeded(arg):
return arg.replace(' ', '" "')
Expand All @@ -67,7 +65,8 @@ def EscapeIfNeeded(arg):
logging.critical(
'android_browser_backend: Could not find preferences file ' +
'%s for %s' % (prefs_file, self._package))
raise browser_backend.BrowserGoneException('Missing preferences file.')
raise browser_gone_exception.BrowserGoneException(
'Missing preferences file.')

with tempfile.NamedTemporaryFile() as raw_f:
self._adb.Pull(prefs_file, raw_f.name)
Expand Down Expand Up @@ -106,6 +105,11 @@ def EscapeIfNeeded(arg):
self.Close()
raise

def GetBrowserStartupArgs(self):
args = super(AndroidBrowserBackend, self).GetBrowserStartupArgs()
args.append('--disable-fre')
return args

def __del__(self):
self.Close()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""Finds android browsers that can be controlled by chrome_remote_control."""

import os
import logging
import logging as real_logging
import re
import subprocess

Expand Down Expand Up @@ -49,12 +49,12 @@ def __init__(self, browser_type, options, *args):
def __repr__(self):
return 'PossibleAndroidBrowser(browser_type=%s)' % self.browser_type

def Create(self, extra_browser_args=None):
def Create(self):
backend = android_browser_backend.AndroidBrowserBackend(
self._options, extra_browser_args, *self._args)
self._options, *self._args)
return browser.Browser(backend)

def FindAllAvailableBrowsers(options):
def FindAllAvailableBrowsers(options, logging=real_logging):
"""Finds all the desktop browsers available on this machine."""
if not adb_commands.IsAndroidSupported():
return []
Expand All @@ -68,14 +68,14 @@ def FindAllAvailableBrowsers(options):
stdin=devnull)
stdout, _ = proc.communicate()
if re.search(re.escape('????????????\tno permissions'), stdout) != None:
logging.warning(
logging.warn(
('adb devices reported a permissions error. Consider '
'restarting adb as root:'))
logging.warning(' adb kill-server')
logging.warning(' sudo `which adb` devices\n\n')
logging.warn(' adb kill-server')
logging.warn(' sudo `which adb` devices\n\n')
except OSError:
logging.info('No adb command found. ' +
'Will not try searching for Android browsers.')
'Will not try searching for Android browsers.')
return []

device = None
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import unittest

from chrome_remote_control import android_browser_finder
from chrome_remote_control import browser_options
from chrome_remote_control import system_stub

class LoggingStub(object):
def __init__(self):
self.warnings = []

def info(self, msg, *args):
pass

def warn(self, msg, *args):
self.warnings.append(msg % args)

class AndroidBrowserFinderTest(unittest.TestCase):
def setUp(self):
self._stubs = system_stub.Override(android_browser_finder,
Expand Down Expand Up @@ -42,21 +51,10 @@ def test_adb_permissions_error(self):
* daemon started successfully *
""")

warnings = []
class TempFilter(logging.Filter):
def filter(self, record):
warnings.append(record)
return 0
temp_filter = TempFilter()

try:
logger = logging.getLogger()
logger.addFilter(temp_filter)

browsers = android_browser_finder.FindAllAvailableBrowsers(options)
finally:
logger.removeFilter(temp_filter)
self.assertEquals(3, len(warnings))
log_stub = LoggingStub()
browsers = android_browser_finder.FindAllAvailableBrowsers(
options, log_stub)
self.assertEquals(3, len(log_stub.warnings))
self.assertEquals(0, len(browsers))


Expand All @@ -66,21 +64,10 @@ def test_adb_two_devices(self):
self._stubs.adb_commands.attached_devices = ['015d14fec128220c',
'015d14fec128220d']

warnings = []
class TempFilter(logging.Filter):
def filter(self, record):
warnings.append(record)
return 0
temp_filter = TempFilter()

try:
logger = logging.getLogger()
logger.addFilter(temp_filter)

browsers = android_browser_finder.FindAllAvailableBrowsers(options)
finally:
logger.removeFilter(temp_filter)
self.assertEquals(1, len(warnings))
log_stub = LoggingStub()
browsers = android_browser_finder.FindAllAvailableBrowsers(
options, log_stub)
self.assertEquals(1, len(log_stub.warnings))
self.assertEquals(0, len(browsers))

def test_adb_one_device(self):
Expand Down
60 changes: 49 additions & 11 deletions tools/chrome_remote_control/chrome_remote_control/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
# found in the LICENSE file.
import os

from chrome_remote_control import replay_server
from chrome_remote_control import temporary_http_server
from chrome_remote_control import browser_credentials
from chrome_remote_control import wpr_modes
from chrome_remote_control import wpr_server

class Browser(object):
"""A running browser instance that can be controlled in a limited way.
Expand All @@ -20,6 +21,8 @@ class Browser(object):
"""
def __init__(self, backend):
self._backend = backend
self._http_server = None
self._wpr_server = None
self.credentials = browser_credentials.BrowserCredentials()

def __enter__(self):
Expand All @@ -44,18 +47,53 @@ def ConnectToNthTab(self, index):
return self._backend.ConnectToNthTab(self, index)

def Close(self):
if self._wpr_server:
self._wpr_server.Close()
self._wpr_server = None

if self._http_server:
self._http_server.Close()
self._http_server = None

self._backend.Close()
self.credentials = None

def CreateTemporaryHTTPServer(self, path):
return temporary_http_server.TemporaryHTTPServer(self._backend, path)
@property
def http_server(self):
return self._http_server

def SetHTTPServerDirectory(self, path):
if path:
abs_path = os.path.abspath(path)
if self._http_server and self._http_server.path == path:
return
else:
abs_path = None

if self._http_server:
self._http_server.Close()
self._http_server = None

if not abs_path:
return

self._http_server = temporary_http_server.TemporaryHTTPServer(
self._backend, abs_path)

def SetReplayArchivePath(self, archive_path):
if self._wpr_server:
self._wpr_server.Close()
self._wpr_server = None

if not archive_path:
return None

if self._backend.wpr_mode == wpr_modes.WPR_OFF:
return

@classmethod
def CanUseReplayServer(cls, archive_path, use_record_mode):
return os.path.isfile(archive_path) or use_record_mode
use_record_mode = self._backend.wpr_mode == wpr_modes.WPR_RECORD
if not use_record_mode:
assert os.path.isfile(archive_path)

def CreateReplayServer(self, archive_path, use_record_mode):
replay_class = replay_server.DoNothingReplayServer
if self.CanUseReplayServer(archive_path, use_record_mode):
replay_class = replay_server.ReplayServer
return replay_class(self._backend, archive_path, use_record_mode)
self._wpr_server = wpr_server.ReplayServer(
self._backend, archive_path, use_record_mode)
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,56 @@
import socket
import json

from chrome_remote_control import browser_gone_exception
from chrome_remote_control import inspector_backend
from chrome_remote_control import tab
from chrome_remote_control import util

class BrowserGoneException(Exception):
pass
from chrome_remote_control import wpr_modes
from chrome_remote_control import wpr_server

class BrowserBackend(object):
"""A base class for broser backends. Provides basic functionality
once a remote-debugger port has been established."""
_common_chrome_browser_args = [
'--disable-background-networking',
'--no-first-run',
]

def __init__(self, is_content_shell):
def __init__(self, is_content_shell, options):
self.is_content_shell = is_content_shell
self.options = options
self._port = None

def GetBrowserStartupArgs(self):
args = []
args.extend(self.options.extra_browser_args)
args.append('--disable-background-networking')
args.append('--no-first-run')
if self.options.wpr_mode != wpr_modes.WPR_OFF:
args.extend(wpr_server.CHROME_FLAGS)
return args

@property
def wpr_mode(self):
return self.options.wpr_mode

def _WaitForBrowserToComeUp(self):
def IsBrowserUp():
try:
self._ListTabs()
except socket.error:
if not self.IsBrowserRunning():
raise BrowserGoneException()
raise browser_gone_exception.BrowserGoneException()
return False
except httplib.BadStatusLine:
if not self.IsBrowserRunning():
raise BrowserGoneException()
raise browser_gone_exception.BrowserGoneException()
return False
except urllib2.URLError:
if not self.IsBrowserRunning():
raise BrowserGoneException()
raise browser_gone_exception.BrowserGoneException()
return False
else:
return True
try:
util.WaitFor(IsBrowserUp, timeout=30)
except util.TimeoutException:
raise BrowserGoneException()
raise browser_gone_exception.BrowserGoneException()

def _ListTabs(self, timeout=None):
if timeout:
Expand Down
Loading

0 comments on commit 918091f

Please sign in to comment.