summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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>