Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1867)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java

Issue 839663003: Upstream partner customizations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed tests Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
new file mode 100644
index 0000000000000000000000000000000000000000..01ccb13012ae7e4d85156e28fb8dfc20a758ab51
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
@@ -0,0 +1,289 @@
+// 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.chrome.browser.partnercustomizations;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksReader;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Reads and caches partner browser customizations information if it exists.
+ */
+public class PartnerBrowserCustomizations {
+ private static final String TAG = "PartnerBrowserProvider";
+ private static final String PROVIDER_AUTHORITY = "com.android.partnerbrowsercustomizations";
+
+ // Private homepage structure.
+ static final String PARTNER_HOMEPAGE_PATH = "homepage";
+ static final String PARTNER_DISABLE_BOOKMARKS_EDITING_PATH = "disablebookmarksediting";
+ @VisibleForTesting
+ public static final String PARTNER_DISABLE_INCOGNITO_MODE_PATH = "disableincognitomode";
+
+ private static String sProviderAuthority = PROVIDER_AUTHORITY;
+ private static boolean sIgnoreBrowserProviderSystemPackageCheck = false;
+ private static volatile String sHomepage;
+ private static volatile boolean sIncognitoModeDisabled;
+ private static volatile boolean sBookmarksEditingDisabled;
+ private static boolean sIsInitialized;
+ private static List<Runnable> sInitializeAsyncCallbacks = new ArrayList<Runnable>();
+
+ /**
+ * @return True if the partner homepage content provider exists and enabled. Note that The data
+ * this method reads is not initialized until the asynchronous initialization of this
+ * class has been completed.
+ */
+ public static boolean isHomepageProviderAvailableAndEnabled() {
+ return !TextUtils.isEmpty(getHomePageUrl());
+ }
+
+ /**
+ * @return Whether incognito mode is disabled by the partner.
+ */
+ public static boolean isIncognitoDisabled() {
+ return sIncognitoModeDisabled;
+ }
+
+ /**
+ * @return Whether partner bookmarks editing is disabled by the partner.
+ */
+ @VisibleForTesting
+ static boolean isBookmarksEditingDisabled() {
+ return sBookmarksEditingDisabled;
+ }
+
+ /**
+ * @return True, if initialization is finished. Checking that there is no provider, or failing
+ * to read provider is also considered initialization.
+ */
+ @VisibleForTesting
+ static boolean isInitialized() {
+ return sIsInitialized;
+ }
+
+ @VisibleForTesting
+ public static void setProviderAuthorityForTests(String providerAuthority) {
+ sProviderAuthority = providerAuthority;
+ }
+
+ /**
+ * For security, we only allow system package to be a browser customizations provider. However,
+ * requiring root and installing system apk makes testing harder, so we decided to have this
+ * hack for testing. This must not be called other than tests.
+ *
+ * @param ignore whether we should ignore browser provider system package checking.
+ */
+ @VisibleForTesting
+ public static void ignoreBrowserProviderSystemPackageCheckForTests(boolean ignore) {
+ sIgnoreBrowserProviderSystemPackageCheck = ignore;
+ }
+
+ @VisibleForTesting
+ public static Uri buildQueryUri(String path) {
+ return new Uri.Builder()
+ .scheme("content")
+ .authority(sProviderAuthority)
+ .appendPath(path)
+ .build();
+ }
+
+ /**
+ * Constructs an async task that reads PartnerBrowserCustomization provider.
+ *
+ * @param context The current application context.
+ * @param timeoutMs If initializing takes more than this time, cancels it. The unit is ms.
+ */
+ public static void initializeAsync(final Context context, long timeoutMs) {
+ sIsInitialized = false;
+ // Setup an initializing async task.
+ final AsyncTask<Void, Void, Void> initializeAsyncTask =
+ new AsyncTask<Void, Void, Void>() {
+ private boolean mDisablePartnerBookmarksShim;
+ private boolean mHomepageUriChanged;
+
+ private void refreshHomepage() {
+ try {
+ ContentResolver contentResolver = context.getContentResolver();
+ Cursor cursor = contentResolver.query(
+ buildQueryUri(PARTNER_HOMEPAGE_PATH), null, null, null, null);
+ if (cursor != null && cursor.moveToFirst() && cursor.getColumnCount() == 1
+ && !isCancelled()) {
+ if (TextUtils.isEmpty(sHomepage)
+ || !sHomepage.equals(cursor.getString(0))) {
+ mHomepageUriChanged = true;
+ }
+ sHomepage = cursor.getString(0);
+ }
+ if (cursor != null) cursor.close();
+ } catch (Exception e) {
+ Log.w(TAG, "Partner homepage provider URL read failed : ", e);
+ }
+ }
+
+ private void refreshIncognitoModeDisabled() {
+ try {
+ ContentResolver contentResolver = context.getContentResolver();
+ Cursor cursor = contentResolver.query(
+ buildQueryUri(PARTNER_DISABLE_INCOGNITO_MODE_PATH),
+ null, null, null, null);
+ if (cursor != null && cursor.moveToFirst() && cursor.getColumnCount() == 1
+ && !isCancelled()) {
+ sIncognitoModeDisabled = cursor.getInt(0) == 1;
+ }
+ if (cursor != null) cursor.close();
+ } catch (Exception e) {
+ Log.w(TAG, "Partner disable incognito mode read failed : ", e);
+ }
+ }
+
+ private void refreshBookmarksEditingDisabled() {
+ try {
+ ContentResolver contentResolver = context.getContentResolver();
+ Cursor cursor = contentResolver.query(
+ buildQueryUri(PARTNER_DISABLE_BOOKMARKS_EDITING_PATH),
+ null, null, null, null);
+ if (cursor != null && cursor.moveToFirst() && cursor.getColumnCount() == 1
+ && !isCancelled()) {
+ boolean bookmarksEditingDisabled = cursor.getInt(0) == 1;
+ if (bookmarksEditingDisabled != sBookmarksEditingDisabled) {
+ mDisablePartnerBookmarksShim = true;
+ }
+ sBookmarksEditingDisabled = bookmarksEditingDisabled;
+ }
+ if (cursor != null) cursor.close();
+ } catch (Exception e) {
+ Log.w(TAG, "Partner disable bookmarks editing read failed : ", e);
+ }
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ ProviderInfo providerInfo = context.getPackageManager()
+ .resolveContentProvider(sProviderAuthority, 0);
+ if (providerInfo == null) return null;
+
+ if ((providerInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
+ && !sIgnoreBrowserProviderSystemPackageCheck) {
+ Log.w("TAG", "Browser Cutomizations content provider package, "
+ + providerInfo.packageName + ", is not a system package. "
+ + "This could be a malicious attepment from a third party app, "
+ + "so skip reading the browser content provider.");
+ return null;
+ }
+
+ if (isCancelled()) return null;
+ refreshIncognitoModeDisabled();
+
+ if (isCancelled()) return null;
+ refreshBookmarksEditingDisabled();
+
+ if (isCancelled()) return null;
+ refreshHomepage();
+ } catch (Exception e) {
+ Log.w(TAG, "Fetching partner customizations failed", e);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ onFinalized();
+ }
+
+ @Override
+ protected void onCancelled(Void result) {
+ onFinalized();
+ }
+
+ private void onFinalized() {
+ sIsInitialized = true;
+
+ for (Runnable callback : sInitializeAsyncCallbacks) {
+ callback.run();
+ }
+ sInitializeAsyncCallbacks.clear();
+
+ if (mHomepageUriChanged) {
+ HomepageManager.getInstance(context).notifyHomepageUpdated();
+ }
+
+ // Disable partner bookmarks editing if necessary.
+ if (mDisablePartnerBookmarksShim) {
+ PartnerBookmarksReader.disablePartnerBookmarksEditing();
+ }
+ }
+ };
+
+ initializeAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+
+ // Cancel the initialization if it reaches timeout.
+ ThreadUtils.postOnUiThreadDelayed(new Runnable() {
+ @Override
+ public void run() {
+ initializeAsyncTask.cancel(true);
+ }
+ }, timeoutMs);
+ }
+
+ /**
+ * Sets a callback that will be executed when the initialization is done.
+ *
+ * @param callback This is called when the initialization is done.
+ */
+ public static void setOnInitializeAsyncFinished(final Runnable callback) {
+ if (sIsInitialized) {
+ ThreadUtils.postOnUiThread(callback);
+ } else {
+ sInitializeAsyncCallbacks.add(callback);
+ }
+ }
+
+ /**
+ * Sets a callback that will be executed when the initialization is done.
+ *
+ * @param callback This is called when the initialization is done.
+ * @param timeoutMs If initializing takes more than this time since this function is called,
+ * force run |callback| early. The unit is ms.
+ */
+ public static void setOnInitializeAsyncFinished(final Runnable callback, long timeoutMs) {
+ sInitializeAsyncCallbacks.add(callback);
+
+ ThreadUtils.postOnUiThreadDelayed(
+ new Runnable() {
+ @Override
+ public void run() {
+ if (sInitializeAsyncCallbacks.remove(callback)) callback.run();
+ }
+ },
+ sIsInitialized ? 0 : timeoutMs);
+ }
+
+ public static void destroy() {
+ sIsInitialized = false;
+ sInitializeAsyncCallbacks.clear();
+ sHomepage = null;
+ }
+
+ /**
+ * @return Home page URL from Android provider. If null, that means either there is no homepage
+ * provider or provider set it to null to disable homepage.
+ */
+ public static String getHomePageUrl() {
+ return sHomepage;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698