summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraberent <aberent@chromium.org>2015-07-24 05:53:54 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-24 12:54:29 +0000
commit1adc137bc1bc1d8cadf5f691dc3a4da2848eb7ed (patch)
tree06c4916ead1628c015ed38ada751c98163ce47fe
parentcc15bf26827fcef7e7f583e11fcb4dd749c6732e (diff)
downloadchromium_src-1adc137bc1bc1d8cadf5f691dc3a4da2848eb7ed.zip
chromium_src-1adc137bc1bc1d8cadf5f691dc3a4da2848eb7ed.tar.gz
chromium_src-1adc137bc1bc1d8cadf5f691dc3a4da2848eb7ed.tar.bz2
Read Android policies early in startup
The IO thread constructor reads preferences that are set from policies, so Chrome should read the policies before the IO thread constructor is called. Two parts to this: 1 - create a persistant policy cache and read it cache synchronously 2 - reorder various things so that the Android PolicyManager and PolicyProviders are created earlier in startup. Also merge (C++) PolicyProviderAndroid into PolicyManager and add Junit tests for the Java PolicyManager. TBR=nyquist BUG=510813 Review URL: https://codereview.chromium.org/1239323002 Cr-Commit-Position: refs/heads/master@{#340265}
-rw-r--r--chrome/android/BUILD.gn1
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java2
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java40
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyManager.java109
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyProvider.java55
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/policy/providers/AppRestrictionsPolicyProvider.java2
-rw-r--r--chrome/browser/android/chrome_jni_registrar.cc2
-rw-r--r--chrome/browser/android/chrome_main_delegate_staging_android.cc4
-rw-r--r--chrome/browser/android/policy/policy_manager.cc65
-rw-r--r--chrome/browser/android/policy/policy_manager.h57
-rw-r--r--chrome/browser/policy/chrome_browser_policy_connector.cc5
-rw-r--r--chrome/chrome_browser.gypi3
-rw-r--r--chrome/test/android/BUILD.gn1
-rw-r--r--components/components_tests.gyp22
-rw-r--r--components/invalidation.gypi17
-rw-r--r--components/policy.gypi39
-rw-r--r--components/policy/android/BUILD.gn11
-rw-r--r--components/policy/android/java/src/org/chromium/policy/AppRestrictionsProvider.java72
-rw-r--r--components/policy/android/java/src/org/chromium/policy/CombinedPolicyProvider.java148
-rw-r--r--components/policy/android/java/src/org/chromium/policy/PolicyProvider.java59
-rw-r--r--components/policy/android/junit/src/org/chromium/policy/CombinedPolicyProviderTest.java189
-rw-r--r--components/policy/core/browser/BUILD.gn22
-rw-r--r--components/policy/core/browser/android/android_combined_policy_provider.cc66
-rw-r--r--components/policy/core/browser/android/android_combined_policy_provider.h67
-rw-r--r--components/policy/core/browser/android/android_combined_policy_provider_unittest.cc92
-rw-r--r--components/policy/core/browser/android/component_jni_registrar.cc2
-rw-r--r--components/policy/core/common/BUILD.gn3
-rw-r--r--components/policy/core/common/policy_provider_android.cc67
-rw-r--r--components/policy/core/common/policy_provider_android.h49
-rw-r--r--components/policy/core/common/policy_provider_android_delegate.h30
-rw-r--r--components/policy/core/common/policy_provider_android_unittest.cc128
-rw-r--r--components/policy/policy_browser.gypi2
-rw-r--r--components/policy/policy_common.gypi3
-rw-r--r--components/test/DEPS1
-rw-r--r--components/test/run_all_unittests.cc2
-rw-r--r--tools/metrics/histograms/histograms.xml15
36 files changed, 826 insertions, 626 deletions
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 2ae9301..b6fc990 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -614,6 +614,7 @@ android_library("chrome_shared_test_java") {
"//components/invalidation/impl:java",
"//components/invalidation/impl:javatests",
"//components/navigation_interception/android:navigation_interception_java",
+ "//components/policy/android:policy_java",
"//components/precache/android:precache_java",
"//components/precache/android:precache_javatests",
"//components/web_contents_delegate_android:web_contents_delegate_android_java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index 2ecf575..3859e8c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -88,7 +88,6 @@ import org.chromium.chrome.browser.nfc.BeamController;
import org.chromium.chrome.browser.nfc.BeamProvider;
import org.chromium.chrome.browser.omaha.OmahaClient;
import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
-import org.chromium.chrome.browser.policy.PolicyManager.PolicyChangeListener;
import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.preferences.PreferencesLauncher;
@@ -121,6 +120,7 @@ import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.common.ContentSwitches;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.readback_types.ReadbackResponse;
+import org.chromium.policy.CombinedPolicyProvider.PolicyChangeListener;
import org.chromium.printing.PrintManagerDelegateImpl;
import org.chromium.printing.PrintingController;
import org.chromium.ui.base.ActivityWindowAndroid;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
index 194bf1e..1bc6d27 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
@@ -61,7 +61,6 @@ import org.chromium.chrome.browser.omaha.UpdateInfoBarHelper;
import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
import org.chromium.chrome.browser.policy.PolicyAuditor;
import org.chromium.chrome.browser.policy.PolicyManager;
-import org.chromium.chrome.browser.policy.PolicyManager.PolicyChangeListener;
import org.chromium.chrome.browser.policy.providers.AppRestrictionsPolicyProvider;
import org.chromium.chrome.browser.preferences.AccessibilityPreferences;
import org.chromium.chrome.browser.preferences.LocationSettings;
@@ -92,6 +91,8 @@ import org.chromium.content.browser.BrowserStartupController;
import org.chromium.content.browser.ChildProcessLauncher;
import org.chromium.content.browser.ContentViewStatics;
import org.chromium.content.browser.DownloadController;
+import org.chromium.policy.CombinedPolicyProvider;
+import org.chromium.policy.CombinedPolicyProvider.PolicyChangeListener;
import org.chromium.printing.PrintingController;
import org.chromium.sync.signin.AccountManagerDelegate;
import org.chromium.sync.signin.AccountManagerHelper;
@@ -183,7 +184,6 @@ public class ChromeApplication extends ContentApplication {
private ChromeLifetimeController mChromeLifetimeController;
private PrintingController mPrintingController;
- private PolicyManager mPolicyManager = new PolicyManager();
/**
* This is called once per ChromeApplication instance, which get created per process
@@ -319,8 +319,7 @@ public class ChromeApplication extends ContentApplication {
stopApplicationActivityTracker();
PartnerBrowserCustomizations.destroy();
ShareHelper.clearSharedScreenshots(this);
- mPolicyManager.destroy();
- mPolicyManager = null;
+ CombinedPolicyProvider.get().destroy();
}
}
@@ -476,9 +475,6 @@ public class ChromeApplication extends ContentApplication {
AppBannerManager.setAppDetailsDelegate(createAppDetailsDelegate());
mChromeLifetimeController = new ChromeLifetimeController(this);
- mPolicyManager.initializeNative();
- registerPolicyProviders(mPolicyManager);
-
PrefServiceBridge.getInstance().migratePreferences(this);
}
@@ -500,6 +496,9 @@ public class ChromeApplication extends ContentApplication {
public void startChromeBrowserProcessesAsync(BrowserStartupController.StartupCallback callback)
throws ProcessInitException {
assert ThreadUtils.runningOnUiThread() : "Tried to start the browser on the wrong thread";
+ // The policies are used by browser startup, so we need to register the policy providers
+ // before starting the browser process.
+ registerPolicyProviders(CombinedPolicyProvider.get());
Context applicationContext = getApplicationContext();
BrowserStartupController.get(applicationContext, LibraryProcessType.PROCESS_BROWSER)
.startBrowserProcessesAsync(callback);
@@ -520,6 +519,9 @@ public class ChromeApplication extends ContentApplication {
LibraryLoader libraryLoader = LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER);
libraryLoader.ensureInitialized(context);
libraryLoader.asyncPrefetchLibrariesToMemory();
+ // The policies are used by browser startup, so we need to register the policy providers
+ // before starting the browser process.
+ registerPolicyProviders(CombinedPolicyProvider.get());
BrowserStartupController.get(context, LibraryProcessType.PROCESS_BROWSER)
.startBrowserProcessesSync(false);
if (initGoogleServicesManager) {
@@ -698,33 +700,47 @@ public class ChromeApplication extends ContentApplication {
return new GSAHelper();
}
+ // TODO(aberent): Change return type and remove cast once downstream CL has landed.
@VisibleForTesting
public PolicyManager getPolicyManagerForTesting() {
- return mPolicyManager;
+ return (PolicyManager) CombinedPolicyProvider.get();
}
/**
* Registers various policy providers with the policy manager.
* Providers are registered in increasing order of precedence so overrides should call this
* method in the end for this method to maintain the highest precedence.
- * @param manager The {@link PolicyManager} to register the providers with.
+ * @param combinedProvider The {@link CombinedPolicyProvider} to register the providers with.
+ */
+ protected void registerPolicyProviders(CombinedPolicyProvider combinedProvider) {
+ combinedProvider.registerProvider(
+ new AppRestrictionsPolicyProvider(getApplicationContext()));
+ }
+
+ /**
+ * Temp - for compatibility with existing downstream code, which overrides this.
+ * @param manager The {@link PolicyManager} to register the providers with
+ *
+ * TODO(aberent): Remove once the downstream CL lands.
*/
protected void registerPolicyProviders(PolicyManager manager) {
- manager.registerProvider(new AppRestrictionsPolicyProvider(getApplicationContext()));
+ // Cast the manager's type to force a call to the other overload, avoiding infinite
+ // recursion
+ registerPolicyProviders((CombinedPolicyProvider) manager);
}
/**
* Add a listener to be notified upon policy changes.
*/
public void addPolicyChangeListener(PolicyChangeListener listener) {
- mPolicyManager.addPolicyChangeListener(listener);
+ CombinedPolicyProvider.get().addPolicyChangeListener(listener);
}
/**
* Remove a listener to be notified upon policy changes.
*/
public void removePolicyChangeListener(PolicyChangeListener listener) {
- mPolicyManager.removePolicyChangeListener(listener);
+ CombinedPolicyProvider.get().removePolicyChangeListener(listener);
}
/**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyManager.java b/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyManager.java
index d4f1e20..2682024 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyManager.java
@@ -4,111 +4,10 @@
package org.chromium.chrome.browser.policy;
-import android.os.Bundle;
-
-import org.chromium.base.CalledByNative;
-import org.chromium.base.ThreadUtils;
-import org.chromium.policy.PolicyConverter;
-
-import java.util.ArrayList;
-import java.util.List;
+import org.chromium.policy.CombinedPolicyProvider;
/**
- * Reads enterprise policies from one or more policy providers
- * and plumbs them through to the policy subsystem.
+ * Temp version of old class to avoid breaking downstream builds
+ * TODO(aberent): Remove once downstream CL lands
*/
-public class PolicyManager {
- private long mNativePolicyManager;
-
- private PolicyConverter mPolicyConverter;
- private final List<PolicyProvider> mPolicyProviders = new ArrayList<>();
- private final List<Bundle> mCachedPolicies = new ArrayList<>();
- private final List<PolicyChangeListener> mPolicyChangeListeners = new ArrayList<>();
-
- public void initializeNative() {
- ThreadUtils.assertOnUiThread();
- mNativePolicyManager = nativeInit();
- mPolicyConverter = nativeCreatePolicyConverter(mNativePolicyManager);
- }
-
- /**
- * PolicyProviders are assigned a unique precedence based on their order of registration.
- * Later Registration -> Higher Precedence.
- * This precedence is also used as a 'source' tag for disambiguating updates.
- */
- public void registerProvider(PolicyProvider provider) {
- mPolicyProviders.add(provider);
- mCachedPolicies.add(null);
- provider.setManagerAndSource(this, mPolicyProviders.size() - 1);
- provider.refresh();
- }
-
- public void destroy() {
- // All the activities registered should have been destroyed by then.
- assert mPolicyChangeListeners.isEmpty();
-
- for (PolicyProvider provider : mPolicyProviders) {
- provider.destroy();
- }
- mPolicyProviders.clear();
-
- nativeDestroy(mNativePolicyManager);
- mNativePolicyManager = 0;
- mPolicyConverter = null;
- }
-
- void onSettingsAvailable(int source, Bundle newSettings) {
- mCachedPolicies.set(source, newSettings);
- // Check if we have policies from all the providers before applying them.
- for (Bundle settings : mCachedPolicies) {
- if (settings == null) return;
- }
- for (Bundle settings : mCachedPolicies) {
- for (String key : settings.keySet()) {
- mPolicyConverter.setPolicy(key, settings.get(key));
- }
- }
- nativeFlushPolicies(mNativePolicyManager);
- }
-
- void terminateIncognitoSession() {
- for (PolicyChangeListener listener : mPolicyChangeListeners) {
- listener.terminateIncognitoSession();
- }
- }
-
- public void addPolicyChangeListener(PolicyChangeListener listener) {
- mPolicyChangeListeners.add(listener);
- }
-
- public void removePolicyChangeListener(PolicyChangeListener listener) {
- assert mPolicyChangeListeners.contains(listener);
- mPolicyChangeListeners.remove(listener);
- }
-
- @CalledByNative
- private void refreshPolicies() {
- assert mPolicyProviders.size() == mCachedPolicies.size();
- for (int i = 0; i < mCachedPolicies.size(); ++i) {
- mCachedPolicies.set(i, null);
- }
- for (PolicyProvider provider : mPolicyProviders) {
- provider.refresh();
- }
- }
-
- /**
- * Interface to handle actions related with policy changes.
- */
- public interface PolicyChangeListener {
- /**
- * Call to notify the listener that incognito browsing is unavailable due to policy.
- */
- void terminateIncognitoSession();
- }
-
- private native long nativeInit();
- private native PolicyConverter nativeCreatePolicyConverter(long nativePolicyManager);
- private native void nativeDestroy(long nativePolicyManager);
- private native void nativeFlushPolicies(long nativePolicyManager);
-}
+public class PolicyManager extends CombinedPolicyProvider {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyProvider.java
index f26e4de..0563ebf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyProvider.java
@@ -5,55 +5,22 @@
package org.chromium.chrome.browser.policy;
import android.content.Context;
-import android.os.Bundle;
+
+import org.chromium.base.annotations.SuppressFBWarnings;
/**
- * Base class for Policy providers.
+ * Temp version of old class to avoid breaking downstream builds
+ * TODO(aberent): Remove once downstream CL lands.
+ * FB warnings suppressed because FB doesn't like the two classes having the
+ * same simple name, which I can't avoid here.
*/
-public abstract class PolicyProvider {
- private PolicyManager mPolicyManager;
- protected final Context mContext;
- private int mSource = -1;
-
- protected PolicyProvider(Context context) {
- mContext = context.getApplicationContext();
- }
-
- protected void notifySettingsAvailable(Bundle settings) {
- mPolicyManager.onSettingsAvailable(mSource, settings);
- }
-
- protected void terminateIncognitoSession() {
- mPolicyManager.terminateIncognitoSession();
- }
-
+@SuppressFBWarnings
+public abstract class PolicyProvider extends org.chromium.policy.PolicyProvider {
/**
- * Called to request a refreshed set of policies.
- * This method must handle notifying the PolicyManager whenever applicable.
+ * @param context
*/
- public abstract void refresh();
-
- /**
- * Register the PolicyProvider for receiving policy changes.
- */
- protected void startListeningForPolicyChanges() {
- }
-
- /**
- * Called by the {@link PolicyManager} to correctly hook it with the Policy system.
- * @param policyManager reference to the PolicyManager to be used like a delegate.
- * @param source tags the PolicyProvider with a source.
- */
- final void setManagerAndSource(PolicyManager policyManager, int source) {
- assert mSource < 0;
- assert source >= 0;
- mSource = source;
- assert mPolicyManager == null;
- mPolicyManager = policyManager;
- startListeningForPolicyChanges();
+ protected PolicyProvider(Context context) {
+ super(context);
}
- /** Called when the provider is unregistered */
- public void destroy() {
- }
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/policy/providers/AppRestrictionsPolicyProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/policy/providers/AppRestrictionsPolicyProvider.java
index 35b9f8c..977fa28 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/policy/providers/AppRestrictionsPolicyProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/policy/providers/AppRestrictionsPolicyProvider.java
@@ -7,8 +7,8 @@ package org.chromium.chrome.browser.policy.providers;
import android.content.Context;
import android.os.Bundle;
-import org.chromium.chrome.browser.policy.PolicyProvider;
import org.chromium.policy.AppRestrictionsProvider;
+import org.chromium.policy.PolicyProvider;
/**
* Policy provider for Android's App Restriction Schema.
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index 94e56b2..a541fc9 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -55,7 +55,6 @@
#include "chrome/browser/android/omnibox/autocomplete_controller_android.h"
#include "chrome/browser/android/omnibox/omnibox_prerender.h"
#include "chrome/browser/android/password_ui_view_android.h"
-#include "chrome/browser/android/policy/policy_manager.h"
#include "chrome/browser/android/precache/precache_launcher.h"
#include "chrome/browser/android/preferences/autofill/autofill_profile_bridge.h"
#include "chrome/browser/android/preferences/pref_service_bridge.h"
@@ -270,7 +269,6 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = {
PermissionUpdateInfoBarDelegate::RegisterPermissionUpdateInfoBarDelegate},
{"PersonalDataManagerAndroid",
autofill::PersonalDataManagerAndroid::Register},
- {"PolicyManager", RegisterPolicyManager},
{"PrecacheLauncher", RegisterPrecacheLauncher},
{"PrefServiceBridge", PrefServiceBridge::RegisterPrefServiceBridge},
{"ProfileAndroid", ProfileAndroid::RegisterProfileAndroid},
diff --git a/chrome/browser/android/chrome_main_delegate_staging_android.cc b/chrome/browser/android/chrome_main_delegate_staging_android.cc
index 2f7ae53..2042718 100644
--- a/chrome/browser/android/chrome_main_delegate_staging_android.cc
+++ b/chrome/browser/android/chrome_main_delegate_staging_android.cc
@@ -8,7 +8,7 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
-#include "components/policy/core/common/policy_provider_android.h"
+#include "components/policy/core/browser/android/android_combined_policy_provider.h"
#if defined(SAFE_BROWSING_DB_REMOTE)
#include "chrome/browser/safe_browsing/safe_browsing_api_handler.h"
@@ -36,7 +36,7 @@ bool ChromeMainDelegateStagingAndroid::BasicStartupComplete(int* exit_code) {
SafeBrowsingResourceThrottleFactory::RegisterFactory(
data_reduction_proxy_throttle_factory_.get());
#endif
- policy::PolicyProviderAndroid::SetShouldWaitForPolicy(true);
+ policy::android::AndroidCombinedPolicyProvider::SetShouldWaitForPolicy(true);
return ChromeMainDelegateAndroid::BasicStartupComplete(exit_code);
}
diff --git a/chrome/browser/android/policy/policy_manager.cc b/chrome/browser/android/policy/policy_manager.cc
deleted file mode 100644
index 696f3a2..0000000
--- a/chrome/browser/android/policy/policy_manager.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2015 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.
-
-#include "chrome/browser/android/policy/policy_manager.h"
-
-#include "base/android/jni_android.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/browser_process_platform_part.h"
-#include "components/policy/core/browser/android/policy_converter.h"
-#include "components/policy/core/browser/browser_policy_connector.h"
-#include "components/policy/core/common/policy_provider_android.h"
-#include "components/policy/core/common/schema.h"
-#include "jni/PolicyManager_jni.h"
-
-using base::android::AttachCurrentThread;
-using base::android::ScopedJavaLocalRef;
-
-PolicyManager::PolicyManager(JNIEnv* env, jobject obj)
- : weak_java_policy_manager_(env, obj) {
- policy_provider_ = static_cast<policy::PolicyProviderAndroid*>(
- g_browser_process->browser_policy_connector()->GetPlatformProvider());
- policy_provider_->SetDelegate(this);
-}
-
-PolicyManager::~PolicyManager() {}
-
-ScopedJavaLocalRef<jobject> PolicyManager::CreatePolicyConverter(JNIEnv* env,
- jobject obj) {
- policy_converter_.reset(new policy::android::PolicyConverter(
- policy_provider_->GetChromeSchema()));
- return ScopedJavaLocalRef<jobject>(policy_converter_->GetJavaObject());
-}
-
-void PolicyManager::RefreshPolicies() {
- JNIEnv* env = AttachCurrentThread();
- Java_PolicyManager_refreshPolicies(
- env, weak_java_policy_manager_.get(env).obj());
-}
-
-void PolicyManager::PolicyProviderShutdown() {
- policy_provider_ = nullptr;
-}
-
-void PolicyManager::FlushPolicies(JNIEnv* env, jobject obj) {
- if (!policy_provider_)
- return;
-
- policy_provider_->SetPolicies(policy_converter_->GetPolicyBundle());
-}
-
-void PolicyManager::Destroy(JNIEnv* env, jobject obj) {
- if (policy_provider_)
- policy_provider_->SetDelegate(nullptr);
-
- delete this;
-}
-
-static jlong Init(JNIEnv* env, jobject obj) {
- return reinterpret_cast<intptr_t>(new PolicyManager(env, obj));
-}
-
-bool RegisterPolicyManager(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
diff --git a/chrome/browser/android/policy/policy_manager.h b/chrome/browser/android/policy/policy_manager.h
deleted file mode 100644
index 21c72be..0000000
--- a/chrome/browser/android/policy/policy_manager.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef CHROME_BROWSER_ANDROID_POLICY_POLICY_MANAGER_H_
-#define CHROME_BROWSER_ANDROID_POLICY_POLICY_MANAGER_H_
-
-#include <jni.h>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "components/policy/core/common/policy_provider_android_delegate.h"
-
-namespace policy {
-
-class PolicyProviderAndroid;
-
-namespace android {
-
-class PolicyConverter;
-
-} // namespace android
-} // namespace policy
-
-class PolicyManager : public policy::PolicyProviderAndroidDelegate {
- public:
- PolicyManager(JNIEnv* env, jobject obj);
-
- void FlushPolicies(JNIEnv* env, jobject obj);
-
- void Destroy(JNIEnv* env, jobject obj);
-
- // Creates the native and java |PolicyConverter|, returns the reference to
- // the java one.
- base::android::ScopedJavaLocalRef<jobject> CreatePolicyConverter(JNIEnv* env,
- jobject obj);
-
- // PolicyProviderAndroidDelegate:
- void RefreshPolicies() override;
- void PolicyProviderShutdown() override;
-
- private:
- ~PolicyManager() override;
-
- JavaObjectWeakGlobalRef weak_java_policy_manager_;
-
- scoped_ptr<policy::android::PolicyConverter> policy_converter_;
- policy::PolicyProviderAndroid* policy_provider_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyManager);
-};
-
-// Register native methods
-bool RegisterPolicyManager(JNIEnv* env);
-
-#endif // CHROME_BROWSER_ANDROID_POLICY_POLICY_MANAGER_H_
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.cc b/chrome/browser/policy/chrome_browser_policy_connector.cc
index e27d38b..5f19b2a 100644
--- a/chrome/browser/policy/chrome_browser_policy_connector.cc
+++ b/chrome/browser/policy/chrome_browser_policy_connector.cc
@@ -37,7 +37,7 @@
#elif defined(OS_POSIX) && !defined(OS_ANDROID)
#include "components/policy/core/common/config_dir_policy_loader.h"
#elif defined(OS_ANDROID)
-#include "components/policy/core/common/policy_provider_android.h"
+#include "components/policy/core/browser/android/android_combined_policy_provider.h"
#endif
using content::BrowserThread;
@@ -114,7 +114,8 @@ ConfigurationPolicyProvider*
return NULL;
}
#elif defined(OS_ANDROID)
- return new PolicyProviderAndroid();
+ return new policy::android::AndroidCombinedPolicyProvider(
+ GetSchemaRegistry());
#else
return NULL;
#endif
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 3756b07..d547c5d 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -190,8 +190,6 @@
'browser/android/omnibox/omnibox_prerender.h',
'browser/android/password_ui_view_android.cc',
'browser/android/password_ui_view_android.h',
- 'browser/android/policy/policy_manager.cc',
- 'browser/android/policy/policy_manager.h',
'browser/android/precache/precache_launcher.cc',
'browser/android/precache/precache_launcher.h',
'browser/android/preferences/autofill/autofill_profile_bridge.cc',
@@ -1755,7 +1753,6 @@
'android/java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java',
'android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java',
'android/java/src/org/chromium/chrome/browser/password_manager/Credential.java',
- 'android/java/src/org/chromium/chrome/browser/policy/PolicyManager.java',
'android/java/src/org/chromium/chrome/browser/PasswordUIView.java',
'android/java/src/org/chromium/chrome/browser/precache/PrecacheLauncher.java',
'android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfileBridge.java',
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 7c09f5a..6f9e4bb 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -15,6 +15,7 @@ android_library("chrome_java_test_support") {
"//chrome/android:chrome_java_resources",
"//components/bookmarks/common/android:bookmarks_java",
"//components/invalidation/impl:java",
+ "//components/policy/android:policy_java",
"//components/web_contents_delegate_android:web_contents_delegate_android_java",
"//content/public/android:content_java",
"//content/public/test/android:content_java_test_support",
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index afa86ee..09d599f 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -396,6 +396,7 @@
'password_manager/core/common/credential_manager_types_unittest.cc',
],
'policy_unittest_sources': [
+ 'policy/core/browser/android/android_combined_policy_provider_unittest.cc',
'policy/core/browser/android/policy_converter_unittest.cc',
'policy/core/browser/autofill_policy_handler_unittest.cc',
'policy/core/browser/browser_policy_connector_unittest.cc',
@@ -429,7 +430,6 @@
'policy/core/common/policy_loader_mac_unittest.cc',
'policy/core/common/policy_loader_win_unittest.cc',
'policy/core/common/policy_map_unittest.cc',
- 'policy/core/common/policy_provider_android_unittest.cc',
'policy/core/common/policy_service_impl_unittest.cc',
'policy/core/common/policy_statistics_collector_unittest.cc',
'policy/core/common/preg_parser_win_unittest.cc',
@@ -990,6 +990,7 @@
'conditions': [
['OS=="android"', {
'dependencies': [
+ 'components.gyp:policy_java',
'../build/android/ndk.gyp:cpu_features',
],
}],
@@ -1556,6 +1557,25 @@
},
'includes': [ '../build/apk_test.gypi' ],
},
+ {
+ 'target_name': 'components_junit_tests',
+ 'type': 'none',
+ 'dependencies': [
+ 'components.gyp:invalidation_java',
+ 'components.gyp:policy_java',
+ '../base/base.gyp:base_java',
+ '../base/base.gyp:base_java_test_support',
+ '../testing/android/junit/junit_test.gyp:junit_test_support',
+ ],
+ 'variables': {
+ 'main_class': 'org.chromium.testing.local.JunitTestMain',
+ 'src_paths': [
+ 'invalidation/impl/android/junit/',
+ 'policy/android/junit/'
+ ],
+ },
+ 'includes': [ '../build/host_jar.gypi' ],
+ },
],
}],
],
diff --git a/components/invalidation.gypi b/components/invalidation.gypi
index 8329c8c..4e361f8 100644
--- a/components/invalidation.gypi
+++ b/components/invalidation.gypi
@@ -231,23 +231,6 @@
'includes': [ '../build/java.gypi' ],
},
{
- 'target_name': 'invalidation_junit_tests',
- 'type': 'none',
- 'dependencies': [
- 'invalidation_java',
- '../base/base.gyp:base_java',
- '../base/base.gyp:base_java_test_support',
- '../testing/android/junit/junit_test.gyp:junit_test_support',
- ],
- 'variables': {
- 'main_class': 'org.chromium.testing.local.JunitTestMain',
- 'src_paths': [
- 'invalidation/impl/android/junit/'
- ],
- },
- 'includes': [ '../build/host_jar.gypi' ],
- },
- {
'target_name': 'invalidation_jni_headers',
'type': 'none',
'sources': [
diff --git a/components/policy.gypi b/components/policy.gypi
index 2302487..d032ace 100644
--- a/components/policy.gypi
+++ b/components/policy.gypi
@@ -62,6 +62,11 @@
'includes': [
'policy/policy_browser.gypi',
],
+ 'conditions': [
+ ['OS=="android"', {
+ 'dependencies': ['policy_jni_headers']},
+ ],
+ ],
},
],
}, { # component=="shared_library"
@@ -82,6 +87,11 @@
'dependencies': [
'policy_component',
],
+ 'conditions': [
+ ['OS=="android"', {
+ 'dependencies': ['policy_jni_headers']},
+ ],
+ ],
},
{
# GN version: //components/policy:policy_component_browser
@@ -339,6 +349,23 @@
},
],
}],
+ ['OS=="android"',
+ {
+ 'targets' : [
+ {
+ 'target_name' : 'policy_jni_headers',
+ 'type': 'none',
+ 'sources': [
+ 'policy/android/java/src/org/chromium/policy/CombinedPolicyProvider.java',
+ 'policy/android/java/src/org/chromium/policy/PolicyConverter.java',
+ ],
+ 'variables': {
+ 'jni_gen_package': 'policy',
+ },
+ 'includes': [ '../build/jni_generator.gypi' ],
+ },
+ ],
+ }],
['OS=="android" and configuration_policy==1', {
'targets': [
{
@@ -395,18 +422,6 @@
},
'includes': [ '../build/java.gypi' ],
},
- {
- # GN: //components/policy/android:jni_headers
- 'target_name': 'policy_jni_headers',
- 'type': 'none',
- 'sources': [
- 'policy/android/java/src/org/chromium/policy/PolicyConverter.java',
- ],
- 'variables': {
- 'jni_gen_package': 'policy',
- },
- 'includes': [ '../build/jni_generator.gypi' ],
- },
],
}],
['OS=="win" and target_arch=="ia32" and configuration_policy==1', {
diff --git a/components/policy/android/BUILD.gn b/components/policy/android/BUILD.gn
index 9784e36..3598072 100644
--- a/components/policy/android/BUILD.gn
+++ b/components/policy/android/BUILD.gn
@@ -4,15 +4,20 @@
import("//build/config/android/rules.gni")
-_jni_sources = [ "java/src/org/chromium/policy/PolicyConverter.java" ]
+_jni_sources = [
+ "java/src/org/chromium/policy/PolicyConverter.java",
+ "java/src/org/chromium/policy/CombinedPolicyProvider.java",
+]
# GYP: //components/components.gyp:policy_java
android_library("policy_java") {
deps = [
"//base:base_java",
]
- java_files = [ "java/src/org/chromium/policy/AppRestrictionsProvider.java" ] +
- _jni_sources
+ java_files = [
+ "java/src/org/chromium/policy/AppRestrictionsProvider.java",
+ "java/src/org/chromium/policy/PolicyProvider.java",
+ ] + _jni_sources
}
# GYP: //components/components.gyp:policy_jni_headers
diff --git a/components/policy/android/java/src/org/chromium/policy/AppRestrictionsProvider.java b/components/policy/android/java/src/org/chromium/policy/AppRestrictionsProvider.java
index cb4f8a0..dc3858e 100644
--- a/components/policy/android/java/src/org/chromium/policy/AppRestrictionsProvider.java
+++ b/components/policy/android/java/src/org/chromium/policy/AppRestrictionsProvider.java
@@ -9,14 +9,22 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.Parcel;
import android.os.UserManager;
+import android.preference.PreferenceManager;
+import android.util.Base64;
+
+import org.chromium.base.metrics.RecordHistogram;
+
+import java.util.concurrent.TimeUnit;
/**
- * Retrieves app restrictions and provides them to a {@link Delegate} object as Bundles.
- * Retrieving the restrictions is done asynchronously.
+ * Retrieves app restrictions and provides them to a {@link Delegate} object as Bundles. Retrieving
+ * the restrictions is done asynchronously.
*/
public class AppRestrictionsProvider {
/** Delegate to notify when restrictions have been received. */
@@ -25,9 +33,12 @@ public class AppRestrictionsProvider {
public void notifyNewAppRestrictionsAvailable(Bundle newAppRestrictions);
}
+ private static final String PREFERENCE_KEY = "App Restrictions";
+
private final UserManager mUserManager;
private final Context mContext;
private final Delegate mDelegate;
+ private final SharedPreferences mSharedPreferences;
private final BroadcastReceiver mAppRestrictionsChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -37,13 +48,14 @@ public class AppRestrictionsProvider {
/**
* @param context The application context.
- * @param appRestrictionsProviderDelegate Object to be notified when new restrictions
- * are available.
+ * @param appRestrictionsProviderDelegate Object to be notified when new restrictions are
+ * available.
*/
public AppRestrictionsProvider(Context context, Delegate appRestrictionsProviderDelegate) {
mContext = context;
mDelegate = appRestrictionsProviderDelegate;
mUserManager = getUserManager();
+ mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
}
/**
@@ -66,15 +78,24 @@ public class AppRestrictionsProvider {
mDelegate.notifyNewAppRestrictionsAvailable(new Bundle());
return;
}
+ final Bundle cachedResult = getCachedPolicies();
+ if (cachedResult != null) {
+ mDelegate.notifyNewAppRestrictionsAvailable(cachedResult);
+ }
new AsyncTask<Void, Void, Bundle>() {
@Override
protected Bundle doInBackground(Void... params) {
- return getApplicationRestrictions();
+ long startTime = System.currentTimeMillis();
+ Bundle bundle = getApplicationRestrictions();
+ RecordHistogram.recordTimesHistogram("Enterprise.AppRestrictionLoadTime",
+ System.currentTimeMillis() - startTime, TimeUnit.MILLISECONDS);
+ return bundle;
}
@Override
protected void onPostExecute(Bundle result) {
+ cachePolicies(result);
mDelegate.notifyNewAppRestrictionsAvailable(result);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
@@ -105,8 +126,8 @@ public class AppRestrictionsProvider {
}
/**
- * Wrap access to the Android UserManager to allow being swapped out in environments where it
- * is not available yet.
+ * Wrap access to the Android UserManager to allow being swapped out in environments where it is
+ * not available yet.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private Bundle getApplicationRestrictions() {
@@ -114,12 +135,45 @@ public class AppRestrictionsProvider {
}
/**
- * Wrap access to the Android UserManager to allow being swapped out in environments where it
- * is not available yet.
+ * Wrap access to the Android UserManager to allow being swapped out in environments where it is
+ * not available yet.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private UserManager getUserManager() {
if (!isRestrictionsSupported()) return null;
return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
}
+
+ private void cachePolicies(Bundle policies) {
+ Parcel p = Parcel.obtain();
+ p.writeBundle(policies);
+ byte bytes[] = p.marshall();
+ String s = Base64.encodeToString(bytes, 0);
+ SharedPreferences.Editor ed = mSharedPreferences.edit();
+ ed.putString(PREFERENCE_KEY, s);
+ ed.apply();
+ }
+
+ private Bundle getCachedPolicies() {
+ String s = mSharedPreferences.getString(PREFERENCE_KEY, null);
+ if (s == null) {
+ return null;
+ }
+ byte bytes[] = Base64.decode(s, 0);
+ Parcel p = Parcel.obtain();
+ // Unmarshalling the parcel is, in theory, unsafe if the Android version or API version has
+ // changed, but the worst that is likely to happen is that the bundle comes back empty, and
+ // this will be corrected once the Android returns the real App Restrictions.
+ p.unmarshall(bytes, 0, bytes.length);
+ p.setDataPosition(0);
+ Bundle result = p.readBundle();
+ try {
+ result = p.readBundle();
+ } catch (IllegalStateException e) {
+ result = null;
+ }
+ RecordHistogram.recordBooleanHistogram(
+ "Enterprise.AppRestrictionsCacheLoad", result != null);
+ return result;
+ }
}
diff --git a/components/policy/android/java/src/org/chromium/policy/CombinedPolicyProvider.java b/components/policy/android/java/src/org/chromium/policy/CombinedPolicyProvider.java
new file mode 100644
index 0000000..13991d9
--- /dev/null
+++ b/components/policy/android/java/src/org/chromium/policy/CombinedPolicyProvider.java
@@ -0,0 +1,148 @@
+// Copyright 2015 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.policy;
+
+import android.os.Bundle;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Reads enterprise policies from one or more policy providers and plumbs them through to the policy
+ * subsystem.
+ */
+@JNINamespace("policy::android")
+public class CombinedPolicyProvider {
+ private static CombinedPolicyProvider sInstance = null;
+
+ private long mNativeCombinedPolicyProvider = 0;
+
+ private PolicyConverter mPolicyConverter;
+ private final List<PolicyProvider> mPolicyProviders = new ArrayList<>();
+ private final List<Bundle> mCachedPolicies = new ArrayList<>();
+ private final List<PolicyChangeListener> mPolicyChangeListeners = new ArrayList<>();
+
+ public static CombinedPolicyProvider get() {
+ if (sInstance == null) {
+ sInstance = new CombinedPolicyProvider();
+ }
+ return sInstance;
+ }
+
+ private void linkNativeInternal(
+ long nativeCombinedPolicyProvider, PolicyConverter policyConverter) {
+ mNativeCombinedPolicyProvider = nativeCombinedPolicyProvider;
+ mPolicyConverter = policyConverter;
+ if (nativeCombinedPolicyProvider != 0) {
+ for (PolicyProvider provider : mPolicyProviders) {
+ provider.refresh();
+ }
+ }
+ }
+
+ @CalledByNative
+ public static CombinedPolicyProvider linkNative(
+ long nativeCombinedPolicyProvider, PolicyConverter policyConverter) {
+ ThreadUtils.assertOnUiThread();
+ get().linkNativeInternal(nativeCombinedPolicyProvider, policyConverter);
+ return get();
+ }
+
+ /**
+ * PolicyProviders are assigned a unique precedence based on their order of registration. Later
+ * Registration -> Higher Precedence. This precedence is also used as a 'source' tag for
+ * disambiguating updates.
+ */
+ public void registerProvider(PolicyProvider provider) {
+ mPolicyProviders.add(provider);
+ mCachedPolicies.add(null);
+ provider.setManagerAndSource(this, mPolicyProviders.size() - 1);
+ if (mNativeCombinedPolicyProvider != 0) provider.refresh();
+ }
+
+ public void destroy() {
+ // All the activities registered should have been destroyed by then.
+ assert mPolicyChangeListeners.isEmpty();
+
+ for (PolicyProvider provider : mPolicyProviders) {
+ provider.destroy();
+ }
+ mPolicyProviders.clear();
+ mPolicyConverter = null;
+ }
+
+ void onSettingsAvailable(int source, Bundle newSettings) {
+ mCachedPolicies.set(source, newSettings);
+ // Check if we have policies from all the providers before applying them.
+ for (Bundle settings : mCachedPolicies) {
+ if (settings == null) return;
+ }
+
+ if (mNativeCombinedPolicyProvider == 0) return;
+
+ for (Bundle settings : mCachedPolicies) {
+ for (String key : settings.keySet()) {
+ mPolicyConverter.setPolicy(key, settings.get(key));
+ }
+ }
+ nativeFlushPolicies(mNativeCombinedPolicyProvider);
+ }
+
+ void terminateIncognitoSession() {
+ for (PolicyChangeListener listener : mPolicyChangeListeners) {
+ listener.terminateIncognitoSession();
+ }
+ }
+
+ public void addPolicyChangeListener(PolicyChangeListener listener) {
+ mPolicyChangeListeners.add(listener);
+ }
+
+ public void removePolicyChangeListener(PolicyChangeListener listener) {
+ assert mPolicyChangeListeners.contains(listener);
+ mPolicyChangeListeners.remove(listener);
+ }
+
+ @VisibleForTesting
+ @CalledByNative
+ void refreshPolicies() {
+ assert mPolicyProviders.size() == mCachedPolicies.size();
+ for (int i = 0; i < mCachedPolicies.size(); ++i) {
+ mCachedPolicies.set(i, null);
+ }
+ for (PolicyProvider provider : mPolicyProviders) {
+ provider.refresh();
+ }
+ }
+
+ /**
+ * Interface to handle actions related with policy changes.
+ */
+ public interface PolicyChangeListener {
+ /**
+ * Call to notify the listener that incognito browsing is unavailable due to policy.
+ */
+ void terminateIncognitoSession();
+ }
+
+ @VisibleForTesting
+ public static void set(CombinedPolicyProvider p) {
+ sInstance = p;
+ }
+
+ // Constructor needs to be public (temporarily) to so that PolicyManager can be derived from
+ // this class. Also needed, with package scope, for testing.
+ // TODO(aberent): Once upstream CL lands change to package scope.
+ // @VisibleForTesting
+ // CombinedPolicyProvider() {}
+
+ @VisibleForTesting
+ protected native void nativeFlushPolicies(long nativeAndroidCombinedPolicyProvider);
+}
diff --git a/components/policy/android/java/src/org/chromium/policy/PolicyProvider.java b/components/policy/android/java/src/org/chromium/policy/PolicyProvider.java
new file mode 100644
index 0000000..4375d24
--- /dev/null
+++ b/components/policy/android/java/src/org/chromium/policy/PolicyProvider.java
@@ -0,0 +1,59 @@
+// Copyright 2015 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.policy;
+
+import android.content.Context;
+import android.os.Bundle;
+
+/**
+ * Base class for Policy providers.
+ */
+public abstract class PolicyProvider {
+ private CombinedPolicyProvider mCombinedPolicyProvider;
+ protected final Context mContext;
+ private int mSource = -1;
+
+ protected PolicyProvider(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ protected void notifySettingsAvailable(Bundle settings) {
+ mCombinedPolicyProvider.onSettingsAvailable(mSource, settings);
+ }
+
+ protected void terminateIncognitoSession() {
+ mCombinedPolicyProvider.terminateIncognitoSession();
+ }
+
+ /**
+ * Called to request a refreshed set of policies. This method must handle notifying the
+ * CombinedPolicyProvider whenever applicable.
+ */
+ public abstract void refresh();
+
+ /**
+ * Register the PolicyProvider for receiving policy changes.
+ */
+ protected void startListeningForPolicyChanges() {}
+
+ /**
+ * Called by the {@link CombinedPolicyProvider} to correctly hook it with the Policy system.
+ *
+ * @param combinedPolicyProvider reference to the CombinedPolicyProvider to be used like a
+ * delegate.
+ * @param source tags the PolicyProvider with a source.
+ */
+ final void setManagerAndSource(CombinedPolicyProvider combinedPolicyProvider, int source) {
+ assert mSource < 0;
+ assert source >= 0;
+ mSource = source;
+ assert mCombinedPolicyProvider == null;
+ mCombinedPolicyProvider = combinedPolicyProvider;
+ startListeningForPolicyChanges();
+ }
+
+ /** Called when the provider is unregistered */
+ public void destroy() {}
+}
diff --git a/components/policy/android/junit/src/org/chromium/policy/CombinedPolicyProviderTest.java b/components/policy/android/junit/src/org/chromium/policy/CombinedPolicyProviderTest.java
new file mode 100644
index 0000000..6d510a0
--- /dev/null
+++ b/components/policy/android/junit/src/org/chromium/policy/CombinedPolicyProviderTest.java
@@ -0,0 +1,189 @@
+// Copyright 2015 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.policy;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.os.Bundle;
+
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+
+/**
+ * Robolectric tests for CombinedPolicyProvider
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class CombinedPolicyProviderTest {
+ private PolicyConverter mPolicyConverter;
+
+ @Before
+ public void setup() {
+ // Stub out the native calls
+ CombinedPolicyProvider provider = spy(new CombinedPolicyProvider());
+ mPolicyConverter = mock(PolicyConverter.class);
+ doNothing().when(mPolicyConverter).setPolicy(anyString(), any());
+ doNothing().when(provider).nativeFlushPolicies(anyLong());
+ CombinedPolicyProvider.set(provider);
+ }
+
+ /**
+ * Dummy concrete class. Needed because PolicyProvider has final functions that cannot be
+ * stubbed and is abstract so can't be directly instantiated to be spied upon.
+ */
+ class DummyPolicyProvider extends PolicyProvider {
+ public DummyPolicyProvider() {
+ super(Robolectric.application);
+ }
+
+ @Override
+ public void refresh() {
+ // Do nothing
+ }
+ }
+
+ @Test
+ public void testRegisterProvider() {
+ // Have to spy not mock here so that the real constructor gets called, hence avoiding
+ // an assert in PolicyProvider.setManagerAndSource.
+ PolicyProvider provider = spy(new DummyPolicyProvider());
+ CombinedPolicyProvider.get().registerProvider(provider);
+ // Can't verify PolicyProvider.setManagerAndSource directly because it is final.
+ // This, at least, demonstrates that it has been called.
+ verify(provider).startListeningForPolicyChanges();
+ verify(provider, never()).refresh();
+ assertEquals(CombinedPolicyProvider.get(),
+ CombinedPolicyProvider.linkNative(1234, mPolicyConverter));
+ verify(provider).refresh();
+ PolicyProvider provider2 = spy(new DummyPolicyProvider());
+ CombinedPolicyProvider.get().registerProvider(provider2);
+ verify(provider2).startListeningForPolicyChanges();
+ verify(provider2).refresh();
+ }
+
+ @Test
+ public void testOnSettingsAvailable_noNative() {
+ // No native policy manager
+ PolicyProvider provider = new DummyPolicyProvider();
+ CombinedPolicyProvider.get().registerProvider(provider);
+ Bundle b = new Bundle();
+ b.putBoolean("BoolPolicy", true);
+ CombinedPolicyProvider.get().onSettingsAvailable(0, b);
+ verify(mPolicyConverter, never()).setPolicy(anyString(), any());
+ verify(CombinedPolicyProvider.get(), never()).nativeFlushPolicies(anyInt());
+ }
+
+ @Test
+ public void testOnSettingsAvailable_oneProvider() {
+ CombinedPolicyProvider.linkNative(1234, mPolicyConverter);
+ PolicyProvider provider = new DummyPolicyProvider();
+ CombinedPolicyProvider.get().registerProvider(provider);
+ Bundle b = new Bundle();
+ b.putBoolean("BoolPolicy", false);
+ b.putInt("IntPolicy", 42);
+ b.putString("StringPolicy", "A string");
+ b.putStringArray("StringArrayPolicy", new String[] {"String1", "String2"});
+ CombinedPolicyProvider.get().onSettingsAvailable(0, b);
+ verify(mPolicyConverter).setPolicy("BoolPolicy", false);
+ verify(mPolicyConverter).setPolicy("IntPolicy", 42);
+ verify(mPolicyConverter).setPolicy("StringPolicy", "A string");
+ verify(mPolicyConverter)
+ .setPolicy("StringArrayPolicy", new String[] {"String1", "String2"});
+ verify(CombinedPolicyProvider.get()).nativeFlushPolicies(1234);
+ }
+
+ @Test
+ public void testOnSettingsAvailable_secondProvider() {
+ CombinedPolicyProvider.linkNative(1234, mPolicyConverter);
+ PolicyProvider provider = new DummyPolicyProvider();
+ CombinedPolicyProvider.get().registerProvider(provider);
+ Bundle b = new Bundle();
+ CombinedPolicyProvider.get().onSettingsAvailable(0, b);
+ verify(CombinedPolicyProvider.get()).nativeFlushPolicies(1234);
+
+ // Second policy provider registered but no settings.
+ PolicyProvider provider2 = new DummyPolicyProvider();
+ CombinedPolicyProvider.get().registerProvider(provider2);
+ b = new Bundle();
+ b.putBoolean("BoolPolicy", true);
+ CombinedPolicyProvider.get().onSettingsAvailable(0, b);
+
+ // Second call should have been ignored, so nothing should have been set
+ verify(mPolicyConverter, never()).setPolicy(anyString(), anyBoolean());
+ // and flush should have been called precisely once.
+ verify(CombinedPolicyProvider.get()).nativeFlushPolicies(1234);
+
+ // Empty but valid bundle from second policy provider should set the policy and push it
+ // to the native code
+ b = new Bundle();
+ CombinedPolicyProvider.get().onSettingsAvailable(1, b);
+ verify(mPolicyConverter).setPolicy("BoolPolicy", true);
+ verify(CombinedPolicyProvider.get(), times(2)).nativeFlushPolicies(1234);
+ }
+
+ @Test
+ public void testRefreshPolicies() {
+ CombinedPolicyProvider.linkNative(1234, mPolicyConverter);
+ PolicyProvider provider = new DummyPolicyProvider();
+ PolicyProvider provider2 = new DummyPolicyProvider();
+ CombinedPolicyProvider.get().registerProvider(provider);
+ CombinedPolicyProvider.get().registerProvider(provider2);
+ Bundle b = new Bundle();
+ b.putBoolean("BoolPolicy", true);
+ CombinedPolicyProvider.get().onSettingsAvailable(0, b);
+ CombinedPolicyProvider.get().onSettingsAvailable(1, b);
+ verify(CombinedPolicyProvider.get(), times(1)).nativeFlushPolicies(1234);
+
+ CombinedPolicyProvider.get().refreshPolicies();
+ // This should have cleared the cached policies, so onSettingsAvailable should now do
+ // nothing until both providers have settings.
+ CombinedPolicyProvider.get().onSettingsAvailable(0, b);
+ // Still only one call.
+ verify(CombinedPolicyProvider.get(), times(1)).nativeFlushPolicies(1234);
+ b = new Bundle();
+ b.putBoolean("BoolPolicy", false);
+ CombinedPolicyProvider.get().onSettingsAvailable(1, b);
+ // That should have caused the second flush.
+ verify(CombinedPolicyProvider.get(), times(2)).nativeFlushPolicies(1234);
+ // And the policy should have been set to the new value.
+ verify(mPolicyConverter).setPolicy("BoolPolicy", false);
+ }
+
+ @Test
+ public void testTerminateIncognitoSession() {
+ CombinedPolicyProvider.PolicyChangeListener l =
+ mock(CombinedPolicyProvider.PolicyChangeListener.class);
+ CombinedPolicyProvider.get().addPolicyChangeListener(l);
+ CombinedPolicyProvider.get().terminateIncognitoSession();
+ verify(l).terminateIncognitoSession();
+ CombinedPolicyProvider.get().removePolicyChangeListener(l);
+ CombinedPolicyProvider.get().terminateIncognitoSession();
+ // Should still have only called the listener once
+ verify(l).terminateIncognitoSession();
+ }
+
+ @Test
+ public void testDestroy() {
+ PolicyProvider provider = spy(new DummyPolicyProvider());
+ CombinedPolicyProvider.get().registerProvider(provider);
+ CombinedPolicyProvider.get().destroy();
+ verify(provider).destroy();
+ }
+}
diff --git a/components/policy/core/browser/BUILD.gn b/components/policy/core/browser/BUILD.gn
index 89cd82c..03340d3 100644
--- a/components/policy/core/browser/BUILD.gn
+++ b/components/policy/core/browser/BUILD.gn
@@ -30,6 +30,18 @@ source_set("browser") {
"//ui/base",
]
+ if (is_android) {
+ sources += [
+ "android/android_combined_policy_provider.cc",
+ "android/android_combined_policy_provider.h",
+ "android/component_jni_registrar.cc",
+ "android/component_jni_registrar.h",
+ "android/policy_converter.cc",
+ "android/policy_converter.h",
+ ]
+ deps += [ "//components/policy/android:jni_headers" ]
+ }
+
if (enable_configuration_policy) {
sources += [
"autofill_policy_handler.cc",
@@ -60,15 +72,5 @@ source_set("browser") {
"//components/policy/proto",
"//third_party/icu",
]
-
- if (is_android) {
- sources += [
- "android/component_jni_registrar.cc",
- "android/component_jni_registrar.h",
- "android/policy_converter.cc",
- "android/policy_converter.h",
- ]
- deps += [ "//components/policy/android:jni_headers" ]
- }
}
}
diff --git a/components/policy/core/browser/android/android_combined_policy_provider.cc b/components/policy/core/browser/android/android_combined_policy_provider.cc
new file mode 100644
index 0000000..c66f5ac
--- /dev/null
+++ b/components/policy/core/browser/android/android_combined_policy_provider.cc
@@ -0,0 +1,66 @@
+// Copyright 2015 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.
+
+#include "components/policy/core/browser/android/android_combined_policy_provider.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "components/policy/core/browser/android/policy_converter.h"
+#include "jni/CombinedPolicyProvider_jni.h"
+
+using base::android::AttachCurrentThread;
+
+namespace {
+
+bool g_wait_for_policies = false;
+
+} // namespace
+
+namespace policy {
+namespace android {
+
+AndroidCombinedPolicyProvider::AndroidCombinedPolicyProvider(
+ SchemaRegistry* registry)
+ : initialized_(!g_wait_for_policies) {
+ PolicyNamespace ns(POLICY_DOMAIN_CHROME, std::string());
+ const Schema* schema = registry->schema_map()->GetSchema(ns);
+ policy_converter_.reset(new policy::android::PolicyConverter(schema));
+ java_combined_policy_provider_.Reset(Java_CombinedPolicyProvider_linkNative(
+ AttachCurrentThread(), reinterpret_cast<intptr_t>(this),
+ policy_converter_->GetJavaObject().obj()));
+}
+
+AndroidCombinedPolicyProvider::~AndroidCombinedPolicyProvider() {
+ Java_CombinedPolicyProvider_linkNative(AttachCurrentThread(), 0, jobject());
+ java_combined_policy_provider_.Reset();
+}
+
+void AndroidCombinedPolicyProvider::RefreshPolicies() {
+ JNIEnv* env = AttachCurrentThread();
+ Java_CombinedPolicyProvider_refreshPolicies(
+ env, java_combined_policy_provider_.obj());
+}
+
+void AndroidCombinedPolicyProvider::FlushPolicies(JNIEnv* env, jobject obj) {
+ initialized_ = true;
+ UpdatePolicy(policy_converter_->GetPolicyBundle().Pass());
+}
+
+// static
+void AndroidCombinedPolicyProvider::SetShouldWaitForPolicy(
+ bool should_wait_for_policy) {
+ g_wait_for_policies = should_wait_for_policy;
+}
+
+bool AndroidCombinedPolicyProvider::IsInitializationComplete(
+ PolicyDomain domain) const {
+ return initialized_;
+}
+
+bool AndroidCombinedPolicyProvider::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace android
+} // namespace policy
diff --git a/components/policy/core/browser/android/android_combined_policy_provider.h b/components/policy/core/browser/android/android_combined_policy_provider.h
new file mode 100644
index 0000000..985d542
--- /dev/null
+++ b/components/policy/core/browser/android/android_combined_policy_provider.h
@@ -0,0 +1,67 @@
+// Copyright 2015 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.
+
+#ifndef COMPONENTS_POLICY_CORE_BROWSER_ANDROID_ANDROID_COMBINED_POLICY_PROVIDER_H_
+#define COMPONENTS_POLICY_CORE_BROWSER_ANDROID_ANDROID_COMBINED_POLICY_PROVIDER_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "components/policy/core/common/configuration_policy_provider.h"
+#include "components/policy/core/common/policy_bundle.h"
+#include "components/policy/policy_export.h"
+
+namespace policy {
+
+class SchemaRegistry;
+
+namespace android {
+
+class PolicyConverter;
+
+class POLICY_EXPORT AndroidCombinedPolicyProvider
+ : public ConfigurationPolicyProvider {
+ public:
+ explicit AndroidCombinedPolicyProvider(SchemaRegistry* registry);
+
+ ~AndroidCombinedPolicyProvider() override;
+
+ // Push the polices updated by the Java policy providers to the core policy
+ // system
+ void FlushPolicies(JNIEnv* env, jobject obj);
+
+ // Call this method to tell the policy system whether it should wait for
+ // policies to be loaded by this provider. If this method is called,
+ // IsInitializationComplete() will only return true after SetPolicies() has
+ // been called at least once, otherwise it will return true immediately.
+ static void SetShouldWaitForPolicy(bool should_wait_for_policy);
+
+ // ConfigurationPolicyProvider:
+ bool IsInitializationComplete(PolicyDomain domain) const override;
+ void RefreshPolicies() override;
+
+ // For testing
+ PolicyConverter* GetPolicyConverterForTesting() {
+ return policy_converter_.get();
+ }
+
+ // Register the JNI methods
+ static bool Register(JNIEnv* env);
+
+ private:
+ bool initialized_;
+ scoped_ptr<policy::android::PolicyConverter> policy_converter_;
+ base::android::ScopedJavaGlobalRef<jobject> java_combined_policy_provider_;
+
+
+ DISALLOW_COPY_AND_ASSIGN(AndroidCombinedPolicyProvider);
+};
+
+} // namespace android
+
+} // namespace policy
+
+#endif // COMPONENTS_POLICY_CORE_BROWSER_ANDROID_ANDROID_COMBINED_POLICY_PROVIDER_H_
diff --git a/components/policy/core/browser/android/android_combined_policy_provider_unittest.cc b/components/policy/core/browser/android/android_combined_policy_provider_unittest.cc
new file mode 100644
index 0000000..b860f2b
--- /dev/null
+++ b/components/policy/core/browser/android/android_combined_policy_provider_unittest.cc
@@ -0,0 +1,92 @@
+// Copyright 2015 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.
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/values.h"
+#include "components/policy/core/browser/android/android_combined_policy_provider.h"
+#include "components/policy/core/browser/android/policy_converter.h"
+#include "components/policy/core/common/policy_bundle.h"
+#include "components/policy/core/common/schema.h"
+#include "components/policy/core/common/schema_registry.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::android::ConvertUTF8ToJavaString;
+using base::android::AttachCurrentThread;
+using base::android::ScopedJavaLocalRef;
+
+namespace policy {
+
+namespace android {
+class AndroidCombinedPolicyProviderTest : public ::testing::Test {
+ void TearDown() override;
+};
+
+void AndroidCombinedPolicyProviderTest::TearDown() {
+ AndroidCombinedPolicyProvider::SetShouldWaitForPolicy(false);
+}
+
+TEST_F(AndroidCombinedPolicyProviderTest, InitializationCompleted) {
+ SchemaRegistry registry;
+ AndroidCombinedPolicyProvider manager(&registry);
+ EXPECT_TRUE(manager.IsInitializationComplete(POLICY_DOMAIN_CHROME));
+ // If the manager is deleted (by going out of scope) without being shutdown
+ // first it DCHECKs.
+ manager.Shutdown();
+}
+
+TEST_F(AndroidCombinedPolicyProviderTest, SetShouldWaitForPolicy) {
+ AndroidCombinedPolicyProvider::SetShouldWaitForPolicy(true);
+ SchemaRegistry registry;
+ AndroidCombinedPolicyProvider manager(&registry);
+ EXPECT_FALSE(manager.IsInitializationComplete(POLICY_DOMAIN_CHROME));
+ manager.FlushPolicies(nullptr, nullptr);
+ EXPECT_TRUE(manager.IsInitializationComplete(POLICY_DOMAIN_CHROME));
+ // If the manager is deleted (by going out of scope) without being shutdown
+ // first it DCHECKs.
+ manager.Shutdown();
+}
+
+TEST_F(AndroidCombinedPolicyProviderTest, FlushPolices) {
+ const char kSchemaTemplate[] =
+ "{"
+ " \"type\": \"object\","
+ " \"properties\": {"
+ " }"
+ "}";
+
+ PolicyNamespace ns(POLICY_DOMAIN_CHROME, std::string());
+ std::string error;
+ Schema schema = Schema::Parse(kSchemaTemplate, &error);
+ SchemaRegistry registry;
+ registry.RegisterComponent(ns, schema);
+ AndroidCombinedPolicyProvider manager(&registry);
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> jpolicy =
+ ConvertUTF8ToJavaString(env, "TestPolicy");
+ ScopedJavaLocalRef<jstring> jvalue =
+ ConvertUTF8ToJavaString(env, "TestValue");
+ manager.GetPolicyConverterForTesting()->SetPolicyString(env, nullptr,
+ jpolicy.obj(),
+ jvalue.obj());
+ manager.FlushPolicies(env, nullptr);
+ const PolicyBundle& bundle = manager.policies();
+ const PolicyMap& map = bundle.Get(ns);
+ const base::Value* value = map.GetValue("TestPolicy");
+ ASSERT_NE(nullptr, value);
+ EXPECT_EQ(base::Value::TYPE_STRING, value->GetType());
+ std::string out_value;
+ EXPECT_TRUE(value->GetAsString(&out_value));
+ EXPECT_EQ("TestValue", out_value);
+ // If the manager is deleted (by going out of scope) without being shutdown
+ // first it DCHECKs.
+ manager.Shutdown();
+}
+
+} // namespace android
+
+} // namespace policy
diff --git a/components/policy/core/browser/android/component_jni_registrar.cc b/components/policy/core/browser/android/component_jni_registrar.cc
index 985bcce..76c4c4d 100644
--- a/components/policy/core/browser/android/component_jni_registrar.cc
+++ b/components/policy/core/browser/android/component_jni_registrar.cc
@@ -7,6 +7,7 @@
#include "base/android/jni_android.h"
#include "base/android/jni_registrar.h"
#include "base/basictypes.h"
+#include "components/policy/core/browser/android/android_combined_policy_provider.h"
#include "components/policy/core/browser/android/policy_converter.h"
namespace policy {
@@ -14,6 +15,7 @@ namespace android {
static base::android::RegistrationMethod kPolicyRegisteredMethods[] = {
{"PolicyConverter", PolicyConverter::Register},
+ {"AndroidCombinedPolicyProvider", AndroidCombinedPolicyProvider::Register},
};
bool RegisterPolicy(JNIEnv* env) {
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn
index 130f583..dc931e6 100644
--- a/components/policy/core/common/BUILD.gn
+++ b/components/policy/core/common/BUILD.gn
@@ -92,9 +92,6 @@ source_set("common") {
"policy_namespace.h",
"policy_pref_names.cc",
"policy_pref_names.h",
- "policy_provider_android.cc",
- "policy_provider_android.h",
- "policy_provider_android_delegate.h",
"policy_service.cc",
"policy_service.h",
"policy_service_impl.cc",
diff --git a/components/policy/core/common/policy_provider_android.cc b/components/policy/core/common/policy_provider_android.cc
deleted file mode 100644
index d307661..0000000
--- a/components/policy/core/common/policy_provider_android.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2014 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.
-
-#include "components/policy/core/common/policy_provider_android.h"
-#include "components/policy/core/common/policy_provider_android_delegate.h"
-
-namespace policy {
-
-namespace {
-
-bool g_wait_for_policies = false;
-
-} // namespace
-
-PolicyProviderAndroid::PolicyProviderAndroid()
- : delegate_(NULL),
- initialized_(!g_wait_for_policies) {}
-
-PolicyProviderAndroid::~PolicyProviderAndroid() {}
-
-const Schema* PolicyProviderAndroid::GetChromeSchema() const {
- PolicyNamespace ns(POLICY_DOMAIN_CHROME, std::string());
- return schema_map()->GetSchema(ns);
-}
-
-// static
-void PolicyProviderAndroid::SetShouldWaitForPolicy(
- bool should_wait_for_policy) {
- g_wait_for_policies = should_wait_for_policy;
-}
-
-void PolicyProviderAndroid::SetDelegate(
- PolicyProviderAndroidDelegate* delegate) {
- DCHECK(!delegate || !delegate_);
- delegate_ = delegate;
-}
-
-void PolicyProviderAndroid::SetPolicies(scoped_ptr<PolicyBundle> policy) {
- initialized_ = true;
- UpdatePolicy(policy.Pass());
-}
-
-void PolicyProviderAndroid::Shutdown() {
- if (delegate_)
- delegate_->PolicyProviderShutdown();
-
- ConfigurationPolicyProvider::Shutdown();
-}
-
-bool PolicyProviderAndroid::IsInitializationComplete(
- PolicyDomain domain) const {
- return initialized_;
-}
-
-void PolicyProviderAndroid::RefreshPolicies() {
- if (delegate_) {
- delegate_->RefreshPolicies();
- } else {
- // If we don't have a delegate, pass a copy of the current policies.
- scoped_ptr<PolicyBundle> bundle(new PolicyBundle());
- bundle->CopyFrom(policies());
- UpdatePolicy(bundle.Pass());
- }
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_provider_android.h b/components/policy/core/common/policy_provider_android.h
deleted file mode 100644
index 76bc515..0000000
--- a/components/policy/core/common/policy_provider_android.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_PROVIDER_ANDROID_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_PROVIDER_ANDROID_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "components/policy/core/common/configuration_policy_provider.h"
-
-namespace policy {
-
-class PolicyProviderAndroidDelegate;
-class Schema;
-
-// Provider for policies set by the Android platform.
-class POLICY_EXPORT PolicyProviderAndroid : public ConfigurationPolicyProvider {
- public:
- PolicyProviderAndroid();
- ~PolicyProviderAndroid() override;
-
- // Call this method to tell the policy system whether it should wait for
- // policies to be loaded by this provider. If this method is called,
- // IsInitializationComplete() will only return true after SetPolicies() has
- // been called at least once, otherwise it will return true immediately.
- static void SetShouldWaitForPolicy(bool should_wait_for_policy);
-
- // Returns the schema for Chrome policies.
- const Schema* GetChromeSchema() const;
-
- void SetDelegate(PolicyProviderAndroidDelegate* delegate);
- void SetPolicies(scoped_ptr<PolicyBundle> policy);
-
- // ConfigurationPolicyProvider:
- void Shutdown() override;
- bool IsInitializationComplete(PolicyDomain domain) const override;
- void RefreshPolicies() override;
-
- private:
- PolicyProviderAndroidDelegate* delegate_;
- bool initialized_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyProviderAndroid);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_PROVIDER_ANDROID_H_
diff --git a/components/policy/core/common/policy_provider_android_delegate.h b/components/policy/core/common/policy_provider_android_delegate.h
deleted file mode 100644
index e5116f04..0000000
--- a/components/policy/core/common/policy_provider_android_delegate.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_PROVIDER_ANDROID_DELEGATE_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_PROVIDER_ANDROID_DELEGATE_H_
-
-#include "base/compiler_specific.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// A delegate for the Android policy provider. This class is responsible for
-// setting policies on the PolicyProviderAndroid and refreshing them on demand.
-class POLICY_EXPORT PolicyProviderAndroidDelegate {
- public:
- // Called to refresh policies. If this method is called, the delegate must
- // eventually call SetPolicies on the provider.
- virtual void RefreshPolicies() = 0;
-
- // Called before the provider is destroyed.
- virtual void PolicyProviderShutdown() = 0;
-
- protected:
- virtual ~PolicyProviderAndroidDelegate() {}
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_PROVIDER_ANDROID_DELEGATE_H_
diff --git a/components/policy/core/common/policy_provider_android_unittest.cc b/components/policy/core/common/policy_provider_android_unittest.cc
deleted file mode 100644
index 12844f3..0000000
--- a/components/policy/core/common/policy_provider_android_unittest.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2014 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.
-
-#include "base/memory/scoped_ptr.h"
-#include "components/policy/core/common/policy_provider_android.h"
-#include "components/policy/core/common/policy_provider_android_delegate.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-namespace {
-
-// Helper to write a policy in |bundle| with less code.
-void SetPolicy(PolicyBundle* bundle,
- const std::string& name,
- const std::string& value) {
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .Set(name,
- POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER,
- new base::StringValue(value),
- NULL);
-}
-
-class MockPolicyProviderAndroidDelegate : public PolicyProviderAndroidDelegate {
- public:
- MockPolicyProviderAndroidDelegate() {}
- virtual ~MockPolicyProviderAndroidDelegate() {}
-
- MOCK_METHOD0(RefreshPolicies, void());
- MOCK_METHOD0(PolicyProviderShutdown, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockPolicyProviderAndroidDelegate);
-};
-
-// Test fixture that makes sure that we always call Shutdown() before destroying
-// the policy provider. Allocate this just like a PolicyProviderAndroid and use
-// Get() to get the policy provider.
-class PolicyProviderAndroidTestFixture {
- public:
- PolicyProviderAndroidTestFixture() {}
- ~PolicyProviderAndroidTestFixture() {
- provider_.Shutdown();
- }
-
- PolicyProviderAndroid* Get() {
- return &provider_;
- }
-
- private:
- PolicyProviderAndroid provider_;
- DISALLOW_COPY_AND_ASSIGN(PolicyProviderAndroidTestFixture);
-};
-
-} // namespace
-
-class PolicyProviderAndroidTest : public ::testing::Test {
- protected:
- PolicyProviderAndroidTest();
- ~PolicyProviderAndroidTest() override;
-
- void SetUp() override;
- void TearDown() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PolicyProviderAndroidTest);
-};
-
-PolicyProviderAndroidTest::PolicyProviderAndroidTest() {}
-PolicyProviderAndroidTest::~PolicyProviderAndroidTest() {}
-
-void PolicyProviderAndroidTest::SetUp() {}
-
-void PolicyProviderAndroidTest::TearDown() {
- PolicyProviderAndroid::SetShouldWaitForPolicy(false);
-}
-
-TEST_F(PolicyProviderAndroidTest, InitializationCompleted) {
- PolicyProviderAndroidTestFixture provider;
- EXPECT_TRUE(provider.Get()->IsInitializationComplete(POLICY_DOMAIN_CHROME));
-
- const PolicyBundle kEmptyBundle;
- EXPECT_TRUE(provider.Get()->policies().Equals(kEmptyBundle));
-}
-
-TEST_F(PolicyProviderAndroidTest, WaitForInitialization) {
- PolicyProviderAndroid::SetShouldWaitForPolicy(true);
- PolicyProviderAndroidTestFixture provider;
- EXPECT_FALSE(provider.Get()->IsInitializationComplete(POLICY_DOMAIN_CHROME));
-
- scoped_ptr<PolicyBundle> policy_bundle(new PolicyBundle);
- SetPolicy(policy_bundle.get(), "key", "value");
- PolicyBundle expected_policy_bundle;
- expected_policy_bundle.CopyFrom(*policy_bundle);
- provider.Get()->SetPolicies(policy_bundle.Pass());
- EXPECT_TRUE(provider.Get()->IsInitializationComplete(POLICY_DOMAIN_CHROME));
- EXPECT_TRUE(provider.Get()->policies().Equals(expected_policy_bundle));
-}
-
-TEST_F(PolicyProviderAndroidTest, RefreshPolicies) {
- MockPolicyProviderAndroidDelegate delegate;
- PolicyProviderAndroidTestFixture provider;
-
- provider.Get()->SetDelegate(&delegate);
-
- scoped_ptr<PolicyBundle> policy_bundle(new PolicyBundle);
- SetPolicy(policy_bundle.get(), "key", "old_value");
- PolicyBundle expected_policy_bundle;
- expected_policy_bundle.CopyFrom(*policy_bundle);
- provider.Get()->SetPolicies(policy_bundle.Pass());
- EXPECT_TRUE(provider.Get()->policies().Equals(expected_policy_bundle));
-
- EXPECT_CALL(delegate, RefreshPolicies()).Times(1);
- provider.Get()->RefreshPolicies();
-
- policy_bundle.reset(new PolicyBundle);
- SetPolicy(policy_bundle.get(), "key", "new_value");
- expected_policy_bundle.CopyFrom(*policy_bundle);
- provider.Get()->SetPolicies(policy_bundle.Pass());
- EXPECT_TRUE(provider.Get()->policies().Equals(expected_policy_bundle));
-
- EXPECT_CALL(delegate, PolicyProviderShutdown()).Times(1);
-}
-
-} // namespace policy
diff --git a/components/policy/policy_browser.gypi b/components/policy/policy_browser.gypi
index 17511d0..8f6ddb3 100644
--- a/components/policy/policy_browser.gypi
+++ b/components/policy/policy_browser.gypi
@@ -66,6 +66,8 @@
'conditions': [
['OS=="android"', {
'sources': [
+ 'core/browser/android/android_combined_policy_provider.cc',
+ 'core/browser/android/android_combined_policy_provider.h',
'core/browser/android/component_jni_registrar.cc',
'core/browser/android/component_jni_registrar.h',
'core/browser/android/policy_converter.cc',
diff --git a/components/policy/policy_common.gypi b/components/policy/policy_common.gypi
index a1b570e..d2468ba 100644
--- a/components/policy/policy_common.gypi
+++ b/components/policy/policy_common.gypi
@@ -107,9 +107,6 @@
'core/common/policy_namespace.h',
'core/common/policy_pref_names.cc',
'core/common/policy_pref_names.h',
- 'core/common/policy_provider_android.cc',
- 'core/common/policy_provider_android.h',
- 'core/common/policy_provider_android_delegate.h',
'core/common/policy_service.cc',
'core/common/policy_service.h',
'core/common/policy_service_impl.cc',
diff --git a/components/test/DEPS b/components/test/DEPS
index 265c5f7..d36f58a 100644
--- a/components/test/DEPS
+++ b/components/test/DEPS
@@ -2,6 +2,7 @@ include_rules = [
# To initialize the global data of content_settings.
"+components/content_settings/core/common",
"+components/invalidation/impl/android/component_jni_registrar.h",
+ "+components/policy/core/browser/android/component_jni_registrar.h",
"+components/safe_json/android/component_jni_registrar.h",
"+content/public/android/java/src/org/chromium/content/browser",
"+content/public/app/content_jni_onload.h",
diff --git a/components/test/run_all_unittests.cc b/components/test/run_all_unittests.cc
index fd327a1..4c29924 100644
--- a/components/test/run_all_unittests.cc
+++ b/components/test/run_all_unittests.cc
@@ -23,6 +23,7 @@
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
#include "components/invalidation/impl/android/component_jni_registrar.h"
+#include "components/policy/core/browser/android/component_jni_registrar.h"
#include "components/safe_json/android/component_jni_registrar.h"
#include "ui/base/android/ui_base_jni_registrar.h"
#include "ui/gfx/android/gfx_jni_registrar.h"
@@ -52,6 +53,7 @@ class ComponentsTestSuite : public base::TestSuite {
ASSERT_TRUE(gfx::android::RegisterJni(env));
ASSERT_TRUE(ui::android::RegisterJni(env));
ASSERT_TRUE(invalidation::android::RegisterInvalidationJni(env));
+ ASSERT_TRUE(policy::android::RegisterPolicy(env));
ASSERT_TRUE(safe_json::android::RegisterSafeJsonJni(env));
#endif
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index f7a606b..6b96f77 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -8145,6 +8145,21 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</summary>
</histogram>
+<histogram name="Enterprise.AppRestrictionLoadTime" units="milliseconds">
+ <owner>aberent@chromium.org</owner>
+ <summary>
+ Android Only - Time to load the App Restrictions from the O.S..
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.AppRestrictionsCacheLoad" enum="BooleanSuccess">
+ <owner>aberent@chromium.org</owner>
+ <summary>
+ Android Only - Whether Chrome was able to read and decode the
+ AppRestrictions policy cache on startup.
+ </summary>
+</histogram>
+
<histogram name="Enterprise.AttributesTPMConsistency"
enum="EnterpriseAttributesTPMConsistencyType">
<owner>tnagel@chromium.org</owner>