text:
<!DOCTYPE html>

        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="viewport" content="user-scalable=no, initial-scale=1, width=device-width, viewport-fit=cover" />
		<meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="mobile-web-app-capable" content="yes">

	    <link rel="apple-touch-icon" href="icons/apple-icon-152x152.png" />
		<link rel="apple-touch-icon" sizes="128x128" href="icon.png">
		<link rel="icon" type="image/x-icon" href="icons/favicon-16x16.png" />

		<link rel="apple-touch-icon" sizes="57x57" href="icons/apple-icon-57x57.png">
		<link rel="apple-touch-icon" sizes="60x60" href="icons/apple-icon-60x60.png">
		<link rel="apple-touch-icon" sizes="72x72" href="icons/apple-icon-72x72.png">
		<link rel="apple-touch-icon" sizes="76x76" href="icons/apple-icon-76x76.png">
		<link rel="apple-touch-icon" sizes="114x114" href="icons/apple-icon-114x114.png">
		<link rel="apple-touch-icon" sizes="120x120" href="icons/apple-icon-120x120.png">
		<link rel="apple-touch-icon" sizes="144x144" href="icons/apple-icon-144x144.png">
		<link rel="apple-touch-icon" sizes="152x152" href="icons/apple-icon-152x152.png">
		<link rel="apple-touch-icon" sizes="180x180" href="icons/apple-icon-180x180.png">
		<link rel="icon" type="image/png" sizes="192x192"  href="icons/android-icon-192x192.png">
		<link rel="icon" type="image/png" sizes="48x48" href="icons/windows-icon-48x48.png">
		<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png">
		<link rel="icon" type="image/png" sizes="96x96" href="icons/favicon-96x96.png">
		<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png">
		<link rel="icon" type="image/png" sizes="256x256" href="icons/windows-icon-256x256.png">
		<link rel="icon" type="image/png" sizes="24x24" href="icons/windows-icon-24x24.png">
		<link rel="manifest" href="icons/manifest.json">
		<meta name="msapplication-TileColor" content="#ffffff">
		<meta name="msapplication-TileImage" content="icons/ms-icon-144x144.png">
		<meta name="theme-color" content="#ffffff">

	    <meta http-equiv="Content-Security-Policy" content="default-src * https://medimage-pair.atomjump.com http://127.0.0.1:5566 http://localhost:5566;  script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src * blob; img-src 'self' data:; connect-src *;">

		<link rel="stylesheet" href="css/onsenui.css"/>
		<link rel="stylesheet" href="css/onsen-css-components-purple-theme.css">

    	<link rel="stylesheet" type="text/css" href="css/ionicons/css/ionicons.css">
    	<link rel="stylesheet" type="text/css" href="css/material-design-iconic-font/css/material-design-iconic-font.css">

        <link rel="stylesheet" type="text/css" href="css/index.css" />
        <title>MedImage</title>

    	<ons-navigator>
         <ons-page>

		    <ons-fab style="z-index: 800;" position="bottom right" onclick="app.openSettings();">
		      <ons-icon icon="md-menu" ></ons-icon>
		    </ons-fab>

		    <ons-fab style="z-index: 800;" position="bottom left" onclick="showDefaultPlatform();">
		      <ons-icon icon="md-bookmark" ></ons-icon>
		    </ons-fab>

             Image ID (e.g. NHI) <ons-icon icon="ion-ios-help" size="20px" fixed-width="true">
<input id="id-entered" type="text" size="9" class="resizedTextbox" value="">

       		<input class="file" type="file" id="mypic" accept="image/jpeg" capture="camera">

					Add app to your Homescreen <ons-icon size="30px" style="color: black;" icon="md-close"></ons-icon>
iOS Android Desktop

Tap , usually along the bottom of the screen, then swipe up, and tap 'Add to Home Screen'. More Info

						Troubleshooting: if you don't see the 'Add to Home Screen' option, scroll to the bottom and tap 'Edit Actions', then tap 'Add' next to the 'Add to Home Screen'. After that, try again. Or see Apple's Guide

Tap the  in the top right corner of the screen, and then choose 'Add to Home Screen'. More Details

Click the  or  or  style icon in the address bar, to the left of the address, and depending on the browser, drag this onto your desktop. More Details

In Edge on Windows, use  > "Apps" > "Install this site as an app".

        		Settings

        		<ons-fab position="top right" onclick="app.closeSettings();">
		      		<ons-icon icon="md-close" ></ons-icon>
		    	</ons-fab>

        			<ons-button style="background-color: #7c5599; color: white;" modifier="large" onclick="app.newServer();">Add a New PC</ons-button>

	        	 <ons-list>
					<ons-list-item>

						ID writes a folder

						<ons-switch style="color: #7c5599;" id="always-create-folder" checked></ons-switch>

					</ons-list-item>
					<ons-list-item>

								Version: 2.2.4

					</ons-list-item>
				  </ons-list>

					Reset Factory Settings

		<form id="photo-sending-frm" method="post" action="/replaced-dynamically-with-medimage-server-path/">
		</form>

        <ons-icon style="vertical-align: middle; color:#f7afbb; filter:alpha(opacity: 0); opacity: 0; -moz-opacity:0;" size="30px" icon="fa-close"></ons-icon>
        <ons-icon style="vertical-align: middle; color:#DDD; filter:alpha(opacity: 0); opacity: 0; -moz-opacity:0;" size="20px" spin icon="fa-spinner"></ons-icon>

       <canvas style="display: none;"></canvas>

     </ons-page>

    </ons-navigator>


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<TITLE>
Àà cn.iaicc.smgk.po.PassPercentageInfo µÄʹÓà (ÉñÃع˿͹ÜÀíƽ̨ API)
</TITLE>

<META NAME="date" CONTENT="2008-11-20">

<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../stylesheet.css" TITLE="Style">

      ¸ÅÊö
      Èí¼þ°ü
      Àà
    ʹÓÃ
      Ê÷
      Òѹýʱ
      Ë÷Òý
      °ïÖú

 ÉÏÒ»¸ö
 ÏÂÒ»¸ö

  ¿ò¼Ü
 ÎÞ¿ò¼Ü

  ËùÓÐÀà

Àà cn.iaicc.smgk.po.PassPercentageInfo
µÄʹÓÃ

ʹÓà PassPercentageInfo µÄÈí¼þ°ü

cn.iaicc.smgk.business

cn.iaicc.smgk.business.service

cn.iaicc.smgk.dao

cn.iaicc.smgk.dao.hibernate

cn.iaicc.smgk.business ÖÐ PassPercentageInfo µÄʹÓÃ

·µ»Ø PassPercentageInfo µÄ cn.iaicc.smgk.business Öеķ½·¨

 PassPercentageInfo
IPassPercentageInfoService.getPassPercentageInfo(java.lang.Long newID)

          »ñÈ¡ÐÂÎÅÐÅÏ¢

·µ»Ø±äÁ¿ÀàÐÍΪ PassPercentageInfo µÄÀàÐ굀 cn.iaicc.smgk.business Öеķ½·¨

 java.util.List<PassPercentageInfo>
IPassPercentageInfoService.findPassPercentageInfoByPage(int firstResult,
                             int maxResult)

          ·ÖÒ³ÐÅÏ¢

 java.util.List<PassPercentageInfo>
IPassPercentageInfoService.getPassPercentageInfoList()

          »ñÈ¡ÐÂÎÅÐÅÏ¢Áбí

²ÎÊýÀàÐÍΪ PassPercentageInfo µÄ cn.iaicc.smgk.business Öеķ½·¨

 void
IPassPercentageInfoService.deletePassPercentageInfo(PassPercentageInfo data)

          ɾ³ýÐÂÎÅÐÅÏ¢

 void
IPassPercentageInfoService.savePassPercentageInfo(PassPercentageInfo data)

          ±£´æÐÂÎÅÐÅÏ¢

 void
IPassPercentageInfoService.updatePassPercentageInfo(PassPercentageInfo data)

          ¸üÐÂÐÂÎÅÐÅÏ¢

cn.iaicc.smgk.business.service ÖÐ PassPercentageInfo µÄʹÓÃ

·µ»Ø PassPercentageInfo µÄ cn.iaicc.smgk.business.service Öеķ½·¨

 PassPercentageInfo
PassPercentageInfoService.getPassPercentageInfo(java.lang.Long newsID)

·µ»Ø±äÁ¿ÀàÐÍΪ PassPercentageInfo µÄÀàÐ굀 cn.iaicc.smgk.business.service Öеķ½·¨

 java.util.List<PassPercentageInfo>
PassPercentageInfoService.findPassPercentageInfoByPage(int firstResult,
                             int maxResult)

 java.util.List<PassPercentageInfo>
PassPercentageInfoService.getPassPercentageInfoList()

²ÎÊýÀàÐÍΪ PassPercentageInfo µÄ cn.iaicc.smgk.business.service Öеķ½·¨

 void
PassPercentageInfoService.deletePassPercentageInfo(PassPercentageInfo data)

 void
PassPercentageInfoService.savePassPercentageInfo(PassPercentageInfo data)

 void
PassPercentageInfoService.updatePassPercentageInfo(PassPercentageInfo data)

cn.iaicc.smgk.dao ÖÐ PassPercentageInfo µÄʹÓÃ

·µ»Ø PassPercentageInfo µÄ cn.iaicc.smgk.dao Öеķ½·¨

 PassPercentageInfo
IPassPercentageInfoDao.getPassPercentageInfo(java.lang.Long newID)

          »ñÈ¡ÍøÕ¾ÐÂÎÅÐÅÏ¢

·µ»Ø±äÁ¿ÀàÐÍΪ PassPercentageInfo µÄÀàÐ굀 cn.iaicc.smgk.dao Öеķ½·¨

 java.util.List<PassPercentageInfo>
IPassPercentageInfoDao.findByPage(int firstResult,
           int maxResult)

          ·ÖÒ³ÐÅÏ¢

 java.util.List<PassPercentageInfo>
IPassPercentageInfoDao.getPassPercentageInfoList()

          »ñÈ¡ÍøÕ¾ÐÂÎÅÐÅÏ¢Áбí

²ÎÊýÀàÐÍΪ PassPercentageInfo µÄ cn.iaicc.smgk.dao Öеķ½·¨

 void
IPassPercentageInfoDao.delete(PassPercentageInfo data)

          ɾ³ýÍøÕ¾ÐÂÎÅÐÅÏ¢

 void
IPassPercentageInfoDao.save(PassPercentageInfo data)

          ±£´æÍøÕ¾ÐÂÎÅÐÅÏ¢

 void
IPassPercentageInfoDao.update(PassPercentageInfo data)

          ¸üÐÂÍøÕ¾ÐÂÎÅÐÅÏ¢

