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.core import util | |
13 from telemetry.core import exceptions | |
14 from telemetry.core import user_agent | |
15 from telemetry.core import wpr_modes | |
16 from telemetry.core import wpr_server | |
17 from telemetry.core.chrome import extension_dict_backend | |
18 from telemetry.core.chrome import tab_list_backend | |
19 from telemetry.core.chrome import tracing_backend | |
20 from telemetry.test import options_for_unittests | |
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 = [extension.path for extension in | |
96 self.options.extensions_to_load if not extension.is_component] | |
97 extension_str = ','.join(extensions) | |
98 if len(extensions) > 0: | |
99 args.append('--load-extension=%s' % extension_str) | |
100 | |
101 component_extensions = [extension.path for extension in | |
102 self.options.extensions_to_load if extension.is_component] | |
103 component_extension_str = ','.join(component_extensions) | |
104 if len(component_extensions) > 0: | |
105 args.append('--load-component-extension=%s' % component_extension_str) | |
106 return args | |
107 | |
108 @property | |
109 def wpr_mode(self): | |
110 return self.options.wpr_mode | |
111 | |
112 def _WaitForBrowserToComeUp(self, timeout=None): | |
113 def IsBrowserUp(): | |
114 try: | |
115 self.Request('', timeout=timeout) | |
116 except (socket.error, httplib.BadStatusLine, urllib2.URLError): | |
117 return False | |
118 else: | |
119 return True | |
120 try: | |
121 util.WaitFor(IsBrowserUp, timeout=30) | |
122 except util.TimeoutException: | |
123 raise exceptions.BrowserGoneException() | |
124 | |
125 def AllExtensionsLoaded(): | |
126 for e in self.options.extensions_to_load: | |
127 if not e.extension_id in self._extension_dict_backend: | |
128 return False | |
129 extension_object = self._extension_dict_backend[e.extension_id] | |
130 extension_object.WaitForDocumentReadyStateToBeInteractiveOrBetter() | |
131 return True | |
132 if self._supports_extensions: | |
133 util.WaitFor(AllExtensionsLoaded, timeout=30) | |
134 | |
135 def _PostBrowserStartupInitialization(self): | |
136 # Detect version information. | |
137 data = self.Request('version') | |
138 resp = json.loads(data) | |
139 if 'Protocol-Version' in resp: | |
140 self._inspector_protocol_version = resp['Protocol-Version'] | |
141 if 'Browser' in resp: | |
142 branch_number_match = re.search('Chrome/\d+\.\d+\.(\d+)\.\d+', | |
143 resp['Browser']) | |
144 else: | |
145 branch_number_match = re.search( | |
146 'Chrome/\d+\.\d+\.(\d+)\.\d+ (Mobile )?Safari', | |
147 resp['User-Agent']) | |
148 webkit_version_match = re.search('\((trunk)?\@(\d+)\)', | |
149 resp['WebKit-Version']) | |
150 | |
151 if branch_number_match: | |
152 self._chrome_branch_number = int(branch_number_match.group(1)) | |
153 else: | |
154 # Content Shell returns '' for Browser, for now we have to | |
155 # fall-back and assume branch 1025. | |
156 self._chrome_branch_number = 1025 | |
157 | |
158 if webkit_version_match: | |
159 self._webkit_base_revision = int(webkit_version_match.group(2)) | |
160 return | |
161 | |
162 # Detection has failed: assume 18.0.1025.168 ~= Chrome Android. | |
163 self._inspector_protocol_version = 1.0 | |
164 self._chrome_branch_number = 1025 | |
165 self._webkit_base_revision = 106313 | |
166 | |
167 def Request(self, path, timeout=None): | |
168 url = 'http://localhost:%i/json' % self._port | |
169 if path: | |
170 url += '/' + path | |
171 req = urllib2.urlopen(url, timeout=timeout) | |
172 return req.read() | |
173 | |
174 @property | |
175 def chrome_branch_number(self): | |
176 return self._chrome_branch_number | |
177 | |
178 @property | |
179 def supports_tab_control(self): | |
180 return self._chrome_branch_number >= 1303 | |
181 | |
182 @property | |
183 def supports_tracing(self): | |
184 return self.is_content_shell or self._chrome_branch_number >= 1385 | |
185 | |
186 def StartTracing(self): | |
187 if self._tracing_backend is None: | |
188 self._tracing_backend = tracing_backend.TracingBackend(self._port) | |
189 self._tracing_backend.BeginTracing() | |
190 | |
191 def StopTracing(self): | |
192 self._tracing_backend.EndTracing() | |
193 | |
194 def GetTraceResultAndReset(self): | |
195 return self._tracing_backend.GetTraceResultAndReset() | |
196 | |
197 def GetRemotePort(self, _): | |
198 return util.GetAvailableLocalPort() | |
199 | |
200 def Close(self): | |
201 if self._tracing_backend: | |
202 self._tracing_backend.Close() | |
203 self._tracing_backend = None | |
204 | |
205 def CreateForwarder(self, *port_pairs): | |
206 raise NotImplementedError() | |
207 | |
208 def IsBrowserRunning(self): | |
209 raise NotImplementedError() | |
210 | |
211 def GetStandardOutput(self): | |
212 raise NotImplementedError() | |
OLD | NEW |