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

Side by Side Diff: content/public/android/java/src/org/chromium/content/common/CommandLine.java

Issue 62333025: [Android] Move CommandLine.java to base (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 7 years, 1 month 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
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
5 package org.chromium.content.common;
6
7 import android.text.TextUtils;
8 import android.util.Log;
9
10 import java.io.File;
11 import java.io.FileInputStream;
12 import java.io.FileNotFoundException;
13 import java.io.IOException;
14 import java.io.InputStreamReader;
15 import java.io.Reader;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.HashMap;
19 import java.util.concurrent.atomic.AtomicReference;
20
21 /**
22 * Java mirror of Chrome command-line utilities (e.g. class CommandLine from bas e/command_line.h).
23 * Command line program adb_command_line can be used to set the Chrome command l ine:
24 * adb shell "echo chrome --my-param > /data/local/chrome-command-line"
25 */
26 public abstract class CommandLine {
27 // Block onCreate() of Chrome until a Java debugger is attached.
28 public static final String WAIT_FOR_JAVA_DEBUGGER = "wait-for-java-debugger" ;
29
30 // Tell Java to use the official command line, loaded from the
31 // official-command-line.xml files. WARNING this is not done
32 // immediately on startup, so early running Java code will not see
33 // these flags.
34 public static final String ADD_OFFICIAL_COMMAND_LINE = "add-official-command -line";
35
36 // Enables test intent handling.
37 public static final String ENABLE_TEST_INTENTS = "enable-test-intents";
38
39 // Adds additional thread idle time information into the trace event output.
40 public static final String ENABLE_IDLE_TRACING = "enable-idle-tracing";
41
42 // Dump frames-per-second to the log
43 public static final String LOG_FPS = "log-fps";
44
45 // Whether Chromium should use a mobile user agent.
46 public static final String USE_MOBILE_UA = "use-mobile-user-agent";
47
48 // tablet specific UI components.
49 // Native switch - chrome_switches::kTabletUI
50 public static final String TABLET_UI = "tablet-ui";
51
52 // Change the url of the JavaScript that gets injected when accessibility mo de is enabled.
53 public static final String ACCESSIBILITY_JAVASCRIPT_URL = "accessibility-js- url";
54
55 public static final String ACCESSIBILITY_DEBUG_BRAILLE_SERVICE = "debug-brai lle-service";
56
57 // Sets the ISO country code that will be used for phone number detection.
58 public static final String NETWORK_COUNTRY_ISO = "network-country-iso";
59
60 // Whether to enable the auto-hiding top controls.
61 public static final String ENABLE_TOP_CONTROLS_POSITION_CALCULATION
62 = "enable-top-controls-position-calculation";
63
64 // The height of the movable top controls.
65 public static final String TOP_CONTROLS_HEIGHT = "top-controls-height";
66
67 // How much of the top controls need to be shown before they will auto show.
68 public static final String TOP_CONTROLS_SHOW_THRESHOLD = "top-controls-show- threshold";
69
70 // How much of the top controls need to be hidden before they will auto hide .
71 public static final String TOP_CONTROLS_HIDE_THRESHOLD = "top-controls-hide- threshold";
72
73 // Native switch - chrome_switches::kEnableInstantExtendedAPI
74 public static final String ENABLE_INSTANT_EXTENDED_API = "enable-instant-ext ended-api";
75
76 // Native switch - content_switches::kEnableSpeechRecognition
77 public static final String ENABLE_SPEECH_RECOGNITION = "enable-speech-recogn ition";
78
79 // Native switch - shell_switches::kDumpRenderTree
80 public static final String DUMP_RENDER_TREE = "dump-render-tree";
81
82 // Native switch - chrome_switches::kDisablePopupBlocking
83 public static final String DISABLE_POPUP_BLOCKING = "disable-popup-blocking" ;
84
85 // Whether to disable the click delay by sending click events during double tap
86 public static final String DISABLE_CLICK_DELAY = "disable-click-delay";
87
88 // Public abstract interface, implemented in derived classes.
89 // All these methods reflect their native-side counterparts.
90 /**
91 * Returns true if this command line contains the given switch.
92 * (Switch names ARE case-sensitive).
93 */
94 public abstract boolean hasSwitch(String switchString);
95
96 /**
97 * Return the value associated with the given switch, or null.
98 * @param switchString The switch key to lookup. It should NOT start with '- -' !
99 * @return switch value, or null if the switch is not set or set to empty.
100 */
101 public abstract String getSwitchValue(String switchString);
102
103 /**
104 * Return the value associated with the given switch, or {@code defaultValue } if the switch
105 * was not specified.
106 * @param switchString The switch key to lookup. It should NOT start with '- -' !
107 * @param defaultValue The default value to return if the switch isn't set.
108 * @return Switch value, or {@code defaultValue} if the switch is not set or set to empty.
109 */
110 public String getSwitchValue(String switchString, String defaultValue) {
111 String value = getSwitchValue(switchString);
112 return TextUtils.isEmpty(value) ? defaultValue : value;
113 }
114
115 /**
116 * Append a switch to the command line. There is no guarantee
117 * this action happens before the switch is needed.
118 * @param switchString the switch to add. It should NOT start with '--' !
119 */
120 public abstract void appendSwitch(String switchString);
121
122 /**
123 * Append a switch and value to the command line. There is no
124 * guarantee this action happens before the switch is needed.
125 * @param switchString the switch to add. It should NOT start with '--' !
126 * @param value the value for this switch.
127 * For example, --foo=bar becomes 'foo', 'bar'.
128 */
129 public abstract void appendSwitchWithValue(String switchString, String value );
130
131 /**
132 * Append switch/value items in "command line" format (excluding argv[0] pro gram name).
133 * E.g. { '--gofast', '--username=fred' }
134 * @param array an array of switch or switch/value items in command line for mat.
135 * Unlike the other append routines, these switches SHOULD start with '--' .
136 * Unlike init(), this does not include the program name in array[0].
137 */
138 public abstract void appendSwitchesAndArguments(String[] array);
139
140 /**
141 * Determine if the command line is bound to the native (JNI) implementation .
142 * @return true if the underlying implementation is delegating to the native command line.
143 */
144 public boolean isNativeImplementation() {
145 return false;
146 }
147
148 private static final AtomicReference<CommandLine> sCommandLine =
149 new AtomicReference<CommandLine>();
150
151 /**
152 * @returns true if the command line has already been initialized.
153 */
154 public static boolean isInitialized() {
155 return sCommandLine.get() != null;
156 }
157
158 // Equivalent to CommandLine::ForCurrentProcess in C++.
159 public static CommandLine getInstance() {
160 CommandLine commandLine = sCommandLine.get();
161 assert commandLine != null;
162 return commandLine;
163 }
164
165 /**
166 * Initialize the singleton instance, must be called exactly once (either di rectly or
167 * via one of the convenience wrappers below) before using the static single ton instance.
168 * @param args command line flags in 'argv' format: args[0] is the program n ame.
169 */
170 public static void init(String[] args) {
171 setInstance(new JavaCommandLine(args));
172 }
173
174 /**
175 * Initialize the command line from the command-line file.
176 *
177 * @param file The fully qualified command line file.
178 */
179 public static void initFromFile(String file) {
180 // Arbitrary clamp of 8k on the amount of file we read in.
181 char[] buffer = readUtf8FileFully(file, 8 * 1024);
182 init(buffer == null ? null : tokenizeQuotedAruments(buffer));
183 }
184
185 /**
186 * Resets both the java proxy and the native command lines. This allows the entire
187 * command line initialization to be re-run including the call to onJniLoade d.
188 */
189 public static void reset() {
190 setInstance(null);
191 }
192
193 /**
194 * Public for testing (TODO: why are the tests in a different package?)
195 * Parse command line flags from a flat buffer, supporting double-quote encl osed strings
196 * containing whitespace. argv elements are derived by splitting the buffer on whitepace;
197 * double quote characters may enclose tokens containing whitespace; a doubl e-quote literal
198 * may be escaped with back-slash. (Otherwise backslash is taken as a litera l).
199 * @param buffer A command line in command line file format as described abo ve.
200 * @return the tokenized arguments, suitable for passing to init().
201 */
202 public static String[] tokenizeQuotedAruments(char[] buffer) {
203 ArrayList<String> args = new ArrayList<String>();
204 StringBuilder arg = null;
205 final char noQuote = '\0';
206 final char singleQuote = '\'';
207 final char doubleQuote = '"';
208 char currentQuote = noQuote;
209 for (char c : buffer) {
210 // Detect start or end of quote block.
211 if ((currentQuote == noQuote && (c == singleQuote || c == doubleQuot e)) ||
212 c == currentQuote) {
213 if (arg != null && arg.length() > 0 && arg.charAt(arg.length() - 1) == '\\') {
214 // Last char was a backslash; pop it, and treat c as a liter al.
215 arg.setCharAt(arg.length() - 1, c);
216 } else {
217 currentQuote = currentQuote == noQuote ? c : noQuote;
218 }
219 } else if (currentQuote == noQuote && Character.isWhitespace(c)) {
220 if (arg != null) {
221 args.add(arg.toString());
222 arg = null;
223 }
224 } else {
225 if (arg == null) arg = new StringBuilder();
226 arg.append(c);
227 }
228 }
229 if (arg != null) {
230 if (currentQuote != noQuote) {
231 Log.w(TAG, "Unterminated quoted string: " + arg);
232 }
233 args.add(arg.toString());
234 }
235 return args.toArray(new String[args.size()]);
236 }
237
238 private static final String TAG = "CommandLine";
239 private static final String SWITCH_PREFIX = "--";
240 private static final String SWITCH_TERMINATOR = SWITCH_PREFIX;
241 private static final String SWITCH_VALUE_SEPARATOR = "=";
242
243 public static void enableNativeProxy() {
244 // Make a best-effort to ensure we make a clean (atomic) switch over fro m the old to
245 // the new command line implementation. If another thread is modifying t he command line
246 // when this happens, all bets are off. (As per the native CommandLine).
247 sCommandLine.set(new NativeCommandLine());
248 }
249
250 public static String[] getJavaSwitchesOrNull() {
251 CommandLine commandLine = sCommandLine.get();
252 if (commandLine != null) {
253 assert !commandLine.isNativeImplementation();
254 return ((JavaCommandLine) commandLine).getCommandLineArguments();
255 }
256 return null;
257 }
258
259 private static void setInstance(CommandLine commandLine) {
260 CommandLine oldCommandLine = sCommandLine.getAndSet(commandLine);
261 if (oldCommandLine != null && oldCommandLine.isNativeImplementation()) {
262 nativeReset();
263 }
264 }
265
266 /**
267 * @param fileName the file to read in.
268 * @param sizeLimit cap on the file size.
269 * @return Array of chars read from the file, or null if the file cannot be read
270 * or if its length exceeds |sizeLimit|.
271 */
272 private static char[] readUtf8FileFully(String fileName, int sizeLimit) {
273 Reader reader = null;
274 File f = new File(fileName);
275 long fileLength = f.length();
276
277 if (fileLength == 0) {
278 return null;
279 }
280
281 if (fileLength > sizeLimit) {
282 Log.w(TAG, "File " + fileName + " length " + fileLength + " exceeds limit "
283 + sizeLimit);
284 return null;
285 }
286
287 try {
288 char[] buffer = new char[(int) fileLength];
289 reader = new InputStreamReader(new FileInputStream(f), "UTF-8");
290 int charsRead = reader.read(buffer);
291 // Debug check that we've exhausted the input stream (will fail e.g. if the
292 // file grew after we inspected its length).
293 assert !reader.ready();
294 return charsRead < buffer.length ? Arrays.copyOfRange(buffer, 0, cha rsRead) : buffer;
295 } catch (FileNotFoundException e) {
296 return null;
297 } catch (IOException e) {
298 return null;
299 } finally {
300 try {
301 if (reader != null) reader.close();
302 } catch (IOException e) {
303 Log.e(TAG, "Unable to close file reader.", e);
304 }
305 }
306 }
307
308 private CommandLine() {}
309
310 private static class JavaCommandLine extends CommandLine {
311 private HashMap<String, String> mSwitches = new HashMap<String, String>( );
312 private ArrayList<String> mArgs = new ArrayList<String>();
313
314 // The arguments begin at index 1, since index 0 contains the executable name.
315 private int mArgsBegin = 1;
316
317 JavaCommandLine(String[] args) {
318 if (args == null || args.length == 0 || args[0] == null) {
319 mArgs.add("");
320 } else {
321 mArgs.add(args[0]);
322 appendSwitchesInternal(args, 1);
323 }
324 // Invariant: we always have the argv[0] program name element.
325 assert mArgs.size() > 0;
326 }
327
328 /**
329 * Returns the switches and arguments passed into the program, with swit ches and their
330 * values coming before all of the arguments.
331 */
332 private String[] getCommandLineArguments() {
333 return mArgs.toArray(new String[mArgs.size()]);
334 }
335
336 @Override
337 public boolean hasSwitch(String switchString) {
338 return mSwitches.containsKey(switchString);
339 }
340
341 @Override
342 public String getSwitchValue(String switchString) {
343 // This is slightly round about, but needed for consistency with the NativeCommandLine
344 // version which does not distinguish empty values from key not pres ent.
345 String value = mSwitches.get(switchString);
346 return value == null || value.isEmpty() ? null : value;
347 }
348
349 @Override
350 public void appendSwitch(String switchString) {
351 appendSwitchWithValue(switchString, null);
352 }
353
354 /**
355 * Appends a switch to the current list.
356 * @param switchString the switch to add. It should NOT start with '--' !
357 * @param value the value for this switch.
358 */
359 @Override
360 public void appendSwitchWithValue(String switchString, String value) {
361 mSwitches.put(switchString, value == null ? "" : value);
362
363 // Append the switch and update the switches/arguments divider mArgs Begin.
364 String combinedSwitchString = SWITCH_PREFIX + switchString;
365 if (value != null && !value.isEmpty())
366 combinedSwitchString += SWITCH_VALUE_SEPARATOR + value;
367
368 mArgs.add(mArgsBegin++, combinedSwitchString);
369 }
370
371 @Override
372 public void appendSwitchesAndArguments(String[] array) {
373 appendSwitchesInternal(array, 0);
374 }
375
376 // Add the specified arguments, but skipping the first |skipCount| eleme nts.
377 private void appendSwitchesInternal(String[] array, int skipCount) {
378 boolean parseSwitches = true;
379 for (String arg : array) {
380 if (skipCount > 0) {
381 --skipCount;
382 continue;
383 }
384
385 if (arg.equals(SWITCH_TERMINATOR)) {
386 parseSwitches = false;
387 }
388
389 if (parseSwitches && arg.startsWith(SWITCH_PREFIX)) {
390 String[] parts = arg.split(SWITCH_VALUE_SEPARATOR, 2);
391 String value = parts.length > 1 ? parts[1] : null;
392 appendSwitchWithValue(parts[0].substring(SWITCH_PREFIX.lengt h()), value);
393 } else {
394 mArgs.add(arg);
395 }
396 }
397 }
398 }
399
400 private static class NativeCommandLine extends CommandLine {
401 @Override
402 public boolean hasSwitch(String switchString) {
403 return nativeHasSwitch(switchString);
404 }
405
406 @Override
407 public String getSwitchValue(String switchString) {
408 return nativeGetSwitchValue(switchString);
409 }
410
411 @Override
412 public void appendSwitch(String switchString) {
413 nativeAppendSwitch(switchString);
414 }
415
416 @Override
417 public void appendSwitchWithValue(String switchString, String value) {
418 nativeAppendSwitchWithValue(switchString, value);
419 }
420
421 @Override
422 public void appendSwitchesAndArguments(String[] array) {
423 nativeAppendSwitchesAndArguments(array);
424 }
425
426 @Override
427 public boolean isNativeImplementation() {
428 return true;
429 }
430 }
431
432 private static native void nativeReset();
433 private static native boolean nativeHasSwitch(String switchString);
434 private static native String nativeGetSwitchValue(String switchString);
435 private static native void nativeAppendSwitch(String switchString);
436 private static native void nativeAppendSwitchWithValue(String switchString, String value);
437 private static native void nativeAppendSwitchesAndArguments(String[] array);
438 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698