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 | |
5 import urllib2 | |
6 import httplib | |
7 import socket | |
8 import json | |
9 import re | |
10 import sys | |
11 | |
12 from telemetry import browser_gone_exception | |
13 from telemetry import extension_dict_backend | |
14 from telemetry import options_for_unittests | |
15 from telemetry import tab_list_backend | |
16 from telemetry import tracing_backend | |
17 from telemetry import user_agent | |
18 from telemetry import util | |
19 from telemetry import wpr_modes | |
20 from telemetry import wpr_server | |
21 | |
22 class ExtensionsNotSupportedException(Exception): | |
23 pass | |
24 | |
25 class BrowserBackend(object): | |
26 """A base class for browser backends. Provides basic functionality | |
27 once a remote-debugger port has been established.""" | |
28 | |
29 WEBPAGEREPLAY_HOST = '127.0.0.1' | |
30 | |
31 def __init__(self, is_content_shell, supports_extensions, options): | |
32 self.browser_type = options.browser_type | |
33 self.is_content_shell = is_content_shell | |
34 self._supports_extensions = supports_extensions | |
35 self.options = options | |
36 self._browser = None | |
37 self._port = None | |
38 | |
39 self._inspector_protocol_version = 0 | |
40 self._chrome_branch_number = 0 | |
41 self._webkit_base_revision = 0 | |
42 self._tracing_backend = None | |
43 | |
44 self.webpagereplay_local_http_port = util.GetAvailableLocalPort() | |
45 self.webpagereplay_local_https_port = util.GetAvailableLocalPort() | |
46 self.webpagereplay_remote_http_port = self.webpagereplay_local_http_port | |
47 self.webpagereplay_remote_https_port = self.webpagereplay_local_https_port | |
48 | |
49 if options.dont_override_profile and not options_for_unittests.AreSet(): | |
50 sys.stderr.write('Warning: Not overriding profile. This can cause ' | |
51 'unexpected effects due to profile-specific settings, ' | |
52 'such as about:flags settings, cookies, and ' | |
53 'extensions.\n') | |
54 self._tab_list_backend = tab_list_backend.TabListBackend(self) | |
55 self._extension_dict_backend = None | |
56 if supports_extensions: | |
57 self._extension_dict_backend = \ | |
58 extension_dict_backend.ExtensionDictBackend(self) | |
59 | |
60 def SetBrowser(self, browser): | |
61 self._browser = browser | |
62 self._tab_list_backend.Init() | |
63 | |
64 @property | |
65 def browser(self): | |
66 return self._browser | |
67 | |
68 @property | |
69 def supports_extensions(self): | |
70 """True if this browser backend supports extensions.""" | |
71 return self._supports_extensions | |
72 | |
73 @property | |
74 def tab_list_backend(self): | |
75 return self._tab_list_backend | |
76 | |
77 @property | |
78 def extension_dict_backend(self): | |
79 return self._extension_dict_backend | |
80 | |
81 def GetBrowserStartupArgs(self): | |
82 args = [] | |
83 args.extend(self.options.extra_browser_args) | |
84 args.append('--disable-background-networking') | |
85 args.append('--metrics-recording-only') | |
86 args.append('--no-first-run') | |
87 if self.options.wpr_mode != wpr_modes.WPR_OFF: | |
88 args.extend(wpr_server.GetChromeFlags( | |
89 self.WEBPAGEREPLAY_HOST, | |
90 self.webpagereplay_remote_http_port, | |
91 self.webpagereplay_remote_https_port)) | |
92 args.extend(user_agent.GetChromeUserAgentArgumentFromType( | |
93 self.options.browser_user_agent_type)) | |
94 | |
95 extensions = ','.join( | |
96 [extension.path for extension in self.options.extensions_to_load]) | |
97 if len(self.options.extensions_to_load) > 0: | |
98 args.append('--load-extension=%s' % extensions) | |
99 | |
100 return args | |
101 | |
102 @property | |
103 def wpr_mode(self): | |
104 return self.options.wpr_mode | |
105 | |
106 def _WaitForBrowserToComeUp(self, timeout=None): | |
107 def IsBrowserUp(): | |
108 try: | |
109 self.Request('', timeout=timeout) | |
110 except (socket.error, httplib.BadStatusLine, urllib2.URLError): | |
111 return False | |
112 else: | |
113 return True | |
114 try: | |
115 util.WaitFor(IsBrowserUp, timeout=30) | |
116 except util.TimeoutException: | |
117 raise browser_gone_exception.BrowserGoneException() | |
118 | |
119 def AllExtensionsLoaded(): | |
120 for e in self.options.extensions_to_load: | |
121 extension_id = e.extension_id() | |
122 if not extension_id in self._extension_dict_backend: | |
123 return False | |
124 extension_object = self._extension_dict_backend[extension_id] | |
125 extension_object.WaitForDocumentReadyStateToBeInteractiveOrBetter() | |
126 return True | |
127 if self._supports_extensions: | |
128 util.WaitFor(AllExtensionsLoaded, timeout=30) | |
129 | |
130 def _PostBrowserStartupInitialization(self): | |
131 # Detect version information. | |
132 data = self.Request('version') | |
133 resp = json.loads(data) | |
134 if 'Protocol-Version' in resp: | |
135 self._inspector_protocol_version = resp['Protocol-Version'] | |
136 if 'Browser' in resp: | |
137 branch_number_match = re.search('Chrome/\d+\.\d+\.(\d+)\.\d+', | |
138 resp['Browser']) | |
139 else: | |
140 branch_number_match = re.search( | |
141 'Chrome/\d+\.\d+\.(\d+)\.\d+ (Mobile )?Safari', | |
142 resp['User-Agent']) | |
143 webkit_version_match = re.search('\((trunk)?\@(\d+)\)', | |
144 resp['WebKit-Version']) | |
145 | |
146 if branch_number_match: | |
147 self._chrome_branch_number = int(branch_number_match.group(1)) | |
148 else: | |
149 # Content Shell returns '' for Browser, for now we have to | |
150 # fall-back and assume branch 1025. | |
151 self._chrome_branch_number = 1025 | |
152 | |
153 if webkit_version_match: | |
154 self._webkit_base_revision = int(webkit_version_match.group(2)) | |
155 return | |
156 | |
157 # Detection has failed: assume 18.0.1025.168 ~= Chrome Android. | |
158 self._inspector_protocol_version = 1.0 | |
159 self._chrome_branch_number = 1025 | |
160 self._webkit_base_revision = 106313 | |
161 | |
162 def Request(self, path, timeout=None): | |
163 url = 'http://localhost:%i/json' % self._port | |
164 if path: | |
165 url += '/' + path | |
166 req = urllib2.urlopen(url, timeout=timeout) | |
167 return req.read() | |
168 | |
169 @property | |
170 def chrome_branch_number(self): | |
171 return self._chrome_branch_number | |
172 | |
173 @property | |
174 def supports_tab_control(self): | |
175 return self._chrome_branch_number >= 1303 | |
176 | |
177 @property | |
178 def supports_tracing(self): | |
179 return self.is_content_shell or self._chrome_branch_number >= 1385 | |
180 | |
181 def StartTracing(self): | |
182 if self._tracing_backend is None: | |
183 self._tracing_backend = tracing_backend.TracingBackend(self._port) | |
184 self._tracing_backend.BeginTracing() | |
185 | |
186 def StopTracing(self): | |
187 self._tracing_backend.EndTracing() | |
188 | |
189 def GetTraceResultAndReset(self): | |
190 return self._tracing_backend.GetTraceResultAndReset() | |
191 | |
192 def GetRemotePort(self, _): | |
193 return util.GetAvailableLocalPort() | |
194 | |
195 def Close(self): | |
196 if self._tracing_backend: | |
197 self._tracing_backend.Close() | |
198 self._tracing_backend = None | |
199 | |
200 def CreateForwarder(self, *port_pairs): | |
201 raise NotImplementedError() | |
202 | |
203 def IsBrowserRunning(self): | |
204 raise NotImplementedError() | |
205 | |
206 def GetStandardOutput(self): | |
207 raise NotImplementedError() | |
OLD | NEW |