cn.iaicc.smgk.dao.hibernate ÖÐ PassPercentageInfo µÄʹÓÃ

·µ»Ø PassPercentageInfo µÄ cn.iaicc.smgk.dao.hibernate Öеķ½·¨

 PassPercentageInfo
PassPercentageInfoDao.getPassPercentageInfo(java.lang.Long passPercentageID)

          ¸ù¾Ý±àºÅ»ñÈ¡ÐÅÏ¢Áбí

·µ»Ø±äÁ¿ÀàÐÍΪ PassPercentageInfo µÄÀàÐ굀 cn.iaicc.smgk.dao.hibernate Öеķ½·¨

 java.util.List<PassPercentageInfo>
PassPercentageInfoDao.findByPage(int firstResult,
           int maxResult)

          ͨ¹ýÖ¸¶¨µÄÆð'ÊýºÍ½áÊøÊýµÃµ½Ò»¸ö¼¯ºÏ

 java.util.List<PassPercentageInfo>
PassPercentageInfoDao.getPassPercentageInfoList()

          »ñÈ¡ÁбíÐÅÏ¢

²ÎÊýÀàÐÍΪ PassPercentageInfo µÄ cn.iaicc.smgk.dao.hibernate Öеķ½·¨

 void
PassPercentageInfoDao.delete(PassPercentageInfo data)

          ɾ³ýÍøÕ¾ÐÂÎÅÐÅÏ¢

 void
PassPercentageInfoDao.save(PassPercentageInfo data)

          ±£´æÍøÕ¾ÐÂÎÅÐÅÏ¢

 void
PassPercentageInfoDao.update(PassPercentageInfo data)

          ¸üб¨¸æ·ÒëÐÅÏ¢

      ¸ÅÊö
      Èí¼þ°ü
      Àà
    ʹÓÃ
      Ê÷
      Òѹýʱ
      Ë÷Òý
      °ïÖú

 ÉÏÒ»¸ö
 ÏÂÒ»¸ö

  ¿ò¼Ü
 ÎÞ¿ò¼Ü

  ËùÓÐÀà

Copyright © 2008 ±±¾©°¬µÏÖÇÈíÐÅÏ¢¼¼ÊõÓÐÏÞÔðÈι«Ë¾. All Rights Reserved.
http://www.idea-soft.cn http://www.iaicc.cn http://www.xsaas.org

redpajama_set_name: RedPajamaGithub


text:
/* eslint-disable @typescript-eslint/no-var-requires */
module.exports = {
  plugins: [
    require("tailwindcss")("tailwind.config.js"),
    require("autoprefixer")(),
  ],
};


text:
// 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.annotation.TargetApi;
import android.app.Activity;
import android.app.SearchManager;
import android.app.assist.AssistContent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.os.SystemClock;
import android.support.v7.app.AlertDialog;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewStub;
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 org.chromium.base.ActivityState;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.BaseSwitches;
import org.chromium.base.Callback;
import org.chromium.base.CommandLine;
import org.chromium.base.ObserverList;
import org.chromium.base.SysUtils;
import org.chromium.base.TraceEvent;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
import org.chromium.chrome.browser.IntentHandler.TabOpenType;
import org.chromium.chrome.browser.appmenu.AppMenu;
import org.chromium.chrome.browser.appmenu.AppMenuHandler;
import org.chromium.chrome.browser.appmenu.AppMenuObserver;
import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
import org.chromium.chrome.browser.blimp.ChromeBlimpClientContextDelegate;
import org.chromium.chrome.browser.bookmarks.BookmarkModel;
import org.chromium.chrome.browser.bookmarks.BookmarkUtils;
import org.chromium.chrome.browser.compositor.CompositorViewHolder;
import org.chromium.chrome.browser.compositor.layouts.Layout;
import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
import org.chromium.chrome.browser.compositor.layouts.LayoutManagerDocument;
import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver;
import org.chromium.chrome.browser.compositor.layouts.content.ContentOffsetProvider;
import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial;
import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager.ContextualSearchTabPromotionDelegate;
import org.chromium.chrome.browser.datausage.DataUseTabUIManager;
import org.chromium.chrome.browser.device.DeviceClassManager;
import org.chromium.chrome.browser.dom_distiller.DistilledPagePrefsView;
import org.chromium.chrome.browser.dom_distiller.ReaderModeManager;
import org.chromium.chrome.browser.download.DownloadManagerService;
import org.chromium.chrome.browser.download.DownloadUtils;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.gsa.ContextReporter;
import org.chromium.chrome.browser.gsa.GSAAccountChangeListener;
import org.chromium.chrome.browser.gsa.GSAState;
import org.chromium.chrome.browser.help.HelpAndFeedback;
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.StartupMetrics;
import org.chromium.chrome.browser.metrics.UmaSessionStats;
import org.chromium.chrome.browser.metrics.UmaUtils;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
import org.chromium.chrome.browser.nfc.BeamController;
import org.chromium.chrome.browser.nfc.BeamProvider;
import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper;
import org.chromium.chrome.browser.pageinfo.WebsiteSettingsPopup;
import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.preferences.PreferencesLauncher;
import org.chromium.chrome.browser.printing.PrintShareActivity;
import org.chromium.chrome.browser.printing.TabPrinter;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.share.ShareHelper;
import org.chromium.chrome.browser.snackbar.DataReductionPromoSnackbarController;
import org.chromium.chrome.browser.snackbar.DataUseSnackbarController;
import org.chromium.chrome.browser.snackbar.SnackbarManager;
import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable;
import org.chromium.chrome.browser.sync.ProfileSyncService;
import org.chromium.chrome.browser.sync.SyncController;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
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.toolbar.Toolbar;
import org.chromium.chrome.browser.toolbar.ToolbarControlContainer;
import org.chromium.chrome.browser.toolbar.ToolbarManager;
import org.chromium.chrome.browser.util.ChromeFileProvider;
import org.chromium.chrome.browser.util.ColorUtils;
import org.chromium.chrome.browser.util.FeatureUtilities;
import org.chromium.chrome.browser.webapps.AddToHomescreenManager;
import org.chromium.chrome.browser.widget.ControlContainer;
import org.chromium.components.bookmarks.BookmarkId;
import org.chromium.content.browser.ContentVideoView;
import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.common.ContentSwitches;
import org.chromium.content_public.browser.ContentBitmapCallback;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.readback_types.ReadbackResponse;
import org.chromium.policy.CombinedPolicyProvider;
import org.chromium.policy.CombinedPolicyProvider.PolicyChangeListener;
import org.chromium.printing.PrintManagerDelegateImpl;
import org.chromium.printing.PrintingController;
import org.chromium.printing.PrintingControllerImpl;
import org.chromium.ui.base.ActivityWindowAndroid;
import org.chromium.ui.base.DeviceFormFactor;
import org.chromium.ui.base.PageTransition;
import org.chromium.ui.base.WindowAndroid;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * A {@link AsyncInitializationActivity} that builds and manages a {@link CompositorViewHolder}
 * and associated classes.
 */
