// 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.webapps;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnSystemUiVisibilityChangeListener;
import android.view.ViewGroup;

import org.chromium.base.ActivityState;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.Log;
import org.chromium.base.StrictModeContext;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.base.task.PostTask;
import org.chromium.blink_public.platform.WebDisplayMode;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.AppHooks;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.SingleTabActivity;
import org.chromium.chrome.browser.WarmupManager;
import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
import org.chromium.chrome.browser.customtabs.CustomTabAppMenuPropertiesDelegate;
import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.document.DocumentUtils;
import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabBrowserControlsState;
import org.chromium.chrome.browser.tab.TabDelegateFactory;
import org.chromium.chrome.browser.tab.TabObserver;
import org.chromium.chrome.browser.tab.TabObserverRegistrar;
import org.chromium.chrome.browser.tab.TabState;
import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer;
import org.chromium.chrome.browser.util.ColorUtils;
import org.chromium.chrome.browser.widget.TintedDrawable;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.NavigationController;
import org.chromium.content_public.browser.NavigationHandle;
import org.chromium.content_public.browser.ScreenOrientationProvider;
import org.chromium.content_public.browser.UiThreadTaskTraits;
import org.chromium.net.NetworkChangeNotifier;
import org.chromium.ui.base.PageTransition;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * Displays a webapp in a nearly UI-less Chrome (InfoBars still appear).
 */
public class WebappActivity extends SingleTabActivity {
    public static final String WEBAPP_SCHEME = "webapp";

    private static final String TAG = "WebappActivity";
    private static final String HISTOGRAM_NAVIGATION_STATUS = "Webapp.NavigationStatus";
    private static final long MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL = 1000;

    private static final int ENTER_IMMERSIVE_MODE_DELAY_MILLIS = 300;
    private static final int RESTORE_IMMERSIVE_MODE_DELAY_MILLIS = 3000;
    static final int IMMERSIVE_MODE_UI_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
            | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
            | View.SYSTEM_UI_FLAG_LOW_PROFILE
            | View.SYSTEM_UI_FLAG_IMMERSIVE;

    private final WebappDirectoryManager mDirectoryManager;

    private WebappInfo mWebappInfo;

    private TabObserverRegistrar mTabObserverRegistrar;

    private SplashController mSplashController;

    private WebappDisclosureSnackbarController mDisclosureSnackbarController;

    private boolean mIsInitialized;
    private Integer mBrandColor;

    private Bitmap mLargestFavicon;

    private Runnable mSetImmersiveRunnable;

    /** Initialization-on-demand holder. This exists for thread-safe lazy initialization. */
    private static class Holder {
        // This static map is used to cache WebappInfo objects between their initial creation in
        // WebappLauncherActivity and final use in WebappActivity.
        private static final HashMap<String, WebappInfo> sWebappInfoMap =
                new HashMap<String, WebappInfo>();
    }

    /** Returns the running WebappActivity with the given tab id. Returns null if there is none. */
    public static WeakReference<WebappActivity> findWebappActivityWithTabId(int tabId) {
        if (tabId == Tab.INVALID_TAB_ID) return null;

        for (Activity activity : ApplicationStatus.getRunningActivities()) {
            if (!(activity instanceof WebappActivity)) continue;

            WebappActivity webappActivity = (WebappActivity) activity;
            Tab tab = webappActivity.getActivityTab();
            if (tab != null && tab.getId() == tabId) {
                return new WeakReference<>(webappActivity);
            }
        }
        return null;
    }

    /** Returns the WebappActivity with the given {@link webappId}. */
    public static WeakReference<WebappActivity> findRunningWebappActivityWithId(String webappId) {
        for (Activity activity : ApplicationStatus.getRunningActivities()) {
            if (!(activity instanceof WebappActivity)) {
                continue;
            }
            WebappActivity webappActivity = (WebappActivity) activity;
            if (webappActivity != null
                    && TextUtils.equals(webappId, webappActivity.getWebappInfo().id())) {
                return new WeakReference<>(webappActivity);
            }
        }
        return null;
    }

