Index: chrome/android/java/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProvider.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProvider.java |
index 04f5e112ba82a5857377d6871df69ea80f56b021..88bd0ea071e86442d5127e0046fa7e6618d9c795 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProvider.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProvider.java |
@@ -14,13 +14,18 @@ import android.os.Bundle; |
import android.os.SystemClock; |
import android.os.UserManager; |
+import org.chromium.base.Callback; |
import org.chromium.base.ThreadUtils; |
import org.chromium.base.VisibleForTesting; |
import org.chromium.base.annotations.CalledByNative; |
import org.chromium.base.library_loader.LibraryLoader; |
import org.chromium.base.library_loader.ProcessInitException; |
import org.chromium.base.metrics.RecordHistogram; |
+import org.chromium.chrome.browser.childaccounts.ChildAccountService; |
+import org.chromium.chrome.browser.firstrun.ForcedSigninProcessor; |
import org.chromium.chrome.browser.init.ChromeBrowserInitializer; |
+import org.chromium.components.signin.ChromeSigninController; |
+import org.chromium.components.supervisedusererrorpage.FilteringBehaviorReason; |
import org.chromium.components.webrestrictions.browser.WebRestrictionsContentProvider; |
import java.util.concurrent.ArrayBlockingQueue; |
@@ -36,24 +41,78 @@ public class SupervisedUserContentProvider extends WebRestrictionsContentProvide |
private long mNativeSupervisedUserContentProvider; |
private boolean mChromeAlreadyStarted; |
private static Object sEnabledLock = new Object(); |
+ private static Object sContentProviderLock = new Object(); |
+ |
+ private static final String TAG = "SupervisedUserContent"; |
// Three value "boolean" caching enabled state, null if not yet known. |
private static Boolean sEnabled; |
- private long getSupervisedUserContentProvider() throws ProcessInitException { |
- mChromeAlreadyStarted = LibraryLoader.isInitialized(); |
- if (mNativeSupervisedUserContentProvider != 0) { |
- return mNativeSupervisedUserContentProvider; |
- } |
- |
- ChromeBrowserInitializer.getInstance(getContext()).handleSynchronousStartup(); |
+ @VisibleForTesting |
+ void startForcedSigninProcessor(Context appContext, Runnable onComplete) { |
+ ForcedSigninProcessor.start(appContext, onComplete); |
+ } |
- mNativeSupervisedUserContentProvider = nativeCreateSupervisedUserContentProvider(); |
- return mNativeSupervisedUserContentProvider; |
+ @VisibleForTesting |
+ void listenForChildAccountStatusChange(Callback<Boolean> callback) { |
+ ChildAccountService.listenForStatusChange(callback); |
} |
- void setNativeSupervisedUserContentProviderForTesting(long nativeProvider) { |
- mNativeSupervisedUserContentProvider = nativeProvider; |
+ private long getSupervisedUserContentProvider() { |
+ // This may lock for some time, but is always called on a background thread, and will only |
+ // take significant time if the Chrome process isn't already running. |
+ synchronized (sContentProviderLock) { |
+ mChromeAlreadyStarted = LibraryLoader.isInitialized(); |
+ if (mNativeSupervisedUserContentProvider != 0) { |
+ return mNativeSupervisedUserContentProvider; |
+ } |
+ final Context appContext = getContext().getApplicationContext(); |
+ final SupervisedUserReply<Long> reply = new SupervisedUserReply<>(); |
+ ThreadUtils.runOnUiThread(new Runnable() { |
+ @Override |
+ public void run() { |
+ try { |
+ ChromeBrowserInitializer.getInstance(appContext).handleSynchronousStartup(); |
+ } catch (ProcessInitException e) { |
+ reply.onQueryFinished(0L); |
+ return; |
+ } |
+ final ChromeSigninController chromeSigninController = |
+ ChromeSigninController.get(appContext); |
+ if (chromeSigninController.isSignedIn()) { |
+ reply.onQueryFinished(nativeCreateSupervisedUserContentProvider()); |
+ return; |
+ } |
+ // Try to sign in, Chrome needs to be signed in to get the URL filter. |
+ startForcedSigninProcessor(appContext, new Runnable() { |
+ @Override |
+ public void run() { |
+ if (!chromeSigninController.isSignedIn()) { |
+ reply.onQueryFinished(0L); |
+ return; |
+ } |
+ // Wait for the status change; Chrome can't check any URLs until this |
+ // has happened. |
+ listenForChildAccountStatusChange(new Callback<Boolean>() { |
+ @Override |
+ public void onResult(Boolean result) { |
+ reply.onQueryFinished( |
+ nativeCreateSupervisedUserContentProvider()); |
+ } |
+ }); |
+ } |
+ }); |
+ } |
+ }); |
+ try { |
+ Long result = reply.getResult(); |
+ if (result == null) return 0; |
+ mNativeSupervisedUserContentProvider = result; |
+ return mNativeSupervisedUserContentProvider; |
+ } catch (InterruptedException e) { |
+ return 0; |
+ } |
+ } |
} |
static class SupervisedUserReply<T> { |
@@ -109,14 +168,15 @@ public class SupervisedUserContentProvider extends WebRestrictionsContentProvide |
// object also handles waiting for the reply. |
long startTimeMs = SystemClock.elapsedRealtime(); |
final SupervisedUserQueryReply queryReply = new SupervisedUserQueryReply(); |
+ final long contentProvider = getSupervisedUserContentProvider(); |
+ if (contentProvider == 0) { |
+ return new WebRestrictionsResult( |
+ false, new int[] {FilteringBehaviorReason.NOT_SIGNED_IN}, null); |
+ } |
ThreadUtils.runOnUiThread(new Runnable() { |
@Override |
public void run() { |
- try { |
- nativeShouldProceed(getSupervisedUserContentProvider(), queryReply, url); |
- } catch (ProcessInitException e) { |
- queryReply.onQueryFailedNoErrorData(); |
- } |
+ nativeShouldProceed(contentProvider, queryReply, url); |
} |
}); |
try { |
@@ -159,14 +219,12 @@ public class SupervisedUserContentProvider extends WebRestrictionsContentProvide |
// reply object for each query, and passing this through the callback structure. The reply |
// object also handles waiting for the reply. |
final SupervisedUserInsertReply insertReply = new SupervisedUserInsertReply(); |
+ final long contentProvider = getSupervisedUserContentProvider(); |
+ if (contentProvider == 0) return false; |
ThreadUtils.runOnUiThread(new Runnable() { |
@Override |
public void run() { |
- try { |
- nativeRequestInsert(getSupervisedUserContentProvider(), insertReply, url); |
- } catch (ProcessInitException e) { |
- insertReply.onInsertRequestSendComplete(false); |
- } |
+ nativeRequestInsert(contentProvider, insertReply, url); |
} |
}); |
try { |
@@ -178,26 +236,6 @@ public class SupervisedUserContentProvider extends WebRestrictionsContentProvide |
} |
} |
- @Override |
- public Bundle call(String method, String arg, Bundle bundle) { |
- if (method.equals("setFilterForTesting")) setFilterForTesting(); |
- return null; |
- } |
- |
- void setFilterForTesting() { |
- ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
- @Override |
- public void run() { |
- try { |
- nativeSetFilterForTesting(getSupervisedUserContentProvider()); |
- } catch (ProcessInitException e) { |
- // There is no way of returning anything sensible here, so ignore the error and |
- // do nothing. |
- } |
- } |
- }); |
- } |
- |
@CalledByNative |
void onSupervisedUserFilterUpdated() { |
onFilterChanged(); |
@@ -249,7 +287,38 @@ public class SupervisedUserContentProvider extends WebRestrictionsContentProvide |
Bundle appRestrictions = userManager |
.getApplicationRestrictions(getContext().getPackageName()); |
setEnabled(appRestrictions.getBoolean(SUPERVISED_USER_CONTENT_PROVIDER_ENABLED)); |
- }; |
+ } |
+ |
+ @Override |
+ protected String[] getErrorColumnNames() { |
+ String result[] = {"Reason", "Allow access requests", "Is child account", |
+ "Profile image URL", "Second profile image URL", "Custodian", "Custodian email", |
+ "Second custodian", "Second custodian email"}; |
+ return result; |
+ } |
+ |
+ // Helpers for testing. |
+ |
+ @Override |
+ public Bundle call(String method, String arg, Bundle bundle) { |
+ if (method.equals("setFilterForTesting")) setFilterForTesting(); |
+ return null; |
+ } |
+ |
+ void setFilterForTesting() { |
+ final long contentProvider = getSupervisedUserContentProvider(); |
+ if (contentProvider == 0) return; |
+ ThreadUtils.runOnUiThread(new Runnable() { |
+ @Override |
+ public void run() { |
+ nativeSetFilterForTesting(contentProvider); |
+ } |
+ }); |
+ } |
+ |
+ void setNativeSupervisedUserContentProviderForTesting(long nativeProvider) { |
+ mNativeSupervisedUserContentProvider = nativeProvider; |
+ } |
@VisibleForTesting |
public static void enableContentProviderForTesting() { |
@@ -266,11 +335,4 @@ public class SupervisedUserContentProvider extends WebRestrictionsContentProvide |
private native void nativeSetFilterForTesting(long nativeSupervisedUserContentProvider); |
- @Override |
- protected String[] getErrorColumnNames() { |
- String result[] = {"Reason", "Allow access requests", "Is child account", |
- "Profile image URL", "Second profile image URL", "Custodian", "Custodian email", |
- "Second custodian", "Second custodian email"}; |
- return result; |
- } |
} |