| Index: base/android/java/src/org/chromium/base/library_loader/Linker.java | 
| diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java | 
| index 8edfba2bacf2c09175d6a6eab313e7fbb9472765..11f98768469bb905f2664984e6aef954f2e61ef1 100644 | 
| --- a/base/android/java/src/org/chromium/base/library_loader/Linker.java | 
| +++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java | 
| @@ -148,6 +148,9 @@ public abstract class Linker { | 
| // Log tag for this class. | 
| private static final String TAG = "cr.library_loader"; | 
|  | 
| +    // Name of the library that contains our JNI code. | 
| +    private static final String LINKER_JNI_LIBRARY = "chromium_android_linker"; | 
| + | 
| // Constants used to control the behaviour of the browser process with | 
| // regards to the shared RELRO section. Not applicable to ModernLinker. | 
| //   NEVER        -> The browser never uses it itself. | 
| @@ -180,9 +183,6 @@ public abstract class Linker { | 
| // Not used by ModernLinker. | 
| protected int mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_INIT; | 
|  | 
| -    // Name of the library that contains our JNI code. | 
| -    protected static final String LINKER_JNI_LIBRARY = "chromium_android_linker"; | 
| - | 
| // Set to true to enable debug logs. | 
| protected static final boolean DEBUG = false; | 
|  | 
| @@ -257,7 +257,7 @@ public abstract class Linker { | 
| * | 
| * @return true if native library linker tests are enabled. | 
| */ | 
| -    public static boolean areLinkerTestsEnabled() { | 
| +    public static boolean areTestsEnabled() { | 
| return NativeLibraries.sEnableLinkerTests; | 
| } | 
|  | 
| @@ -292,7 +292,7 @@ public abstract class Linker { | 
| * | 
| * @param type LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN | 
| */ | 
| -    public static final void setLinkerImplementationForTesting(int type) { | 
| +    public static final void setImplementationForTesting(int type) { | 
| // Sanity check. This method may only be called during tests. | 
| assertLinkerTestsAreEnabled(); | 
| assertForTesting(type == LINKER_IMPLEMENTATION_LEGACY | 
| @@ -318,18 +318,21 @@ public abstract class Linker { | 
| * | 
| * @return LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN | 
| */ | 
| -    public int getLinkerImplementationForTesting() { | 
| +    public int getImplementationForTesting() { | 
| // Sanity check. This method may only be called during tests. | 
| assertLinkerTestsAreEnabled(); | 
| -        assertForTesting(sSingleton != null); | 
|  | 
| -        if (sSingleton instanceof ModernLinker) { | 
| -            return LINKER_IMPLEMENTATION_MODERN; | 
| -        } else if (sSingleton instanceof LegacyLinker) { | 
| -            return LINKER_IMPLEMENTATION_LEGACY; | 
| +        synchronized (sSingletonLock) { | 
| +            assertForTesting(sSingleton != null); | 
| + | 
| +            if (sSingleton instanceof ModernLinker) { | 
| +                return LINKER_IMPLEMENTATION_MODERN; | 
| +            } else if (sSingleton instanceof LegacyLinker) { | 
| +                return LINKER_IMPLEMENTATION_LEGACY; | 
| +            } | 
| +            Log.e(TAG, "Invalid linker: " + sSingleton.getClass().getName()); | 
| +            return 0; | 
| } | 
| -        Log.e(TAG, "Invalid linker: " + sSingleton.getClass().getName()); | 
| -        return 0; | 
| } | 
|  | 
| /** | 
| @@ -358,7 +361,7 @@ public abstract class Linker { | 
| */ | 
| public void setTestRunnerClassNameForTesting(String testRunnerClassName) { | 
| if (DEBUG) { | 
| -            Log.i(TAG, "setTestRunnerByClassNameForTesting(" + testRunnerClassName + ") called"); | 
| +            Log.i(TAG, "setTestRunnerClassNameForTesting(" + testRunnerClassName + ") called"); | 
| } | 
| // Sanity check. This method may only be called during tests. | 
| assertLinkerTestsAreEnabled(); | 
| @@ -387,6 +390,42 @@ public abstract class Linker { | 
| } | 
|  | 
| /** | 
| +     * Set up the Linker for a test. | 
| +     * Convenience function that calls setImplementationForTesting() to force an | 
| +     * implementation, and then setTestRunnerClassNameForTesting() to set the test | 
| +     * class name. | 
| +     * | 
| +     * On first call, instantiates a Linker of the requested type and sets its test | 
| +     * runner class name. On subsequent calls, checks that the singleton produced by | 
| +     * the first call matches the requested type and test runner class name. | 
| +     */ | 
| +    public static void setupForTesting(int type, String testRunnerClassName) { | 
| +        if (DEBUG) { | 
| +            Log.i(TAG, "setupForTesting(" + type + ", " + testRunnerClassName + ") called"); | 
| +        } | 
| +        // Sanity check. This method may only be called during tests. | 
| +        assertLinkerTestsAreEnabled(); | 
| + | 
| +        synchronized (sSingletonLock) { | 
| +            // If this is the first call, configure the Linker to the given type and test class. | 
| +            if (sSingleton == null) { | 
| +                setImplementationForTesting(type); | 
| +                sSingleton.setTestRunnerClassNameForTesting(testRunnerClassName); | 
| +                return; | 
| +            } | 
| + | 
| +            // If not the first call, check that the Linker configuration matches this request. | 
| +            assertForTesting(sSingleton.getImplementationForTesting() == type); | 
| +            String ourTestRunnerClassName = sSingleton.getTestRunnerClassNameForTesting(); | 
| +            if (testRunnerClassName == null) { | 
| +                assertForTesting(ourTestRunnerClassName == null); | 
| +            } else { | 
| +                assertForTesting(ourTestRunnerClassName.equals(testRunnerClassName)); | 
| +            } | 
| +        } | 
| +    } | 
| + | 
| +    /** | 
| * Instantiate and run the current TestRunner, if any. The TestRunner implementation | 
| * must be instantiated _after_ all libraries are loaded to ensure that its | 
| * native methods are properly registered. | 
| @@ -472,15 +511,15 @@ public abstract class Linker { | 
| * In a component build, the suffix ".cr" is added to each library name, so | 
| * if the initial load fails we retry with a suffix. | 
| */ | 
| -    protected void loadLinkerJNILibrary() { | 
| +    protected static void loadLinkerJniLibrary() { | 
| String libName = "lib" + LINKER_JNI_LIBRARY + ".so"; | 
| if (DEBUG) { | 
| Log.i(TAG, "Loading " + libName); | 
| } | 
| try { | 
| System.loadLibrary(LINKER_JNI_LIBRARY); | 
| -        } catch (UnsatisfiedLinkError  e) { | 
| -            Log.w(TAG, "Couldn't load " + libName + ", trying " + libName + ".so"); | 
| +        } catch (UnsatisfiedLinkError e) { | 
| +            Log.w(TAG, "Couldn't load " + libName + ", trying " + libName + ".cr"); | 
| System.loadLibrary(LINKER_JNI_LIBRARY + ".cr"); | 
| } | 
| } | 
| @@ -554,7 +593,7 @@ public abstract class Linker { | 
| * Call this method to determine if the chromium project must load the library | 
| * directly from a zip file. | 
| */ | 
| -    public boolean isInZipFile() { | 
| +    public static boolean isInZipFile() { | 
| // The auto-generated NativeLibraries.sUseLibraryInZipFile variable will be true | 
| // if the library remains embedded in the APK zip file on the target. | 
| return NativeLibraries.sUseLibraryInZipFile; | 
| @@ -565,7 +604,11 @@ public abstract class Linker { | 
| * use this linker. If not, System.loadLibrary() should be used to load | 
| * libraries instead. | 
| */ | 
| -    public abstract boolean isUsed(); | 
| +    public static boolean isUsed() { | 
| +        // The auto-generated NativeLibraries.sUseLinker variable will be true if the | 
| +        // build has not explicitly disabled Linker features. | 
| +        return NativeLibraries.sUseLinker; | 
| +    } | 
|  | 
| /** | 
| * Call this method to determine if the linker will try to use shared RELROs | 
|  |