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

Unified Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/ChromeActivity.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 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_staging/src/org/chromium/chrome/browser/ChromeActivity.java
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/ChromeActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..1097a84f9360e45441cb7d36f898ef98dde989c6
--- /dev/null
+++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -0,0 +1,798 @@
+// 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;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.SearchManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Build;
+import android.os.Looper;
+import android.os.MessageQueue;
+import android.os.SystemClock;
+import android.preference.PreferenceManager;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.Surface;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
+import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
+
+import com.google.android.apps.chrome.R;
+
+import org.chromium.base.BaseSwitches;
+import org.chromium.base.CommandLine;
+import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
+import org.chromium.chrome.browser.IntentHandler.TabOpenType;
+import org.chromium.chrome.browser.compositor.layouts.content.ContentOffsetProvider;
+import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
+import org.chromium.chrome.browser.device.DeviceClassManager;
+import org.chromium.chrome.browser.fullscreen.FullscreenManager;
+import org.chromium.chrome.browser.gsa.ContextReporter;
+import org.chromium.chrome.browser.gsa.GSAServiceClient;
+import org.chromium.chrome.browser.gsa.GSAState;
+import org.chromium.chrome.browser.infobar.InfoBarContainer;
+import org.chromium.chrome.browser.init.AsyncInitializationActivity;
+import org.chromium.chrome.browser.metrics.LaunchMetrics;
+import org.chromium.chrome.browser.metrics.UmaSessionStats;
+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.share.ShareHelper;
+import org.chromium.chrome.browser.sync.ProfileSyncService;
+import org.chromium.chrome.browser.tabmodel.ChromeTabCreator;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModel;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
+import org.chromium.chrome.browser.tabmodel.TabModelUtils;
+import org.chromium.chrome.browser.tabmodel.TabWindowManager;
+import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.content.browser.ContentReadbackHandler;
+import org.chromium.content.browser.ContentViewCore;
+import org.chromium.content.common.ContentSwitches;
+import org.chromium.content_public.browser.readback_types.ReadbackResponse;
+import org.chromium.ui.base.DeviceFormFactor;
+import org.chromium.ui.base.WindowAndroid;
+
+import java.lang.reflect.Field;
+
+/**
+ * The main Chrome activity. This exposes extra methods that relate to the {@link TabModelSelector}
+ * and lists of tabs.
+ */
+public abstract class ChromeActivity extends AsyncInitializationActivity implements
+ TabCreatorManager, AccessibilityStateChangeListener, PolicyChangeListener {
+
+ private static final String SNAPSHOT_DATABASE_REMOVED = "snapshot_database_removed";
+ private static final String SNAPSHOT_DATABASE_NAME = "snapshots.db";
+
+ /** Delay in ms after first page load finishes before we initiate deferred startup actions. */
+ private static final int DEFERRED_STARTUP_DELAY_MS = 1000;
+
+ /**
+ * Timeout in ms for reading PartnerBrowserCustomizations provider.
+ */
+ private static final int PARTNER_BROWSER_CUSTOMIZATIONS_TIMEOUT_MS = 10000;
+
+ private TabModelSelector mTabModelSelector;
+ private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
+ private ChromeTabCreator mRegularTabCreator;
+ private ChromeTabCreator mIncognitoTabCreator;
+ private TabContentManager mTabContentManager;
+ private UmaSessionStats mUmaSessionStats;
+ private ContextReporter mContextReporter;
+ protected GSAServiceClient mGSAServiceClient;
+
+ private int mCurrentOrientation = Surface.ROTATION_0;
+ private boolean mPartnerBrowserRefreshNeeded = false;
+
+ protected IntentHandler mIntentHandler;
+ protected boolean mIsTablet = false;
+ private long mLastUserInteractionTime;
+
+ /** Whether onDeferredStartup() has been run. */
+ private boolean mDeferredStartupNotified;
+
+ // The class cannot implement TouchExplorationStateChangeListener,
+ // because it is only available for Build.VERSION_CODES.KITKAT and later.
+ // We have to instantiate the TouchExplorationStateChangeListner object in the code.
+ private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener;
+
+ // Observes when sync becomes ready to create the mContextReporter.
+ private ProfileSyncService.SyncStateChangedListener mSyncStateChangedListener;
+
+ @SuppressLint("NewApi")
+ @Override
+ protected void onDestroy() {
+ getChromeApplication().removePolicyChangeListener(this);
+ if (mTabContentManager != null) mTabContentManager.destroy();
+ if (mTabModelSelectorTabObserver != null) mTabModelSelectorTabObserver.destroy();
+
+ AccessibilityManager manager = (AccessibilityManager)
+ getBaseContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+ manager.removeAccessibilityStateChangeListener(this);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ manager.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener);
+ }
+
+ super.onDestroy();
+ }
+
+ /**
+ * {@link TabModelSelector} no longer implements TabModel. Use getTabModelSelector() or
+ * getCurrentTabModel() depending on your needs.
+ * @return The {@link TabModelSelector}, possibly null.
+ */
+ public TabModelSelector getTabModelSelector() {
+ return mTabModelSelector;
+ }
+
+ /**
+ * Sets the {@link TabModelSelector} owned by this {@link ChromeActivity}.
+ * @param tabModelSelector A {@link TabModelSelector} instance.
+ */
+ protected void setTabModelSelector(TabModelSelector tabModelSelector) {
+ mTabModelSelector = tabModelSelector;
+
+ if (mTabModelSelectorTabObserver != null) mTabModelSelectorTabObserver.destroy();
+ mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(tabModelSelector) {
+ @Override
+ public void onLoadStopped(Tab tab) {
+ postDeferredStartupIfNeeded();
+ showUpdateInfoBarIfNecessary();
+ }
+
+ @Override
+ public void onPageLoadFinished(Tab tab) {
+ postDeferredStartupIfNeeded();
+ showUpdateInfoBarIfNecessary();
+ }
+
+ @Override
+ public void onCrash(Tab tab, boolean sadTabShown) {
+ postDeferredStartupIfNeeded();
+ }
+ };
+ }
+
+ @Override
+ public ChromeTabCreator getTabCreator(boolean incognito) {
+ return incognito ? mIncognitoTabCreator : mRegularTabCreator;
+ }
+
+ /**
+ * Sets the {@link ChromeTabCreator}s owned by this {@link ChromeActivity}.
+ * @param regularTabCreator A {@link ChromeTabCreator} instance.
+ */
+ public void setTabCreators(ChromeTabCreator regularTabCreator,
+ ChromeTabCreator incognitoTabCreator) {
+ mRegularTabCreator = regularTabCreator;
+ mIncognitoTabCreator = incognitoTabCreator;
+ }
+
+ /**
+ * Convenience method that returns a tab creator for the currently selected {@link TabModel}.
+ * @return A tab creator for the currently selected {@link TabModel}.
+ */
+ public ChromeTabCreator getCurrentTabCreator() {
+ return getTabCreator(getTabModelSelector().isIncognitoSelected());
+ }
+
+ /**
+ * Gets the {@link TabContentManager} instance which holds snapshots of the tabs in this model.
+ * @return The thumbnail cache, possibly null.
+ */
+ public TabContentManager getTabContentManager() {
+ return mTabContentManager;
+ }
+
+ /**
+ * Sets the {@link TabContentManager} owned by this {@link ChromeActivity}.
+ * @param tabContentManager A {@link TabContentManager} instance.
+ */
+ protected void setTabContentManager(TabContentManager tabContentManager) {
+ mTabContentManager = tabContentManager;
+ }
+
+ /**
+ * Gets the current (inner) TabModel. This is a convenience function for
+ * getModelSelector().getCurrentModel(). It is *not* equivalent to the former getModel()
+ * @return Never null, if modelSelector or its field is uninstantiated returns a
+ * {@link EmptyTabModel} singleton
+ */
+ public TabModel getCurrentTabModel() {
+ TabModelSelector modelSelector = getTabModelSelector();
+ if (modelSelector == null) return EmptyTabModel.getInstance();
+ return modelSelector.getCurrentModel();
+ }
+
+ /**
+ * Returns the tab being displayed by this ChromeActivity instance. This allows differentiation
+ * between ChromeActivity subclasses that swap between multiple tabs (e.g. ChromeTabbedActivity)
+ * and subclasses that only display one Tab (e.g. FullScreenActivity and DocumentActivity).
+ *
+ * The default implementation grabs the tab currently selected by the TabModel, which may be
+ * null if the Tab does not exist or the system is not initialized.
+ */
+ public Tab getActivityTab() {
+ return TabModelUtils.getCurrentTab(getCurrentTabModel());
+ }
+
+ /**
+ * @return The current ContentViewCore, or null if the tab does not exist or is not showing a
+ * ContentViewCore.
+ */
+ public ContentViewCore getCurrentContentViewCore() {
+ return TabModelUtils.getCurrentContentViewCore(getCurrentTabModel());
+ }
+
+ /**
+ * Gets the full screen manager.
+ * @return The fullscreen manager, possibly null
+ */
+ public FullscreenManager getFullscreenManager() {
+ return null;
+ }
+
+ /**
+ * @return The content offset provider, may be null.
+ */
+ public ContentOffsetProvider getContentOffsetProvider() {
+ return null;
+ }
+
+ /**
+ * @return The content readback handler, may be null.
+ */
+ public ContentReadbackHandler getContentReadbackHandler() {
+ return null;
+ }
+
+ @Override
+ public void preInflationStartup() {
+ super.preInflationStartup();
+ ApplicationInitialization.enableFullscreenFlags(
+ getResources(), this, getControlContainerHeightResource());
+ mIsTablet = DeviceFormFactor.isTablet(this);
+ getWindow().setBackgroundDrawableResource(R.color.light_background_color);
+ }
+
+ @SuppressLint("NewApi")
+ @Override
+ public void postInflationStartup() {
+ super.postInflationStartup();
+ // Low end device UI should be allowed only after a fresh install or when the data has
+ // been cleared. This must happen before anyone calls SysUtils.isLowEndDevice() or
+ // SysUtils.isLowEndDevice() will always return the wrong value.
+ if (OmahaClient.isFreshInstallOrDataHasBeenCleared(this)) {
+ ChromePreferenceManager.getInstance(this).setAllowLowEndDeviceUi();
+ }
+
+ if (!ChromePreferenceManager.getInstance(this).getAllowLowEndDeviceUi()) {
+ CommandLine.getInstance().appendSwitch(
+ BaseSwitches.DISABLE_LOW_END_DEVICE_MODE);
+ }
+
+ AccessibilityManager manager = (AccessibilityManager)
+ getBaseContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+ manager.addAccessibilityStateChangeListener(this);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ mTouchExplorationStateChangeListener = new TouchExplorationStateChangeListener() {
+ @Override
+ public void onTouchExplorationStateChanged(boolean enabled) {
+ checkAccessibility();
+ }
+ };
+ manager.addTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener);
+ }
+ }
+
+ @Override
+ public void initializeCompositor() {
+ super.initializeCompositor();
+ }
+
+ @Override
+ public void initializeState() {
+ super.initializeState();
+ IntentHandler.setTestIntentsEnabled(
+ CommandLine.getInstance().hasSwitch(ContentSwitches.ENABLE_TEST_INTENTS));
+ mIntentHandler = new IntentHandler(createIntentHandlerDelegate(), getPackageName());
+ }
+
+ @Override
+ public void finishNativeInitialization() {
+ // Set up the initial orientation of the device.
+ checkOrientation();
+ findViewById(android.R.id.content).addOnLayoutChangeListener(
+ new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ checkOrientation();
+ }
+ });
+
+ // Make the activity listen to policy change events
+ getChromeApplication().addPolicyChangeListener(this);
+
+ super.finishNativeInitialization();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (mContextReporter != null) mContextReporter.enable();
+
+ if (mPartnerBrowserRefreshNeeded) {
+ mPartnerBrowserRefreshNeeded = false;
+ PartnerBrowserCustomizations.initializeAsync(getApplicationContext(),
+ PARTNER_BROWSER_CUSTOMIZATIONS_TIMEOUT_MS);
+ PartnerBrowserCustomizations.setOnInitializeAsyncFinished(new Runnable() {
+ @Override
+ public void run() {
+ if (PartnerBrowserCustomizations.isIncognitoDisabled()) {
+ terminateIncognitoSession();
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if (mContextReporter != null) mContextReporter.disable();
+
+ // We want to refresh partner browser provider every onStart().
+ mPartnerBrowserRefreshNeeded = true;
+ }
+
+ @Override
+ public void onStartWithNative() {
+ super.onStartWithNative();
+ getChromeApplication().onStartWithNative();
+ Tab tab = getActivityTab();
+ if (tab != null) tab.onActivityStart();
+ FeatureUtilities.setDocumentModeEnabled(FeatureUtilities.isDocumentMode(this));
+ WarmupManager.getInstance().clearWebContentsIfNecessary();
+
+ if (GSAState.getInstance(this).isGsaAvailable()) {
+ mGSAServiceClient = new GSAServiceClient(this);
+ mGSAServiceClient.connect();
+ createContextReporterIfNeeded();
+ } else {
+ ContextReporter.reportStatus(ContextReporter.STATUS_GSA_NOT_AVAILABLE);
+ }
+ }
+
+ private void createContextReporterIfNeeded() {
+ if (mContextReporter != null || getActivityTab() == null) return;
+
+ final ProfileSyncService syncService = ProfileSyncService.get(this);
+
+ if (syncService.isSyncingUrlsWithKeystorePassphrase()) {
+ mContextReporter = ((ChromeMobileApplication) getApplicationContext()).createGsaHelper()
+ .getContextReporter(this);
+
+ if (mSyncStateChangedListener != null) {
+ syncService.removeSyncStateChangedListener(mSyncStateChangedListener);
+ mSyncStateChangedListener = null;
+ }
+
+ return;
+ } else {
+ ContextReporter.reportSyncStatus(syncService);
+ }
+
+ if (mSyncStateChangedListener == null) {
+ mSyncStateChangedListener = new ProfileSyncService.SyncStateChangedListener() {
+ @Override
+ public void syncStateChanged() {
+ createContextReporterIfNeeded();
+ }
+ };
+ syncService.addSyncStateChangedListener(mSyncStateChangedListener);
+ }
+ }
+
+ @Override
+ public void onResumeWithNative() {
+ super.onResumeWithNative();
+ markSessionResume();
+
+ if (getActivityTab() != null) {
+ LaunchMetrics.commitLaunchMetrics(getActivityTab().getWebContents());
+ }
+ }
+
+ @Override
+ public void onPauseWithNative() {
+ markSessionEnd();
+ super.onPauseWithNative();
+ }
+
+ @Override
+ public void onStopWithNative() {
+ if (mGSAServiceClient != null) {
+ mGSAServiceClient.disconnect();
+ mGSAServiceClient = null;
+ if (mSyncStateChangedListener != null) {
+ ProfileSyncService syncService = ProfileSyncService.get(this);
+ syncService.removeSyncStateChangedListener(mSyncStateChangedListener);
+ mSyncStateChangedListener = null;
+ }
+ }
+
+ super.onStopWithNative();
+ }
+
+ @Override
+ public void onNewIntentWithNative(Intent intent) {
+ super.onNewIntentWithNative(intent);
+ if (mIntentHandler.shouldIgnoreIntent(this, intent)) return;
+
+ mIntentHandler.onNewIntent(intent);
+ }
+
+ /**
+ * Called when the orientation of the device changes. The orientation is checked/detected on
+ * root view layouts.
+ * @param orientation One of {@link Surface#ROTATION_0} (no rotation),
+ * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, or
+ * {@link Surface#ROTATION_270}.
+ */
+ protected void onOrientationChange(int orientation) {
+ }
+
+ /**
+ * Called when the accessibility status of this device changes. This might be triggered by
+ * touch exploration or general accessibility status updates. It is an aggregate of two other
+ * accessibility update methods.
+ * @see #onAccessibilityModeChanged(boolean)
+ * @see #onTouchExplorationStateChanged(boolean)
+ * @param enabled Whether or not accessibility and touch exploration are currently enabled.
+ */
+ protected void onAccessibilityModeChanged(boolean enabled) {
+ InfoBarContainer.setIsAllowedToAutoHide(!enabled);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item != null && onMenuOrKeyboardAction(item.getItemId(), true)) {
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onUserInteraction() {
+ mLastUserInteractionTime = SystemClock.elapsedRealtime();
+ }
+
+ /**
+ * Handles menu item selection and keyboard shortcuts.
+ *
+ * @param id The ID of the selected menu item (defined in main_menu.xml) or
+ * keyboard shortcut (defined in values.xml).
+ * @param fromMenu Whether this was triggered from the menu.
+ * @return Whether the action was handled.
+ */
+ public boolean onMenuOrKeyboardAction(int id, boolean fromMenu) {
+ return false;
+ }
+
+ /**
+ * Triggered when the share menu item is selected.
+ * This creates and shows a share intent picker dialog or starts a share intent directly.
+ *
+ * @param currentTab The {@link Tab} a user is watching.
+ * @param windowAndroid The {@link WindowAndroid} currentTab is linked to.
+ * @param shareDirectly Whether it should share directly with the activity that was most
+ * recently used to share.
+ * @param isIncognito Whether currentTab is incognito.
+ */
+ public void onShareMenuItemSelected(final Tab currentTab,
+ final WindowAndroid windowAndroid, final boolean shareDirectly, boolean isIncognito) {
+ if (currentTab == null) return;
+
+ final Activity mainActivity = this;
+ ContentReadbackHandler.GetBitmapCallback bitmapCallback =
+ new ContentReadbackHandler.GetBitmapCallback() {
+ @Override
+ public void onFinishGetBitmap(Bitmap bitmap, int reponse) {
+ ShareHelper.share(shareDirectly, mainActivity, currentTab.getTitle(),
+ currentTab.getUrl(), bitmap);
+ if (shareDirectly) {
+ RecordUserAction.record("MobileMenuDirectShare");
+ } else {
+ RecordUserAction.record("MobileMenuShare");
+ }
+ }
+ };
+ ContentReadbackHandler readbackHandler = getContentReadbackHandler();
+ if (isIncognito || readbackHandler == null || windowAndroid == null
+ || currentTab.getContentViewCore() == null) {
+ bitmapCallback.onFinishGetBitmap(null, ReadbackResponse.SURFACE_UNAVAILABLE);
+ } else {
+ readbackHandler.getContentBitmapAsync(1, new Rect(), currentTab.getContentViewCore(),
+ Bitmap.Config.ARGB_8888, bitmapCallback);
+ }
+ }
+
+ /**
+ * @return Whether the activity is running in tablet mode.
+ */
+ public boolean isTablet() {
+ return mIsTablet;
+ }
+
+ /**
+ * @return Whether the activity is in overview mode.
+ */
+ public boolean isInOverviewMode() {
+ return false;
+ }
+
+ /**
+ * @return Whether the app menu should be shown.
+ */
+ public boolean shouldShowAppMenu() {
+ return false;
+ }
+
+ /**
+ * Allows Activities that extend ChromeActivity to do additional hiding/showing of menu items.
+ * @param menu Menu that is going to be shown when the menu button is pressed.
+ */
+ public void prepareMenu(Menu menu) {
+ }
+
+ /**
+ * @return timestamp when the last user interaction was made.
+ */
+ public long getLastUserInteractionTime() {
+ return mLastUserInteractionTime;
+ }
+
+ protected IntentHandlerDelegate createIntentHandlerDelegate() {
+ return new IntentHandlerDelegate() {
+ @Override
+ public void processWebSearchIntent(String query) {
+ Intent searchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
+ searchIntent.putExtra(SearchManager.QUERY, query);
+ startActivity(searchIntent);
+ }
+
+ @Override
+ public void processUrlViewIntent(String url, String headers, TabOpenType tabOpenType,
+ String externalAppId, int tabIdToBringToFront, Intent intent) {
+ }
+ };
+ }
+
+ /**
+ * @return The resource id that contains how large the top controls are.
+ */
+ protected int getControlContainerHeightResource() {
+ return R.dimen.control_container_height;
+ }
+
+ private void markSessionResume() {
+ // Start new session for UMA.
+ if (mUmaSessionStats == null) {
+ mUmaSessionStats = new UmaSessionStats(this);
+ }
+
+ mUmaSessionStats.updateMetricsServiceState();
+ // In DocumentMode we need the application-level TabModelSelector instead of per
+ // activity which only manages a single tab.
+ if (FeatureUtilities.isDocumentMode(this)) {
+ mUmaSessionStats.startNewSession(
+ ChromeMobileApplication.getDocumentTabModelSelector());
+ } else {
+ mUmaSessionStats.startNewSession(getTabModelSelector());
+ }
+ }
+
+ /**
+ * Mark that the UMA session has ended.
+ */
+ private void markSessionEnd() {
+ if (mUmaSessionStats == null) {
+ // If you hit this assert, please update crbug.com/172653 on how you got there.
+ assert false;
+ return;
+ }
+ // Record session metrics.
+ mUmaSessionStats.logMultiWindowStats(windowArea(), displayArea(),
+ TabWindowManager.getInstance().getNumberOfAssignedTabModelSelectors());
+ mUmaSessionStats.logAndEndSession();
+ }
+
+ private int windowArea() {
+ Window window = getWindow();
+ if (window != null) {
+ View view = window.getDecorView();
+ return view.getWidth() * view.getHeight();
+ }
+ return -1;
+ }
+
+ private int displayArea() {
+ if (getResources() != null && getResources().getDisplayMetrics() != null) {
+ DisplayMetrics metrics = getResources().getDisplayMetrics();
+ return metrics.heightPixels * metrics.widthPixels;
+ }
+ return -1;
+ }
+
+ @Override
+ public final void onAccessibilityStateChanged(boolean enabled) {
+ checkAccessibility();
+ }
+
+ private void checkAccessibility() {
+ onAccessibilityModeChanged(DeviceClassManager.isAccessibilityModeEnabled(this));
+ }
+
+ private void checkOrientation() {
+ WindowManager wm = getWindowManager();
+ if (wm == null) return;
+
+ Display display = wm.getDefaultDisplay();
+ if (display == null) return;
+
+ int oldOrientation = mCurrentOrientation;
+ mCurrentOrientation = display.getRotation();
+
+ if (oldOrientation != mCurrentOrientation) onOrientationChange(mCurrentOrientation);
+ }
+
+ /**
+ * Removes the window background.
+ */
+ protected void removeWindowBackground() {
+ boolean removeWindowBackground = true;
+ try {
+ Field field = Settings.Secure.class.getField(
+ "ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED");
+ field.setAccessible(true);
+
+ if (field.getType() == String.class) {
+ String accessibilityMagnificationSetting = (String) field.get(null);
+ // When Accessibility magnification is turned on, setting a null window
+ // background causes the overlaid android views to stretch when panning.
+ // (crbug/332994)
+ if (Settings.Secure.getInt(
+ getContentResolver(), accessibilityMagnificationSetting) == 1) {
+ removeWindowBackground = false;
+ }
+ }
+ } catch (SettingNotFoundException e) {
+ // Window background is removed if an exception occurs.
+ } catch (NoSuchFieldException e) {
+ // Window background is removed if an exception occurs.
+ } catch (IllegalAccessException e) {
+ // Window background is removed if an exception occurs.
+ } catch (IllegalArgumentException e) {
+ // Window background is removed if an exception occurs.
+ }
+ if (removeWindowBackground) getWindow().setBackgroundDrawable(null);
+ }
+
+ /**
+ * @return A casted version of {@link #getApplication()}.
+ */
+ public ChromeMobileApplication getChromeApplication() {
+ return (ChromeMobileApplication) getApplication();
+ }
+
+ /**
+ * @return Whether the update infobar may be shown.
+ */
+ public boolean mayShowUpdateInfoBar() {
+ return true;
+ }
+
+ /**
+ * Actions that may be run at some point after startup. Place tasks that are not critical to the
+ * startup path here. This method will be called automatically and should not be called
+ * directly by subclasses. Overriding methods should call super.onDeferredStartup().
+ */
+ protected void onDeferredStartup() {
+ boolean crashDumpUploadingDisabled = getIntent() != null
+ && getIntent().hasExtra(
+ ChromeTabbedActivity.INTENT_EXTRA_DISABLE_CRASH_DUMP_UPLOADING);
+ DeferredStartupHandler.getInstance()
+ .onDeferredStartup(getChromeApplication(), crashDumpUploadingDisabled);
+
+ BeamController.registerForBeam(this, new BeamProvider() {
+ @Override
+ public String getTabUrlForBeam() {
+ if (isOverlayVisible()) return null;
+ if (getActivityTab() == null) return null;
+ return getActivityTab().getUrl();
+ }
+ });
+
+ getChromeApplication().getUpdateInfoBarHelper().checkForUpdateOnBackgroundThread(this);
+ removeSnapshotDatabase();
+ }
+
+ private void postDeferredStartupIfNeeded() {
+ if (!mDeferredStartupNotified) {
+ // We want to perform deferred startup tasks a short time after the first page
+ // load completes, but only when the main thread Looper has become idle.
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (!mDeferredStartupNotified && !isActivityDestroyed()) {
+ mDeferredStartupNotified = true;
+ Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
+ @Override
+ public boolean queueIdle() {
+ onDeferredStartup();
+ return false; // Remove this idle handler.
+ }
+ });
+ }
+ }
+ }, DEFERRED_STARTUP_DELAY_MS);
+ }
+ }
+
+ private void showUpdateInfoBarIfNecessary() {
+ getChromeApplication().getUpdateInfoBarHelper().showUpdateInfobarIfNecessary(this);
+ }
+
+ /**
+ * Determines whether the ContentView is currently visible and not hidden by an overlay
+ * @return true if the ContentView is fully hidden by another view (i.e. the tab stack)
+ */
+ public boolean isOverlayVisible() {
+ return false;
+ }
+
+ /**
+ * Deletes the snapshot database which is no longer used because the feature has been removed
+ * in Chrome M41.
+ */
+ private void removeSnapshotDatabase() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ if (!prefs.getBoolean(SNAPSHOT_DATABASE_REMOVED, false)) {
+ deleteDatabase(SNAPSHOT_DATABASE_NAME);
+ prefs.edit().putBoolean(SNAPSHOT_DATABASE_REMOVED, true).apply();
+ }
+ }
+
+ @Override
+ public void terminateIncognitoSession() {}
+
+ /**
+ * @return The {@code ContextualSearchManager} or {@code null} if none;
+ */
+ public ContextualSearchManager getContextualSearchManager() {
+ return null;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698