public abstract class ChromeActivity extends AsyncInitializationActivity
        implements TabCreatorManager, AccessibilityStateChangeListener, PolicyChangeListener,
        ContextualSearchTabPromotionDelegate, SnackbarManageable, SceneChangeObserver {
    /**
     * Factory which creates the AppMenuHandler.
     */
    public interface AppMenuHandlerFactory {
        /**
         * @return AppMenuHandler for the given activity and menu resource id.
         */
        public AppMenuHandler get(Activity activity, AppMenuPropertiesDelegate delegate,
                int menuResourceId);
    }

    /**
     * No control container to inflate during initialization.
     */
    static final int NO_CONTROL_CONTAINER = -1;

    /**
     * No toolbar layout to inflate during initialization.
     */
    static final int NO_TOOLBAR_LAYOUT = -1;

    private static final int RECORD_MULTI_WINDOW_SCREEN_WIDTH_DELAY_MS = 5000;

    /**
     * Timeout in ms for reading PartnerBrowserCustomizations provider.
     */
    private static final int PARTNER_BROWSER_CUSTOMIZATIONS_TIMEOUT_MS = 10000;
    private static final String TAG = "ChromeActivity";
    private static final Rect EMPTY_RECT = new Rect();

    private static AppMenuHandlerFactory sAppMenuHandlerFactory = new AppMenuHandlerFactory() {
        @Override
        public AppMenuHandler get(
                Activity activity, AppMenuPropertiesDelegate delegate, int menuResourceId) {
            return new AppMenuHandler(activity, delegate, menuResourceId);
        }
    };

    private TabModelSelector mTabModelSelector;
    private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
    private TabCreatorManager.TabCreator mRegularTabCreator;
    private TabCreatorManager.TabCreator mIncognitoTabCreator;
    private TabContentManager mTabContentManager;
    private UmaSessionStats mUmaSessionStats;
    private ContextReporter mContextReporter;

    private boolean mPartnerBrowserRefreshNeeded;

    protected IntentHandler mIntentHandler;

    private boolean mDeferredStartupPosted;
    private boolean mTabModelsInitialized;

    // 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.
    @SuppressLint("NewApi")
    private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener;

    // Observes when sync becomes ready to create the mContextReporter.
    private ProfileSyncService.SyncStateChangedListener mSyncStateChangedListener;

    private ActivityWindowAndroid mWindowAndroid;

    private ChromeFullscreenManager mFullscreenManager;
    private boolean mCreatedFullscreenManager;

    private CompositorViewHolder mCompositorViewHolder;
    private InsetObserverView mInsetObserverView;
    private ContextualSearchManager mContextualSearchManager;
    private ReaderModeManager mReaderModeManager;
    private SnackbarManager mSnackbarManager;
    private DataUseSnackbarController mDataUseSnackbarController;
    private DataReductionPromoSnackbarController mDataReductionPromoSnackbarController;
    private AppMenuPropertiesDelegate mAppMenuPropertiesDelegate;
    private AppMenuHandler mAppMenuHandler;
    private ToolbarManager mToolbarManager;

    // Time in ms that it took took us to inflate the initial layout
    private long mInflateInitialLayoutDurationMs;

    private int mScreenWidthDp;
    private Runnable mRecordMultiWindowModeScreenWidthRunnable;

    private AssistStatusHandler mAssistStatusHandler;

    // A set of views obscuring all tabs. When this set is nonempty,
    // all tab content will be hidden from the accessibility tree.
    private List<View> mViewsObscuringAllTabs = new ArrayList<>();

    // Callbacks to be called when a context menu is closed.
    private final ObserverList<Callback<Menu>> mContextMenuCloseObservers = new ObserverList<>();

    // See enableHardwareAcceleration()
    private boolean mSetWindowHWA;

    // Chrome delegate that includes functionalities needed by Blimp client.
    private ChromeBlimpClientContextDelegate mBlimpClientContextDelegate;

    // Skips capturing screenshot for testing purpose.
    private boolean mScreenshotCaptureSkippedForTesting;

    /**
     * @param The {@link AppMenuHandlerFactory} for creating {@link mAppMenuHandler}
     */
    @VisibleForTesting
    public static void setAppMenuHandlerFactoryForTesting(AppMenuHandlerFactory factory) {
        sAppMenuHandlerFactory = factory;
    }

    @Override
    public void preInflationStartup() {
        super.preInflationStartup();

        // Force a partner customizations refresh if it has yet to be initialized.  This can happen
        // if Chrome is killed and you refocus a previous activity from Android recents, which does
        // not go through ChromeLauncherActivity that would have normally triggered this.
        mPartnerBrowserRefreshNeeded = !PartnerBrowserCustomizations.isInitialized();

        ApplicationInitialization.enableFullscreenFlags(
                getResources(), this, getControlContainerHeightResource());
        getWindow().setBackgroundDrawable(getBackgroundDrawable());
        mWindowAndroid = new ChromeWindow(this);
        mWindowAndroid.restoreInstanceState(getSavedInstanceState());

        mFullscreenManager = createFullscreenManager();
        mCreatedFullscreenManager = true;
    }

    @SuppressLint("NewApi")
    @Override
    public void postInflationStartup() {
        super.postInflationStartup();

        mSnackbarManager = new SnackbarManager(this);
        mDataUseSnackbarController = new DataUseSnackbarController(this, getSnackbarManager());

        mAssistStatusHandler = createAssistStatusHandler();
        if (mAssistStatusHandler != null) {
            if (mTabModelSelector != null) {
                mAssistStatusHandler.setTabModelSelector(mTabModelSelector);
            }
            mAssistStatusHandler.updateAssistState();
        }

        // If a user had ALLOW_LOW_END_DEVICE_UI explicitly set to false then we manually override
        // SysUtils.isLowEndDevice() with a switch so that they continue to see the normal UI. This
        // is only the case for grandfathered-in svelte users. We no longer do so for newer users.
        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);
        }

        // Make the activity listen to policy change events
        CombinedPolicyProvider.get().addPolicyChangeListener(this);

        // Set up the animation placeholder to be the SurfaceView. This disables the
        // SurfaceView's 'hole' clipping during animations that are notified to the window.
        mWindowAndroid.setAnimationPlaceholderView(mCompositorViewHolder.getSurfaceView());

        // Inform the WindowAndroid of the keyboard accessory view.
        mWindowAndroid.setKeyboardAccessoryView((ViewGroup) findViewById(R.id.keyboard_accessory));
        initializeToolbar();
        initializeTabModels();
        if (!isFinishing() && getFullscreenManager() != null) {
            getFullscreenManager().initialize(
                    (ControlContainer) findViewById(R.id.control_container),
                    getTabModelSelector(),
                    getControlContainerHeightResource());
        }
    }

    @Override
    protected View getViewToBeDrawnBeforeInitializingNative() {
        View controlContainer = findViewById(R.id.control_container);
        return controlContainer != null ? controlContainer
                : super.getViewToBeDrawnBeforeInitializingNative();
    }

    /**
     * This function builds the {@link CompositorViewHolder}.  Subclasses *must* call
     * super.setContentView() before using {@link #getTabModelSelector()} or
     * {@link #getCompositorViewHolder()}.
     */
    @Override
    protected final void setContentView() {
        final long begin = SystemClock.elapsedRealtime();
        TraceEvent.begin("onCreate->setContentView()");

        enableHardwareAcceleration();
        setLowEndTheme();
        int controlContainerLayoutId = getControlContainerLayoutId();
        WarmupManager warmupManager = WarmupManager.getInstance();
        if (warmupManager.hasViewHierarchyWithToolbar(controlContainerLayoutId)) {
            View placeHolderView = new View(this);
            setContentView(placeHolderView);
            ViewGroup contentParent = (ViewGroup) placeHolderView.getParent();
            warmupManager.transferViewHierarchyTo(contentParent);
            contentParent.removeView(placeHolderView);
        } else {
            warmupManager.clearViewHierarchy();

            // Allow disk access for the content view and toolbar container setup.
            // On certain android devices this setup sequence results in disk writes outside
            // of our control, so we have to disable StrictMode to work. See crbug.com/639352.
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
            try {
                setContentView(R.layout.main);
                if (controlContainerLayoutId != NO_CONTROL_CONTAINER) {
                    ViewStub toolbarContainerStub =
                            ((ViewStub) findViewById(R.id.control_container_stub));
                    toolbarContainerStub.setLayoutResource(controlContainerLayoutId);
                    toolbarContainerStub.inflate();
                }

                // It cannot be assumed that the result of toolbarContainerStub.inflate() will be
                // the control container since it may be wrapped in another view.
                ControlContainer controlContainer =
                        (ControlContainer) findViewById(R.id.control_container);

                // Inflate the correct toolbar layout for the device.
                int toolbarLayoutId = getToolbarLayoutId();
                if (toolbarLayoutId != NO_TOOLBAR_LAYOUT && controlContainer != null) {
                    controlContainer.initWithToolbar(toolbarLayoutId);
                }
            } finally {
                StrictMode.setThreadPolicy(oldPolicy);
            }
        }
        TraceEvent.end("onCreate->setContentView()");
        mInflateInitialLayoutDurationMs = SystemClock.elapsedRealtime() - begin;

        // Set the status bar color to black by default. This is an optimization for
        // Chrome not to draw under status and navigation bars when we use the default
        // black status bar
        ApiCompatibilityUtils.setStatusBarColor(getWindow(), Color.BLACK);

        ViewGroup rootView = (ViewGroup) getWindow().getDecorView().getRootView();
        mCompositorViewHolder = (CompositorViewHolder) findViewById(R.id.compositor_view_holder);
        mCompositorViewHolder.setRootView(rootView);

        // Setting fitsSystemWindows to false ensures that the root view doesn't consume the insets.
        rootView.setFitsSystemWindows(false);

        // Add a custom view right after the root view that stores the insets to access later.
        // ContentViewCore needs the insets to determine the portion of the screen obscured by
        // non-content displaying things such as the OSK.
        mInsetObserverView = InsetObserverView.create(this);
        rootView.addView(mInsetObserverView, 0);
    }

    /**
     * Constructs {@link ToolbarManager} and the handler necessary for controlling the menu on the
     * {@link Toolbar}. Extending classes can override this call to avoid creating the toolbar.
     */
    protected void initializeToolbar() {
        final View controlContainer = findViewById(R.id.control_container);
        assert controlContainer != null;
        ToolbarControlContainer toolbarContainer = (ToolbarControlContainer) controlContainer;
        mAppMenuPropertiesDelegate = createAppMenuPropertiesDelegate();
        mAppMenuHandler = sAppMenuHandlerFactory.get(this, mAppMenuPropertiesDelegate,
                getAppMenuLayoutId());
        mToolbarManager = new ToolbarManager(this, toolbarContainer, mAppMenuHandler,
                mAppMenuPropertiesDelegate, getCompositorViewHolder().getInvalidator());
        mAppMenuHandler.addObserver(new AppMenuObserver() {
            @Override
            public void onMenuVisibilityChanged(boolean isVisible) {
                if (isVisible && !isInOverviewMode()) {
                    // The app menu badge should be removed the first time the menu is opened.
                    if (mToolbarManager.getToolbar().isShowingAppMenuUpdateBadge()) {
                        mToolbarManager.getToolbar().removeAppMenuUpdateBadge(true);
                        mCompositorViewHolder.requestRender();
                    }
                }
                if (!isVisible) {
                    mAppMenuPropertiesDelegate.onMenuDismissed();
                    MenuItem updateMenuItem = mAppMenuHandler.getAppMenu().getMenu().findItem(
                            R.id.update_menu_id);
                    if (updateMenuItem != null && updateMenuItem.isVisible()) {
                        UpdateMenuItemHelper.getInstance().onMenuDismissed();
                    }
                }
            }
        });
    }

    /**
     * Initialize the {@link TabModelSelector}, {@link TabModel}s, and
     * {@link org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator} needed by
     * this activity.
     */
    protected final void initializeTabModels() {
        if (mTabModelsInitialized) return;

        mTabModelSelector = createTabModelSelector();
        if (mTabModelSelector == null) {
            assert isFinishing();
            mTabModelsInitialized = true;
            return;
        }

        Pair<? extends TabCreator, ? extends TabCreator> tabCreators = createTabCreators();
        mRegularTabCreator = tabCreators.first;
        mIncognitoTabCreator = tabCreators.second;

        if (mTabModelSelectorTabObserver != null) mTabModelSelectorTabObserver.destroy();

        mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(mTabModelSelector) {
            @Override
            public void didFirstVisuallyNonEmptyPaint(Tab tab) {
                if (DataUseTabUIManager.checkAndResetDataUseTrackingStarted(tab)
                        && DataUseTabUIManager.shouldShowDataUseStartedUI()) {
                    mDataUseSnackbarController.showDataUseTrackingStartedBar();
                } else if (DataUseTabUIManager.shouldShowDataUseEndedUI()
                        && DataUseTabUIManager.shouldShowDataUseEndedSnackbar(
                                   getApplicationContext())
                        && DataUseTabUIManager.checkAndResetDataUseTrackingEnded(tab)) {
                    mDataUseSnackbarController.showDataUseTrackingEndedBar();
                }

                // Only alert about data savings once the first paint has happened. It doesn't make
                // sense to show a snackbar about savings when nothing has been displayed yet.
                if (DataReductionProxySettings.getInstance().isSnackbarPromoAllowed(tab.getUrl())) {
                    if (mDataReductionPromoSnackbarController == null) {
                        mDataReductionPromoSnackbarController =
                                new DataReductionPromoSnackbarController(
                                        getApplicationContext(), getSnackbarManager());
                    }
                    mDataReductionPromoSnackbarController.maybeShowDataReductionPromoSnackbar(
                            DataReductionProxySettings.getInstance()
                                    .getTotalHttpContentLengthSaved());
                }
            }

            @Override
            public void onShown(Tab tab) {
                setStatusBarColor(tab, tab.getThemeColor());
            }

            @Override
            public void onHidden(Tab tab) {
                mDataUseSnackbarController.dismissDataUseBar();
            }

            @Override
            public void onDestroyed(Tab tab) {
                mDataUseSnackbarController.dismissDataUseBar();
            }

            @Override
            public void onLoadStopped(Tab tab, boolean toDifferentDocument) {
                postDeferredStartupIfNeeded();
            }

            @Override
            public void onPageLoadFinished(Tab tab) {
                postDeferredStartupIfNeeded();
                OfflinePageUtils.showOfflineSnackbarIfNecessary(ChromeActivity.this, tab);
            }

            @Override
            public void onCrash(Tab tab, boolean sadTabShown) {
                postDeferredStartupIfNeeded();
            }

            @Override
            public void onDidChangeThemeColor(Tab tab, int color) {
                if (getActivityTab() != tab) return;
                setStatusBarColor(tab, color);

                if (getToolbarManager() == null) return;
                getToolbarManager().updatePrimaryColor(color, true);

                ControlContainer controlContainer =
                        (ControlContainer) findViewById(R.id.control_container);
                controlContainer.getToolbarResourceAdapter().invalidate(null);
            }
        };

        if (mAssistStatusHandler != null) {
            mAssistStatusHandler.setTabModelSelector(mTabModelSelector);
        }

        mTabModelsInitialized = true;
    }

    /**
     * @return The {@link TabModelSelector} owned by this {@link ChromeActivity}.
     */
    protected abstract TabModelSelector createTabModelSelector();

    /**
     * @return The {@link org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator}s owned
     *         by this {@link ChromeActivity}.  The first item in the Pair is the normal model tab
     *         creator, and the second is the tab creator for incognito tabs.
     */
    protected abstract Pair<? extends TabCreator, ? extends TabCreator> createTabCreators();

    /**
     * @return {@link ToolbarManager} that belongs to this activity.
     */
    @VisibleForTesting
    public ToolbarManager getToolbarManager() {
        return mToolbarManager;
    }

    /**
     * @return The resource id for the menu to use in {@link AppMenu}. Default is R.menu.main_menu.
     */
    protected int getAppMenuLayoutId() {
        return R.menu.main_menu;
    }

    /**
     * @return {@link AppMenuPropertiesDelegate} instance that the {@link AppMenuHandler}
     *         should be using in this activity.
     */
    protected AppMenuPropertiesDelegate createAppMenuPropertiesDelegate() {
        return new AppMenuPropertiesDelegate(this);
    }

    /**
     * @return The assist handler for this activity.
     */
    protected AssistStatusHandler getAssistStatusHandler() {
        return mAssistStatusHandler;
    }

    /**
     * @return A newly constructed assist handler for this given activity type.
     */
    protected AssistStatusHandler createAssistStatusHandler() {
        return new AssistStatusHandler(this);
    }

    /**
     * @return The resource id for the layout to use for {@link ControlContainer}. 0 by default.
     */
    protected int getControlContainerLayoutId() {
        return NO_CONTROL_CONTAINER;
    }

    /**
     * @return The layout ID for the toolbar to use.
     */
    protected int getToolbarLayoutId() {
        return NO_TOOLBAR_LAYOUT;
    }

    /**
     * @return Whether contextual search is allowed for this activity or not.
     */
    protected boolean isContextualSearchAllowed() {
        return true;
    }

    @Override
    public void initializeState() {
        super.initializeState();
        mBlimpClientContextDelegate =
                ChromeBlimpClientContextDelegate.createAndSetDelegateForContext(
                        Profile.getLastUsedProfile().getOriginalProfile());

        IntentHandler.setTestIntentsEnabled(
                CommandLine.getInstance().hasSwitch(ContentSwitches.ENABLE_TEST_INTENTS));
        mIntentHandler = new IntentHandler(createIntentHandlerDelegate(), getPackageName());
    }

    @Override
    public void initializeCompositor() {
        TraceEvent.begin("ChromeActivity:CompositorInitialization");
        super.initializeCompositor();

        setTabContentManager(new TabContentManager(this, getContentOffsetProvider(),
                DeviceClassManager.enableSnapshots()));
        mCompositorViewHolder.onNativeLibraryReady(mWindowAndroid, getTabContentManager());

        if (isContextualSearchAllowed() && ContextualSearchFieldTrial.isEnabled()) {
            mContextualSearchManager = new ContextualSearchManager(this, mWindowAndroid, this);
        }

        if (ReaderModeManager.isEnabled(this)) {
            mReaderModeManager = new ReaderModeManager(getTabModelSelector(), this);
            if (mToolbarManager != null) {
                mToolbarManager.addFindToolbarObserver(
                        mReaderModeManager.getFindToolbarObserver());
            }
        }

        TraceEvent.end("ChromeActivity:CompositorInitialization");
    }

    @Override
    public void onStartWithNative() {
        super.onStartWithNative();
        UpdateMenuItemHelper.getInstance().onStart();
        ChromeActivitySessionTracker.getInstance().onStartWithNative();

        if (GSAState.getInstance(this).isGsaAvailable()) {
            GSAAccountChangeListener.getInstance().connect();
            createContextReporterIfNeeded();
        } else {
            ContextReporter.reportStatus(ContextReporter.STATUS_GSA_NOT_AVAILABLE);
        }
        mCompositorViewHolder.resetFlags();

        // postDeferredStartupIfNeeded() is called in TabModelSelectorTabObsever#onLoadStopped(),
        // #onPageLoadFinished() and #onCrash(). If we are not actively loading a tab (e.g.
        // in Android N multi-instance, which is created by re-parenting an existing tab),
        // ensure onDeferredStartup() gets called by calling postDeferredStartupIfNeeded() here.
        if (getActivityTab() == null || !getActivityTab().isLoading()) {
            postDeferredStartupIfNeeded();
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        Tab tab = getActivityTab();
        if (tab == null) return;
        if (hasFocus) {
            tab.onActivityShown();
        } else {
            boolean stopped = ApplicationStatus.getStateForActivity(this) == ActivityState.STOPPED;
            if (stopped) tab.onActivityHidden();
        }
    }

    /**
     * Set device status bar to a given color.
     * @param tab The tab that is currently showing.
     * @param color The color that the status bar should be set to.
     */
    protected void setStatusBarColor(Tab tab, int color) {
        int statusBarColor = (tab != null && tab.isDefaultThemeColor())
                ? Color.BLACK : ColorUtils.getDarkenedColorForStatusBar(color);
        ApiCompatibilityUtils.setStatusBarColor(getWindow(), statusBarColor);
    }

    private void createContextReporterIfNeeded() {
        if (mContextReporter != null || getActivityTab() == null) return;

        final SyncController syncController = SyncController.get(this);
        final ProfileSyncService syncService = ProfileSyncService.get();

        if (syncController != null && syncController.isSyncingUrlsWithKeystorePassphrase()) {
            assert syncService != null;
            mContextReporter = ((ChromeApplication) getApplicationContext()).createGsaHelper()
                    .getContextReporter(this);

            if (mSyncStateChangedListener != null) {
                syncService.removeSyncStateChangedListener(mSyncStateChangedListener);
                mSyncStateChangedListener = null;
            }

            return;
        } else {
            ContextReporter.reportSyncStatus(syncService);
        }

        if (mSyncStateChangedListener == null && syncService != null) {
            mSyncStateChangedListener = new ProfileSyncService.SyncStateChangedListener() {
                @Override
                public void syncStateChanged() {
                    createContextReporterIfNeeded();
                }
            };
            syncService.addSyncStateChangedListener(mSyncStateChangedListener);
        }
    }

    @Override
    public void onResumeWithNative() {
        super.onResumeWithNative();
        markSessionResume();
        RecordUserAction.record("MobileComeToForeground");

        if (getActivityTab() != null) {
            LaunchMetrics.commitLaunchMetrics(getActivityTab().getWebContents());
        }
        FeatureUtilities.setCustomTabVisible(isCustomTab());
        FeatureUtilities.setIsInMultiWindowMode(
                MultiWindowUtils.getInstance().isInMultiWindowMode(this));
    }

    @Override
    public void onPauseWithNative() {
        RecordUserAction.record("MobileGoToBackground");
        Tab tab = getActivityTab();
        if (tab != null) {
            getTabContentManager().cacheTabThumbnail(tab);
        }
        markSessionEnd();
        super.onPauseWithNative();
    }

    @Override
    public void onStopWithNative() {
        Tab tab = getActivityTab();
        if (tab != null && !hasWindowFocus()) tab.onActivityHidden();
        if (mAppMenuHandler != null) mAppMenuHandler.hideAppMenu();

        if (GSAState.getInstance(this).isGsaAvailable()) {
            GSAAccountChangeListener.getInstance().disconnect();
            if (mSyncStateChangedListener != null) {
                ProfileSyncService syncService = ProfileSyncService.get();
                if (syncService != null) {
                    syncService.removeSyncStateChangedListener(mSyncStateChangedListener);
                }
                mSyncStateChangedListener = null;
            }
        }
        super.onStopWithNative();
    }

    @Override
    public void onNewIntentWithNative(Intent intent) {
        super.onNewIntentWithNative(intent);
        if (mIntentHandler.shouldIgnoreIntent(this, intent)) return;

        mIntentHandler.onNewIntent(this, intent);
    }

    /**
     * @return Whether the given activity contains a CustomTab.
     */
    public boolean isCustomTab() {
        return false;
    }

    /**
     * Overriding methods should queue tasks on the DeferredStartupHandler before or after calling
     * super depending on whether the tasks should run before or after these ones.
     */
    @Override
    protected void onDeferredStartup() {
        super.onDeferredStartup();
        initDeferredStartupForActivity();
        DeferredStartupHandler.getInstance().initDeferredStartupForApp();
        DeferredStartupHandler.getInstance().queueDeferredTasksOnIdleHandler();
    }

    /**
     * All deferred startup tasks that require the activity rather than the app should go here.
     */
    private void initDeferredStartupForActivity() {
        DeferredStartupHandler.getInstance().addDeferredTask(new Runnable() {
            @Override
            public void run() {
                if (isActivityDestroyed()) return;
                BeamController.registerForBeam(ChromeActivity.this, new BeamProvider() {
                    @Override
                    public String getTabUrlForBeam() {
                        if (isOverlayVisible()) return null;
                        if (getActivityTab() == null) return null;
                        return getActivityTab().getUrl();
                    }
                });

                UpdateMenuItemHelper.getInstance().checkForUpdateOnBackgroundThread(
                        ChromeActivity.this);
            }
        });

        DeferredStartupHandler.getInstance().addDeferredTask(new Runnable() {
            @Override
            public void run() {
                if (isActivityDestroyed()) return;
                if (mToolbarManager != null) {
                    String simpleName = getClass().getSimpleName();
                    RecordHistogram.recordTimesHistogram(
                            "MobileStartup.ToolbarInflationTime." + simpleName,
                            mInflateInitialLayoutDurationMs, TimeUnit.MILLISECONDS);
                    mToolbarManager.onDeferredStartup(getOnCreateTimestampMs(), simpleName);
                }

                if (MultiWindowUtils.getInstance().isInMultiWindowMode(ChromeActivity.this)) {
                    onDeferredStartupForMultiWindowMode();
                }
            }
        });
    }

    /**
     * Actions that may be run at some point after startup for Android N multi-window mode. Should
     * be called from #onDeferredStartup() if the activity is in multi-window mode.
     */
    protected void onDeferredStartupForMultiWindowMode() {
        // If the Activity was launched in multi-window mode, record a user action and the screen
        // width.
        recordMultiWindowModeChangedUserAction(true);
        recordMultiWindowModeScreenWidth();
    }

    @Override
    public void onStart() {
        if (AsyncTabParamsManager.hasParamsWithTabToReparent()) {
            mCompositorViewHolder.prepareForTabReparenting();
        }
        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();
                    }
                }
            });
        }
        if (mCompositorViewHolder != null) mCompositorViewHolder.onStart();
        mSnackbarManager.onStart();

        // Explicitly call checkAccessibility() so things are initialized correctly when Chrome has
        // been re-started after closing due to the last tab being closed when homepage is enabled.
        // See crbug.com/541546.
        checkAccessibility();

        mScreenWidthDp = getResources().getConfiguration().screenWidthDp;
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mContextReporter != null) mContextReporter.disable();

        // We want to refresh partner browser provider every onStart().
        mPartnerBrowserRefreshNeeded = true;
        if (mCompositorViewHolder != null) mCompositorViewHolder.onStop();
        mSnackbarManager.onStop();
    }

    @Override
    @TargetApi(Build.VERSION_CODES.M)
    public void onProvideAssistContent(AssistContent outContent) {
        if (getAssistStatusHandler() == null || !getAssistStatusHandler().isAssistSupported()) {
            // No information is provided in incognito mode.
            return;
        }
        Tab tab = getActivityTab();
        if (tab != null && !isInOverviewMode()) {
            outContent.setWebUri(Uri.parse(tab.getUrl()));
        }
    }

    @Override
    public long getOnCreateTimestampMs() {
        return super.getOnCreateTimestampMs();
    }

    /**
     * This cannot be overridden in order to preserve destruction order.  Override
     * {@link #onDestroyInternal()} instead to perform clean up tasks.
     */
    @SuppressLint("NewApi")
    @Override
    protected final void onDestroy() {
        if (mReaderModeManager != null) {
            mReaderModeManager.destroy();
            mReaderModeManager = null;
        }

        if (mContextualSearchManager != null) {
            mContextualSearchManager.destroy();
            mContextualSearchManager = null;
        }

        if (mTabModelSelectorTabObserver != null) {
            mTabModelSelectorTabObserver.destroy();
            mTabModelSelectorTabObserver = null;
        }

        if (mCompositorViewHolder != null) {
            if (mCompositorViewHolder.getLayoutManager() != null) {
                mCompositorViewHolder.getLayoutManager().removeSceneChangeObserver(this);
            }
            mCompositorViewHolder.shutDown();
            mCompositorViewHolder = null;
        }

        onDestroyInternal();

        if (mToolbarManager != null) {
            mToolbarManager.destroy();
            mToolbarManager = null;
        }

        if (mTabModelsInitialized) {
            TabModelSelector selector = getTabModelSelector();
            if (selector != null) selector.destroy();
        }

        if (mWindowAndroid != null) {
            mWindowAndroid.destroy();
            mWindowAndroid = null;
        }

        CombinedPolicyProvider.get().removePolicyChangeListener(this);

        if (mTabContentManager != null) {
            mTabContentManager.destroy();
            mTabContentManager = null;
        }

        AccessibilityManager manager = (AccessibilityManager)
                getBaseContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
        manager.removeAccessibilityStateChangeListener(this);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            manager.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener);
        }

        if (mBlimpClientContextDelegate != null) {
            mBlimpClientContextDelegate.destroy();
            mBlimpClientContextDelegate = null;
        }

        super.onDestroy();
    }

    /**
     * Override this to perform destruction tasks.  Note that by the time this is called, the
     * {@link CompositorViewHolder} will be destroyed, but the {@link WindowAndroid} and
     * {@link TabModelSelector} will not.
     * <p>
     * After returning from this, the {@link TabModelSelector} will be destroyed followed
     * by the {@link WindowAndroid}.
     */
    protected void onDestroyInternal() {
    }

    /**
     * This will handle passing {@link Intent} results back to the {@link WindowAndroid}.  It will
     * return whether or not the {@link WindowAndroid} has consumed the event or not.
     */
    @Override
    public boolean onActivityResultWithNative(int requestCode, int resultCode, Intent intent) {
        if (super.onActivityResultWithNative(requestCode, resultCode, intent)) return true;
        return mWindowAndroid.onActivityResult(requestCode, resultCode, intent);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions,
            int[] grantResults) {
        if (mWindowAndroid != null) {
            if (mWindowAndroid.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
                return;
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mWindowAndroid.saveInstanceState(outState);
    }

    /**
     * @return The unified manager for all snackbar related operations.
     */
    @Override
    public SnackbarManager getSnackbarManager() {
        return mSnackbarManager;
    }

    protected Drawable getBackgroundDrawable() {
        return new ColorDrawable(
                ApiCompatibilityUtils.getColor(getResources(), R.color.light_background_color));
    }

    @Override
    public void finishNativeInitialization() {
        // The window background color is used as the resizing background color in Android N+
        // multi-window mode. See crbug.com/602366.
        if (Build.VERSION.CODENAME.equals("N") || Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            getWindow().setBackgroundDrawable(new ColorDrawable(
                    ApiCompatibilityUtils.getColor(getResources(),
                            R.color.resizing_background_color)));
        } else {
            removeWindowBackground();
        }
        DownloadManagerService.getDownloadManagerService(
                getApplicationContext()).onActivityLaunched();

        super.finishNativeInitialization();
    }

    /**
     * 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);
        if (mToolbarManager != null) mToolbarManager.onAccessibilityStatusChanged(enabled);
        if (mContextualSearchManager != null) {
            mContextualSearchManager.onAccessibilityModeChanged(enabled);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item != null && onMenuOrKeyboardAction(item.getItemId(), true)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @VisibleForTesting
    public void setScreenshotCaptureSkippedForTesting(boolean value) {
        mScreenshotCaptureSkippedForTesting = value;
    }

    /**
     * Triggered when the share menu item is selected.
     * This creates and shows a share intent picker dialog or starts a share intent directly.
     * @param shareDirectly Whether it should share directly with the activity that was most
     *                      recently used to share.
     * @param isIncognito Whether currentTab is incognito.
     */
    @VisibleForTesting
    public void onShareMenuItemSelected(final boolean shareDirectly, final boolean isIncognito) {
        final Tab currentTab = getActivityTab();
        if (currentTab == null) return;

        PrintingController printingController = PrintingControllerImpl.getInstance();
        if (printingController != null && !currentTab.isNativePage() && !printingController.isBusy()
                && PrefServiceBridge.getInstance().isPrintingEnabled()) {
            PrintShareActivity.enablePrintShareOption(this, new Runnable() {
                @Override
                public void run() {
                    triggerShare(currentTab, shareDirectly, isIncognito);
                }
            });
            return;
        }

        triggerShare(currentTab, shareDirectly, isIncognito);
    }

    private void triggerShare(
            final Tab currentTab, final boolean shareDirectly, boolean isIncognito) {
        final Activity mainActivity = this;
        WebContents webContents = currentTab.getWebContents();

        RecordHistogram.recordBooleanHistogram(
                "OfflinePages.SharedPageWasOffline", currentTab.isOfflinePage());
        boolean canShareOfflinePage = OfflinePageBridge.isPageSharingEnabled();

        // Share an empty blockingUri in place of screenshot file. The file ready notification is
        // sent by onScreenshotReady call below when the file is written.
        final Uri blockingUri = (isIncognito || webContents == null)
                ? null
                : ChromeFileProvider.generateUriAndBlockAccess(mainActivity);
        if (canShareOfflinePage) {
            OfflinePageUtils.shareOfflinePage(shareDirectly, true, mainActivity, null,
                    blockingUri, null, currentTab);
        } else {
            ShareHelper.share(shareDirectly, true, mainActivity, currentTab.getTitle(), null,
                    currentTab.getUrl(), null, blockingUri, null);
            if (shareDirectly) {
                RecordUserAction.record("MobileMenuDirectShare");
            } else {
                RecordUserAction.record("MobileMenuShare");
            }
        }

        if (blockingUri == null) return;

        // Start screenshot capture and notify the provider when it is ready.
        ContentBitmapCallback callback = new ContentBitmapCallback() {
            @Override
            public void onFinishGetBitmap(Bitmap bitmap, int response) {
                ShareHelper.saveScreenshotToDisk(bitmap, mainActivity,
                        new Callback<Uri>() {
                            @Override
                            public void onResult(Uri result) {
                                // Unblock the file once it is saved to disk.
                                ChromeFileProvider.notifyFileReady(blockingUri, result);
                            }
                        });
            }
        };
        if (!mScreenshotCaptureSkippedForTesting) {
            webContents.getContentBitmapAsync(Bitmap.Config.ARGB_8888, 1.f, EMPTY_RECT, callback);
        } else {
            callback.onFinishGetBitmap(null, ReadbackResponse.SURFACE_UNAVAILABLE);
        }
    }

    /**
     * @return Whether the activity is in overview mode.
     */
    public boolean isInOverviewMode() {
        return false;
    }

    /**
     * @return Whether the app menu should be shown.
     */
    public boolean shouldShowAppMenu() {
        // Do not show the menu if Contextual Search or Reader Mode panel is opened.
        // TODO(mdjones): This could potentially be handled by the OverlayPanelManager or as
        // an event if the panels were SceneOverlays.
        if ((mContextualSearchManager != null && mContextualSearchManager.isSearchPanelOpened())
                || (mReaderModeManager != null && mReaderModeManager.isPanelOpened())) {
            return false;
        }

        return true;
    }

    /**
    * Shows the app menu (if possible) for a key press on the keyboard with the correct anchor view
    * chosen depending on device configuration and the visible menu button to the user.
    */
    protected void showAppMenuForKeyboardEvent() {
        if (getAppMenuHandler() == null) return;

        boolean hasPermanentMenuKey = ViewConfiguration.get(this).hasPermanentMenuKey();
        getAppMenuHandler().showAppMenu(
                hasPermanentMenuKey ? null : getToolbarManager().getMenuAnchor(), 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) {
    }

    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 referer, String headers,
                    TabOpenType tabOpenType, String externalAppId, int tabIdToBringToFront,
                    boolean hasUserGesture, Intent intent) {
            }
        };
    }

    /**
     * @return The resource id that contains how large the browser controls are.
     */
    public int getControlContainerHeightResource() {
        return R.dimen.control_container_height;
    }

    @Override
    public final void onAccessibilityStateChanged(boolean enabled) {
        checkAccessibility();
    }

    private void checkAccessibility() {
        onAccessibilityModeChanged(DeviceClassManager.isAccessibilityModeEnabled(this));
    }

    /**
     * @return A casted version of {@link #getApplication()}.
     */
    public ChromeApplication getChromeApplication() {
        return (ChromeApplication) getApplication();
    }

    /**
     * Add the specified tab to bookmarks or allows to edit the bookmark if the specified tab is
     * already bookmarked. If a new bookmark is added, a snackbar will be shown.
     * @param tabToBookmark The tab that needs to be bookmarked.
     */
    public void addOrEditBookmark(final Tab tabToBookmark) {
        if (tabToBookmark == null || tabToBookmark.isFrozen()) {
            return;
        }

        // Defense in depth against the UI being erroneously enabled.
        if (!mToolbarManager.getBookmarkBridge().isEditBookmarksEnabled()) {
            assert false;
            return;
        }

        // Note the use of getUserBookmarkId() over getBookmarkId() here: Managed bookmarks can't be
        // edited. If the current URL is only bookmarked by managed bookmarks, this will return
        // INVALID_BOOKMARK_ID, so the code below will fall back on adding a new bookmark instead.
        // TODO(bauerb): This does not take partner bookmarks into account.
        final long bookmarkId = tabToBookmark.getUserBookmarkId();

        final BookmarkModel bookmarkModel = new BookmarkModel();
        bookmarkModel.runAfterBookmarkModelLoaded(new Runnable() {
            @Override
            public void run() {
                // Gives up the bookmarking if the tab is being destroyed.
                if (!tabToBookmark.isClosing() && tabToBookmark.isInitialized()) {
                    // The BookmarkModel will be destroyed by BookmarkUtils#addOrEditBookmark() when
                    // done.
                    BookmarkId newBookmarkId =
                            BookmarkUtils.addOrEditBookmark(bookmarkId, bookmarkModel,
                                    tabToBookmark, getSnackbarManager(), ChromeActivity.this);
                    // If a new bookmark was created, try to save an offline page for it.
                    if (newBookmarkId != null && newBookmarkId.getId() != bookmarkId) {
                        OfflinePageUtils.saveBookmarkOffline(newBookmarkId, tabToBookmark);
                    }
                } else {
                    bookmarkModel.destroy();
                }
            }
        });
    }

    /**
     * {@link TabModelSelector} no longer implements TabModel.  Use getTabModelSelector() or
     * getCurrentTabModel() depending on your needs.
     * @return The {@link TabModelSelector}, possibly null.
     */
    public TabModelSelector getTabModelSelector() {
        if (!mTabModelsInitialized) {
            throw new IllegalStateException(
                    "Attempting to access TabModelSelector before initialization");
        }
        return mTabModelSelector;
    }

    /**
     * Returns the {@link InsetObserverView} that has the current system window
     * insets information.
     * @return The {@link InsetObserverView}, possibly null.
     */
    public InsetObserverView getInsetObserverView() {
        return mInsetObserverView;
    }

    @Override
    public TabCreatorManager.TabCreator getTabCreator(boolean incognito) {
        if (!mTabModelsInitialized) {
            throw new IllegalStateException(
                    "Attempting to access TabCreator before initialization");
        }
        return incognito ? mIncognitoTabCreator : mRegularTabCreator;
    }

    /**
     * Convenience method that returns a tab creator for the currently selected {@link TabModel}.
     * @return A tab creator for the currently selected {@link TabModel}.
     */
    public TabCreatorManager.TabCreator 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());
    }

    /**
     * @return A {@link WindowAndroid} instance.
     */
    public WindowAndroid getWindowAndroid() {
        return mWindowAndroid;
    }

    /**
     * @return A {@link CompositorViewHolder} instance.
     */
    public CompositorViewHolder getCompositorViewHolder() {
        return mCompositorViewHolder;
    }

    /**
     * Gets the full screen manager.
     * @return The fullscreen manager, possibly null
     */
    public ChromeFullscreenManager getFullscreenManager() {
        if (!mCreatedFullscreenManager) {
            throw new IllegalStateException(
                    "Attempting to access FullscreenManager before it has been created.");
        }
        return mFullscreenManager;
    }

    /**
     * @return The content offset provider, may be null.
     */
    public ContentOffsetProvider getContentOffsetProvider() {
        return mCompositorViewHolder;
    }

    /**
     * @return The {@code ContextualSearchManager} or {@code null} if none;
     */
    public ContextualSearchManager getContextualSearchManager() {
        return mContextualSearchManager;
    }

    /**
     * @return The {@code ReaderModeManager} or {@code null} if none;
     */
    @VisibleForTesting
    public ReaderModeManager getReaderModeManager() {
        return mReaderModeManager;
    }

    /**
     * Create a full-screen manager to be used by this activity.
     * Note: This is called during {@link #postInflationStartup}, so native code may not have been
     * initialized, but Android Views will have been.
     * @return A {@link ChromeFullscreenManager} instance that's been created.
     */
    protected ChromeFullscreenManager createFullscreenManager() {
        return new ChromeFullscreenManager(this, false);
    }

    /**
     * Exits the fullscreen mode, if any. Does nothing if no fullscreen is present.
     * @return Whether the fullscreen mode is currently showing.
     */
    protected boolean exitFullscreenIfShowing() {
        ContentVideoView view = ContentVideoView.getContentVideoView();
        if (view != null && view.getContext() == this) {
            view.exitFullscreen(false);
            return true;
        }
        if (getFullscreenManager() != null
                && getFullscreenManager().getPersistentFullscreenMode()) {
            getFullscreenManager().setPersistentFullscreenMode(false);
            return true;
        }
        return false;
    }

    /**
     * Initializes the {@link CompositorViewHolder} with the relevant content it needs to properly
     * show content on the screen.
     * @param layoutManager             A {@link LayoutManagerDocument} instance.  This class is
     *                                  responsible for driving all high level screen content and
     *                                  determines which {@link Layout} is shown when.
     * @param urlBar                    The {@link View} representing the URL bar (must be
     *                                  focusable) or {@code null} if none exists.
     * @param contentContainer          A {@link ViewGroup} that can have content attached by
     *                                  {@link Layout}s.
     * @param controlContainer          A {@link ControlContainer} instance to draw.
     */
    protected void initializeCompositorContent(
            LayoutManagerDocument layoutManager, View urlBar, ViewGroup contentContainer,
            ControlContainer controlContainer) {
        if (mContextualSearchManager != null) {
            mContextualSearchManager.initialize(contentContainer);
            mContextualSearchManager.setSearchContentViewDelegate(layoutManager);
        }

        layoutManager.addSceneChangeObserver(this);
        mCompositorViewHolder.setLayoutManager(layoutManager);
        mCompositorViewHolder.setFocusable(false);
        mCompositorViewHolder.setControlContainer(controlContainer);
        mCompositorViewHolder.setFullscreenHandler(getFullscreenManager());
        mCompositorViewHolder.setUrlBar(urlBar);
        mCompositorViewHolder.onFinishNativeInitialization(getTabModelSelector(), this,
                getTabContentManager(), contentContainer, mContextualSearchManager,
                mReaderModeManager);

        if (controlContainer != null
                && DeviceClassManager.enableToolbarSwipe()) {
            controlContainer.setSwipeHandler(
                    getCompositorViewHolder().getLayoutManager().getTopSwipeHandler());
        }
    }

    /**
     * Called when the back button is pressed.
     * @return Whether or not the back button was handled.
     */
    protected abstract boolean handleBackPressed();

    @Override
    public void onOrientationChange(int orientation) {
        if (mToolbarManager != null) mToolbarManager.onOrientationChange();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        if (mAppMenuHandler != null) mAppMenuHandler.hideAppMenu();
        super.onConfigurationChanged(newConfig);

        if (newConfig.screenWidthDp != mScreenWidthDp) {
            mScreenWidthDp = newConfig.screenWidthDp;
            final Activity activity = this;

            if (mRecordMultiWindowModeScreenWidthRunnable != null) {
                mHandler.removeCallbacks(mRecordMultiWindowModeScreenWidthRunnable);
            }

            // When exiting Android N multi-window mode, onConfigurationChanged() gets called before
            // isInMultiWindowMode() returns false. Delay to avoid recording width when exiting
            // multi-window mode. This also ensures that we don't record intermediate widths seen
            // only for a brief period of time.
            mRecordMultiWindowModeScreenWidthRunnable = new Runnable() {
                @Override
                public void run() {
                    mRecordMultiWindowModeScreenWidthRunnable = null;
                    if (MultiWindowUtils.getInstance().isInMultiWindowMode(activity)) {
                        recordMultiWindowModeScreenWidth();
                    }
                }
            };
            mHandler.postDelayed(mRecordMultiWindowModeScreenWidthRunnable,
                    RECORD_MULTI_WINDOW_SCREEN_WIDTH_DELAY_MS);
        }
    }

    /**
     * Called by the system when the activity changes from fullscreen mode to multi-window mode
     * and visa-versa.
     * @param isInMultiWindowMode True if the activity is in multi-window mode.
     */
    public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
        recordMultiWindowModeChangedUserAction(isInMultiWindowMode);

        if (!isInMultiWindowMode
                && ApplicationStatus.getStateForActivity(this) == ActivityState.RESUMED) {
            // Start a new UMA session when exiting multi-window mode if the activity is currently
            // resumed. When entering multi-window Android recents gains focus, so ChromeActivity
            // will get a call to onPauseWithNative(), ending the current UMA session. When exiting
            // multi-window, however, if ChromeActivity is resumed it stays in that state.
            markSessionEnd();
            markSessionResume();
            FeatureUtilities.setIsInMultiWindowMode(
                    MultiWindowUtils.getInstance().isInMultiWindowMode(this));
        }

        super.onMultiWindowModeChanged(isInMultiWindowMode);
    }

    /**
     * Records user actions associated with entering and exiting Android N multi-window mode
     * @param isInMultiWindowMode True if the activity is in multi-window mode.
     */
    protected void recordMultiWindowModeChangedUserAction(boolean isInMultiWindowMode) {
        if (isInMultiWindowMode) {
            RecordUserAction.record("Android.MultiWindowMode.Enter");
        } else {
            RecordUserAction.record("Android.MultiWindowMode.Exit");
        }
    }

    @Override
    public final void onBackPressed() {
        RecordUserAction.record("SystemBack");
        if (mCompositorViewHolder != null) {
            LayoutManager layoutManager = mCompositorViewHolder.getLayoutManager();
            if (layoutManager != null && layoutManager.onBackPressed()) return;
        }

        ContentViewCore contentViewCore = getContentViewCore();
        if (contentViewCore != null && contentViewCore.isSelectActionBarShowing()) {
            contentViewCore.clearSelection();
            return;
        }

        if (mContextualSearchManager != null && mContextualSearchManager.onBackPressed()) return;

        if (handleBackPressed()) return;

        super.onBackPressed();
    }

    private ContentViewCore getContentViewCore() {
        Tab tab = getActivityTab();
        if (tab == null) return null;
        return tab.getContentViewCore();
    }

    @Override
    public void createContextualSearchTab(String searchUrl) {
        Tab currentTab = getActivityTab();
        if (currentTab == null) return;

        TabCreator tabCreator = getTabCreator(currentTab.isIncognito());
        if (tabCreator == null) return;

        tabCreator.createNewTab(
                new LoadUrlParams(searchUrl, PageTransition.LINK),
                TabModel.TabLaunchType.FROM_LINK, getActivityTab());
    }

    /**
     * @return The {@link AppMenuHandler} associated with this activity.
     */
    @VisibleForTesting
    public AppMenuHandler getAppMenuHandler() {
        return mAppMenuHandler;
    }

    /**
     * @return The {@link AppMenuPropertiesDelegate} associated with this activity.
     */
    @VisibleForTesting
    public AppMenuPropertiesDelegate getAppMenuPropertiesDelegate() {
        return mAppMenuPropertiesDelegate;
    }

    /**
     * Callback after UpdateMenuItemHelper#checkForUpdateOnBackgroundThread is complete.
     * @param updateAvailable Whether an update is available.
     */
    public void onCheckForUpdate(boolean updateAvailable) {
        if (UpdateMenuItemHelper.getInstance().shouldShowToolbarBadge(this)) {
            mToolbarManager.getToolbar().showAppMenuUpdateBadge();
            mCompositorViewHolder.requestRender();
        } else {
            mToolbarManager.getToolbar().removeAppMenuUpdateBadge(false);
        }
    }

    /**
     * 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) {
        if (id == R.id.preferences_id) {
            PreferencesLauncher.launchSettingsPage(this, null);
            RecordUserAction.record("MobileMenuSettings");
        } else if (id == R.id.show_menu) {
            showAppMenuForKeyboardEvent();
        }

        if (id == R.id.update_menu_id) {
            UpdateMenuItemHelper.getInstance().onMenuItemClicked(this);
            return true;
        }

        // All the code below assumes currentTab is not null, so return early if it is null.
        final Tab currentTab = getActivityTab();
        if (currentTab == null) {
            return false;
        } else if (id == R.id.forward_menu_id) {
            if (currentTab.canGoForward()) {
                currentTab.goForward();
                RecordUserAction.record("MobileMenuForward");
                RecordUserAction.record("MobileTabClobbered");
            }
        } else if (id == R.id.bookmark_this_page_id) {
            addOrEditBookmark(currentTab);
            RecordUserAction.record("MobileMenuAddToBookmarks");
        } else if (id == R.id.offline_page_id) {
            DownloadUtils.downloadOfflinePage(this, currentTab);
            RecordUserAction.record("MobileMenuDownloadPage");
        } else if (id == R.id.reload_menu_id) {
            if (currentTab.isLoading()) {
                currentTab.stopLoading();
                RecordUserAction.record("MobileMenuStop");
            } else {
                currentTab.reload();
                RecordUserAction.record("MobileMenuReload");
            }
        } else if (id == R.id.info_menu_id) {
            WebsiteSettingsPopup.show(
                    this, currentTab, null, WebsiteSettingsPopup.OPENED_FROM_MENU);
        } else if (id == R.id.open_history_menu_id) {
            currentTab.loadUrl(
                    new LoadUrlParams(UrlConstants.HISTORY_URL, PageTransition.AUTO_TOPLEVEL));
            RecordUserAction.record("MobileMenuHistory");
            StartupMetrics.getInstance().recordOpenedHistory();
        } else if (id == R.id.share_menu_id || id == R.id.direct_share_menu_id) {
            onShareMenuItemSelected(id == R.id.direct_share_menu_id,
                    getCurrentTabModel().isIncognito());
        } else if (id == R.id.print_id) {
            PrintingController printingController = PrintingControllerImpl.getInstance();
            if (printingController != null && !printingController.isBusy()
                    && PrefServiceBridge.getInstance().isPrintingEnabled()) {
                printingController.startPrint(new TabPrinter(currentTab),
                        new PrintManagerDelegateImpl(this));
                RecordUserAction.record("MobileMenuPrint");
            }
        } else if (id == R.id.add_to_homescreen_id) {
            AddToHomescreenManager addToHomescreenManager =
                    new AddToHomescreenManager(this, currentTab);
            addToHomescreenManager.start();
            RecordUserAction.record("MobileMenuAddToHomescreen");
        } else if (id == R.id.request_desktop_site_id) {
            final boolean reloadOnChange = !currentTab.isNativePage();
            final boolean usingDesktopUserAgent = currentTab.getUseDesktopUserAgent();
            currentTab.setUseDesktopUserAgent(!usingDesktopUserAgent, reloadOnChange);
            RecordUserAction.record("MobileMenuRequestDesktopSite");
        } else if (id == R.id.reader_mode_prefs_id) {
            if (currentTab.getWebContents() != null) {
                RecordUserAction.record("DomDistiller_DistilledPagePrefsOpened");
                AlertDialog.Builder builder =
                        new AlertDialog.Builder(this, R.style.AlertDialogTheme);
                builder.setView(DistilledPagePrefsView.create(this));
                builder.show();
            }
        } else if (id == R.id.help_id) {
            // Since reading back the compositor is asynchronous, we need to do the readback
            // before starting the GoogleHelp.
            String helpContextId = HelpAndFeedback.getHelpContextIdFromUrl(
                    this, currentTab.getUrl(), getCurrentTabModel().isIncognito());
            HelpAndFeedback.getInstance(this)
                    .show(this, helpContextId, currentTab.getProfile(), currentTab.getUrl());
            RecordUserAction.record("MobileMenuFeedback");
        } else {
            return false;
        }
        return true;
    }

    /**
     * Tests if VR Shell (the mode displaying browser UI and tab contents in VR) is currently
     * enabled.
     */
    public boolean isVrShellEnabled() {
        return false;
    }

    /**
     * Add a view to the set of views that obscure the content of all tabs for
     * accessibility. As long as this set is nonempty, all tabs should be
     * hidden from the accessibility tree.
     *
     * @param view The view that obscures the contents of all tabs.
     */
    public void addViewObscuringAllTabs(View view) {
        mViewsObscuringAllTabs.add(view);

        Tab tab = getActivityTab();
        if (tab != null) tab.updateAccessibilityVisibility();
    }

    /**
     * Remove a view that previously obscured the content of all tabs.
     *
     * @param view The view that no longer obscures the contents of all tabs.
     */
    public void removeViewObscuringAllTabs(View view) {
        mViewsObscuringAllTabs.remove(view);

        Tab tab = getActivityTab();
        if (tab != null) tab.updateAccessibilityVisibility();
    }

    /**
     * Returns whether or not any views obscure all tabs.
     */
    public boolean isViewObscuringAllTabs() {
        return !mViewsObscuringAllTabs.isEmpty();
    }

    private void markSessionResume() {
        // Start new session for UMA.
        if (mUmaSessionStats == null) {
            mUmaSessionStats = new UmaSessionStats(this);
        }

        mUmaSessionStats.updateMetricsServiceState();
        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;
    }

    protected final void postDeferredStartupIfNeeded() {
        if (!mDeferredStartupPosted) {
            mDeferredStartupPosted = true;
            RecordHistogram.recordLongTimesHistogram(
                    "UMA.Debug.EnableCrashUpload.PostDeferredStartUptime2",
                    SystemClock.uptimeMillis() - UmaUtils.getForegroundStartTime(),
                    TimeUnit.MILLISECONDS);
            onDeferredStartup();
        }
    }

    /**
     * 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;
    }

    @Override
    public void terminateIncognitoSession() {}

    @Override
    public void onTabSelectionHinted(int tabId) { }

    @Override
    public void onSceneChange(Layout layout) { }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();

        // See enableHardwareAcceleration()
        if (mSetWindowHWA) {
            mSetWindowHWA = false;
            getWindow().setWindowManager(
                    getWindow().getWindowManager(),
                    getWindow().getAttributes().token,
                    getComponentName().flattenToString(),
                    true /* hardwareAccelerated */);
        }
    }

    /**
     * Adds a {@link Callback} that will be triggered whenever a ContextMenu is closed.
     */
    public void addContextMenuCloseCallback(Callback<Menu> callback) {
        mContextMenuCloseObservers.addObserver(callback);
    }

    @Override
    public void onContextMenuClosed(Menu menu) {
        for (Callback<Menu> callback : mContextMenuCloseObservers) {
            callback.onResult(menu);
        }
    }

    /**
     * Removes a {@link Callback} from the list of callbacks that will be triggered when a
     * ContextMenu is closed.
     */
    public void removeContextMenuCloseCallback(Callback<Menu> callback) {
        mContextMenuCloseObservers.removeObserver(callback);
    }

    private boolean shouldDisableHardwareAcceleration() {
        // Low end devices should disable hardware acceleration for memory gains.
        if (SysUtils.isLowEndDevice()) return true;

        // Turning off hardware acceleration reduces crash rates. See http://crbug.com/651918
        // GT-S7580 on JDQ39 accounts for 42% of crashes in libPowerStretch.so on dev and beta.
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1
                && Build.MODEL.equals("GT-S7580")) {
            return true;
        }
        // SM-N9005 on JSS15J accounts for 44% of crashes in libPowerStretch.so on stable channel.
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2
                && Build.MODEL.equals("SM-N9005")) {
            return true;
        }
        return false;
    }

    private void enableHardwareAcceleration() {
        // HW acceleration is disabled in the manifest and may be re-enabled here.
        if (!shouldDisableHardwareAcceleration()) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

            // When HW acceleration is enabled manually for an activity, child windows (e.g.
            // dialogs) don't inherit HW acceleration state. However, when HW acceleration is
            // enabled in the manifest, child windows do inherit HW acceleration state. That
            // looks like a bug, so I filed b/23036374
            //
            // In the meanwhile the workaround is to call
            //   window.setWindowManager(..., hardwareAccelerated=true)
            // to let the window know that it's HW accelerated. However, since there is no way
            // to know 'appToken' argument until window's view is attached to the window (!!),
            // we have to do the workaround in onAttachedToWindow()
            mSetWindowHWA = true;
        }
    }

    /** @return the theme ID to use. */
    public static int getThemeId() {
        boolean useLowEndTheme =
                SysUtils.isLowEndDevice() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
        return (useLowEndTheme ? R.style.MainTheme_LowEnd : R.style.MainTheme);
    }

    private void setLowEndTheme() {
        if (getThemeId() == R.style.MainTheme_LowEnd) setTheme(R.style.MainTheme_LowEnd);
    }

    /**
     * Records UMA histograms for the current screen width. Should only be called when the activity
     * is in Android N multi-window mode.
     */
    protected void recordMultiWindowModeScreenWidth() {
        if (!DeviceFormFactor.isTablet(this)) return;

        RecordHistogram.recordBooleanHistogram(
                "Android.MultiWindowMode.IsTabletScreenWidthBelow600",
                mScreenWidthDp < DeviceFormFactor.MINIMUM_TABLET_WIDTH_DP);

        if (mScreenWidthDp < DeviceFormFactor.MINIMUM_TABLET_WIDTH_DP) {
            RecordHistogram.recordLinearCountHistogram(
                    "Android.MultiWindowMode.TabletScreenWidth", mScreenWidthDp, 1,
                    DeviceFormFactor.MINIMUM_TABLET_WIDTH_DP, 50);
        }
    }
}


