OLD | NEW |
| (Empty) |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 import urllib2 | |
5 import httplib | |
6 import socket | |
7 import json | |
8 | |
9 from chrome_remote_control import browser_gone_exception | |
10 from chrome_remote_control import inspector_backend | |
11 from chrome_remote_control import tab | |
12 from chrome_remote_control import util | |
13 from chrome_remote_control import wpr_modes | |
14 from chrome_remote_control import wpr_server | |
15 | |
16 class BrowserBackend(object): | |
17 """A base class for broser backends. Provides basic functionality | |
18 once a remote-debugger port has been established.""" | |
19 def __init__(self, is_content_shell, options): | |
20 self.is_content_shell = is_content_shell | |
21 self.options = options | |
22 self._port = None | |
23 | |
24 def GetBrowserStartupArgs(self): | |
25 args = [] | |
26 args.extend(self.options.extra_browser_args) | |
27 args.append('--disable-background-networking') | |
28 args.append('--metrics-recording-only') | |
29 args.append('--no-first-run') | |
30 if self.options.wpr_mode != wpr_modes.WPR_OFF: | |
31 args.extend(wpr_server.CHROME_FLAGS) | |
32 return args | |
33 | |
34 @property | |
35 def wpr_mode(self): | |
36 return self.options.wpr_mode | |
37 | |
38 def _WaitForBrowserToComeUp(self): | |
39 def IsBrowserUp(): | |
40 try: | |
41 self._ListTabs() | |
42 except socket.error: | |
43 if not self.IsBrowserRunning(): | |
44 raise browser_gone_exception.BrowserGoneException() | |
45 return False | |
46 except httplib.BadStatusLine: | |
47 if not self.IsBrowserRunning(): | |
48 raise browser_gone_exception.BrowserGoneException() | |
49 return False | |
50 except urllib2.URLError: | |
51 if not self.IsBrowserRunning(): | |
52 raise browser_gone_exception.BrowserGoneException() | |
53 return False | |
54 else: | |
55 return True | |
56 try: | |
57 util.WaitFor(IsBrowserUp, timeout=30) | |
58 except util.TimeoutException: | |
59 raise browser_gone_exception.BrowserGoneException() | |
60 | |
61 @property | |
62 def _debugger_url(self): | |
63 return 'http://localhost:%i/json' % self._port | |
64 | |
65 def _ListTabs(self, timeout=None): | |
66 req = urllib2.urlopen(self._debugger_url, timeout=timeout) | |
67 data = req.read() | |
68 all_contexts = json.loads(data) | |
69 tabs = [ctx for ctx in all_contexts | |
70 if not ctx['url'].startswith('chrome-extension://')] | |
71 # FIXME(dtu): The remote debugger protocol returns in order of most | |
72 # recently created tab first. In order to convert it to the UI tab | |
73 # order, we just reverse the list, which assumes we can't move tabs. | |
74 # We should guarantee that the remote debugger returns in the UI tab order. | |
75 tabs.reverse() | |
76 return tabs | |
77 | |
78 def NewTab(self, timeout=None): | |
79 req = urllib2.urlopen(self._debugger_url + '/new', timeout=timeout) | |
80 data = req.read() | |
81 new_tab = json.loads(data) | |
82 return new_tab | |
83 | |
84 def CloseTab(self, index, timeout=None): | |
85 assert self.num_tabs > 1, 'Closing the last tab not supported.' | |
86 target_tab = self._ListTabs()[index] | |
87 tab_id = target_tab['webSocketDebuggerUrl'].split('/')[-1] | |
88 target_num_tabs = self.num_tabs - 1 | |
89 | |
90 urllib2.urlopen('%s/close/%s' % (self._debugger_url, tab_id), | |
91 timeout=timeout) | |
92 | |
93 util.WaitFor(lambda: self.num_tabs == target_num_tabs, timeout=5) | |
94 | |
95 @property | |
96 def num_tabs(self): | |
97 return len(self._ListTabs()) | |
98 | |
99 def GetNthTabUrl(self, index): | |
100 return self._ListTabs()[index]['url'] | |
101 | |
102 def ConnectToNthTab(self, browser, index): | |
103 ib = inspector_backend.InspectorBackend(self, self._ListTabs()[index]) | |
104 return tab.Tab(browser, ib) | |
105 | |
106 def DoesDebuggerUrlExist(self, url): | |
107 matches = [t for t in self._ListTabs() | |
108 if t['webSocketDebuggerUrl'] == url] | |
109 return len(matches) >= 1 | |
110 | |
111 def CreateForwarder(self, host_port): | |
112 raise NotImplementedError() | |
113 | |
114 def IsBrowserRunning(self): | |
115 raise NotImplementedError() | |
OLD | NEW |