    /**
     * Construct all the variables that shouldn't change.  We do it here both to clarify when the
     * objects are created and to ensure that they exist throughout the parallelized initialization
     * of the WebappActivity.
     */
    public WebappActivity() {
        mWebappInfo = createWebappInfo(null);
        mDirectoryManager = new WebappDirectoryManager();
        mTabObserverRegistrar = new TabObserverRegistrar(getLifecycleDispatcher());
        mSplashController =
                new SplashController(this, getLifecycleDispatcher(), mTabObserverRegistrar);
        mDisclosureSnackbarController = new WebappDisclosureSnackbarController();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        if (intent == null) return;

        if (AppHooks.get().interceptWebAppIntent(intent, this)) return;

        super.onNewIntent(intent);

        WebappInfo newWebappInfo = popWebappInfo(WebappInfo.idFromIntent(intent));
        if (newWebappInfo == null) newWebappInfo = createWebappInfo(intent);

        if (newWebappInfo == null) {
            Log.e(TAG, "Failed to parse new Intent: " + intent);
            ApiCompatibilityUtils.finishAndRemoveTask(this);
        } else if (newWebappInfo.shouldForceNavigation() && mIsInitialized) {
            loadUrl(newWebappInfo, getActivityTab());
        }
    }

    @Override
    public @ChromeActivity.ActivityType int getActivityType() {
        return ChromeActivity.ActivityType.WEBAPP;
    }

    protected boolean loadUrlIfPostShareTarget(WebappInfo webappInfo) {
        return false;
    }

    protected void loadUrl(WebappInfo webappInfo, Tab tab) {
        if (loadUrlIfPostShareTarget(webappInfo)) {
            // Web Share Target Post was successful, so don't load anything.
            return;
        }
        LoadUrlParams params =
                new LoadUrlParams(webappInfo.uri().toString(), PageTransition.AUTO_TOPLEVEL);
        params.setShouldClearHistoryList(true);
        tab.loadUrl(params);
    }

    protected boolean isInitialized() {
        return mIsInitialized;
    }

    protected WebappInfo createWebappInfo(Intent intent) {
        return (intent == null) ? WebappInfo.createEmpty() : WebappInfo.create(intent);
    }

    @Override
    public void initializeState() {
        super.initializeState();
        mTabObserverRegistrar.addObserversForTab(getActivityTab());
        initializeUI(getSavedInstanceState());
    }