text:
package service

import (
	"fmt"

	"go-common/app/admin/main/block/conf"
	"go-common/app/admin/main/block/model"
	"go-common/library/log"
)

// MSGInfo get msg info
func (s *Service) MSGInfo(source model.BlockSource, action model.BlockAction, area model.BlockArea, reason string, days int64) (code string, title, content string) {
	if source == model.BlockSourceBlackHouse {
		areaStr := area.String()
		if areaStr != "" {
			areaStr = fmt.Sprintf("在%s中", areaStr)
		}
		if action == model.BlockActionLimit {
			code = conf.Conf.Property.MSG.BlackHouseLimit.Code
			title = conf.Conf.Property.MSG.BlackHouseLimit.Title
			content = fmt.Sprintf(conf.Conf.Property.MSG.BlackHouseLimit.Content, areaStr, s.convertReason(reason), days)
			return
		}
		if action == model.BlockActionForever {
			code = conf.Conf.Property.MSG.BlackHouseForever.Code
			title = conf.Conf.Property.MSG.BlackHouseForever.Title
			content = fmt.Sprintf(conf.Conf.Property.MSG.BlackHouseForever.Content, areaStr, s.convertReason(reason))
			return
		}
	}
	if source == model.BlockSourceSys {
		if action == model.BlockActionLimit {
			code = conf.Conf.Property.MSG.SysLimit.Code
			title = conf.Conf.Property.MSG.SysLimit.Title
			content = fmt.Sprintf(conf.Conf.Property.MSG.SysLimit.Content, s.convertReason(reason), days)
			return
		}
		if action == model.BlockActionForever {
			code = conf.Conf.Property.MSG.SysForever.Code
			title = conf.Conf.Property.MSG.SysForever.Title
			content = fmt.Sprintf(conf.Conf.Property.MSG.SysForever.Content, s.convertReason(reason))
			return
		}
	}
	if action == model.BlockActionAdminRemove || action == model.BlockActionSelfRemove {
		code = conf.Conf.Property.MSG.BlockRemove.Code
		title = conf.Conf.Property.MSG.BlockRemove.Title
		content = conf.Conf.Property.MSG.BlockRemove.Content
		return
	}
	log.Error("s.MSGInfo unkown source[%v] action[%v] area[%v] reason[%s] days[%d]", source, action, area, reason, days)
	return
}

