diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 10:22:43 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 12:36:28 +0000 |
commit | 271a6c3487a14599023a9106329505597638d793 (patch) | |
tree | e040d58ffc86c1480b79ca8528020ca9ec919bf8 /chromium/components/module_installer | |
parent | 7b2ffa587235a47d4094787d72f38102089f402a (diff) | |
download | qtwebengine-chromium-271a6c3487a14599023a9106329505597638d793.tar.gz |
BASELINE: Update Chromium to 77.0.3865.59
Change-Id: I1e89a5f3b009a9519a6705102ad65c92fe736f21
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/module_installer')
11 files changed, 202 insertions, 151 deletions
diff --git a/chromium/components/module_installer/OWNERS b/chromium/components/module_installer/OWNERS index b18865e9e42..9fac46f8fb0 100644 --- a/chromium/components/module_installer/OWNERS +++ b/chromium/components/module_installer/OWNERS @@ -1,2 +1,3 @@ agrieve@chromium.org tiborg@chromium.org +# COMPONENT: Mobile>FeatureModules diff --git a/chromium/components/module_installer/android/BUILD.gn b/chromium/components/module_installer/android/BUILD.gn index e781862bd76..41d2ab4c02a 100644 --- a/chromium/components/module_installer/android/BUILD.gn +++ b/chromium/components/module_installer/android/BUILD.gn @@ -10,11 +10,12 @@ import("//build/config/android/rules.gni") # build. android_library("module_installer_java") { java_files = [ - "java/src-stub/org/chromium/components/module_installer/ModuleInstaller.java", + "java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java", + "java/src-common/org/chromium/components/module_installer/ModuleInstaller.java", "java/src-common/org/chromium/components/module_installer/OnModuleInstallFinishedListener.java", "java/src-common/org/chromium/components/module_installer/Module.java", ] - jar_excluded_patterns = [ "*/ModuleInstaller.class" ] + jar_excluded_patterns = [ "*/ModuleInstallerImpl.class" ] deps = [ "//base:base_java", ] @@ -24,7 +25,7 @@ android_library("module_installer_java") { # Contains stub implementation to be used for builds not supporting modules # (e.g. APKs). android_library("module_installer_stub_java") { - java_files = [ "java/src-stub/org/chromium/components/module_installer/ModuleInstaller.java" ] + java_files = [ "java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java" ] deps = [ ":module_installer_java", "//base:base_java", @@ -36,7 +37,7 @@ android_library("module_installer_stub_java") { # bundles). android_library("module_installer_impl_java") { java_files = [ - "java/src-impl/org/chromium/components/module_installer/ModuleInstaller.java", + "java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java", "java/src-impl/org/chromium/components/module_installer/ModuleInstallerBackend.java", "java/src-impl/org/chromium/components/module_installer/FakeModuleInstallerBackend.java", "java/src-impl/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java", @@ -50,10 +51,12 @@ android_library("module_installer_impl_java") { } android_library("module_installer_test_java") { - java_files = [ "java/src-test/org/chromium/components/module_installer/ModuleInstaller.java" ] + testonly = true + java_files = [ "javatests/src/org/chromium/components/module_installer/ModuleInstallerRule.java" ] deps = [ ":module_installer_java", "//base:base_java", + "//third_party/junit", ] jacoco_never_instrument = true } diff --git a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java b/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java index fd7a492f3a6..ccd6e5ab591 100644 --- a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java +++ b/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java @@ -55,8 +55,8 @@ public class Module<T> { if (mImpl != null) return true; // Accessing classes in the module may cause its DEX file to be loaded. And on some devices // that causes a read mode violation. - try (StrictModeContext unused = StrictModeContext.allowDiskReads()) { - ModuleInstaller.init(); + try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { + ModuleInstaller.getInstance().init(); Class.forName(mImplClassName); return true; } catch (ClassNotFoundException e) { @@ -64,18 +64,18 @@ public class Module<T> { } } - /** Requests install of the module. See {@link ModuleInstaller#install} for more details. */ + /** Requests install of the module. See {@link ModuleInstallerImpl#install} for more details. */ public void install(OnModuleInstallFinishedListener onFinishedListener) { assert !isInstalled(); - ModuleInstaller.install(mName, onFinishedListener); + ModuleInstaller.getInstance().install(mName, onFinishedListener); } /** - * Requests deferred install of the module. See {@link ModuleInstaller#installDeferred} for + * Requests deferred install of the module. See {@link ModuleInstallerImpl#installDeferred} for * more details. */ public void installDeferred() { - ModuleInstaller.installDeferred(mName); + ModuleInstaller.getInstance().installDeferred(mName); } /** @@ -85,10 +85,10 @@ public class Module<T> { public T getImpl() { assert isInstalled(); if (mImpl == null) { - ModuleInstaller.init(); + ModuleInstaller.getInstance().init(); // Accessing classes in the module may cause its DEX file to be loaded. And on some // devices that causes a read mode violation. - try (StrictModeContext unused = StrictModeContext.allowDiskReads()) { + try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { mImpl = mInterfaceClass.cast(Class.forName(mImplClassName).newInstance()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException e) { diff --git a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java b/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java new file mode 100644 index 00000000000..b5083a5c6ac --- /dev/null +++ b/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java @@ -0,0 +1,63 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.module_installer; + +import android.content.Context; + +import org.chromium.base.VisibleForTesting; + +/** + * This interface contains all the necessary methods to orchestrate the installation of dynamic + * feature modules (DFMs). + */ +public interface ModuleInstaller { + /** Returns the singleton instance from the correct implementation. */ + static ModuleInstaller getInstance() { + return ModuleInstallerImpl.getInstance(); + } + + @VisibleForTesting + static void setInstanceForTesting(ModuleInstaller moduleInstaller) { + ModuleInstallerImpl.setInstanceForTesting(moduleInstaller); + } + + /** Needs to be called before trying to access a module. */ + default void init() {} + + /** + * Needs to be called in attachBaseContext of the activities that want to have access to + * splits prior to application restart. + * + * For details, see: + * https://developer.android.com/reference/com/google/android/play/core/splitcompat/SplitCompat.html#install(android.content.Context) + */ + default void initActivity(Context context) {} + + /** + * Records via UMA all modules that have been requested and are currently installed. The intent + * is to measure the install penetration of each module. + */ + default void recordModuleAvailability() {} + + /** Writes fully installed and emulated modules to crash keys. */ + default void updateCrashKeys() {} + + /** + * Requests the install of a module. The install will be performed asynchronously. + * + * @param moduleName Name of the module as defined in GN. + * @param onFinishedListener Listener to be called once installation is finished. + */ + default void install(String moduleName, OnModuleInstallFinishedListener onFinishedListener) {} + + /** + * Asynchronously installs module in the background when on unmetered connection and charging. + * Install is best effort and may fail silently. Upon success, the module will only be available + * after Chrome restarts. + * + * @param moduleName Name of the module. + */ + default void installDeferred(String moduleName) {} +} diff --git a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/FakeModuleInstallerBackend.java b/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/FakeModuleInstallerBackend.java index dae242dc9b5..9bc39a7b1bf 100644 --- a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/FakeModuleInstallerBackend.java +++ b/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/FakeModuleInstallerBackend.java @@ -70,7 +70,7 @@ class FakeModuleInstallerBackend extends ModuleInstallerBackend { private boolean installInternal(String moduleName) { Context context = ContextUtils.getApplicationContext(); - int versionCode = BuildInfo.getInstance().versionCode; + long versionCode = BuildInfo.getInstance().versionCode; // Get list of all files at path where SplitCompat looks for downloaded modules. // May change in future releases of the Play Core SDK. @@ -102,7 +102,7 @@ class FakeModuleInstallerBackend extends ModuleInstallerBackend { if (srcModuleFileName.endsWith(".apk") && srcModuleFileName.startsWith(moduleName)) { // Construct destination file corresponding to each source file. File dstModuleFile = joinPaths(context.getFilesDir().getPath(), "splitcompat", - Integer.toString(versionCode), "unverified-splits", srcModuleFileName); + Long.toString(versionCode), "unverified-splits", srcModuleFileName); // NOTE: Need to give Chrome storage permission for this to work. try { diff --git a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstaller.java b/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java index d01bc2c3abd..7e0b24c10ab 100644 --- a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstaller.java +++ b/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java @@ -18,6 +18,7 @@ import org.chromium.base.CommandLine; import org.chromium.base.ContextUtils; import org.chromium.base.StrictModeContext; import org.chromium.base.ThreadUtils; +import org.chromium.base.annotations.MainDex; import org.chromium.components.crash.CrashKeyIndex; import org.chromium.components.crash.CrashKeys; @@ -30,53 +31,55 @@ import java.util.Set; import java.util.TreeSet; /** Installs dynamic feature modules (DFMs). */ -public class ModuleInstaller { +@MainDex +public class ModuleInstallerImpl implements ModuleInstaller { /** Command line switch for activating the fake backend. */ private static final String FAKE_FEATURE_MODULE_INSTALL = "fake-feature-module-install"; - private static final Map<String, List<OnModuleInstallFinishedListener>> sModuleNameListenerMap = + private static ModuleInstaller sInstance = new ModuleInstallerImpl(); + private static boolean sAppContextSplitCompatted; + private final Map<String, List<OnModuleInstallFinishedListener>> mModuleNameListenerMap = new HashMap<>(); - private static ModuleInstallerBackend sBackend; - private static boolean sSplitCompatted; + private ModuleInstallerBackend mBackend; - /** Needs to be called before trying to access a module. */ - public static void init() { - if (sSplitCompatted) return; + /** Returns the singleton instance. */ + public static ModuleInstaller getInstance() { + return sInstance; + } + + public static void setInstanceForTesting(ModuleInstaller moduleInstaller) { + sInstance = moduleInstaller; + } + + @Override + public void init() { + if (sAppContextSplitCompatted) return; // SplitCompat.install may copy modules into Chrome's internal folder or clean them up. - try (StrictModeContext unused = StrictModeContext.allowDiskWrites()) { + try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) { SplitCompat.install(ContextUtils.getApplicationContext()); - sSplitCompatted = true; + sAppContextSplitCompatted = true; } // SplitCompat.install may add emulated modules. Thus, update crash keys. updateCrashKeys(); } - /** - * Needs to be called in attachBaseContext of the activities that want to have access to - * splits prior to application restart. - * - * For details, see: - * https://developer.android.com/reference/com/google/android/play/core/splitcompat/SplitCompat.html#install(android.content.Context) - */ - public static void initActivity(Context context) { + @Override + public void initActivity(Context context) { SplitCompat.install(context); } - /** - * Records via UMA all modules that have been requested and are currently installed. The intent - * is to measure the install penetration of each module. - */ - public static void recordModuleAvailability() { + @Override + public void recordModuleAvailability() { if (!CommandLine.getInstance().hasSwitch(FAKE_FEATURE_MODULE_INSTALL)) { PlayCoreModuleInstallerBackend.recordModuleAvailability(); } } - /** Writes fully installed and emulated modules to crash keys. */ - public static void updateCrashKeys() { + @Override + public void updateCrashKeys() { Context context = ContextUtils.getApplicationContext(); // Get modules that are fully installed as split APKs (excluding base which is always - // intalled). Tree set to have ordered and, thus, deterministic results. + // installed). Tree set to have ordered and, thus, deterministic results. Set<String> fullyInstalledModules = new TreeSet<>(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Split APKs are only supported on Android L+. @@ -97,7 +100,7 @@ public class ModuleInstaller { // emulation of later modules won't work. If splitcompat has not been called no modules are // emulated. Therefore, use an empty set in that case. Set<String> emulatedModules = new TreeSet<>(); - if (sSplitCompatted) { + if (sAppContextSplitCompatted) { emulatedModules.addAll( SplitInstallManagerFactory.create(context).getInstalledModules()); emulatedModules.removeAll(fullyInstalledModules); @@ -109,21 +112,15 @@ public class ModuleInstaller { CrashKeyIndex.EMULATED_MODULES, encodeCrashKeyValue(emulatedModules)); } - /** - * Requests the install of a module. The install will be performed asynchronously. - * - * @param moduleName Name of the module as defined in GN. - * @param onFinishedListener Listener to be called once installation is finished. - */ - public static void install( - String moduleName, OnModuleInstallFinishedListener onFinishedListener) { + @Override + public void install(String moduleName, OnModuleInstallFinishedListener onFinishedListener) { ThreadUtils.assertOnUiThread(); - if (!sModuleNameListenerMap.containsKey(moduleName)) { - sModuleNameListenerMap.put(moduleName, new LinkedList<>()); + if (!mModuleNameListenerMap.containsKey(moduleName)) { + mModuleNameListenerMap.put(moduleName, new LinkedList<>()); } List<OnModuleInstallFinishedListener> onFinishedListeners = - sModuleNameListenerMap.get(moduleName); + mModuleNameListenerMap.get(moduleName); onFinishedListeners.add(onFinishedListener); if (onFinishedListeners.size() > 1) { // Request is already running. @@ -132,56 +129,50 @@ public class ModuleInstaller { getBackend().install(moduleName); } - /** - * Asynchronously installs module in the background when on unmetered connection and charging. - * Install is best effort and may fail silently. Upon success, the module will only be available - * after Chrome restarts. - * - * @param moduleName Name of the module. - */ - public static void installDeferred(String moduleName) { + @Override + public void installDeferred(String moduleName) { ThreadUtils.assertOnUiThread(); getBackend().installDeferred(moduleName); } - private static void onFinished(boolean success, List<String> moduleNames) { + private void onFinished(boolean success, List<String> moduleNames) { ThreadUtils.assertOnUiThread(); for (String moduleName : moduleNames) { List<OnModuleInstallFinishedListener> onFinishedListeners = - sModuleNameListenerMap.get(moduleName); + mModuleNameListenerMap.get(moduleName); if (onFinishedListeners == null) continue; for (OnModuleInstallFinishedListener listener : onFinishedListeners) { listener.onFinished(success); } - sModuleNameListenerMap.remove(moduleName); + mModuleNameListenerMap.remove(moduleName); } - if (sModuleNameListenerMap.isEmpty()) { - sBackend.close(); - sBackend = null; + if (mModuleNameListenerMap.isEmpty()) { + mBackend.close(); + mBackend = null; } updateCrashKeys(); } - private static ModuleInstallerBackend getBackend() { - if (sBackend == null) { - ModuleInstallerBackend.OnFinishedListener listener = ModuleInstaller::onFinished; - sBackend = CommandLine.getInstance().hasSwitch(FAKE_FEATURE_MODULE_INSTALL) + private ModuleInstallerBackend getBackend() { + if (mBackend == null) { + ModuleInstallerBackend.OnFinishedListener listener = this::onFinished; + mBackend = CommandLine.getInstance().hasSwitch(FAKE_FEATURE_MODULE_INSTALL) ? new FakeModuleInstallerBackend(listener) : new PlayCoreModuleInstallerBackend(listener); } - return sBackend; + return mBackend; } - private static String encodeCrashKeyValue(Set<String> moduleNames) { + private String encodeCrashKeyValue(Set<String> moduleNames) { if (moduleNames.isEmpty()) return "<none>"; // Values with dots are interpreted as URLs. Some module names have dots in them. Make sure // they don't get sanitized. return TextUtils.join(",", moduleNames).replace('.', '$'); } - private ModuleInstaller() {} + private ModuleInstallerImpl() {} } diff --git a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java b/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java index cee192c177d..b64387c4516 100644 --- a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java +++ b/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java @@ -20,7 +20,6 @@ import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample; import org.chromium.base.metrics.RecordHistogram; -import org.chromium.components.module_installer.ModuleInstallerBackend.OnFinishedListener; import java.util.Collections; import java.util.HashMap; @@ -93,7 +92,7 @@ import java.util.Set; /** Records via UMA all modules that have been requested and are currently installed. */ public static void recordModuleAvailability() { // MUST call init before creating a SplitInstallManager. - ModuleInstaller.init(); + ModuleInstaller.getInstance().init(); SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); Set<String> requestedModules = new HashSet<>(); requestedModules.addAll( @@ -128,7 +127,7 @@ import java.util.Set; public PlayCoreModuleInstallerBackend(OnFinishedListener listener) { super(listener); // MUST call init before creating a SplitInstallManager. - ModuleInstaller.init(); + ModuleInstaller.getInstance().init(); mManager = SplitInstallManagerFactory.create(ContextUtils.getApplicationContext()); mManager.registerListener(this); } @@ -179,6 +178,7 @@ import java.util.Set; @Override public void onStateUpdate(SplitInstallSessionState state) { assert !mIsClosed; + Log.i(TAG, "Status for modules '%s' updated to %d", state.moduleNames(), state.status()); switch (state.status()) { case SplitInstallSessionStatus.DOWNLOADING: case SplitInstallSessionStatus.INSTALLING: diff --git a/chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstaller.java b/chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstaller.java deleted file mode 100644 index f88b9ca3486..00000000000 --- a/chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstaller.java +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.components.module_installer; - -import android.content.Context; - -import org.chromium.base.VisibleForTesting; - -/** Dummy fallback of ModuleInstaller for APK builds. */ -public class ModuleInstaller { - public static void init() {} - - public static void initActivity(Context context) {} - - public static void recordModuleAvailability() {} - - public static void updateCrashKeys(){}; - - public static void install( - String moduleName, OnModuleInstallFinishedListener onFinishedListener) { - throw new UnsupportedOperationException("Cannot install module if APK"); - } - - public static void installDeferred(String moduleName) { - throw new UnsupportedOperationException("Cannot deferred install module if APK"); - } - - @VisibleForTesting - public static boolean didRequestDeferred(String moduleName) { - throw new UnsupportedOperationException(); - } - - private ModuleInstaller() {} -} diff --git a/chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java b/chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java new file mode 100644 index 00000000000..25654c30cba --- /dev/null +++ b/chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java @@ -0,0 +1,35 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.module_installer; + +import org.chromium.base.annotations.MainDex; + +/** Dummy fallback of ModuleInstaller for APK builds. */ +@MainDex +public class ModuleInstallerImpl implements ModuleInstaller { + /** A valid singleton instance is necessary for tests to swap it out. */ + private static ModuleInstaller sInstance = new ModuleInstallerImpl(); + + /** Returns the singleton instance. */ + public static ModuleInstaller getInstance() { + return sInstance; + } + + public static void setInstanceForTesting(ModuleInstaller moduleInstaller) { + sInstance = moduleInstaller; + } + + @Override + public void install(String moduleName, OnModuleInstallFinishedListener onFinishedListener) { + throw new UnsupportedOperationException("Cannot install module if APK"); + } + + @Override + public void installDeferred(String moduleName) { + throw new UnsupportedOperationException("Cannot deferred install module if APK"); + } + + private ModuleInstallerImpl() {} +} diff --git a/chromium/components/module_installer/android/java/src-test/org/chromium/components/module_installer/ModuleInstaller.java b/chromium/components/module_installer/android/java/src-test/org/chromium/components/module_installer/ModuleInstaller.java deleted file mode 100644 index 02b8519a6b2..00000000000 --- a/chromium/components/module_installer/android/java/src-test/org/chromium/components/module_installer/ModuleInstaller.java +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.components.module_installer; - -import android.content.Context; - -import org.chromium.base.VisibleForTesting; - -import java.util.HashSet; -import java.util.Set; - -/** Mock ModuleInstaller for use in tests. */ -public class ModuleInstaller { - private static Set<String> sModulesRequestedDeffered = new HashSet<>(); - - public static void init() {} - - public static void initActivity(Context context) {} - - public static void recordModuleAvailability() {} - - public static void updateCrashKeys(){}; - - public static void install( - String moduleName, OnModuleInstallFinishedListener onFinishedListener) {} - - public static void installDeferred(String moduleName) { - sModulesRequestedDeffered.add(moduleName); - } - - @VisibleForTesting - public static boolean didRequestDeferred(String moduleName) { - return sModulesRequestedDeffered.contains(moduleName); - } - - private ModuleInstaller() {} -} diff --git a/chromium/components/module_installer/android/javatests/src/org/chromium/components/module_installer/ModuleInstallerRule.java b/chromium/components/module_installer/android/javatests/src/org/chromium/components/module_installer/ModuleInstallerRule.java new file mode 100644 index 00000000000..f9a9418f097 --- /dev/null +++ b/chromium/components/module_installer/android/javatests/src/org/chromium/components/module_installer/ModuleInstallerRule.java @@ -0,0 +1,33 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.module_installer; + +import org.junit.rules.ExternalResource; + +/** + * This rule allows the caller to specify their own {@link ModuleInstaller} for the duration of the + * test and resets it back to what it was before. + * + * TODO(wnwen): This should eventually become ModuleConfigRule. + */ +public class ModuleInstallerRule extends ExternalResource { + private ModuleInstaller mOldModuleInstaller; + private final ModuleInstaller mMockModuleInstaller; + + public ModuleInstallerRule(ModuleInstaller mockModuleInstaller) { + mMockModuleInstaller = mockModuleInstaller; + } + + @Override + protected void before() { + mOldModuleInstaller = ModuleInstaller.getInstance(); + ModuleInstaller.setInstanceForTesting(mMockModuleInstaller); + } + + @Override + protected void after() { + ModuleInstaller.setInstanceForTesting(mOldModuleInstaller); + } +} |