1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/webrtc/trunk/build/android/pylib/flag_changer.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,144 @@ 1.4 +# Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.5 +# Use of this source code is governed by a BSD-style license that can be 1.6 +# found in the LICENSE file. 1.7 + 1.8 +import constants 1.9 +import traceback 1.10 +import warnings 1.11 + 1.12 + 1.13 +# Location where chrome reads command line flags from 1.14 +CHROME_COMMAND_FILE = constants.TEST_EXECUTABLE_DIR + '/chrome-command-line' 1.15 + 1.16 +class FlagChanger(object): 1.17 + """Changes the flags Chrome runs with. 1.18 + 1.19 + There are two different use cases for this file: 1.20 + * Flags are permanently set by calling Set(). 1.21 + * Flags can be temporarily set for a particular set of unit tests. These 1.22 + tests should call Restore() to revert the flags to their original state 1.23 + once the tests have completed. 1.24 + """ 1.25 + 1.26 + def __init__(self, android_cmd): 1.27 + self._android_cmd = android_cmd 1.28 + 1.29 + # Save the original flags. 1.30 + self._orig_line = self._android_cmd.GetFileContents(CHROME_COMMAND_FILE) 1.31 + if self._orig_line: 1.32 + self._orig_line = self._orig_line[0].strip() 1.33 + 1.34 + # Parse out the flags into a list to facilitate adding and removing flags. 1.35 + self._current_flags = self._TokenizeFlags(self._orig_line) 1.36 + 1.37 + def Get(self): 1.38 + """Returns list of current flags.""" 1.39 + return self._current_flags 1.40 + 1.41 + def Set(self, flags): 1.42 + """Replaces all flags on the current command line with the flags given. 1.43 + 1.44 + Args: 1.45 + flags: A list of flags to set, eg. ['--single-process']. 1.46 + """ 1.47 + if flags: 1.48 + assert flags[0] != 'chrome' 1.49 + 1.50 + self._current_flags = flags 1.51 + self._UpdateCommandLineFile() 1.52 + 1.53 + def AddFlags(self, flags): 1.54 + """Appends flags to the command line if they aren't already there. 1.55 + 1.56 + Args: 1.57 + flags: A list of flags to add on, eg. ['--single-process']. 1.58 + """ 1.59 + if flags: 1.60 + assert flags[0] != 'chrome' 1.61 + 1.62 + # Avoid appending flags that are already present. 1.63 + for flag in flags: 1.64 + if flag not in self._current_flags: 1.65 + self._current_flags.append(flag) 1.66 + self._UpdateCommandLineFile() 1.67 + 1.68 + def RemoveFlags(self, flags): 1.69 + """Removes flags from the command line, if they exist. 1.70 + 1.71 + Args: 1.72 + flags: A list of flags to remove, eg. ['--single-process']. Note that we 1.73 + expect a complete match when removing flags; if you want to remove 1.74 + a switch with a value, you must use the exact string used to add 1.75 + it in the first place. 1.76 + """ 1.77 + if flags: 1.78 + assert flags[0] != 'chrome' 1.79 + 1.80 + for flag in flags: 1.81 + if flag in self._current_flags: 1.82 + self._current_flags.remove(flag) 1.83 + self._UpdateCommandLineFile() 1.84 + 1.85 + def Restore(self): 1.86 + """Restores the flags to their original state.""" 1.87 + self._current_flags = self._TokenizeFlags(self._orig_line) 1.88 + self._UpdateCommandLineFile() 1.89 + 1.90 + def _UpdateCommandLineFile(self): 1.91 + """Writes out the command line to the file, or removes it if empty.""" 1.92 + print "Current flags: ", self._current_flags 1.93 + 1.94 + if self._current_flags: 1.95 + self._android_cmd.SetFileContents(CHROME_COMMAND_FILE, 1.96 + 'chrome ' + 1.97 + ' '.join(self._current_flags)) 1.98 + else: 1.99 + self._android_cmd.RunShellCommand('rm ' + CHROME_COMMAND_FILE) 1.100 + 1.101 + def _TokenizeFlags(self, line): 1.102 + """Changes the string containing the command line into a list of flags. 1.103 + 1.104 + Follows similar logic to CommandLine.java::tokenizeQuotedArguments: 1.105 + * Flags are split using whitespace, unless the whitespace is within a 1.106 + pair of quotation marks. 1.107 + * Unlike the Java version, we keep the quotation marks around switch 1.108 + values since we need them to re-create the file when new flags are 1.109 + appended. 1.110 + 1.111 + Args: 1.112 + line: A string containing the entire command line. The first token is 1.113 + assumed to be the program name. 1.114 + """ 1.115 + if not line: 1.116 + return [] 1.117 + 1.118 + tokenized_flags = [] 1.119 + current_flag = "" 1.120 + within_quotations = False 1.121 + 1.122 + # Move through the string character by character and build up each flag 1.123 + # along the way. 1.124 + for c in line.strip(): 1.125 + if c is '"': 1.126 + if len(current_flag) > 0 and current_flag[-1] == '\\': 1.127 + # Last char was a backslash; pop it, and treat this " as a literal. 1.128 + current_flag = current_flag[0:-1] + '"' 1.129 + else: 1.130 + within_quotations = not within_quotations 1.131 + current_flag += c 1.132 + elif not within_quotations and (c is ' ' or c is '\t'): 1.133 + if current_flag is not "": 1.134 + tokenized_flags.append(current_flag) 1.135 + current_flag = "" 1.136 + else: 1.137 + current_flag += c 1.138 + 1.139 + # Tack on the last flag. 1.140 + if not current_flag: 1.141 + if within_quotations: 1.142 + warnings.warn("Unterminated quoted string: " + current_flag) 1.143 + else: 1.144 + tokenized_flags.append(current_flag) 1.145 + 1.146 + # Return everything but the program name. 1.147 + return tokenized_flags[1:]