func (s *Service) convertReason(reason string) string {
	switch reason {
	case "账号资料相关违规":
		return "账号资料违规"
	case "作品投稿违规":
		return "作品投稿违规"
	case "异常注册账号":
		return "异常注册"
	case "异常答题账号":
		return "异常答题"
	case "异常数据行为":
		return "异常数据行为"
	case "发布违规信息":
		return "发布违规信息"
	case "其他自动封禁", "手动封禁":
		return "违反社区规则"
	default:
		return reason
	}
}


text:
'use strict';

angular.module('machine_reg', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/machine_registration', {
    templateUrl: 'machine_registration/machine_registration.html',
    controller: 'Machine_registrationCtrl'
  });
}])

.controller('Machine_registrationCtrl', ['$scope', '$http','$location','$rootScope','$window',
  function($scope, $http,$location,$rootScope,$window,DTOptionsBuilder) {
//$scope.myUrl = $location.absUrl();

$scope.machineregistration = {id: null,

name: "",
  machine_id: "",
  type: "",
  controller_name: "",
  controller_model:"",
  serial_number: "",
  ip: "",
  manufacture_year: "",
  manufacture_name: "",
  section_id: null};

 $scope.newmachine = function(){

        var machineregistration = {

"name": $scope.machineregistration.name,
  "machine_id": $scope.machineregistration.machine_id,
  "machine_type":$scope.machineregistration.type,
  "controller_name":$scope.machineregistration.controller_name,
  "controller_model":$scope.machineregistration.controller_model,
  "serial_number": $scope.machineregistration.serial_number,
  "ip":$scope.machineregistration.ip,
  "manufacture_year": $scope.machineregistration.manufacture_year,
  "manufacture_name": $scope.machineregistration.manufacture_name,
  "section_id": $scope.machineregistration.section_id};

      if ($scope.machineregistration.id== null){
       // alert(machineregistration.machine_ip);
      $http({
        method: 'post',
        url: $rootScope.api_url+'machines',
        data: machineregistration
      })

      .success(function(data) {
        if(data){

      alert("Registration completed");
      //$window.location.reload();
      $scope.machineinit();
      $(document).ready(function () {
   $('#machine').modal('hide');
 });
        }else{
        alert('Registration Failed');
        }
      });
    }
    else
    {

$http({
        method: 'put',
        url: $rootScope.api_url+'machines/'+$scope.machineregistration.id,
        data: machineregistration
      })

      .success(function(data) {
        if(data){
        alert("Updated Successfully");
       // $window.location.reload();
       $scope.machineinit();
       $(document).ready(function () {
   $('#machine').modal('hide');
 });
        }else{
        alert('Updation Failed');
        }
      });
    }
    }

/*app.js end*/
$scope.machineinit=function(){
  if($scope.role_type_name=='Tenant'){

$http({
    method:'GET',
    url:$rootScope.api_url+'tenant_machine?tenant_id='+$scope.tenant_id
  })
  .then(function(response){

   $rootScope.machines = response.data;

    })
}//if block end
else{

$http({
    method:'GET',
    url:$rootScope.api_url+'unit_machine?unit_id='+$scope.reference_id
  })
  .then(function(response){

   $rootScope.machines = response.data;

    })

}

if($scope.role_type_name=='Tenant'){

    $http({

    method:'GET',
    url:$rootScope.api_url+'tenant_section?tenant_id='+$scope.tenant_id
  })
  .then(function(response){
    $scope.sections_details=[]
   $rootScope.section_for_machine= response.data;

   for(var i in $rootScope.section_for_machine){

    for(var j in $rootScope.section_for_machine[i].sections){
       var temp={id:$rootScope.section_for_machine[i].sections[j].id,
        name:$rootScope.section_for_machine[i].name+"-"+$rootScope.section_for_machine[i].sections[j].name};
 $scope.sections_details.push(temp);

    }

   }

    })
}//if close
else{

$http({
  method:'GET',
  url:$rootScope.api_url+'unit_section?unit_id='+$scope.reference_id
}).then(function(response){
$scope.sections_details=response.data;

})

}

}
$scope.cleandata= function(id) {
  $scope.machineregist = {id: null,machine_name:"",machine_model:"",machine_serial_no:"",machine_type:"",machine_ip:"",tenant_id: null};
 $scope.machineregistration = angular.copy($scope.machineregist);

    }

  //tableedit
    $scope.edit = function(id) {
   var i;
   for(i in $rootScope.machines) {

            if($rootScope.machines[i].id == id) {
               var machine_id=$rootScope.machines[i];
               $scope.machineregistration = angular.copy(machine_id);
            }

        }
    }//editend
/*$scope.newQuote=function(){

alert("hi");
}*/
//delete table
$scope.delete = function(id) {

$http.delete($rootScope.api_url+'machines/'+id).success(function(data) {

        if(data){

      alert("Deleted Successfully");
      //$window.location.reload();
      $scope.machineinit();
        }else{
        alert('Delete Failed');
        }
      });
}//end

}]);


