Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: tools/telemetry/telemetry/core/chrome/desktop_browser_backend.py

Issue 23072018: [telemetry] Move telemetry/core/chrome/ to telemetry/core/backends/chrome/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: penguin Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 glob
5 import heapq
6 import logging
7 import os
8 import subprocess as subprocess
9 import shutil
10 import sys
11 import tempfile
12 import time
13
14 from telemetry.core import util
15 from telemetry.core.backends import browser_backend
16 from telemetry.core.backends.chrome import chrome_browser_backend
17
18 class DesktopBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
19 """The backend for controlling a locally-executed browser instance, on Linux,
20 Mac or Windows.
21 """
22 def __init__(self, options, executable, flash_path, is_content_shell,
23 browser_directory, delete_profile_dir_after_run=True):
24 super(DesktopBrowserBackend, self).__init__(
25 is_content_shell=is_content_shell,
26 supports_extensions=not is_content_shell,
27 options=options)
28
29 # Initialize fields so that an explosion during init doesn't break in Close.
30 self._proc = None
31 self._tmp_profile_dir = None
32 self._tmp_output_file = None
33
34 self._executable = executable
35 if not self._executable:
36 raise Exception('Cannot create browser, no executable found!')
37
38 self._flash_path = flash_path
39 if self._flash_path and not os.path.exists(self._flash_path):
40 logging.warning(('Could not find flash at %s. Running without flash.\n\n'
41 'To fix this see http://go/read-src-internal') %
42 self._flash_path)
43 self._flash_path = None
44
45 if len(options.extensions_to_load) > 0 and is_content_shell:
46 raise browser_backend.ExtensionsNotSupportedException(
47 'Content shell does not support extensions.')
48
49 self._browser_directory = browser_directory
50 self._port = util.GetAvailableLocalPort()
51 self._profile_dir = None
52 self._supports_net_benchmarking = True
53 self._delete_profile_dir_after_run = delete_profile_dir_after_run
54 self._tmp_minidump_dir = tempfile.mkdtemp()
55
56 self._SetupProfile()
57
58 def _SetupProfile(self):
59 if not self.options.dont_override_profile:
60 self._tmp_profile_dir = tempfile.mkdtemp()
61 profile_dir = self._profile_dir or self.options.profile_dir
62 if profile_dir:
63 if self.is_content_shell:
64 logging.critical('Profiles cannot be used with content shell')
65 sys.exit(1)
66 shutil.rmtree(self._tmp_profile_dir)
67 shutil.copytree(profile_dir, self._tmp_profile_dir)
68
69 def _LaunchBrowser(self):
70 args = [self._executable]
71 args.extend(self.GetBrowserStartupArgs())
72 env = os.environ.copy()
73 env['CHROME_HEADLESS'] = '1' # Don't upload minidumps.
74 env['BREAKPAD_DUMP_LOCATION'] = self._tmp_minidump_dir
75 if not self.options.show_stdout:
76 self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
77 self._proc = subprocess.Popen(
78 args, stdout=self._tmp_output_file, stderr=subprocess.STDOUT, env=env)
79 else:
80 self._proc = subprocess.Popen(args, env=env)
81
82 try:
83 self._WaitForBrowserToComeUp()
84 self._PostBrowserStartupInitialization()
85 except:
86 self.Close()
87 raise
88
89 def GetBrowserStartupArgs(self):
90 args = super(DesktopBrowserBackend, self).GetBrowserStartupArgs()
91 args.append('--remote-debugging-port=%i' % self._port)
92 args.append('--enable-crash-reporter-for-testing')
93 if not self.is_content_shell:
94 args.append('--window-size=1280,1024')
95 if self._flash_path:
96 args.append('--ppapi-flash-path=%s' % self._flash_path)
97 if self._supports_net_benchmarking:
98 args.append('--enable-net-benchmarking')
99 else:
100 args.append('--enable-benchmarking')
101 if not self.options.dont_override_profile:
102 args.append('--user-data-dir=%s' % self._tmp_profile_dir)
103 return args
104
105 def SetProfileDirectory(self, profile_dir):
106 # Make sure _profile_dir hasn't already been set.
107 assert self._profile_dir is None
108
109 if self.is_content_shell:
110 logging.critical('Profile creation cannot be used with content shell')
111 sys.exit(1)
112
113 self._profile_dir = profile_dir
114
115 def Start(self):
116 self._LaunchBrowser()
117
118 # For old chrome versions, might have to relaunch to have the
119 # correct net_benchmarking switch.
120 if self._chrome_branch_number < 1418:
121 self.Close()
122 self._supports_net_benchmarking = False
123 self._LaunchBrowser()
124
125 @property
126 def pid(self):
127 if self._proc:
128 return self._proc.pid
129 return None
130
131 @property
132 def browser_directory(self):
133 return self._browser_directory
134
135 @property
136 def profile_directory(self):
137 return self._tmp_profile_dir
138
139 def IsBrowserRunning(self):
140 return self._proc.poll() == None
141
142 def GetStandardOutput(self):
143 assert self._tmp_output_file, "Can't get standard output with show_stdout"
144 self._tmp_output_file.flush()
145 try:
146 with open(self._tmp_output_file.name) as f:
147 return f.read()
148 except IOError:
149 return ''
150
151 def GetStackTrace(self):
152 executable_dir = os.path.dirname(self._executable)
153 stackwalk = os.path.join(executable_dir, 'minidump_stackwalk')
154 if not os.path.exists(stackwalk):
155 logging.warning('minidump_stackwalk binary not found. Must build it to '
156 'symbolize crash dumps. Returning browser stdout.')
157 return self.GetStandardOutput()
158
159 dumps = glob.glob(os.path.join(self._tmp_minidump_dir, '*.dmp'))
160 if not dumps:
161 logging.warning('No crash dump found. Returning browser stdout.')
162 return self.GetStandardOutput()
163 most_recent_dump = heapq.nlargest(1, dumps, os.path.getmtime)[0]
164 if os.path.getmtime(most_recent_dump) < (time.time() - (5 * 60)):
165 logging.warn('Crash dump is older than 5 minutes. May not be correct.')
166
167 minidump = most_recent_dump + '.stripped'
168 with open(most_recent_dump, 'rb') as infile:
169 with open(minidump, 'wb') as outfile:
170 outfile.write(''.join(infile.read().partition('MDMP')[1:]))
171
172 symbols = glob.glob(os.path.join(executable_dir, 'chrome.breakpad.*'))[0]
173 if not symbols:
174 logging.warning('No breakpad symbols found. Returning browser stdout.')
175 return self.GetStandardOutput()
176
177 symbols_path = os.path.join(self._tmp_minidump_dir, 'symbols')
178 with open(symbols, 'r') as f:
179 _, _, _, sha, binary = f.readline().split()
180 symbol_path = os.path.join(symbols_path, binary, sha)
181 os.makedirs(symbol_path)
182 shutil.copyfile(symbols, os.path.join(symbol_path, binary + '.sym'))
183
184 error = tempfile.NamedTemporaryFile('w', 0)
185 return subprocess.Popen(
186 [stackwalk, minidump, symbols_path],
187 stdout=subprocess.PIPE, stderr=error).communicate()[0]
188
189 def __del__(self):
190 self.Close()
191
192 def Close(self):
193 super(DesktopBrowserBackend, self).Close()
194
195 if self._proc:
196
197 def IsClosed():
198 if not self._proc:
199 return True
200 return self._proc.poll() != None
201
202 # Try to politely shutdown, first.
203 self._proc.terminate()
204 try:
205 util.WaitFor(IsClosed, timeout=1)
206 self._proc = None
207 except util.TimeoutException:
208 pass
209
210 # Kill it.
211 if not IsClosed():
212 self._proc.kill()
213 try:
214 util.WaitFor(IsClosed, timeout=5)
215 self._proc = None
216 except util.TimeoutException:
217 self._proc = None
218 raise Exception('Could not shutdown the browser.')
219
220 if self._delete_profile_dir_after_run and \
221 self._tmp_profile_dir and os.path.exists(self._tmp_profile_dir):
222 shutil.rmtree(self._tmp_profile_dir, ignore_errors=True)
223 self._tmp_profile_dir = None
224
225 if self._tmp_output_file:
226 self._tmp_output_file.close()
227 self._tmp_output_file = None
228
229 def CreateForwarder(self, *port_pairs):
230 return browser_backend.DoNothingForwarder(*port_pairs)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698