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

Side by Side Diff: ppapi/native_client/tools/browser_tester/browsertester/browserlauncher.py

Issue 10914053: Relocating files in the nacl repo that belong in chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 8 years, 3 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 #!/usr/bin/python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import os.path
7 import re
8 import shutil
9 import sys
10 import tempfile
11 import time
12
13 import browserprocess
14
15 class LaunchFailure(Exception):
16 pass
17
18
19 def GetPlatform():
20 if sys.platform == 'darwin':
21 platform = 'mac'
22 elif sys.platform.startswith('linux'):
23 platform = 'linux'
24 elif sys.platform in ('cygwin', 'win32'):
25 platform = 'windows'
26 else:
27 raise LaunchFailure('Unknown platform: %s' % sys.platform)
28 return platform
29
30
31 PLATFORM = GetPlatform()
32
33
34 def SelectRunCommand():
35 # The subprocess module added support for .kill in Python 2.6
36 assert (sys.version_info[0] >= 3 or (sys.version_info[0] == 2 and
37 sys.version_info[1] >= 6))
38 if PLATFORM == 'linux':
39 return browserprocess.RunCommandInProcessGroup
40 else:
41 return browserprocess.RunCommandWithSubprocess
42
43
44 RunCommand = SelectRunCommand()
45
46 def RemoveDirectory(path):
47 retry = 5
48 sleep_time = 0.25
49 while True:
50 try:
51 shutil.rmtree(path)
52 except Exception:
53 # Windows processes sometime hang onto files too long
54 if retry > 0:
55 retry -= 1
56 time.sleep(sleep_time)
57 sleep_time *= 2
58 else:
59 # No luck - don't mask the error
60 raise
61 else:
62 # succeeded
63 break
64
65
66
67 # In Windows, subprocess seems to have an issue with file names that
68 # contain spaces.
69 def EscapeSpaces(path):
70 if PLATFORM == 'windows' and ' ' in path:
71 return '"%s"' % path
72 return path
73
74
75 def MakeEnv(options):
76 env = dict(os.environ)
77 # Enable PPAPI Dev interfaces for testing.
78 env['NACL_ENABLE_PPAPI_DEV'] = str(options.enable_ppapi_dev)
79 if options.debug:
80 env['PPAPI_BROWSER_DEBUG'] = '1'
81 env['NACL_PLUGIN_DEBUG'] = '1'
82 env['NACL_PPAPI_PROXY_DEBUG'] = '1'
83 # env['NACL_SRPC_DEBUG'] = '1'
84 return env
85
86
87 class BrowserLauncher(object):
88
89 WAIT_TIME = 20
90 WAIT_STEPS = 80
91 SLEEP_TIME = float(WAIT_TIME) / WAIT_STEPS
92
93 def __init__(self, options):
94 self.options = options
95 self.profile = None
96 self.binary = None
97 self.tool_log_dir = None
98
99 def KnownPath(self):
100 raise NotImplementedError
101
102 def BinaryName(self):
103 raise NotImplementedError
104
105 def CreateProfile(self):
106 raise NotImplementedError
107
108 def MakeCmd(self, url):
109 raise NotImplementedError
110
111 def CreateToolLogDir(self):
112 self.tool_log_dir = tempfile.mkdtemp(prefix='vglogs_')
113 return self.tool_log_dir
114
115 def FindBinary(self):
116 if self.options.browser_path:
117 return self.options.browser_path
118 else:
119 path = self.KnownPath()
120 if path is None or not os.path.exists(path):
121 raise LaunchFailure('Cannot find the browser directory')
122 binary = os.path.join(path, self.BinaryName())
123 if not os.path.exists(binary):
124 raise LaunchFailure('Cannot find the browser binary')
125 return binary
126
127 def WaitForProcessDeath(self):
128 self.browser_process.Wait(self.WAIT_STEPS, self.SLEEP_TIME)
129
130 def Cleanup(self):
131 self.browser_process.Kill()
132
133 RemoveDirectory(self.profile)
134 if self.tool_log_dir is not None:
135 RemoveDirectory(self.tool_log_dir)
136
137 def MakeProfileDirectory(self):
138 self.profile = tempfile.mkdtemp(prefix='browserprofile_')
139 return self.profile
140
141 def SetStandardStream(self, env, var_name, redirect_file, is_output):
142 if redirect_file is None:
143 return
144 file_prefix = 'file:'
145 dev_prefix = 'dev:'
146 debug_warning = 'DEBUG_ONLY:'
147 # logic must match src/trusted/service_runtime/nacl_resource.*
148 # resource specification notation. file: is the default
149 # interpretation, so we must have an exhaustive list of
150 # alternative schemes accepted. if we remove the file-is-default
151 # interpretation, replace with
152 # is_file = redirect_file.startswith(file_prefix)
153 # and remove the list of non-file schemes.
154 is_file = (not (redirect_file.startswith(dev_prefix) or
155 redirect_file.startswith(debug_warning + dev_prefix)))
156 if is_file:
157 if redirect_file.startswith(file_prefix):
158 bare_file = redirect_file[len(file_prefix)]
159 else:
160 bare_file = redirect_file
161 # why always abspath? does chrome chdir or might it in the
162 # future? this means we do not test/use the relative path case.
163 redirect_file = file_prefix + os.path.abspath(bare_file)
164 else:
165 bare_file = None # ensure error if used without checking is_file
166 env[var_name] = redirect_file
167 if is_output:
168 # sel_ldr appends program output to the file so we need to clear it
169 # in order to get the stable result.
170 if is_file:
171 if os.path.exists(bare_file):
172 os.remove(bare_file)
173 parent_dir = os.path.dirname(bare_file)
174 # parent directory may not exist.
175 if not os.path.exists(parent_dir):
176 os.makedirs(parent_dir)
177
178 def Launch(self, cmd, env):
179 browser_path = cmd[0]
180 if not os.path.exists(browser_path):
181 raise LaunchFailure('Browser does not exist %r'% browser_path)
182 if not os.access(browser_path, os.X_OK):
183 raise LaunchFailure('Browser cannot be executed %r (Is this binary on an '
184 'NFS volume?)' % browser_path)
185 if self.options.sel_ldr:
186 env['NACL_SEL_LDR'] = self.options.sel_ldr
187 if self.options.sel_ldr_bootstrap:
188 env['NACL_SEL_LDR_BOOTSTRAP'] = self.options.sel_ldr_bootstrap
189 if self.options.irt_library:
190 env['NACL_IRT_LIBRARY'] = self.options.irt_library
191 if self.options.prefer_portable_in_manifest:
192 env['NACL_PREFER_PORTABLE_IN_MANIFEST'] = '1'
193 self.SetStandardStream(env, 'NACL_EXE_STDIN',
194 self.options.nacl_exe_stdin, False)
195 self.SetStandardStream(env, 'NACL_EXE_STDOUT',
196 self.options.nacl_exe_stdout, True)
197 self.SetStandardStream(env, 'NACL_EXE_STDERR',
198 self.options.nacl_exe_stderr, True)
199 print 'ENV:', ' '.join(['='.join(pair) for pair in env.iteritems()])
200 print 'LAUNCHING: %s' % ' '.join(cmd)
201 sys.stdout.flush()
202 self.browser_process = RunCommand(cmd, env=env)
203
204 def IsRunning(self):
205 return self.browser_process.IsRunning()
206
207 def GetReturnCode(self):
208 return self.browser_process.GetReturnCode()
209
210 def Run(self, url, port):
211 self.binary = EscapeSpaces(self.FindBinary())
212 self.profile = self.CreateProfile()
213 if self.options.tool is not None:
214 self.tool_log_dir = self.CreateToolLogDir()
215 cmd = self.MakeCmd(url, port)
216 self.Launch(cmd, MakeEnv(self.options))
217
218
219 def EnsureDirectory(path):
220 if not os.path.exists(path):
221 os.makedirs(path)
222
223
224 def EnsureDirectoryForFile(path):
225 EnsureDirectory(os.path.dirname(path))
226
227
228 class ChromeLauncher(BrowserLauncher):
229
230 def KnownPath(self):
231 if PLATFORM == 'linux':
232 # TODO(ncbray): look in path?
233 return '/opt/google/chrome'
234 elif PLATFORM == 'mac':
235 return '/Applications/Google Chrome.app/Contents/MacOS'
236 else:
237 homedir = os.path.expanduser('~')
238 path = os.path.join(homedir, r'AppData\Local\Google\Chrome\Application')
239 return path
240
241 def BinaryName(self):
242 if PLATFORM == 'mac':
243 return 'Google Chrome'
244 elif PLATFORM == 'windows':
245 return 'chrome.exe'
246 else:
247 return 'chrome'
248
249 def MakeEmptyJSONFile(self, path):
250 EnsureDirectoryForFile(path)
251 f = open(path, 'w')
252 f.write('{}')
253 f.close()
254
255 def CreateProfile(self):
256 profile = self.MakeProfileDirectory()
257
258 # Squelch warnings by creating bogus files.
259 self.MakeEmptyJSONFile(os.path.join(profile, 'Default', 'Preferences'))
260 self.MakeEmptyJSONFile(os.path.join(profile, 'Local State'))
261
262 return profile
263
264 def NetLogName(self):
265 return os.path.join(self.profile, 'netlog.json')
266
267 def MakeCmd(self, url, port):
268 cmd = [self.binary,
269 '--disable-web-resources',
270 '--disable-preconnect',
271 '--no-first-run',
272 '--no-default-browser-check',
273 '--enable-logging',
274 '--log-level=1',
275 '--safebrowsing-disable-auto-update',
276 # Chrome explicitly blacklists some ports as "unsafe" because
277 # certain protocols use them. Chrome gives an error like this:
278 # Error 312 (net::ERR_UNSAFE_PORT): Unknown error
279 # Unfortunately, the browser tester can randomly choose a
280 # blacklisted port. To work around this, the tester whitelists
281 # whatever port it is using.
282 '--explicitly-allowed-ports=%d' % port,
283 '--user-data-dir=%s' % self.profile]
284 # Log network requests to assist debugging.
285 cmd.append('--log-net-log=%s' % self.NetLogName())
286 if self.options.ppapi_plugin is None:
287 cmd.append('--enable-nacl')
288 disable_sandbox = False
289 # Sandboxing Chrome on Linux requires a SUIDed helper binary. This
290 # binary may not be installed, so disable sandboxing to avoid the
291 # corner cases where it may fail. This is a little scarry, because it
292 # means we are not testing NaCl inside the outer sandbox on Linux.
293 disable_sandbox |= PLATFORM == 'linux'
294 # Chrome process can't access file within sandbox
295 disable_sandbox |= self.options.nacl_exe_stdin is not None
296 disable_sandbox |= self.options.nacl_exe_stdout is not None
297 disable_sandbox |= self.options.nacl_exe_stderr is not None
298 if disable_sandbox:
299 cmd.append('--no-sandbox')
300 else:
301 cmd.append('--register-pepper-plugins=%s;application/x-nacl'
302 % self.options.ppapi_plugin)
303 cmd.append('--no-sandbox')
304 if self.options.browser_extensions:
305 cmd.append('--load-extension=%s' %
306 ','.join(self.options.browser_extensions))
307 cmd.append('--enable-experimental-extension-apis')
308 if self.options.tool == 'memcheck':
309 cmd = ['src/third_party/valgrind/memcheck.sh',
310 '-v',
311 '--xml=yes',
312 '--leak-check=no',
313 '--gen-suppressions=all',
314 '--num-callers=30',
315 '--trace-children=yes',
316 '--nacl-file=%s' % (self.options.files[0],),
317 '--suppressions=' +
318 '../tools/valgrind/memcheck/suppressions.txt',
319 '--xml-file=%s/xml.%%p' % (self.tool_log_dir,),
320 '--log-file=%s/log.%%p' % (self.tool_log_dir,)] + cmd
321 elif self.options.tool == 'tsan':
322 cmd = ['src/third_party/valgrind/tsan.sh',
323 '-v',
324 '--num-callers=30',
325 '--trace-children=yes',
326 '--nacl-file=%s' % (self.options.files[0],),
327 '--ignore=../tools/valgrind/tsan/ignores.txt',
328 '--suppressions=../tools/valgrind/tsan/suppressions.txt',
329 '--log-file=%s/log.%%p' % (self.tool_log_dir,)] + cmd
330 elif self.options.tool != None:
331 raise LaunchFailure('Invalid tool name "%s"' % (self.options.tool,))
332 cmd.extend(self.options.browser_flags)
333 cmd.append(url)
334 return cmd
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698