summaryrefslogtreecommitdiffstats
path: root/components
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 /components
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}
Diffstat (limited to 'components')
-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
22 files changed, 759 insertions, 332 deletions
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