15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/python 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os.path 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import shutil 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import tempfile 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import time 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import urlparse 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import browserprocess 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LaunchFailure(Exception): 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetPlatform(): 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if sys.platform == 'darwin': 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform = 'mac' 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif sys.platform.startswith('linux'): 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform = 'linux' 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif sys.platform in ('cygwin', 'win32'): 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform = 'windows' 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise LaunchFailure('Unknown platform: %s' % sys.platform) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return platform 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PLATFORM = GetPlatform() 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def SelectRunCommand(): 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # The subprocess module added support for .kill in Python 2.6 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert (sys.version_info[0] >= 3 or (sys.version_info[0] == 2 and 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.version_info[1] >= 6)) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if PLATFORM == 'linux': 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browserprocess.RunCommandInProcessGroup 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browserprocess.RunCommandWithSubprocess 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RunCommand = SelectRunCommand() 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def RemoveDirectory(path): 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retry = 5 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sleep_time = 0.25 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while True: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutil.rmtree(path) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except Exception: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Windows processes sometime hang onto files too long 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if retry > 0: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retry -= 1 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time.sleep(sleep_time) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sleep_time *= 2 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # No luck - don't mask the error 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # succeeded 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# In Windows, subprocess seems to have an issue with file names that 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# contain spaces. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def EscapeSpaces(path): 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if PLATFORM == 'windows' and ' ' in path: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '"%s"' % path 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def MakeEnv(options): 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env = dict(os.environ) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Enable PPAPI Dev interfaces for testing. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env['NACL_ENABLE_PPAPI_DEV'] = str(options.enable_ppapi_dev) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if options.debug: 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env['NACL_PLUGIN_DEBUG'] = '1' 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # env['NACL_SRPC_DEBUG'] = '1' 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return env 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BrowserLauncher(object): 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WAIT_TIME = 20 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WAIT_STEPS = 80 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SLEEP_TIME = float(WAIT_TIME) / WAIT_STEPS 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, options): 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.options = options 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.profile = None 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.binary = None 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.tool_log_dir = None 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def KnownPath(self): 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def BinaryName(self): 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateProfile(self): 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) def MakeCmd(self, url, host, port): 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateToolLogDir(self): 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.tool_log_dir = tempfile.mkdtemp(prefix='vglogs_') 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.tool_log_dir 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def FindBinary(self): 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.options.browser_path: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.options.browser_path 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path = self.KnownPath() 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if path is None or not os.path.exists(path): 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise LaunchFailure('Cannot find the browser directory') 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) binary = os.path.join(path, self.BinaryName()) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not os.path.exists(binary): 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise LaunchFailure('Cannot find the browser binary') 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return binary 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def WaitForProcessDeath(self): 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.browser_process.Wait(self.WAIT_STEPS, self.SLEEP_TIME) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Cleanup(self): 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.browser_process.Kill() 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveDirectory(self.profile) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.tool_log_dir is not None: 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveDirectory(self.tool_log_dir) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def MakeProfileDirectory(self): 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.profile = tempfile.mkdtemp(prefix='browserprofile_') 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.profile 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def SetStandardStream(self, env, var_name, redirect_file, is_output): 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if redirect_file is None: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_prefix = 'file:' 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dev_prefix = 'dev:' 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_warning = 'DEBUG_ONLY:' 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # logic must match src/trusted/service_runtime/nacl_resource.* 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # resource specification notation. file: is the default 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # interpretation, so we must have an exhaustive list of 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # alternative schemes accepted. if we remove the file-is-default 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # interpretation, replace with 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # is_file = redirect_file.startswith(file_prefix) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # and remove the list of non-file schemes. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_file = (not (redirect_file.startswith(dev_prefix) or 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_file.startswith(debug_warning + dev_prefix))) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if is_file: 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if redirect_file.startswith(file_prefix): 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bare_file = redirect_file[len(file_prefix)] 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bare_file = redirect_file 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # why always abspath? does chrome chdir or might it in the 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # future? this means we do not test/use the relative path case. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_file = file_prefix + os.path.abspath(bare_file) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bare_file = None # ensure error if used without checking is_file 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env[var_name] = redirect_file 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if is_output: 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # sel_ldr appends program output to the file so we need to clear it 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # in order to get the stable result. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if is_file: 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.exists(bare_file): 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.remove(bare_file) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_dir = os.path.dirname(bare_file) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # parent directory may not exist. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not os.path.exists(parent_dir): 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.makedirs(parent_dir) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Launch(self, cmd, env): 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_path = cmd[0] 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not os.path.exists(browser_path): 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise LaunchFailure('Browser does not exist %r'% browser_path) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not os.access(browser_path, os.X_OK): 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise LaunchFailure('Browser cannot be executed %r (Is this binary on an ' 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'NFS volume?)' % browser_path) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.options.sel_ldr: 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env['NACL_SEL_LDR'] = self.options.sel_ldr 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.options.sel_ldr_bootstrap: 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env['NACL_SEL_LDR_BOOTSTRAP'] = self.options.sel_ldr_bootstrap 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.options.irt_library: 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env['NACL_IRT_LIBRARY'] = self.options.irt_library 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.SetStandardStream(env, 'NACL_EXE_STDIN', 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.options.nacl_exe_stdin, False) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.SetStandardStream(env, 'NACL_EXE_STDOUT', 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.options.nacl_exe_stdout, True) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.SetStandardStream(env, 'NACL_EXE_STDERR', 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.options.nacl_exe_stderr, True) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print 'ENV:', ' '.join(['='.join(pair) for pair in env.iteritems()]) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print 'LAUNCHING: %s' % ' '.join(cmd) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.stdout.flush() 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.browser_process = RunCommand(cmd, env=env) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def IsRunning(self): 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.browser_process.IsRunning() 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetReturnCode(self): 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.browser_process.GetReturnCode() 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) def Run(self, url, host, port): 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.binary = EscapeSpaces(self.FindBinary()) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.profile = self.CreateProfile() 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.options.tool is not None: 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.tool_log_dir = self.CreateToolLogDir() 2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) cmd = self.MakeCmd(url, host, port) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.Launch(cmd, MakeEnv(self.options)) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def EnsureDirectory(path): 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not os.path.exists(path): 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.makedirs(path) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def EnsureDirectoryForFile(path): 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureDirectory(os.path.dirname(path)) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromeLauncher(BrowserLauncher): 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def KnownPath(self): 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if PLATFORM == 'linux': 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(ncbray): look in path? 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '/opt/google/chrome' 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif PLATFORM == 'mac': 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '/Applications/Google Chrome.app/Contents/MacOS' 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) homedir = os.path.expanduser('~') 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path = os.path.join(homedir, r'AppData\Local\Google\Chrome\Application') 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def BinaryName(self): 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if PLATFORM == 'mac': 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'Google Chrome' 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif PLATFORM == 'windows': 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'chrome.exe' 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'chrome' 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def MakeEmptyJSONFile(self, path): 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureDirectoryForFile(path) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f = open(path, 'w') 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.write('{}') 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.close() 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateProfile(self): 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile = self.MakeProfileDirectory() 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Squelch warnings by creating bogus files. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.MakeEmptyJSONFile(os.path.join(profile, 'Default', 'Preferences')) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.MakeEmptyJSONFile(os.path.join(profile, 'Local State')) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return profile 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def NetLogName(self): 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return os.path.join(self.profile, 'netlog.json') 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) def MakeCmd(self, url, host, port): 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd = [self.binary, 266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # --enable-logging enables stderr output from Chromium subprocesses 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # on Windows (see 268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # https://code.google.com/p/chromium/issues/detail?id=171836) 269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) '--enable-logging', 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--disable-web-resources', 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--disable-preconnect', 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # This is speculative, sync should not occur with a clean profile. 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) '--disable-sync', 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # This prevents Chrome from making "hidden" network requests at 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # startup. These requests could be a source of non-determinism, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # and they also add noise to the netlogs. 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) '--dns-prefetch-disable', 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--no-first-run', 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--no-default-browser-check', 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--log-level=1', 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--safebrowsing-disable-auto-update', 2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) '--disable-default-apps', 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Suppress metrics reporting. This prevents misconfigured bots, 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # people testing at their desktop, etc from poisoning the UMA data. 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) '--metrics-recording-only', 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Chrome explicitly blacklists some ports as "unsafe" because 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # certain protocols use them. Chrome gives an error like this: 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Error 312 (net::ERR_UNSAFE_PORT): Unknown error 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Unfortunately, the browser tester can randomly choose a 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # blacklisted port. To work around this, the tester whitelists 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # whatever port it is using. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--explicitly-allowed-ports=%d' % port, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--user-data-dir=%s' % self.profile] 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Log network requests to assist debugging. 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd.append('--log-net-log=%s' % self.NetLogName()) 2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if PLATFORM == 'linux': 2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) # Explicitly run with mesa on linux. The test infrastructure doesn't have 2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) # sufficient native GL contextes to run these tests. 2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cmd.append('--use-gl=osmesa') 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.options.ppapi_plugin is None: 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd.append('--enable-nacl') 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_sandbox = False 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Chrome process can't access file within sandbox 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_sandbox |= self.options.nacl_exe_stdin is not None 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_sandbox |= self.options.nacl_exe_stdout is not None 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_sandbox |= self.options.nacl_exe_stderr is not None 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if disable_sandbox: 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd.append('--no-sandbox') 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) cmd.append('--register-pepper-plugins=%s;%s' 311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) % (self.options.ppapi_plugin, 312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) self.options.ppapi_plugin_mimetype)) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd.append('--no-sandbox') 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.options.browser_extensions: 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd.append('--load-extension=%s' % 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ','.join(self.options.browser_extensions)) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd.append('--enable-experimental-extension-apis') 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if self.options.enable_crash_reporter: 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cmd.append('--enable-crash-reporter-for-testing') 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.options.tool == 'memcheck': 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd = ['src/third_party/valgrind/memcheck.sh', 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '-v', 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--xml=yes', 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--leak-check=no', 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--gen-suppressions=all', 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--num-callers=30', 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--trace-children=yes', 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--nacl-file=%s' % (self.options.files[0],), 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--suppressions=' + 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '../tools/valgrind/memcheck/suppressions.txt', 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--xml-file=%s/xml.%%p' % (self.tool_log_dir,), 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--log-file=%s/log.%%p' % (self.tool_log_dir,)] + cmd 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif self.options.tool == 'tsan': 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd = ['src/third_party/valgrind/tsan.sh', 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '-v', 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--num-callers=30', 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--trace-children=yes', 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--nacl-file=%s' % (self.options.files[0],), 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--ignore=../tools/valgrind/tsan/ignores.txt', 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--suppressions=../tools/valgrind/tsan/suppressions.txt', 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--log-file=%s/log.%%p' % (self.tool_log_dir,)] + cmd 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif self.options.tool != None: 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise LaunchFailure('Invalid tool name "%s"' % (self.options.tool,)) 3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if self.options.enable_sockets: 3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) cmd.append('--allow-nacl-socket-api=%s' % host) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd.extend(self.options.browser_flags) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd.append(url) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cmd 349