text:
(function() {
	'use strict';

	angular
		.module('supermodular.asyncwaterfall')
		.controller('AsyncWaterfallController', AsyncWaterfallController);

	AsyncWaterfallController.$inject = ['$scope','$timeout', 'asyncWaterfallService'];

	/* @ngInject */
	function AsyncWaterfallController($scope, $timeout, asyncWaterfallService) {
		var vm = angular.extend(this, {
			run: run
		});

		/*
		 * A complex taks that takes up to 5 seconds to be completed.
		 */
		function task1(callback){
			console.log('Task 1 started. Wait for 5 sec for completion.');
			$timeout(function(){
				console.log('Task 1 completed.');
				var errorOccurred = null;
				callback(errorOccurred, 5);
			},
			5000);
		}

		/*
		 * A less complex taks that takes up to 2 seconds to be completed.
		 */
		function task2(task1Result, callback){
			console.log('Task 2 started. Wait for 2 sec for completion.');
			$timeout(function(){
				console.log('Task 2 completed.');
				var errorOccurred = null;
				var value = task1Result * 2;

				callback(errorOccurred, value);
			},
			2000);
		}

		function run(){

			async.waterfall([
				task1,
				task2,
				],
				function(err, result){
					console.log('Result: ', result);
					console.log('DONE.');
			});
		}

	}
})();


text:
from .peekable import Peekable

def sequence(*iterables, by=None, compare=None):
    if compare is not None:
        compare = compare
    elif by is not None:
        compare = lambda i1, i2: by(i1) <= by(i2)
    else:
        compare = lambda i1, i2: i1 <= i2

    iterables = [Peekable(it) for it in iterables]

    done = False
    while not done:

        next_i = None

        for i, it in enumerate(iterables):
            if not it.empty():
                if next_i is None or compare(it.peek(), iterables[next_i].peek()):
                    next_i = i

        if next_i is None:
            done = True
        else:
            yield next(iterables[next_i])