    @Override
    protected void doLayoutInflation() {
        // Because we delay the layout inflation, the CompositorSurfaceManager and its
        // SurfaceView(s) are created and attached late (ie after the first draw). At the time of
        // the first attach of a SurfaceView to the view hierarchy (regardless of the SurfaceView's
        // actual opacity), the window transparency hint changes (because the window creates a
        // transparent hole and attaches the SurfaceView to that hole). This may cause older android
        // versions to destroy the window and redraw it causing a flicker. This line sets the window
        // transparency hint early so that when the SurfaceView gets attached later, the
        // transparency hint need not change and no flickering occurs.
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        // No need to inflate layout synchronously since splash screen is displayed.
        new Thread() {
            @Override
            public void run() {
                ViewGroup mainView = WarmupManager.inflateViewHierarchy(
                        WebappActivity.this, getControlContainerLayoutId(), getToolbarLayoutId());
                if (isActivityFinishingOrDestroyed()) return;
                if (mainView != null) {
                    PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
                        if (isActivityFinishingOrDestroyed()) return;
                        onLayoutInflated(mainView);
                    });
                } else {
                    if (isActivityFinishingOrDestroyed()) return;
                    PostTask.postTask(UiThreadTaskTraits.DEFAULT,
                            () -> WebappActivity.super.doLayoutInflation());
                }
            }
        }
                .start();
    }

    private void onLayoutInflated(ViewGroup mainView) {
        ViewGroup contentView = (ViewGroup) findViewById(android.R.id.content);
        WarmupManager.transferViewHeirarchy(mainView, contentView);
        mSplashController.bringSplashBackToFront();
        onInitialLayoutInflationComplete();
    }

    protected void initializeUI(Bundle savedInstanceState) {
        Tab tab = getActivityTab();

        // We do not load URL when restoring from saved instance states. However, it's possible that
        // we saved instance state before loading a URL, so even after restoring from
        // SavedInstanceState we might not have a URL and should initialize from the intent.
        if (tab.getUrl().isEmpty()) {
            loadUrl(mWebappInfo, tab);
        } else {
            if (!mWebappInfo.isForWebApk() && NetworkChangeNotifier.isOnline()) {
                tab.reloadIgnoringCache();
            }
        }
        tab.addObserver(createTabObserver());
    }

    @Override
    public void performPreInflationStartup() {
        Intent intent = getIntent();
        String id = WebappInfo.idFromIntent(intent);
        WebappInfo info = popWebappInfo(id);
        // When WebappActivity is killed by the Android OS, and an entry stays in "Android Recents"
        // (The user does not swipe it away), when WebappActivity is relaunched it is relaunched
        // with the intent stored in WebappActivity#getIntent() at the time that the WebappActivity
        // was killed. WebappActivity may be relaunched from:

        // (A) An intent from WebappLauncherActivity (e.g. as a result of a notification or a deep
        // link). Android drops the intent from WebappLauncherActivity in favor of
        // WebappActivity#getIntent() at the time that the WebappActivity was killed.

        // (B) The user selecting the WebappActivity in recents. In case (A) we want to use the
        // intent sent to WebappLauncherActivity and ignore WebappActivity#getSavedInstanceState().
        // In case (B) we want to restore to saved tab state.
        if (info == null) {
            info = createWebappInfo(intent);
        } else if (info.shouldForceNavigation()) {
            // Don't restore to previous page, navigate using WebappInfo retrieved from cache.
            resetSavedInstanceState();
        }

        if (info == null) {
            // If {@link info} is null, there isn't much we can do, abort.
            ApiCompatibilityUtils.finishAndRemoveTask(this);
            return;
        }

        mWebappInfo = info;

        // Initialize the WebappRegistry and warm up the shared preferences for this web app. No-ops
        // if the registry and this web app are already initialized. Must override Strict Mode to
        // avoid a violation.
        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
        try {
            WebappRegistry.getInstance();
            WebappRegistry.warmUpSharedPrefsForId(id);
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }

        // When turning on TalkBack on Android, hitting app switcher to bring a WebappActivity to
        // front will speak "Web App", which is the label of WebappActivity. Therefore, we set title
        // of the WebappActivity explicitly to make it speak the short name of the Web App.
        setTitle(mWebappInfo.shortName());

        super.performPreInflationStartup();

        applyScreenOrientation();

        if (mWebappInfo.displayMode() == WebDisplayMode.FULLSCREEN) {
            enterImmersiveMode();
        }

        initSplash();
    }

    @Override
    public void finishNativeInitialization() {
        LayoutManager layoutDriver = new LayoutManager(getCompositorViewHolder());
        initializeCompositorContent(layoutDriver, findViewById(R.id.url_bar),
                (ViewGroup) findViewById(android.R.id.content),
                (ToolbarControlContainer) findViewById(R.id.control_container));
        getToolbarManager().initializeWithNative(getTabModelSelector(),
                getFullscreenManager().getBrowserVisibilityDelegate(), null, layoutDriver, null,
                null, null, view -> onToolbarCloseButtonClicked());
        getToolbarManager().setShowTitle(true);
        getToolbarManager().setCloseButtonDrawable(null); // Hides close button.

        getFullscreenManager().setTab(getActivityTab());
        super.finishNativeInitialization();
        mIsInitialized = true;
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mDirectoryManager.cancelCleanup();
        saveState(outState);
    }

    @Override
    public void onStartWithNative() {
        super.onStartWithNative();
        mDirectoryManager.cleanUpDirectories(this, getActivityId());
    }

    @Override
    public void onStopWithNative() {
        super.onStopWithNative();
        getFullscreenManager().exitPersistentFullscreenMode();
    }

    /**
     * Saves the tab data out to a file.
     */
    private void saveState(Bundle outState) {
        if (getActivityTab() == null || getActivityTab().getUrl() == null
                || getActivityTab().getUrl().isEmpty()) {
            return;
        }

        outState.putInt(BUNDLE_TAB_ID, getActivityTab().getId());

        String tabFileName = TabState.getTabStateFilename(getActivityTab().getId(), false);
        File tabFile = new File(getActivityDirectory(), tabFileName);

        // TODO(crbug.com/525785): Temporarily allowing disk access until more permanent fix is in.
        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
            TabState.saveState(tabFile, TabState.from(getActivityTab()), false);
        }
    }

    @Override
    protected TabState restoreTabState(Bundle savedInstanceState, int tabId) {
        return TabState.restoreTabState(getActivityDirectory(), tabId);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

        // Re-enter immersive mode after users switch back to this Activity.
        if (hasFocus) {
            asyncSetImmersive(ENTER_IMMERSIVE_MODE_DELAY_MILLIS);
        }
    }

    /**
     * Sets activity's decor view into an immersive mode.
     * If immersive mode is not supported, this method no-ops.
     */
    private void enterImmersiveMode() {
        // Immersive mode is only supported in API 19+.
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;

        if (mSetImmersiveRunnable == null) {
            final View decor = getWindow().getDecorView();

            mSetImmersiveRunnable = new Runnable() {
                @Override
                public void run() {
                    int currentFlags = decor.getSystemUiVisibility();
                    int desiredFlags = currentFlags | IMMERSIVE_MODE_UI_FLAGS;
                    if (currentFlags != desiredFlags) {
                        decor.setSystemUiVisibility(desiredFlags);
                    }
                }
            };

            // When we enter immersive mode for the first time, register a
            // SystemUiVisibilityChangeListener that restores immersive mode. This is necessary
            // because user actions like focusing a keyboard will break out of immersive mode.
            decor.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
                @Override
                public void onSystemUiVisibilityChange(int newFlags) {
                    if ((newFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                        asyncSetImmersive(RESTORE_IMMERSIVE_MODE_DELAY_MILLIS);
                    }
                }
            });
        }

        asyncSetImmersive(0);
    }

    /**
     * This method no-ops before {@link #enterImmersiveMode()} is called explicitly.
     */
    private void asyncSetImmersive(int delayInMills) {
        if (mSetImmersiveRunnable == null) return;

        mHandler.removeCallbacks(mSetImmersiveRunnable);
        mHandler.postDelayed(mSetImmersiveRunnable, delayInMills);
    }

    @Override
    public void onResume() {
        if (!isFinishing()) {
            if (getIntent() != null) {
                // Avoid situations where Android starts two Activities with the same data.
                DocumentUtils.finishOtherTasksWithData(getIntent().getData(), getTaskId());
            }
            updateTaskDescription();
        }
        super.onResume();
    }

    @Override
    public void onResumeWithNative() {
        super.onResumeWithNative();
        WebappActionsNotificationManager.maybeShowNotification(getActivityTab(), mWebappInfo);
        WebappDataStorage storage =
                WebappRegistry.getInstance().getWebappDataStorage(mWebappInfo.id());
        if (storage != null) {
            mDisclosureSnackbarController.maybeShowDisclosure(this, storage, false /* force */);
        }
    }

    @Override
    public void onPauseWithNative() {
        WebappActionsNotificationManager.cancelNotification();
        super.onPauseWithNative();
    }

    @Override
    protected void initDeferredStartupForActivity() {
        super.initDeferredStartupForActivity();

        WebappDataStorage storage =
                WebappRegistry.getInstance().getWebappDataStorage(mWebappInfo.id());
        if (storage != null) {
            onDeferredStartupWithStorage(storage);
        } else {
            onDeferredStartupWithNullStorage();
        }
    }

    @Override
    protected void recordIntentToCreationTime(long timeMs) {
        super.recordIntentToCreationTime(timeMs);

        RecordHistogram.recordTimesHistogram("MobileStartup.IntentToCreationTime.WebApp", timeMs);
    }

    protected void onDeferredStartupWithStorage(WebappDataStorage storage) {
        updateStorage(storage);
    }

    protected void onDeferredStartupWithNullStorage() {
        if (!mWebappInfo.isForWebApk()) return;

        // WebappDataStorage objects are cleared if a user clears Chrome's data. Recreate them
        // for WebAPKs since we need to store metadata for updates and disclosure notifications.
        WebappRegistry.getInstance().register(
                mWebappInfo.id(), new WebappRegistry.FetchWebappDataStorageCallback() {
                    @Override
                    public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                        if (isActivityFinishingOrDestroyed()) return;

                        onDeferredStartupWithStorage(storage);
                        // Set force == true to indicate that we need to show a privacy
                        // disclosure for the newly installed unbound WebAPKs which
                        // have no storage yet. We can't simply default to a showing if the
                        // storage has a default value as we don't want to show this disclosure
                        // for pre-existing unbound WebAPKs.
                        mDisclosureSnackbarController.maybeShowDisclosure(
                                WebappActivity.this, storage, true /* force */);
                    }
                });
    }

    @Override
    protected int getControlContainerLayoutId() {
        return R.layout.custom_tabs_control_container;
    }

    @Override
    protected int getToolbarLayoutId() {
        return R.layout.custom_tabs_toolbar;
    }

    @Override
    public AppMenuPropertiesDelegate createAppMenuPropertiesDelegate() {
        return new CustomTabAppMenuPropertiesDelegate(this, getActivityTabProvider(),
                getMultiWindowModeStateDispatcher(), getTabModelSelector(), getToolbarManager(),
                getWindow().getDecorView(),
                CustomTabIntentDataProvider.CustomTabsUiType.MINIMAL_UI_WEBAPP,
                new ArrayList<String>(), true /* is opened by Chrome */,
                true /* should show share */, false /* should show star (bookmarking) */,
                false /* should show download */, false /* is incognito */);
    }

    /**
     * @return Structure containing data about the webapp currently displayed.
     *         The return value should not be cached.
     */
    public WebappInfo getWebappInfo() {
        return mWebappInfo;
    }

    /**
     * @return A string containing the scope of the webapp opened in this activity.
     */
    public String getWebappScope() {
        return mWebappInfo.scopeUri().toString();
    }

    public static void addWebappInfo(String id, WebappInfo info) {
        Holder.sWebappInfoMap.put(id, info);
    }

    public static WebappInfo popWebappInfo(String id) {
        return Holder.sWebappInfoMap.remove(id);
    }

    protected void updateStorage(WebappDataStorage storage) {
        // The information in the WebappDataStorage may have been purged by the
        // user clearing their history or not launching the web app recently.
        // Restore the data if necessary from the intent.
        storage.updateFromShortcutIntent(getIntent());

        // A recent last used time is the indicator that the web app is still
        // present on the home screen, and enables sources such as notifications to
        // launch web apps. Thus, we do not update the last used time when the web
        // app is not directly launched from the home screen, as this interferes
        // with the heuristic.
        if (mWebappInfo.isLaunchedFromHomescreen()) {
            boolean previouslyLaunched = storage.hasBeenLaunched();
            long previousUsageTimestamp = storage.getLastUsedTimeMs();
            storage.setHasBeenLaunched();
            // TODO(yusufo): WebappRegistry#unregisterOldWebapps uses this information to delete
            // WebappDataStorage objects for legacy webapps which haven't been used in a while.
            // That will need to be updated to not delete anything for a TWA which remains installed
            storage.updateLastUsedTime();
            onUpdatedLastUsedTime(storage, previouslyLaunched, previousUsageTimestamp);
        }
    }

    /**
     * Called after updating the last used time in {@link WebappDataStorage}.
     * @param previouslyLaunched Whether the webapp has been previously launched from the home
     *     screen.
     * @param previousUsageTimestamp The previous time that the webapp was used.
     */
    protected void onUpdatedLastUsedTime(
            WebappDataStorage storage, boolean previouslyLaunched, long previousUsageTimestamp) {}

    protected TabObserver createTabObserver() {
        return new EmptyTabObserver() {
            @Override
            public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) {
                if (navigation.hasCommitted() && navigation.isInMainFrame()) {
                    // Notify the renderer to permanently hide the top controls since they do
                    // not apply to fullscreen content views.
                    TabBrowserControlsState.update(
                            tab, TabBrowserControlsState.getConstraints(tab), true);

                    RecordHistogram.recordBooleanHistogram(
                            HISTOGRAM_NAVIGATION_STATUS, !navigation.isErrorPage());

                    updateToolbarCloseButtonVisibility();

                    if (!WebappScopePolicy.isUrlInScope(
                                scopePolicy(), mWebappInfo, navigation.getUrl())) {
                        // Briefly show the toolbar for off-scope navigations.
                        getFullscreenManager()
                                .getBrowserVisibilityDelegate()
                                .showControlsTransient();
                    }
                }
            }

            @Override
            public void onDidChangeThemeColor(Tab tab, int color) {
                mBrandColor = color;
                updateTaskDescription();
            }

            @Override
            public void onTitleUpdated(Tab tab) {
                updateTaskDescription();
            }

            @Override
            public void onFaviconUpdated(Tab tab, Bitmap icon) {
                // No need to cache the favicon if there is an icon declared in app manifest.
                if (mWebappInfo.icon() != null || icon == null) return;
                if (mLargestFavicon == null || icon.getWidth() > mLargestFavicon.getWidth()
                        || icon.getHeight() > mLargestFavicon.getHeight()) {
                    mLargestFavicon = icon;
                    updateTaskDescription();
                }
            }

            @Override
            public void onDidAttachInterstitialPage(Tab tab) {
                int state = ApplicationStatus.getStateForActivity(WebappActivity.this);
                if (state == ActivityState.PAUSED || state == ActivityState.STOPPED
                        || state == ActivityState.DESTROYED) {
                    return;
                }

                // Kick the interstitial navigation to Chrome.
                Intent intent =
                        new Intent(Intent.ACTION_VIEW, Uri.parse(getActivityTab().getUrl()));
                intent.setPackage(getPackageName());
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                IntentHandler.startChromeLauncherActivityForTrustedIntent(intent);

                // Pretend like the navigation never happened.  We delay so that this happens while
                // the Activity is in the background.
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (getActivityTab().canGoBack()) {
                            getActivityTab().goBack();
                        } else {
                            if (mWebappInfo.isSplashProvidedByWebApk()) {
                                // We need to call into WebAPK to finish activity stack because:
                                // 1) WebApkActivity is not the root of the task.
                                // 2) The activity stack no longer has focus and thus cannot rely on
                                //    the client's Activity#onResume() behaviour.
                                WebApkServiceClient.getInstance().finishAndRemoveTaskSdk23(
                                        (WebApkActivity) WebappActivity.this);
                            } else {
                                ApiCompatibilityUtils.finishAndRemoveTask(WebappActivity.this);
                            }
                        }
                    }
                }, MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL);
            }
        };
    }

    public @WebappScopePolicy.Type int scopePolicy() {
        return WebappScopePolicy.Type.LEGACY;
    }

    /**
     * @return The package name if this Activity is associated with an APK. Null if there is no
     *         associated Android native client.
     */
    public @Nullable String getWebApkPackageName() {
        return null;
    }

    private void updateToolbarCloseButtonVisibility() {
        if (WebappBrowserControlsDelegate.shouldShowToolbarCloseButton(this)) {
            getToolbarManager().setCloseButtonDrawable(
                    TintedDrawable.constructTintedDrawable(this, R.drawable.btn_close));
            // Applies light or dark tint to icons depending on the theme color.
            getToolbarManager().updateLocationBarVisualsForState();
        } else {
            getToolbarManager().setCloseButtonDrawable(null);
        }
    }

    /**
     * Moves the user back in history to most recent on-origin location.
     */
    private void onToolbarCloseButtonClicked() {
        NavigationController nc = getActivityTab().getWebContents().getNavigationController();

        final int lastIndex = nc.getLastCommittedEntryIndex();
        int index = lastIndex;
        while (index > 0
                && !WebappScopePolicy.isUrlInScope(
                           scopePolicy(), getWebappInfo(), nc.getEntryAtIndex(index).getUrl())) {
            index--;
        }

        if (index != lastIndex) {
            nc.goToNavigationIndex(index);
        }
    }

    private void updateTaskDescription() {
        String title = null;
        if (!TextUtils.isEmpty(mWebappInfo.shortName())) {
            title = mWebappInfo.shortName();
        } else if (getActivityTab() != null) {
            title = getActivityTab().getTitle();
        }

        Bitmap icon = null;
        if (mWebappInfo.icon() != null) {
            icon = mWebappInfo.icon();
        } else if (getActivityTab() != null) {
            icon = mLargestFavicon;
        }

        if (mBrandColor == null && mWebappInfo.hasValidThemeColor()) {
            mBrandColor = (int) mWebappInfo.themeColor();
        }

        int taskDescriptionColor =
                ApiCompatibilityUtils.getColor(getResources(), R.color.default_primary_color);

        // Don't use the brand color for the status bars if we're in display: fullscreen. This works
        // around an issue where the status bars go transparent and can't be seen on top of the page
        // content when users swipe them in or they appear because the on-screen keyboard was
        // triggered.
        if (mBrandColor != null && mWebappInfo.displayMode() != WebDisplayMode.FULLSCREEN) {
            taskDescriptionColor = mBrandColor;
            if (getToolbarManager() != null) {
                getToolbarManager().onThemeColorChanged(mBrandColor, false);
            }
        }

        ApiCompatibilityUtils.setTaskDescription(this, title, icon,
                ColorUtils.getOpaqueColor(taskDescriptionColor));
        getStatusBarColorController().updateStatusBarColor(isStatusBarDefaultThemeColor());
    }

    @Override
    public int getBaseStatusBarColor() {
        return isStatusBarDefaultThemeColor() ? Color.BLACK : mBrandColor;
    }

    @Override
    public boolean isStatusBarDefaultThemeColor() {
        // Don't use the brand color for the status bars if we're in display: fullscreen. This works
        // around an issue where the status bars go transparent and can't be seen on top of the page
        // content when users swipe them in or they appear because the on-screen keyboard was
        // triggered.
        return mBrandColor == null || mWebappInfo.displayMode() == WebDisplayMode.FULLSCREEN;
    }

    @Override
    public boolean onMenuOrKeyboardAction(int id, boolean fromMenu) {
        if (id == R.id.open_in_browser_id) {
            openCurrentUrlInChrome();
            if (fromMenu) {
                RecordUserAction.record("WebappMenuOpenInChrome");
            } else {
                RecordUserAction.record("Webapp.NotificationOpenInChrome");
            }
            return true;
        }
        return super.onMenuOrKeyboardAction(id, fromMenu);
    }

    /**
     * Opens the URL currently being displayed in the browser by reparenting the tab.
     */
    private boolean openCurrentUrlInChrome() {
        Tab tab = getActivityTab();
        if (tab == null) return false;

        String url = tab.getOriginalUrl();
        if (TextUtils.isEmpty(url)) {
            url = IntentHandler.getUrlFromIntent(getIntent());
        }

        // TODO(piotrs): Bring reparenting back once CCT animation is fixed. See crbug/774326
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setClass(this, ChromeLauncherActivity.class);
        IntentHandler.startActivityForTrustedIntent(intent);

        return true;
    }

    /**
     * Returns a unique identifier for this WebappActivity.
     * Note: do not call this function when you need {@link WebappInfo#id()}. Subclasses like
     * WebappManagedActivity and WebApkManagedActivity overwrite this function and return the
     * index of the activity.
     */
    protected String getActivityId() {
        return mWebappInfo.id();
    }

    /**
     * Get the active directory by this web app.
     *
     * @return The directory used for the current web app.
     */
    private File getActivityDirectory() {
        return mDirectoryManager.getWebappDirectory(this, getActivityId());
    }

    @VisibleForTesting
    View getSplashScreenForTests() {
        return mSplashController.getSplashScreenForTests();
    }

    @Override
    public int getControlContainerHeightResource() {
        return R.dimen.custom_tabs_control_container_height;
    }

    @Override
    protected Drawable getBackgroundDrawable() {
        return null;
    }

    @Override
    protected TabDelegateFactory createTabDelegateFactory() {
        return new WebappDelegateFactory(this);
    }

    @Override
    protected TabDelegate createTabDelegate(boolean incognito) {
        return new WebappTabDelegate(incognito, mWebappInfo);
    }

    // We're temporarily disable CS on webapp since there are some issues. (http://crbug.com/471950)
    // TODO(changwan): re-enable it once the issues are resolved.
    @Override
    protected boolean isContextualSearchAllowed() {
        return false;
    }

    /** Inits the splash screen */
    protected void initSplash() {
        // Splash screen is shown after preInflationStartup() is run and the delegate is set.
        boolean isWindowInitiallyTranslucent = mWebappInfo.isSplashProvidedByWebApk();
        mSplashController.setConfig(new WebappSplashDelegate(this, getLifecycleDispatcher(),
                                            mTabObserverRegistrar, mWebappInfo),
                isWindowInitiallyTranslucent, WebappSplashDelegate.HIDE_ANIMATION_DURATION_MS);
    }

    /** Sets the screen orientation. */
    private void applyScreenOrientation() {
        if (mWebappInfo.isSplashProvidedByWebApk()
                && Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
            // When the splash screen is provided by the WebAPK, the activity is initially
            // translucent. Setting the screen orientation while the activity is translucent
            // throws an exception on O (but not O MR1). Delay setting it.
            ScreenOrientationProvider.getInstance().delayOrientationRequests(getWindowAndroid());

            addSplashscreenObserver(new SplashscreenObserver() {
                @Override
                public void onTranslucencyRemoved() {
                    ScreenOrientationProvider.getInstance().runDelayedOrientationRequests(
                            getWindowAndroid());
                }

                @Override
                public void onSplashscreenHidden(long startTimestamp, long endTimestamp) {}
            });

            // Fall through and queue up request for the default screen orientation because the web
            // page might change it via JavaScript.
        }
        ScreenOrientationProvider.getInstance().lockOrientation(
                getWindowAndroid(), (byte) mWebappInfo.orientation());
    }

    /**
     * Register an observer to the splashscreen hidden/visible events for this activity.
     */
    protected void addSplashscreenObserver(SplashscreenObserver observer) {
        mSplashController.addObserver(observer);
    }

    /**
     * Deregister an observer to the splashscreen hidden/visible events for this activity.
     */
    protected void removeSplashscreenObserver(SplashscreenObserver observer) {
        mSplashController.removeObserver(observer);
    }
}
