// Copyright 2016 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.customtabs;
import android.content.Intent;
import android.os.SystemClock;
import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
import org.chromium.chrome.browser.IntentHandler.TabOpenType;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.ChromeTabCreator;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.webapps.ActivityAssigner;
/**
* Manages the state of separate task Custom Tabs for Android versions prior to L.
*
* L provides the ability to force tasks to be in separate stacks via the NEW_DOCUMENT flag, but
* no corresponding flag is available in KitKat and before. To work around this, we predefine an
* limited number of activities that we will cycle through.
*/
public class SeparateTaskManagedCustomTabActivity extends SeparateTaskCustomTabActivity {
private static final String FORCE_FINISH = "CCT.ForceFinish";
// Time at which an intent was received and handled.
private long mIntentHandlingTimeMs = 0;
@Override
public void onStartWithNative() {
super.onStartWithNative();
if (!isFinishing()) {
ActivityAssigner.instance(ActivityAssigner.SEPARATE_TASK_CCT_NAMESPACE)
.markActivityUsed(getActivityIndex(), getIntent().getData().getAuthority());
}
}
@Override
public void onNewIntent(Intent intent) {
mIntentHandlingTimeMs = SystemClock.uptimeMillis();
if (intent != null && intent.getBooleanExtra(FORCE_FINISH, false)) {
finish();
return;
}
super.onNewIntent(intent);
}
@Override
public ChromeTabCreator getTabCreator(boolean incognito) {
TabCreator tabCreator = super.getTabCreator(incognito);
assert tabCreator instanceof ChromeTabCreator;
return (ChromeTabCreator) tabCreator;
}
@Override
protected IntentHandlerDelegate createIntentHandlerDelegate() {
return new IntentHandlerDelegate() {
@Override
public void processWebSearchIntent(String query) {
}
@Override
public void processUrlViewIntent(String url, String referer, String headers,
TabOpenType tabOpenType, String externalAppId, int tabIdToBringToFront,
boolean hasUserGesture, Intent intent) {
Tab currentTab = getTabCreator(false).launchUrlFromExternalApp(
url, referer, headers, externalAppId, true, intent, mIntentHandlingTimeMs);
// Close all existing tabs from the previous session.
TabModel tabModel = getTabModelSelector().getModel(false);
for (int i = tabModel.getCount() - 1; i >= 0; i--) {
if (tabModel.getTabAt(i).equals(currentTab)) continue;
tabModel.closeTab(tabModel.getTabAt(i), false, false, false);
}
}
};
}
private int getActivityIndex() {
// Cull out the activity index from the class name.
String baseClassName = SeparateTaskCustomTabActivity.class.getSimpleName();
String className = this.getClass().getSimpleName();
assert className.matches("^" + baseClassName + "[0-9]+$");
String indexString = className.substring(baseClassName.length());
return Integer.parseInt(indexString);
}
@Override
protected void handleFinishAndClose() {
Intent intent = new Intent(getIntent());
intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.putExtra(FORCE_FINISH, true);
startActivity(intent);
}
}