| Index: chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/AsyncDocumentLauncher.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/AsyncDocumentLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/AsyncDocumentLauncher.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..98d7a188917678ca8837c74b63b43ccdfbb118a6
|
| --- /dev/null
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/AsyncDocumentLauncher.java
|
| @@ -0,0 +1,112 @@
|
| +// 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.tabmodel.document;
|
| +
|
| +import android.app.Activity;
|
| +import android.os.Handler;
|
| +import android.os.SystemClock;
|
| +
|
| +import org.chromium.base.ThreadUtils;
|
| +import org.chromium.chrome.browser.Tab;
|
| +import org.chromium.chrome.browser.document.ChromeLauncherActivity;
|
| +import org.chromium.chrome.browser.document.DocumentActivity;
|
| +import org.chromium.chrome.browser.document.IncognitoDocumentActivity;
|
| +import org.chromium.chrome.browser.tabmodel.document.DocumentTabModel.Entry;
|
| +
|
| +import java.util.ArrayList;
|
| +
|
| +/**
|
| + * Fires an Intent to launch a new DocumentActivity. Waits for the ActivityManager to acknowledge
|
| + * that our task exists before firing the next Intent.
|
| + */
|
| +public class AsyncDocumentLauncher {
|
| + /**
|
| + * Milliseconds to wait for Android to acknowledge that our Activity's task exists.
|
| + * This value is empirically defined because Android doesn't let us know when it finishes
|
| + * animating Activities, nor does it let us Observe the ActivityManager for when our task
|
| + * exists (crbug.com/498920).
|
| + */
|
| + private static final int MAX_WAIT_MS = 3000;
|
| +
|
| + /** Milliseconds to wait between polls of the ActivityManager. */
|
| + private static final int POLLING_DELAY_MS = 100;
|
| +
|
| + private class LaunchRunnable implements Runnable {
|
| + private final int mParentId;
|
| + private final AsyncTabCreationParams mAsyncParams;
|
| + private int mLaunchedId;
|
| + private long mLaunchTimestamp;
|
| +
|
| + public LaunchRunnable(int parentId, AsyncTabCreationParams asyncParams) {
|
| + mParentId = parentId;
|
| + mAsyncParams = asyncParams;
|
| + mLaunchedId = Tab.INVALID_TAB_ID;
|
| + }
|
| +
|
| + /** Starts an Activity to with the stored parameters. */
|
| + public void launch() {
|
| + final Activity parentActivity = ActivityDelegate.getActivityForTabId(mParentId);
|
| + mLaunchedId = ChromeLauncherActivity.launchDocumentInstance(
|
| + parentActivity, mIsIncognito, mAsyncParams);
|
| + mLaunchTimestamp = SystemClock.elapsedRealtime();
|
| + run();
|
| + }
|
| +
|
| + @Override
|
| + public void run() {
|
| + // Check if the Activity was already launched.
|
| + for (Entry task : mActivityDelegate.getTasksFromRecents(mIsIncognito)) {
|
| + if (task.tabId == mLaunchedId) {
|
| + finishLaunch();
|
| + return;
|
| + }
|
| + }
|
| +
|
| + if (SystemClock.elapsedRealtime() - mLaunchTimestamp > MAX_WAIT_MS) {
|
| + // Check if the launch is taking excessively long. This will likely make the
|
| + // previous tab disappear, but it's better than making the user wait.
|
| + finishLaunch();
|
| + } else {
|
| + // Wait a bit longer.
|
| + mHandler.postDelayed(this, POLLING_DELAY_MS);
|
| + }
|
| + }
|
| +
|
| + /** Start up the next tab. */
|
| + private void finishLaunch() {
|
| + mCurrentRunnable = null;
|
| + if (mQueue.size() != 0) {
|
| + mCurrentRunnable = mQueue.remove(0);
|
| + mCurrentRunnable.launch();
|
| + }
|
| + }
|
| + }
|
| +
|
| + private final boolean mIsIncognito;
|
| + private final Handler mHandler;
|
| + private final ActivityDelegate mActivityDelegate;
|
| + private final ArrayList<LaunchRunnable> mQueue;
|
| + private LaunchRunnable mCurrentRunnable;
|
| +
|
| + public AsyncDocumentLauncher(boolean incognito) {
|
| + mIsIncognito = incognito;
|
| + mHandler = new Handler();
|
| + mActivityDelegate = new ActivityDelegate(
|
| + DocumentActivity.class, IncognitoDocumentActivity.class);
|
| + mQueue = new ArrayList<LaunchRunnable>();
|
| + }
|
| +
|
| + /** Enqueues a tab to be launched asynchronously. */
|
| + public void enqueueLaunch(int parentId, AsyncTabCreationParams asyncParams) {
|
| + ThreadUtils.assertOnUiThread();
|
| + LaunchRunnable runnable = new LaunchRunnable(parentId, asyncParams);
|
| + if (mCurrentRunnable == null) {
|
| + mCurrentRunnable = runnable;
|
| + mCurrentRunnable.launch();
|
| + } else {
|
| + mQueue.add(runnable);
|
| + }
|
| + }
|
| +}
|
|
|