EMMA Coverage Report (generated Fri Aug 23 16:39:17 PDT 2013)
[all classes][org.chromium.content.common]

COVERAGE SUMMARY FOR SOURCE FILE [CommandLine.java]

nameclass, %method, %block, %line, %
CommandLine.java75%  (3/4)100% (38/38)75%  (472/628)83%  (100/121)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class CommandLine100% (1/1)100% (20/20)61%  (238/388)72%  (51.6/72)
readUtf8FileFully (String, int): char [] 100% (1/1)12%  (16/138)23%  (5/22)
setInstance (CommandLine): void 100% (1/1)67%  (8/12)68%  (2.7/4)
getInstance (): CommandLine 100% (1/1)71%  (10/14)89%  (2.7/3)
getJavaSwitchesOrNull (): String [] 100% (1/1)81%  (17/21)91%  (4.6/5)
<static initializer> 100% (1/1)83%  (10/12)92%  (1.8/2)
initFromFile (String): void 100% (1/1)83%  (10/12)94%  (2.8/3)
getSwitchValue (String, String): String 100% (1/1)91%  (10/11)95%  (1.9/2)
tokenizeQuotedAruments (char []): String [] 100% (1/1)91%  (110/121)95%  (21/22)
CommandLine (): void 100% (1/1)100% (3/3)100% (1/1)
CommandLine (CommandLine$1): void 100% (1/1)100% (3/3)100% (1/1)
access$300 (String): boolean 100% (1/1)100% (3/3)100% (1/1)
access$400 (String): String 100% (1/1)100% (3/3)100% (1/1)
access$500 (String): void 100% (1/1)100% (3/3)100% (1/1)
access$600 (String, String): void 100% (1/1)100% (4/4)100% (1/1)
access$700 (String []): void 100% (1/1)100% (3/3)100% (1/1)
enableNativeProxy (): void 100% (1/1)100% (7/7)100% (2/2)
init (String []): void 100% (1/1)100% (6/6)100% (2/2)
isInitialized (): boolean 100% (1/1)100% (7/7)100% (1/1)
isNativeImplementation (): boolean 100% (1/1)100% (2/2)100% (1/1)
reset (): void 100% (1/1)100% (3/3)100% (2/2)
     
class CommandLine$10%   (0/1)100% (0/0)100% (0/0)100% (0/0)
     
class CommandLine$JavaCommandLine100% (1/1)100% (10/10)97%  (209/215)98%  (38.4/39)
<static initializer> 100% (1/1)75%  (6/8)75%  (0.8/1)
CommandLine$JavaCommandLine (String []): void 100% (1/1)92%  (49/53)96%  (9.6/10)
access$100 (CommandLine$JavaCommandLine): String [] 100% (1/1)100% (3/3)100% (1/1)
appendSwitch (String): void 100% (1/1)100% (5/5)100% (2/2)
appendSwitchWithValue (String, String): void 100% (1/1)100% (47/47)100% (6/6)
appendSwitchesAndArguments (String []): void 100% (1/1)100% (5/5)100% (2/2)
appendSwitchesInternal (String [], int): void 100% (1/1)100% (65/65)100% (14/14)
getCommandLineArguments (): String [] 100% (1/1)100% (9/9)100% (1/1)
getSwitchValue (String): String 100% (1/1)100% (15/15)100% (2/2)
hasSwitch (String): boolean 100% (1/1)100% (5/5)100% (1/1)
     
class CommandLine$NativeCommandLine100% (1/1)100% (8/8)100% (25/25)100% (10/10)
CommandLine$NativeCommandLine (): void 100% (1/1)100% (4/4)100% (1/1)
CommandLine$NativeCommandLine (CommandLine$1): void 100% (1/1)100% (3/3)100% (1/1)
appendSwitch (String): void 100% (1/1)100% (3/3)100% (2/2)
appendSwitchWithValue (String, String): void 100% (1/1)100% (4/4)100% (2/2)
appendSwitchesAndArguments (String []): void 100% (1/1)100% (3/3)100% (2/2)
getSwitchValue (String): String 100% (1/1)100% (3/3)100% (1/1)
hasSwitch (String): boolean 100% (1/1)100% (3/3)100% (1/1)
isNativeImplementation (): boolean 100% (1/1)100% (2/2)100% (1/1)

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

[all classes][org.chromium.content.common]
EMMA 2.0.5312 (C) Vladimir Roubtsov