diff --git a/DEPS b/DEPS
index fbc03ab..35cfd74 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '11f9b0549e4409f0daab970f20be3c62cadecd4d',
+  'v8_revision': '3d7c892d19ff27d4b8c046c50b68116814c4d746',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/android_webview/tools/system_webview_shell/layout_tests/src/org/chromium/webview_shell/test/WebViewLayoutTest.java b/android_webview/tools/system_webview_shell/layout_tests/src/org/chromium/webview_shell/test/WebViewLayoutTest.java
index e4dee47..03f8188 100644
--- a/android_webview/tools/system_webview_shell/layout_tests/src/org/chromium/webview_shell/test/WebViewLayoutTest.java
+++ b/android_webview/tools/system_webview_shell/layout_tests/src/org/chromium/webview_shell/test/WebViewLayoutTest.java
@@ -193,7 +193,6 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "crbug.com/719974")
     public void testWebViewIncludedStableInterfaces() throws Exception {
         ensureJsTestCopied();
         loadUrlWebViewAsync("file://" + PATH_BLINK_PREFIX
diff --git a/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt b/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
index e2db01cf..950ad60 100644
--- a/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
+++ b/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
@@ -41,6 +41,7 @@
 
 # web payments api not enabled in webiew, crbug.com/667069
 interface HTMLIFrameElement : HTMLElement
+    getter allowPaymentRequest
     setter allowPaymentRequest
 
 # Android does not support switching the audio output device, crbug.com/589500
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java
index c3c9262e..1a91056 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java
@@ -55,16 +55,6 @@
     }
 
     /**
-     * Returns the previously determined value of whether there is a child account on the device.
-     * Should only be called after the native library and profile have been loaded.
-     *
-     * @return The previously determined value of whether there is a child account on the device.
-     */
-    public static boolean isChildAccount() {
-        return nativeIsChildAccount();
-    }
-
-    /**
      * Set a callback to be called the next time a child account status change is received
      * @param callback the callback to be called when the status changes.
      */
@@ -97,8 +87,6 @@
         });
     }
 
-    private static native boolean nativeIsChildAccount();
-
     private static native void nativeListenForChildStatusReceived(Callback<Boolean> callback);
 
     private static native void nativeOnReauthenticationResult(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
index 53c63681..6150503 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
@@ -68,14 +68,11 @@
         int categoryIndex = 0;
         for (int category : categories) {
             int categoryStatus = suggestionsSource.getCategoryStatus(category);
-            if (categoryStatus == CategoryStatus.LOADING_ERROR
-                    || categoryStatus == CategoryStatus.NOT_PROVIDED
-                    || categoryStatus == CategoryStatus.CATEGORY_EXPLICITLY_DISABLED) {
-                continue;
+            int suggestionsCount = 0;
+            if (SnippetsBridge.isCategoryEnabled(categoryStatus)) {
+                suggestionsCount = resetSection(category, categoryStatus, alwaysAllowEmptySections);
             }
-
-            suggestionsPerCategory[categoryIndex] =
-                    resetSection(category, categoryStatus, alwaysAllowEmptySections);
+            suggestionsPerCategory[categoryIndex] = suggestionsCount;
             ++categoryIndex;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/profiles/Profile.java b/chrome/android/java/src/org/chromium/chrome/browser/profiles/Profile.java
index 9637c6a..fd5c15c2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/profiles/Profile.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/profiles/Profile.java
@@ -64,6 +64,13 @@
     }
 
     /**
+     * @return Whether the profile is signed in to a child account.
+     */
+    public boolean isChild() {
+        return nativeIsChild(mNativeProfileAndroid);
+    }
+
+    /**
      * @return Whether or not the native side profile exists.
      */
     @VisibleForTesting
@@ -97,4 +104,5 @@
     private native Object nativeGetOffTheRecordProfile(long nativeProfileAndroid);
     private native boolean nativeHasOffTheRecordProfile(long nativeProfileAndroid);
     private native boolean nativeIsOffTheRecord(long nativeProfileAndroid);
+    private native boolean nativeIsChild(long nativeProfileAndroid);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java
index 5b4e0af..3e7b971 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java
@@ -38,7 +38,6 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.AppHooks;
-import org.chromium.chrome.browser.childaccounts.ChildAccountService;
 import org.chromium.chrome.browser.preferences.ChromeBasePreference;
 import org.chromium.chrome.browser.preferences.ManagedPreferenceDelegate;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
@@ -117,6 +116,8 @@
 
     private ArrayList<Preference> mAccountsListPreferences = new ArrayList<Preference>();
 
+    private Profile mProfile;
+
     @Override
     public void onCreate(Bundle savedState) {
         super.onCreate(savedState);
@@ -134,6 +135,8 @@
                     getArguments().getInt(SHOW_GAIA_SERVICE_TYPE_EXTRA, mGaiaServiceType);
         }
 
+        mProfile = Profile.getLastUsedProfile();
+
         AccountManagementScreenHelper.logEvent(
                 ProfileAccountManagementMetrics.VIEW,
                 mGaiaServiceType);
@@ -233,10 +236,8 @@
     }
 
     private void configureSignOutSwitch() {
-        boolean isChildAccount = ChildAccountService.isChildAccount();
-
         Preference signOutSwitch = findPreference(PREF_SIGN_OUT);
-        if (isChildAccount) {
+        if (mProfile.isChild()) {
             getPreferenceScreen().removePreference(signOutSwitch);
         } else {
             signOutSwitch.setEnabled(getSignOutAllowedPreferenceValue(getActivity()));
@@ -301,7 +302,7 @@
 
     private void configureGoogleActivityControls() {
         Preference pref = findPreference(PREF_GOOGLE_ACTIVITY_CONTROLS);
-        if (ChildAccountService.isChildAccount()) {
+        if (mProfile.isChild()) {
             pref.setSummary(R.string.sign_in_google_activity_controls_message_child_account);
         }
         pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@@ -319,7 +320,7 @@
     private void configureAddAccountPreference() {
         ChromeBasePreference addAccount = (ChromeBasePreference) findPreference(PREF_ADD_ACCOUNT);
 
-        if (ChildAccountService.isChildAccount()) {
+        if (mProfile.isChild()) {
             getPreferenceScreen().removePreference(addAccount);
         } else {
             addAccount.setTitle(getResources().getString(
@@ -356,7 +357,7 @@
     private void configureChildAccountPreferences() {
         Preference parentAccounts = findPreference(PREF_PARENT_ACCOUNTS);
         Preference childContent = findPreference(PREF_CHILD_CONTENT);
-        if (ChildAccountService.isChildAccount()) {
+        if (mProfile.isChild()) {
             Resources res = getActivity().getResources();
             PrefServiceBridge prefService = PrefServiceBridge.getInstance();
 
@@ -423,7 +424,7 @@
             pref.setSelectable(false);
             pref.setTitle(account.name);
 
-            boolean isChildAccount = ChildAccountService.isChildAccount();
+            boolean isChildAccount = mProfile.isChild();
             pref.setUseReducedPadding(isChildAccount);
             pref.setIcon(new BitmapDrawable(getResources(),
                     isChildAccount ? getBadgedUserPicture(account.name, getResources()) :
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
index 14d8da28..ee09c158 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
@@ -16,10 +16,10 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.AppHooks;
-import org.chromium.chrome.browser.childaccounts.ChildAccountService;
 import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator;
 import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory;
 import org.chromium.chrome.browser.invalidation.InvalidationController;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.AccountManagementFragment;
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.sync.ui.PassphraseActivity;
@@ -147,7 +147,7 @@
         if (isSyncEnabled) {
             mProfileSyncService.requestStart();
         } else {
-            if (ChildAccountService.isChildAccount()) {
+            if (Profile.getLastUsedProfile().isChild()) {
                 // For child accounts, Sync needs to stay enabled, so we reenable it in settings.
                 // TODO(bauerb): Remove the dependency on child account code and instead go through
                 // prefs (here and in the Sync customization UI).
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java
index 7e5abc0..e2de479 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java
@@ -35,10 +35,10 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
-import org.chromium.chrome.browser.childaccounts.ChildAccountService;
 import org.chromium.chrome.browser.invalidation.InvalidationController;
 import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
 import org.chromium.chrome.browser.preferences.SyncedAccountPreference;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.sync.GoogleServiceAuthError;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
@@ -253,7 +253,7 @@
      * @return Whether Sync can be disabled.
      */
     private boolean canDisableSync() {
-        return !ChildAccountService.isChildAccount();
+        return !Profile.getLastUsedProfile().isChild();
     }
 
     private boolean isSyncTypePreference(Preference preference) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
index 93f8ac9..e52f2f8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -28,8 +28,8 @@
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.childaccounts.ChildAccountService;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.signin.SigninManager.SignInStateObserver;
 import org.chromium.chrome.browser.widget.TintedImageButton;
@@ -511,7 +511,7 @@
             @Override
             public Boolean call() throws Exception {
                 PrefServiceBridge.getInstance().setSupervisedUserId("ChildAccountSUID");
-                return ChildAccountService.isChildAccount()
+                return Profile.getLastUsedProfile().isChild()
                         && !PrefServiceBridge.getInstance().canDeleteBrowsingHistory()
                         && !PrefServiceBridge.getInstance().isIncognitoModeEnabled();
             }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderTest.java
index 209bb2ea..d3e02de 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderTest.java
@@ -25,8 +25,8 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.childaccounts.ChildAccountService;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
@@ -99,7 +99,7 @@
             @Override
             public Boolean call() throws Exception {
                 PrefServiceBridge.getInstance().setSupervisedUserId("");
-                return ChildAccountService.isChildAccount();
+                return Profile.getLastUsedProfile().isChild();
             }
 
         }));
@@ -124,7 +124,7 @@
             @Override
             public Boolean call() throws Exception {
                 PrefServiceBridge.getInstance().setSupervisedUserId("ChildAccountSUID");
-                return ChildAccountService.isChildAccount();
+                return Profile.getLastUsedProfile().isChild();
             }
 
         }));
diff --git a/chrome/android/webapk/shell_apk/BUILD.gn b/chrome/android/webapk/shell_apk/BUILD.gn
index 2a9adc89..f1f4c0f0 100644
--- a/chrome/android/webapk/shell_apk/BUILD.gn
+++ b/chrome/android/webapk/shell_apk/BUILD.gn
@@ -105,6 +105,9 @@
 android_resources("shell_apk_resources") {
   resource_dirs = [ "res" ]
   custom_package = "org.chromium.webapk.shell_apk"
+  deps = [
+    ":webapk_strings_grd",
+  ]
 }
 
 android_library("webapk_java") {
@@ -152,6 +155,57 @@
   }
 }
 
+java_strings_grd("webapk_strings_grd") {
+  grd_file = "//chrome/android/webapk/strings/android_webapk_strings.grd"
+
+  outputs = [
+    "values-am/android_webapk_strings.xml",
+    "values-ar/android_webapk_strings.xml",
+    "values-bg/android_webapk_strings.xml",
+    "values-ca/android_webapk_strings.xml",
+    "values-cs/android_webapk_strings.xml",
+    "values-da/android_webapk_strings.xml",
+    "values-de/android_webapk_strings.xml",
+    "values-el/android_webapk_strings.xml",
+    "values/android_webapk_strings.xml",
+    "values-en-rGB/android_webapk_strings.xml",
+    "values-es/android_webapk_strings.xml",
+    "values-es-rUS/android_webapk_strings.xml",
+    "values-fa/android_webapk_strings.xml",
+    "values-fi/android_webapk_strings.xml",
+    "values-tl/android_webapk_strings.xml",
+    "values-fr/android_webapk_strings.xml",
+    "values-hi/android_webapk_strings.xml",
+    "values-hr/android_webapk_strings.xml",
+    "values-hu/android_webapk_strings.xml",
+    "values-in/android_webapk_strings.xml",
+    "values-it/android_webapk_strings.xml",
+    "values-iw/android_webapk_strings.xml",
+    "values-ja/android_webapk_strings.xml",
+    "values-ko/android_webapk_strings.xml",
+    "values-lt/android_webapk_strings.xml",
+    "values-lv/android_webapk_strings.xml",
+    "values-nl/android_webapk_strings.xml",
+    "values-nb/android_webapk_strings.xml",
+    "values-pl/android_webapk_strings.xml",
+    "values-pt-rBR/android_webapk_strings.xml",
+    "values-pt-rPT/android_webapk_strings.xml",
+    "values-ro/android_webapk_strings.xml",
+    "values-ru/android_webapk_strings.xml",
+    "values-sk/android_webapk_strings.xml",
+    "values-sl/android_webapk_strings.xml",
+    "values-sr/android_webapk_strings.xml",
+    "values-sv/android_webapk_strings.xml",
+    "values-sw/android_webapk_strings.xml",
+    "values-th/android_webapk_strings.xml",
+    "values-tr/android_webapk_strings.xml",
+    "values-uk/android_webapk_strings.xml",
+    "values-vi/android_webapk_strings.xml",
+    "values-zh-rCN/android_webapk_strings.xml",
+    "values-zh-rTW/android_webapk_strings.xml",
+  ]
+}
+
 # Template for WebAPK. When a WebAPK is generated:
 # - Android manifest is customized to the website.
 # - App icon is extracted from the website and added to the APK's resources.
diff --git a/chrome/android/webapk/strings/android_webapk_strings.grd b/chrome/android/webapk/strings/android_webapk_strings.grd
new file mode 100644
index 0000000..8461366
--- /dev/null
+++ b/chrome/android/webapk/strings/android_webapk_strings.grd
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
+  <outputs>
+    <output filename="values-am/android_webapk_strings.xml" lang="am" type="android" />
+    <output filename="values-ar/android_webapk_strings.xml" lang="ar" type="android" />
+    <output filename="values-bg/android_webapk_strings.xml" lang="bg" type="android" />
+    <output filename="values-ca/android_webapk_strings.xml" lang="ca" type="android" />
+    <output filename="values-cs/android_webapk_strings.xml" lang="cs" type="android" />
+    <output filename="values-da/android_webapk_strings.xml" lang="da" type="android" />
+    <output filename="values-de/android_webapk_strings.xml" lang="de" type="android" />
+    <output filename="values-el/android_webapk_strings.xml" lang="el" type="android" />
+    <output filename="values/android_webapk_strings.xml" lang="en" type="android" />
+    <output filename="values-en-rGB/android_webapk_strings.xml" lang="en-GB" type="android" />
+    <output filename="values-es/android_webapk_strings.xml" lang="es" type="android" />
+    <output filename="values-es-rUS/android_webapk_strings.xml" lang="es-419" type="android" />
+    <output filename="values-fa/android_webapk_strings.xml" lang="fa" type="android" />
+    <output filename="values-fi/android_webapk_strings.xml" lang="fi" type="android" />
+    <output filename="values-tl/android_webapk_strings.xml" lang="fil" type="android" />
+    <output filename="values-fr/android_webapk_strings.xml" lang="fr" type="android" />
+    <output filename="values-hi/android_webapk_strings.xml" lang="hi" type="android" />
+    <output filename="values-hr/android_webapk_strings.xml" lang="hr" type="android" />
+    <output filename="values-hu/android_webapk_strings.xml" lang="hu" type="android" />
+    <output filename="values-in/android_webapk_strings.xml" lang="id" type="android" />
+    <output filename="values-it/android_webapk_strings.xml" lang="it" type="android" />
+    <output filename="values-iw/android_webapk_strings.xml" lang="iw" type="android" />
+    <output filename="values-ja/android_webapk_strings.xml" lang="ja" type="android" />
+    <output filename="values-ko/android_webapk_strings.xml" lang="ko" type="android" />
+    <output filename="values-lt/android_webapk_strings.xml" lang="lt" type="android" />
+    <output filename="values-lv/android_webapk_strings.xml" lang="lv" type="android" />
+    <output filename="values-nl/android_webapk_strings.xml" lang="nl" type="android" />
+    <output filename="values-nb/android_webapk_strings.xml" lang="no" type="android" />
+    <output filename="values-pl/android_webapk_strings.xml" lang="pl" type="android" />
+    <output filename="values-pt-rBR/android_webapk_strings.xml" lang="pt-BR" type="android" />
+    <output filename="values-pt-rPT/android_webapk_strings.xml" lang="pt-PT" type="android" />
+    <output filename="values-ro/android_webapk_strings.xml" lang="ro" type="android" />
+    <output filename="values-ru/android_webapk_strings.xml" lang="ru" type="android" />
+    <output filename="values-sk/android_webapk_strings.xml" lang="sk" type="android" />
+    <output filename="values-sl/android_webapk_strings.xml" lang="sl" type="android" />
+    <output filename="values-sr/android_webapk_strings.xml" lang="sr" type="android" />
+    <output filename="values-sv/android_webapk_strings.xml" lang="sv" type="android" />
+    <output filename="values-sw/android_webapk_strings.xml" lang="sw" type="android" />
+    <output filename="values-th/android_webapk_strings.xml" lang="th" type="android" />
+    <output filename="values-tr/android_webapk_strings.xml" lang="tr" type="android" />
+    <output filename="values-uk/android_webapk_strings.xml" lang="uk" type="android" />
+    <output filename="values-vi/android_webapk_strings.xml" lang="vi" type="android" />
+    <output filename="values-zh-rCN/android_webapk_strings.xml" lang="zh-CN" type="android" />
+    <output filename="values-zh-rTW/android_webapk_strings.xml" lang="zh-TW" type="android" />
+  </outputs>
+  <translations>
+    <file lang="am" path="translations/android_webapk_strings_am.xtb" />
+    <file lang="ar" path="translations/android_webapk_strings_ar.xtb" />
+    <file lang="bg" path="translations/android_webapk_strings_bg.xtb" />
+    <file lang="ca" path="translations/android_webapk_strings_ca.xtb" />
+    <file lang="cs" path="translations/android_webapk_strings_cs.xtb" />
+    <file lang="da" path="translations/android_webapk_strings_da.xtb" />
+    <file lang="de" path="translations/android_webapk_strings_de.xtb" />
+    <file lang="el" path="translations/android_webapk_strings_el.xtb" />
+    <file lang="en-GB" path="translations/android_webapk_strings_en-GB.xtb" />
+    <file lang="es" path="translations/android_webapk_strings_es.xtb" />
+    <file lang="es-419" path="translations/android_webapk_strings_es-419.xtb" />
+    <file lang="fa" path="translations/android_webapk_strings_fa.xtb" />
+    <file lang="fi" path="translations/android_webapk_strings_fi.xtb" />
+    <file lang="fil" path="translations/android_webapk_strings_fil.xtb" />
+    <file lang="fr" path="translations/android_webapk_strings_fr.xtb" />
+    <file lang="hi" path="translations/android_webapk_strings_hi.xtb" />
+    <file lang="hr" path="translations/android_webapk_strings_hr.xtb" />
+    <file lang="hu" path="translations/android_webapk_strings_hu.xtb" />
+    <file lang="id" path="translations/android_webapk_strings_id.xtb" />
+    <file lang="it" path="translations/android_webapk_strings_it.xtb" />
+    <file lang="iw" path="translations/android_webapk_strings_iw.xtb" />
+    <file lang="ja" path="translations/android_webapk_strings_ja.xtb" />
+    <file lang="ko" path="translations/android_webapk_strings_ko.xtb" />
+    <file lang="lt" path="translations/android_webapk_strings_lt.xtb" />
+    <file lang="lv" path="translations/android_webapk_strings_lv.xtb" />
+    <file lang="nl" path="translations/android_webapk_strings_nl.xtb" />
+    <file lang="no" path="translations/android_webapk_strings_no.xtb" />
+    <file lang="pl" path="translations/android_webapk_strings_pl.xtb" />
+    <file lang="pt-BR" path="translations/android_webapk_strings_pt-BR.xtb" />
+    <file lang="pt-PT" path="translations/android_webapk_strings_pt-PT.xtb" />
+    <file lang="ro" path="translations/android_webapk_strings_ro.xtb" />
+    <file lang="ru" path="translations/android_webapk_strings_ru.xtb" />
+    <file lang="sk" path="translations/android_webapk_strings_sk.xtb" />
+    <file lang="sl" path="translations/android_webapk_strings_sl.xtb" />
+    <file lang="sr" path="translations/android_webapk_strings_sr.xtb" />
+    <file lang="sv" path="translations/android_webapk_strings_sv.xtb" />
+    <file lang="sw" path="translations/android_webapk_strings_sw.xtb" />
+    <file lang="th" path="translations/android_webapk_strings_th.xtb" />
+    <file lang="tr" path="translations/android_webapk_strings_tr.xtb" />
+    <file lang="uk" path="translations/android_webapk_strings_uk.xtb" />
+    <file lang="vi" path="translations/android_webapk_strings_vi.xtb" />
+    <file lang="zh-CN" path="translations/android_webapk_strings_zh-CN.xtb" />
+    <file lang="zh-TW" path="translations/android_webapk_strings_zh-TW.xtb" />
+  </translations>
+  <release allow_pseudo="false" seq="1">
+    <messages fallback_to_english="true">
+      <!-- Select host browser dialog -->
+      <message name="IDS_CHOOSE_HOST_BROWSER_DIALOG_TITLE" desc="Title for the host browser picker dialog, which is used to ask users to pick a browser to launch the installed WebAPK.">
+        <ph name="WEBAPK_SITE">%1$s<ex>Housing.com</ex></ph> needs a Web browser to run
+      </message>
+      <message name="IDS_CHOOSE_HOST_BROWSER" desc="Content for the host browser picker dialog, which is used to ask users to pick a browser to launch the installed WebAPK.">
+        Please select the browser you'd like to use to run <ph name="WEBAPK_SITE">%1$s<ex>Housing.com</ex></ph>
+      </message>
+      
+    </messages>
+  </release>
+</grit>
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_am.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_am.xtb
new file mode 100644
index 0000000..92406ec2
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_am.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="am">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_ar.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_ar.xtb
new file mode 100644
index 0000000..198ea62
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_ar.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ar">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_bg.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_bg.xtb
new file mode 100644
index 0000000..6681995
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_bg.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="bg">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_ca.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_ca.xtb
new file mode 100644
index 0000000..71cdd772
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_ca.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ca">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_cs.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_cs.xtb
new file mode 100644
index 0000000..dc153a85
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_cs.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="cs">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_da.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_da.xtb
new file mode 100644
index 0000000..1256832
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_da.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="da">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_de.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_de.xtb
new file mode 100644
index 0000000..43dd909
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_de.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="de">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_el.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_el.xtb
new file mode 100644
index 0000000..1b096642
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_el.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="el">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_en-GB.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_en-GB.xtb
new file mode 100644
index 0000000..12c3fa00
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_en-GB.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="en-GB">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_es-419.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_es-419.xtb
new file mode 100644
index 0000000..b652ed0
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_es-419.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="es-419">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_es.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_es.xtb
new file mode 100644
index 0000000..4d4f400
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_es.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="es">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_fa.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_fa.xtb
new file mode 100644
index 0000000..4cff15d
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_fa.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fa">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_fi.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_fi.xtb
new file mode 100644
index 0000000..60ba9aa
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_fi.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fi">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_fil.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_fil.xtb
new file mode 100644
index 0000000..8f6a880
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_fil.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fil">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_fr.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_fr.xtb
new file mode 100644
index 0000000..bf48975a
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_fr.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fr">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_hi.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_hi.xtb
new file mode 100644
index 0000000..279503cd
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_hi.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hi">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_hr.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_hr.xtb
new file mode 100644
index 0000000..9ec62af
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_hr.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hr">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_hu.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_hu.xtb
new file mode 100644
index 0000000..bdc02ee
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_hu.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hu">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_id.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_id.xtb
new file mode 100644
index 0000000..5f2882d
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_id.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="id">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_it.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_it.xtb
new file mode 100644
index 0000000..e7df702
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_it.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="it">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_iw.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_iw.xtb
new file mode 100644
index 0000000..a29d4ad
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_iw.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="iw">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_ja.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_ja.xtb
new file mode 100644
index 0000000..d8a3543
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_ja.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ja">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_ko.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_ko.xtb
new file mode 100644
index 0000000..558b05b
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_ko.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ko">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_lt.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_lt.xtb
new file mode 100644
index 0000000..f20c0fa2
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_lt.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="lt">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_lv.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_lv.xtb
new file mode 100644
index 0000000..6f3afbc
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_lv.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="lv">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_nl.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_nl.xtb
new file mode 100644
index 0000000..05ab957
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_nl.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="nl">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_no.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_no.xtb
new file mode 100644
index 0000000..ede4de30
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_no.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="no">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_pl.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_pl.xtb
new file mode 100644
index 0000000..1bf17bd5
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_pl.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pl">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_pt-BR.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_pt-BR.xtb
new file mode 100644
index 0000000..de39dfa
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_pt-BR.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pt-BR">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_pt-PT.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_pt-PT.xtb
new file mode 100644
index 0000000..0b98ee77
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_pt-PT.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pt-PT">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_ro.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_ro.xtb
new file mode 100644
index 0000000..7129eb4
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_ro.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ro">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_ru.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_ru.xtb
new file mode 100644
index 0000000..6dfaa442
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_ru.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ru">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_sk.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_sk.xtb
new file mode 100644
index 0000000..202e515a
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_sk.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sk">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_sl.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_sl.xtb
new file mode 100644
index 0000000..31b5a1a
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_sl.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sl">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_sr.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_sr.xtb
new file mode 100644
index 0000000..984d7192
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_sr.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sr">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_sv.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_sv.xtb
new file mode 100644
index 0000000..9a787b8
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_sv.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sv">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_sw.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_sw.xtb
new file mode 100644
index 0000000..9aa61cb
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_sw.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sw">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_th.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_th.xtb
new file mode 100644
index 0000000..dbe6a601
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_th.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="th">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_tr.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_tr.xtb
new file mode 100644
index 0000000..d99480c0
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_tr.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="tr">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_uk.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_uk.xtb
new file mode 100644
index 0000000..6e80099d
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_uk.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="uk">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_vi.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_vi.xtb
new file mode 100644
index 0000000..8a42ab1
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_vi.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="vi">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_zh-CN.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_zh-CN.xtb
new file mode 100644
index 0000000..c7d76e8
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_zh-CN.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zh-CN">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_zh-TW.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_zh-TW.xtb
new file mode 100644
index 0000000..3e0c306
--- /dev/null
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_zh-TW.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zh-TW">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a3a3e8c..1baf8743 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -693,14 +693,13 @@
 };
 
 #if !defined(OS_ANDROID)
-const FeatureEntry::Choice kEnableDefaultMediaSessionChoices[] = {
-    {flag_descriptions::kEnableDefaultMediaSessionDisabled, "", ""},
-    {flag_descriptions::kEnableDefaultMediaSessionEnabled,
-     switches::kEnableDefaultMediaSession, ""},
+const FeatureEntry::Choice kEnableAudioFocusChoices[] = {
+    {flag_descriptions::kEnableAudioFocusDisabled, "", ""},
+    {flag_descriptions::kEnableAudioFocusEnabled, switches::kEnableAudioFocus,
+     ""},
 #if BUILDFLAG(ENABLE_PLUGINS)
-    {flag_descriptions::kEnableDefaultMediaSessionEnabledDuckFlash,
-     switches::kEnableDefaultMediaSession,
-     switches::kEnableDefaultMediaSessionDuckFlash},
+    {flag_descriptions::kEnableAudioFocusEnabledDuckFlash,
+     switches::kEnableAudioFocus, switches::kEnableAudioFocusDuckFlash},
 #endif  // BUILDFLAG(ENABLE_PLUGINS)
 };
 #endif  // !defined(OS_ANDROID)
@@ -2539,10 +2538,9 @@
      FEATURE_VALUE_TYPE(features::kEnumerateAudioDevices)},
 #endif  // OS_CHROMEOS
 #if !defined(OS_ANDROID)
-    {"enable-default-media-session",
-     flag_descriptions::kEnableDefaultMediaSessionName,
-     flag_descriptions::kEnableDefaultMediaSessionDescription, kOsDesktop,
-     MULTI_VALUE_TYPE(kEnableDefaultMediaSessionChoices)},
+    {"enable-audio-focus", flag_descriptions::kEnableAudioFocusName,
+     flag_descriptions::kEnableAudioFocusDescription, kOsDesktop,
+     MULTI_VALUE_TYPE(kEnableAudioFocusChoices)},
 #endif  // !OS_ANDROID
 #if defined(OS_ANDROID)
     {"modal-permission-prompts", flag_descriptions::kModalPermissionPromptsName,
@@ -2892,6 +2890,17 @@
      FEATURE_VALUE_TYPE(features::kD3DVsync)},
 #endif  // defined(OS_WIN)
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+    {"use-google-local-ntp", flag_descriptions::kUseGoogleLocalNtpName,
+     flag_descriptions::kUseGoogleLocalNtpDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(features::kUseGoogleLocalNtp)},
+
+    {"one-google-bar-on-local-ntp",
+     flag_descriptions::kOneGoogleBarOnLocalNtpName,
+     flag_descriptions::kOneGoogleBarOnLocalNtpDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(features::kOneGoogleBarOnLocalNtp)},
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+
     // NOTE: Adding new command-line switches requires adding corresponding
     // entries to enum "LoginCustomFlags" in histograms/enums.xml. See note in
     // enums.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc
index a666358..3062ff6 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -1044,38 +1044,25 @@
 std::vector<const UiElement*> VrShellGl::GetElementsInDrawOrder(
     const vr::Mat4f& view_matrix,
     const std::vector<const UiElement*>& elements) {
-  typedef std::pair<float, const UiElement*> DistanceElementPair;
-  std::vector<DistanceElementPair> zOrderedElementPairs;
-  zOrderedElementPairs.reserve(elements.size());
-
-  for (const auto* element : elements) {
-    // Distance is the abs(z) value in view space.
-    gfx::Vector3dF element_position =
-        vr::GetTranslation(element->TransformMatrix());
-
-    float distance =
-        std::fabs(vr::MatrixVectorMul(view_matrix, element_position).z());
-    zOrderedElementPairs.push_back(std::make_pair(distance, element));
-  }
+  std::vector<const UiElement*> sorted_elements = elements;
 
   // Sort elements primarily based on their draw phase (lower draw phase first)
-  // and secondarily based on their distance (larger distance first).
-  std::sort(
-      zOrderedElementPairs.begin(), zOrderedElementPairs.end(),
-      [](const DistanceElementPair& first, const DistanceElementPair& second) {
-        if (first.second->draw_phase() != second.second->draw_phase()) {
-          return first.second->draw_phase() < second.second->draw_phase();
-        } else {
-          return first.first > second.first;
-        }
-      });
+  // and secondarily based on their z-axis distance (more distant first).
+  // TODO(mthiesse, crbug.com/721356): This will not work well for elements not
+  // directly in front of the user, but works well enough for our initial
+  // release, and provides a consistent ordering that we can easily design
+  // around.
+  std::sort(sorted_elements.begin(), sorted_elements.end(),
+            [](const UiElement* first, const UiElement* second) {
+              if (first->draw_phase() != second->draw_phase()) {
+                return first->draw_phase() < second->draw_phase();
+              } else {
+                return vr::GetTranslation(first->TransformMatrix()).z() <
+                       vr::GetTranslation(second->TransformMatrix()).z();
+              }
+            });
 
-  std::vector<const UiElement*> zOrderedElements;
-  zOrderedElements.reserve(elements.size());
-  for (auto distanceElementPair : zOrderedElementPairs) {
-    zOrderedElements.push_back(distanceElementPair.second);
-  }
-  return zOrderedElements;
+  return sorted_elements;
 }
 
 void VrShellGl::DrawCursor(const vr::Mat4f& render_matrix) {
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 069ca6d6..954dcef 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -1471,9 +1471,9 @@
   }
 
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableDefaultMediaSession)) {
+          switches::kEnableAudioFocus)) {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kEnableDefaultMediaSession);
+        switches::kEnableAudioFocus);
   }
 }
 
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8b0b6b0..ee29df2 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2659,16 +2659,16 @@
 
 #if !defined(OS_ANDROID)
 
-const char kEnableDefaultMediaSessionName[] = "Manage audio focus across tabs";
+const char kEnableAudioFocusName[] = "Manage audio focus across tabs";
 
-const char kEnableDefaultMediaSessionDescription[] =
+const char kEnableAudioFocusDescription[] =
     "Manage audio focus across tabs to improve the audio mixing.";
 
-const char kEnableDefaultMediaSessionDisabled[] = "Disabled";
+const char kEnableAudioFocusDisabled[] = "Disabled";
 
-const char kEnableDefaultMediaSessionEnabled[] = "Enabled";
+const char kEnableAudioFocusEnabled[] = "Enabled";
 
-const char kEnableDefaultMediaSessionEnabledDuckFlash[] =
+const char kEnableAudioFocusEnabledDuckFlash[] =
     "Enabled (Flash lowers volume when interrupted by other sound, "
     "experimental)";
 
@@ -3153,4 +3153,18 @@
 
 #endif  // defined(OS_WIN)
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+
+const char kUseGoogleLocalNtpName[] = "Enable using the Google local NTP";
+const char kUseGoogleLocalNtpDescription[] =
+    "Use the local New Tab page if Google is the default search engine.";
+
+const char kOneGoogleBarOnLocalNtpName[] =
+    "Enable the OneGoogleBar on the local NTP";
+const char kOneGoogleBarOnLocalNtpDescription[] =
+    "Show a OneGoogleBar on the local New Tab page if Google is the default "
+    "search engine.";
+
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+
 }  // namespace flag_descriptions
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 50ce589..7520fcd4 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2888,20 +2888,20 @@
 
 #if !defined(OS_ANDROID)
 
-// Name for the flag to enable default MediaSession on desktop
-extern const char kEnableDefaultMediaSessionName[];
+// Name for the flag to enable audio focus on desktop.
+extern const char kEnableAudioFocusName[];
 
-// Desciption for the flag to enable default MediaSession on desktop
-extern const char kEnableDefaultMediaSessionDescription[];
+// Desciption for the flag to enable audio focus on desktop.
+extern const char kEnableAudioFocusDescription[];
 
-// Option for disabling the default MediaSession
-extern const char kEnableDefaultMediaSessionDisabled[];
+// Option for disabling audio focus on desktop.
+extern const char kEnableAudioFocusDisabled[];
 
-// Option for enabling the default MediaSession
-extern const char kEnableDefaultMediaSessionEnabled[];
+// Option for enabling audio focus on desktop.
+extern const char kEnableAudioFocusEnabled[];
 
-// Option for enabling the default MediaSession with Flash
-extern const char kEnableDefaultMediaSessionEnabledDuckFlash[];
+// Option for enabling audio focus with Flash support on desktop.
+extern const char kEnableAudioFocusEnabledDuckFlash[];
 
 #endif  // !defined(OS_ANDROID)
 
@@ -3422,6 +3422,19 @@
 
 #endif  // defined(OS_WIN)
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+
+// Name and description for the flag to use the local NTP if Google is the
+// default search engine.
+extern const char kUseGoogleLocalNtpName[];
+extern const char kUseGoogleLocalNtpDescription[];
+
+// Name and description for the flag to show a OneGoogleBar on the local NTP.
+extern const char kOneGoogleBarOnLocalNtpName[];
+extern const char kOneGoogleBarOnLocalNtpDescription[];
+
+#endif
+
 }  // namespace flag_descriptions
 
 #endif  // CHROME_BROWSER_FLAG_DESCRIPTIONS_H_
diff --git a/chrome/browser/profiles/profile_android.cc b/chrome/browser/profiles/profile_android.cc
index 3bb20c5..ddcba395 100644
--- a/chrome/browser/profiles/profile_android.cc
+++ b/chrome/browser/profiles/profile_android.cc
@@ -104,6 +104,12 @@
   return profile_->IsOffTheRecord();
 }
 
+jboolean ProfileAndroid::IsChild(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj) {
+  return profile_->IsChild();
+}
+
 // static
 ScopedJavaLocalRef<jobject> GetLastUsedProfile(
     JNIEnv* env,
diff --git a/chrome/browser/profiles/profile_android.h b/chrome/browser/profiles/profile_android.h
index b7a55d3e7..8f881869 100644
--- a/chrome/browser/profiles/profile_android.h
+++ b/chrome/browser/profiles/profile_android.h
@@ -52,6 +52,10 @@
   jboolean IsOffTheRecord(JNIEnv* env,
                           const base::android::JavaParamRef<jobject>& obj);
 
+  // Whether this profile is signed in to a child account.
+  jboolean IsChild(JNIEnv* env,
+                   const base::android::JavaParamRef<jobject>& obj);
+
   explicit ProfileAndroid(Profile* profile);
   ~ProfileAndroid() override;
 
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js
index 7c8e8fca..9e154d20 100644
--- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js
+++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js
@@ -74,7 +74,7 @@
       localStorage['brailleSideBySide'] === 'true' ?
       currentlyDisplayingSideBySide : currentlyDisplayingInterleave;
 
-  chrome.commandLinePrivate.hasSwitch('enable-default-media-session',
+  chrome.commandLinePrivate.hasSwitch('enable-audio-focus',
       function(result) {
         if (!result) {
           $('audioStrategy').hidden = true;
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js
index a06ac1f..ff6f1fa 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js
@@ -5,7 +5,7 @@
 /**
  * @fileoverview Handles media automation events.  Note that to perform any of
  * the actions below such as ducking, and suspension of media sessions, the
- * --enable-default-media-session flag must be passed at the command line.
+ * --enable-audio-focus flag must be passed at the command line.
  */
 
 goog.provide('MediaAutomationHandler');
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index 182a416..6fab4ea 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
@@ -48,9 +49,6 @@
 
 namespace {
 
-base::Feature kOneGoogleBarOnLocalNtpFeature{"OneGoogleBarOnLocalNtp",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Signifies a locally constructed resource, i.e. not from grit/.
 const int kLocalResource = -1;
 
@@ -240,7 +238,7 @@
       weak_ptr_factory_(this) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  if (base::FeatureList::IsEnabled(kOneGoogleBarOnLocalNtpFeature)) {
+  if (base::FeatureList::IsEnabled(features::kOneGoogleBarOnLocalNtp)) {
     one_google_bar_service_ =
         OneGoogleBarServiceFactory::GetForProfile(profile_);
   }
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc
index f5f3a58..41cdec8 100644
--- a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc
+++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc
@@ -8,15 +8,16 @@
 #include <utility>
 
 #include "base/callback.h"
-#include "base/command_line.h"
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/search/one_google_bar/one_google_bar_data.h"
 #include "chrome/common/chrome_content_client.h"
+#include "chrome/common/chrome_features.h"
 #include "components/google/core/browser/google_url_tracker.h"
 #include "components/safe_json/safe_json_parser.h"
 #include "components/signin/core/browser/access_token_fetcher.h"
@@ -191,11 +192,12 @@
 
 GURL OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::GetApiUrl(
     bool use_oauth) const {
-  std::string api_url(kApiUrl);
-  // TODO(treib): Attach to feature instead of cmdline.
-  base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
-  if (cmdline->HasSwitch("one-google-api-url"))
-    api_url = cmdline->GetSwitchValueASCII("one-google-api-url");
+  std::string api_url = base::GetFieldTrialParamValueByFeature(
+      features::kOneGoogleBarOnLocalNtp, "one-google-api-url");
+  if (api_url.empty()) {
+    api_url = kApiUrl;
+  }
+
   // Append the API key only for unauthenticated requests.
   if (!use_oauth) {
     api_url +=
@@ -207,10 +209,11 @@
 
 std::string OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::GetRequestBody()
     const {
-  // TODO(treib): Attach to feature instead of cmdline.
-  base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
-  if (cmdline->HasSwitch("one-google-bar-options"))
-    return cmdline->GetSwitchValueASCII("one-google-bar-options");
+  std::string override_options = base::GetFieldTrialParamValueByFeature(
+      features::kOneGoogleBarOnLocalNtp, "one-google-bar-options");
+  if (!override_options.empty()) {
+    return override_options;
+  }
 
   base::DictionaryValue dict;
   dict.SetInteger("subproduct", 243);
@@ -303,8 +306,9 @@
 
 void OneGoogleBarFetcherImpl::IssueRequestIfNoneOngoing() {
   // If there is an ongoing request, let it complete.
-  if (pending_request_.get())
+  if (pending_request_.get()) {
     return;
+  }
 
   pending_request_ = base::MakeUnique<AuthenticatedURLFetcher>(
       signin_manager_, token_service_, request_context_,
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index a3d0a8e3..e0bd3d89 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_instant_controller.h"
 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/features.h"
 #include "chrome/common/pref_names.h"
@@ -81,10 +82,6 @@
   NEW_TAB_URL_MAX
 };
 
-base::Feature kUseGoogleLocalNtp {
-  "UseGoogleLocalNtp", base::FEATURE_DISABLED_BY_DEFAULT
-};
-
 const TemplateURL* GetDefaultSearchProviderTemplateURL(Profile* profile) {
   if (profile) {
     TemplateURLService* template_url_service =
@@ -198,7 +195,7 @@
 #endif  // defined(OS_CHROMEOS)
 
   if (!profile->IsOffTheRecord() &&
-      base::FeatureList::IsEnabled(kUseGoogleLocalNtp) &&
+      base::FeatureList::IsEnabled(features::kUseGoogleLocalNtp) &&
       DefaultSearchProviderIsGoogle(profile)) {
     return true;
   }
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
index 92d4e7d3b..6c1a9d1 100644
--- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
+++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
@@ -121,9 +121,18 @@
     bool activated) {
   const GURL& url(navigation_handle->GetURL());
   DCHECK(navigation_handle->IsInMainFrame());
+
+  // If the site is no longer activated, clear the metadata. This is to maintain
+  // the invariant that metadata implies activated.
+  if (!activated && url.SchemeIsHTTPOrHTTPS())
+    settings_manager_->ClearSiteMetadata(url);
+
   // Return whether the activation should be whitelisted.
   return whitelisted_hosts_.count(url.host()) ||
          settings_manager_->GetSitePermission(url) == CONTENT_SETTING_BLOCK;
+  // TODO(csharrison): Consider setting the metadata to an empty dict here if
+  // the site is activated and not whitelisted. Need to be careful about various
+  // edge cases like |should_suppress_notification| and DRYRUN activation.
 }
 
 void ChromeSubresourceFilterClient::WhitelistByContentSettings(
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
index 0fec6e74..8aad111c 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
@@ -52,11 +52,9 @@
   DCHECK(settings_map_);
   settings_map_->AddObserver(this);
 
-  if (should_use_smart_ui()) {
-    if (auto* history_service = HistoryServiceFactory::GetForProfile(
-            profile, ServiceAccessType::EXPLICIT_ACCESS)) {
-      history_observer_.Add(history_service);
-    }
+  if (auto* history_service = HistoryServiceFactory::GetForProfile(
+          profile, ServiceAccessType::EXPLICIT_ACCESS)) {
+    history_observer_.Add(history_service);
   }
 }
 
@@ -85,8 +83,6 @@
 }
 
 void SubresourceFilterContentSettingsManager::OnDidShowUI(const GURL& url) {
-  if (!should_use_smart_ui())
-    return;
   auto dict = base::MakeUnique<base::DictionaryValue>();
   double now = clock_->Now().ToDoubleT();
   dict->SetDouble(kInfobarLastShownTimeKey, now);
@@ -111,6 +107,11 @@
   return true;
 }
 
+void SubresourceFilterContentSettingsManager::ClearSiteMetadata(
+    const GURL& url) {
+  SetSiteMetadata(url, nullptr);
+}
+
 std::unique_ptr<base::DictionaryValue>
 SubresourceFilterContentSettingsManager::GetSiteMetadata(
     const GURL& url) const {
@@ -179,16 +180,13 @@
     NOTREACHED();
   }
 
-  if (!should_use_smart_ui())
-    return;
-
   if (!ShouldShowUIForSite(url)) {
     ChromeSubresourceFilterClient::LogAction(
         kActionContentSettingsBlockedWhileUISuppressed);
   }
-
-  // Reset the smart UI to ensure the user can easily change their decision.
-  SetSiteMetadata(url, nullptr);
+  // Note: could potentially reset the smart UI here to enable the user to
+  // easily change their decision. If that code is added we should make sure not
+  // to delete the metadata, but merely remove / reset the timestamp.
 }
 
 // When history URLs are deleted, clear the metadata for the smart UI.
@@ -198,7 +196,6 @@
     bool expired,
     const history::URLRows& deleted_rows,
     const std::set<GURL>& favicon_urls) {
-  DCHECK(should_use_smart_ui());
   if (all_history) {
     settings_map_->ClearSettingsForOneType(
         CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER_DATA);
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
index 31be433..8f55ef6 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
@@ -48,11 +48,16 @@
   // the content setting to turn off the subresource filter.
   void WhitelistSite(const GURL& url);
 
+  // Public for testing.
+  std::unique_ptr<base::DictionaryValue> GetSiteMetadata(const GURL& url) const;
+
   // Specific logic for more intelligent UI.
   void OnDidShowUI(const GURL& url);
   bool ShouldShowUIForSite(const GURL& url) const;
   bool should_use_smart_ui() const { return should_use_smart_ui_; }
 
+  void ClearSiteMetadata(const GURL& url);
+
   void set_clock_for_testing(std::unique_ptr<base::Clock> tick_clock) {
     clock_ = std::move(tick_clock);
   }
@@ -76,7 +81,6 @@
                      const history::URLRows& deleted_rows,
                      const std::set<GURL>& favicon_urls) override;
 
-  std::unique_ptr<base::DictionaryValue> GetSiteMetadata(const GURL& url) const;
   void SetSiteMetadata(const GURL& url,
                        std::unique_ptr<base::DictionaryValue> dict);
 
diff --git a/chrome/browser/subresource_filter/subresource_filter_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_unittest.cc
index 588dfc1..3dab716 100644
--- a/chrome/browser/subresource_filter/subresource_filter_unittest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_unittest.cc
@@ -15,14 +15,20 @@
 #include "chrome/browser/after_startup_task_utils.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
 #include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h"
+#include "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h"
+#include "chrome/browser/subresource_filter/subresource_filter_profile_context.h"
+#include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h"
 #include "chrome/browser/subresource_filter/test_ruleset_publisher.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/safe_browsing_db/v4_protocol_manager_util.h"
 #include "components/subresource_filter/content/browser/content_ruleset_service.h"
+#include "components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h"
 #include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h"
 #include "components/subresource_filter/core/browser/ruleset_service.h"
 #include "components/subresource_filter/core/browser/subresource_filter_features.h"
@@ -154,6 +160,20 @@
     return ChromeSubresourceFilterClient::FromWebContents(web_contents());
   }
 
+  void RemoveURLFromBlacklist(const GURL& url) {
+    fake_safe_browsing_database_->RemoveBlacklistedUrl(url);
+  }
+
+  SubresourceFilterContentSettingsManager* settings_manager() {
+    return SubresourceFilterProfileContextFactory::GetForProfile(
+               static_cast<Profile*>(profile()))
+        ->settings_manager();
+  }
+
+  ScopedSubresourceFilterConfigurator& scoped_configuration() {
+    return scoped_configuration_;
+  }
+
  private:
   base::ScopedTempDir ruleset_service_dir_;
   TestingPrefServiceSimple pref_service_;
@@ -179,3 +199,60 @@
   EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh()));
   EXPECT_TRUE(client()->did_show_ui_for_navigation());
 }
+
+TEST_F(SubresourceFilterTest, DeactivateUrl_ClearsSiteMetadata) {
+  GURL url("https://a.test");
+  ConfigureAsSubresourceFilterOnlyURL(url);
+  SimulateNavigateAndCommit(url, main_rfh());
+  EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh()));
+
+  EXPECT_NE(nullptr, settings_manager()->GetSiteMetadata(url));
+
+  RemoveURLFromBlacklist(url);
+
+  // Navigate to |url| again and expect the site metadata to clear.
+  SimulateNavigateAndCommit(url, main_rfh());
+  EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh()));
+
+  EXPECT_EQ(nullptr, settings_manager()->GetSiteMetadata(url));
+}
+
+// If the underlying configuration changes and a site only activates to DRYRUN,
+// we should clear the metadata.
+TEST_F(SubresourceFilterTest, ActivationToDryRun_ClearsSiteMetadata) {
+  GURL url("https://a.test");
+  ConfigureAsSubresourceFilterOnlyURL(url);
+  SimulateNavigateAndCommit(url, main_rfh());
+  EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh()));
+
+  EXPECT_NE(nullptr, settings_manager()->GetSiteMetadata(url));
+
+  // If the site later activates as DRYRUN due to e.g. a configuration change,
+  // it should also be removed from the metadata.
+  scoped_configuration().ResetConfiguration(subresource_filter::Configuration(
+      subresource_filter::ActivationLevel::DRYRUN,
+      subresource_filter::ActivationScope::ACTIVATION_LIST,
+      subresource_filter::ActivationList::SUBRESOURCE_FILTER));
+
+  // Navigate to |url| again and expect the site metadata to clear.
+  SimulateNavigateAndCommit(url, main_rfh());
+  EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh()));
+
+  EXPECT_EQ(nullptr, settings_manager()->GetSiteMetadata(url));
+}
+
+TEST_F(SubresourceFilterTest, ExplicitWhitelisting_ShouldNotClearMetadata) {
+  GURL url("https://a.test");
+  ConfigureAsSubresourceFilterOnlyURL(url);
+  SimulateNavigateAndCommit(url, main_rfh());
+  EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh()));
+
+  // Simulate explicit whitelisting and reload.
+  settings_manager()->WhitelistSite(url);
+  SimulateNavigateAndCommit(url, main_rfh());
+  EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh()));
+
+  // Should not have cleared the metadata, since the site is still on the SB
+  // blacklist.
+  EXPECT_NE(nullptr, settings_manager()->GetSiteMetadata(url));
+}
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service_android.cc b/chrome/browser/supervised_user/child_accounts/child_account_service_android.cc
index cc6d860a0..097583f 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service_android.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service_android.cc
@@ -23,11 +23,6 @@
 using base::android::RunCallbackAndroid;
 using base::android::ScopedJavaGlobalRef;
 
-jboolean IsChildAccount(JNIEnv* env, const JavaParamRef<jclass>& jcaller) {
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  return profile_manager->GetLastUsedProfile()->IsChild();
-}
-
 bool RegisterChildAccountService(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.cc b/chrome/browser/ui/views/payments/payment_request_views_util.cc
index 405c62b5..2d3b335 100644
--- a/chrome/browser/ui/views/payments/payment_request_views_util.cc
+++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -305,9 +305,10 @@
   std::unique_ptr<views::View> base_label =
       GetShippingAddressLabel(type, locale, profile, /*disabled_state=*/false);
 
-  base_label->AddChildView(GetLabelForMissingInformation(
-                               comp.GetStringForMissingShippingFields(profile))
-                               .release());
+  base::string16 missing = comp.GetStringForMissingShippingFields(profile);
+  if (!missing.empty()) {
+    base_label->AddChildView(GetLabelForMissingInformation(missing).release());
+  }
   return base_label;
 }
 
@@ -339,9 +340,10 @@
   std::unique_ptr<views::View> base_label =
       GetBaseProfileLabel(type, name, phone, email);
 
-  base_label->AddChildView(GetLabelForMissingInformation(
-                               comp.GetStringForMissingContactFields(profile))
-                               .release());
+  base::string16 missing = comp.GetStringForMissingContactFields(profile);
+  if (!missing.empty()) {
+    base_label->AddChildView(GetLabelForMissingInformation(missing).release());
+  }
   return base_label;
 }
 
diff --git a/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc
index 9e73b878..1dfe682f 100644
--- a/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc
@@ -45,6 +45,10 @@
 
   // Go to the shipping address screen and select the first address (MI state).
   OpenShippingAddressSectionScreen();
+  // There is no error at the top of this screen, because no address has been
+  // selected yet.
+  EXPECT_EQ(nullptr, dialog_view()->GetViewByID(static_cast<int>(
+                         DialogViewID::SHIPPING_ADDRESS_OPTION_ERROR)));
   ResetEventObserverForSequence(std::list<DialogEvent>{
       DialogEvent::BACK_NAVIGATION, DialogEvent::SPEC_DONE_UPDATING});
   ClickOnChildInListViewAndWait(
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index f237984..3e1baaa 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -249,6 +249,12 @@
 const base::Feature kOfflinePageDownloadSuggestionsFeature{
     "NTPOfflinePageDownloadSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+// Enables or disabled the OneGoogleBar on the local NTP.
+const base::Feature kOneGoogleBarOnLocalNtp{"OneGoogleBarOnLocalNtp",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
 // Enables Permissions Blacklisting via Safe Browsing.
 const base::Feature kPermissionsBlacklist{
     "PermissionsBlacklist", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -323,6 +329,10 @@
                                           base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
+// Enables using the local NTP if Google is the default search engine.
+const base::Feature kUseGoogleLocalNtp{"UseGoogleLocalNtp",
+                                       base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Experiment to use grouped permission infobars which could show and handle
 // multiple permission requests.
 const base::Feature kUseGroupedPermissionInfobars{
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index ea7460a6..c3dae15b 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -136,6 +136,10 @@
 
 extern const base::Feature kOfflinePageDownloadSuggestionsFeature;
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+extern const base::Feature kOneGoogleBarOnLocalNtp;
+#endif
+
 extern const base::Feature kPermissionsBlacklist;
 
 #if defined(OS_WIN)
@@ -178,6 +182,8 @@
 
 extern const base::Feature kTabsInCbd;
 
+extern const base::Feature kUseGoogleLocalNtp;
+
 extern const base::Feature kUseGroupedPermissionInfobars;
 
 extern const base::Feature kUsePermissionManagerForMediaRequests;
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index efb21bf..aab5d07 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -225,8 +225,8 @@
 #else
     // GPU shader disk cache disabling is largely to conserve disk space.
     {switches::kDisableGpuShaderDiskCache, ""},
-    // Enable media sessions by default (even on non-Android platforms).
-    {switches::kEnableDefaultMediaSession, ""},
+    // Enable audio focus by default (even on non-Android platforms).
+    {switches::kEnableAudioFocus, ""},
 #endif
 #if BUILDFLAG(IS_CAST_AUDIO_ONLY)
     {switches::kDisableGpu, ""},
diff --git a/components/components_chromium_strings.grd b/components/components_chromium_strings.grd
index 21ea9785..cb80238 100644
--- a/components/components_chromium_strings.grd
+++ b/components/components_chromium_strings.grd
@@ -220,11 +220,6 @@
       <message name="IDS_SESSION_CRASHED_VIEW_MESSAGE" desc="Message shown when the last session didn't exit cleanly.">
         Chromium didn't shut down correctly.
       </message>
-
-      <!-- Strings describing Chromium security policy for DevTools security panel -->
-      <message name="IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION" desc="Description of a security problem where the site collects private user data on an insecure page, which results in an omnibox warning." translateable="false">
-        This page includes a password or credit card input over HTTP. A warning has been added to the URL bar.
-      </message>
     </messages>
   </release>
 </grit>
diff --git a/components/components_google_chrome_strings.grd b/components/components_google_chrome_strings.grd
index 061ab79..3c41235 100644
--- a/components/components_google_chrome_strings.grd
+++ b/components/components_google_chrome_strings.grd
@@ -220,11 +220,6 @@
       <message name="IDS_SESSION_CRASHED_VIEW_MESSAGE" desc="Message shown when the last session didn't exit cleanly.">
         Chrome didn't shut down correctly.
       </message>
-
-      <!-- Strings describing Chrome security policy for DevTools security panel -->
-      <message name="IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION" desc="Description of a security problem where the site collects private user data on an insecure page, which results in an omnibox warning." translateable="false">
-        This page includes a password or credit card input over HTTP. A warning has been added to the URL bar.
-      </message>
     </messages>
   </release>
 </grit>
diff --git a/components/content_settings/core/browser/website_settings_registry.cc b/components/content_settings/core/browser/website_settings_registry.cc
index e019486..4d49cef9 100644
--- a/components/content_settings/core/browser/website_settings_registry.cc
+++ b/components/content_settings/core/browser/website_settings_registry.cc
@@ -165,11 +165,14 @@
       WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
       WebsiteSettingsInfo::REQUESTING_ORIGIN_ONLY_SCOPE,
       DESKTOP | PLATFORM_ANDROID, WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
-  Register(CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER_DATA,
-           "subresource-filter-data", nullptr, WebsiteSettingsInfo::UNSYNCABLE,
-           WebsiteSettingsInfo::LOSSY,
-           WebsiteSettingsInfo::REQUESTING_ORIGIN_ONLY_SCOPE, PLATFORM_ANDROID,
-           WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
+  // Set when an origin is activated for subresource filtering and the
+  // associated UI is shown to the user. Cleared when a site is de-activated or
+  // the first URL matching the origin is removed from history.
+  Register(
+      CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER_DATA, "subresource-filter-data",
+      nullptr, WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
+      WebsiteSettingsInfo::REQUESTING_ORIGIN_ONLY_SCOPE,
+      DESKTOP | PLATFORM_ANDROID, WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
 }
 
 }  // namespace content_settings
diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h
index 3c31cde2e..580a94a 100644
--- a/components/content_settings/core/common/content_settings_types.h
+++ b/components/content_settings/core/common/content_settings_types.h
@@ -51,8 +51,7 @@
   CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER,
 
   // Website setting which stores metadata for the subresource filter to aid in
-  // decisions for whether or not to show the UI. Currently only used on
-  // Android.
+  // decisions for whether or not to show the UI.
   CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER_DATA,
 
   // This is special-cased in the permissions layer to always allow, and as
diff --git a/components/font_service/font_service_app.cc b/components/font_service/font_service_app.cc
index 06c42a2..7a78c81a 100644
--- a/components/font_service/font_service_app.cc
+++ b/components/font_service/font_service_app.cc
@@ -58,7 +58,7 @@
 
 void FontServiceApp::MatchFamilyName(const std::string& family_name,
                                      mojom::TypefaceStylePtr requested_style,
-                                     const MatchFamilyNameCallback& callback) {
+                                     MatchFamilyNameCallback callback) {
   SkFontConfigInterface::FontIdentity result_identity;
   SkString result_family;
   SkFontStyle result_style;
@@ -76,7 +76,7 @@
     style->weight = SkFontStyle().weight();
     style->width = SkFontStyle().width();
     style->slant = static_cast<mojom::TypefaceSlant>(SkFontStyle().slant());
-    callback.Run(nullptr, "", std::move(style));
+    std::move(callback).Run(nullptr, "", std::move(style));
     return;
   }
 
@@ -94,17 +94,18 @@
   style->width = result_style.width();
   style->slant = static_cast<mojom::TypefaceSlant>(result_style.slant());
 
-  callback.Run(std::move(identity), result_family.c_str(), std::move(style));
+  std::move(callback).Run(std::move(identity), result_family.c_str(),
+                          std::move(style));
 }
 
 void FontServiceApp::OpenStream(uint32_t id_number,
-                                const OpenStreamCallback& callback) {
+                                OpenStreamCallback callback) {
   base::File file;
   if (id_number < static_cast<uint32_t>(paths_.size())) {
     file = GetFileForPath(base::FilePath(paths_[id_number].c_str()));
   }
 
-  callback.Run(std::move(file));
+  std::move(callback).Run(std::move(file));
 }
 
 void FontServiceApp::Create(const service_manager::BindSourceInfo& source_info,
diff --git a/components/font_service/font_service_app.h b/components/font_service/font_service_app.h
index bafbbd1..c60c315 100644
--- a/components/font_service/font_service_app.h
+++ b/components/font_service/font_service_app.h
@@ -33,9 +33,8 @@
   // FontService:
   void MatchFamilyName(const std::string& family_name,
                        mojom::TypefaceStylePtr requested_style,
-                       const MatchFamilyNameCallback& callback) override;
-  void OpenStream(uint32_t id_number,
-                  const OpenStreamCallback& callback) override;
+                       MatchFamilyNameCallback callback) override;
+  void OpenStream(uint32_t id_number, OpenStreamCallback callback) override;
 
   void Create(const service_manager::BindSourceInfo& source_info,
               mojom::FontServiceRequest request);
diff --git a/components/font_service/public/interfaces/BUILD.gn b/components/font_service/public/interfaces/BUILD.gn
index 206f3c1..12efaaf 100644
--- a/components/font_service/public/interfaces/BUILD.gn
+++ b/components/font_service/public/interfaces/BUILD.gn
@@ -12,7 +12,4 @@
   public_deps = [
     "//mojo/common:common_custom_types",
   ]
-
-  # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
-  use_once_callback = false
 }
diff --git a/components/payments/content/BUILD.gn b/components/payments/content/BUILD.gn
index 7b6216a..49c1e13 100644
--- a/components/payments/content/BUILD.gn
+++ b/components/payments/content/BUILD.gn
@@ -88,6 +88,7 @@
     "//components/payments/core",
     "//components/payments/core:test_support",
     "//components/payments/mojom",
+    "//components/strings:components_strings_grit",
     "//content/test:test_support",
     "//net:test_support",
     "//testing/gtest",
diff --git a/components/payments/content/payment_request_spec.cc b/components/payments/content/payment_request_spec.cc
index 2f7a7e4..5ba0670 100644
--- a/components/payments/content/payment_request_spec.cc
+++ b/components/payments/content/payment_request_spec.cc
@@ -59,7 +59,7 @@
       observer_for_testing_(nullptr) {
   if (observer)
     AddObserver(observer);
-  UpdateSelectedShippingOption();
+  UpdateSelectedShippingOption(/*after_update=*/false);
   PopulateValidatedMethodData(method_data);
 }
 PaymentRequestSpec::~PaymentRequestSpec() {}
@@ -67,7 +67,7 @@
 void PaymentRequestSpec::UpdateWith(mojom::PaymentDetailsPtr details) {
   details_ = std::move(details);
   // We reparse the |details_| and update the observers.
-  UpdateSelectedShippingOption();
+  UpdateSelectedShippingOption(/*after_update=*/true);
   NotifyOnSpecUpdated();
 }
 
@@ -170,13 +170,31 @@
                                       supported_card_networks_.end());
 }
 
-void PaymentRequestSpec::UpdateSelectedShippingOption() {
+void PaymentRequestSpec::UpdateSelectedShippingOption(bool after_update) {
   if (!request_shipping())
     return;
 
+  selected_shipping_option_ = nullptr;
   selected_shipping_option_error_.clear();
+  if (details().shipping_options.empty()) {
+    // No options are provided by the merchant.
+    if (after_update) {
+      // This is after an update, which means that the selected address is no
+      // supported. The merchant may have customized the error string, or a
+      // generic one is used.
+      if (!details().error.empty()) {
+        selected_shipping_option_error_ = base::UTF8ToUTF16(details().error);
+      } else {
+        selected_shipping_option_error_ = l10n_util::GetStringUTF16(
+            IDS_PAYMENTS_UNSUPPORTED_SHIPPING_ADDRESS);
+      }
+    }
+    return;
+  }
+
   // As per the spec, the selected shipping option should initially be the last
-  // one in the array that has its selected field set to true.
+  // one in the array that has its selected field set to true. If none are
+  // selected by the merchant, |selected_shipping_option_| stays nullptr.
   auto selected_shipping_option_it = std::find_if(
       details().shipping_options.rbegin(), details().shipping_options.rend(),
       [](const payments::mojom::PaymentShippingOptionPtr& element) {
@@ -184,15 +202,6 @@
       });
   if (selected_shipping_option_it != details().shipping_options.rend()) {
     selected_shipping_option_ = selected_shipping_option_it->get();
-  } else {
-    // It's possible that there is no selected shipping option.
-    if (!details().error.empty()) {
-      selected_shipping_option_error_ = base::UTF8ToUTF16(details().error);
-    } else {
-      selected_shipping_option_error_ =
-          l10n_util::GetStringUTF16(IDS_PAYMENTS_UNSUPPORTED_SHIPPING_ADDRESS);
-    }
-    selected_shipping_option_ = nullptr;
   }
 }
 
diff --git a/components/payments/content/payment_request_spec.h b/components/payments/content/payment_request_spec.h
index 98e7d67..e7bc5ff 100644
--- a/components/payments/content/payment_request_spec.h
+++ b/components/payments/content/payment_request_spec.h
@@ -121,10 +121,13 @@
   void PopulateValidatedMethodData(
       const std::vector<mojom::PaymentMethodDataPtr>& method_data);
 
-  // Updates the selected_shipping_option based on the data passed to this
+  // Updates the |selected_shipping_option| based on the data passed to this
   // payment request by the website. This will set selected_shipping_option_ to
-  // the last option marked selected in the options array.
-  void UpdateSelectedShippingOption();
+  // the last option marked selected in the options array. If no options are
+  // provided and this method is called |after_update|, it means the merchant
+  // doesn't ship to this location. In this case,
+  // |selected_shipping_option_error_| will be set.
+  void UpdateSelectedShippingOption(bool after_update);
 
   // Will notify all observers that the spec has changed.
   void NotifyOnSpecUpdated();
diff --git a/components/payments/content/payment_request_spec_unittest.cc b/components/payments/content/payment_request_spec_unittest.cc
index 7414a61..28d2774b 100644
--- a/components/payments/content/payment_request_spec_unittest.cc
+++ b/components/payments/content/payment_request_spec_unittest.cc
@@ -7,8 +7,11 @@
 #include <utility>
 
 #include "base/memory/weak_ptr.h"
+#include "base/strings/utf_string_conversions.h"
 #include "components/payments/mojom/payment_request.mojom.h"
+#include "components/strings/grit/components_strings.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace payments {
 
@@ -281,22 +284,61 @@
   RecreateSpecWithOptionsAndDetails(std::move(options), std::move(details));
 
   EXPECT_EQ("option:2", spec()->selected_shipping_option()->id);
+  EXPECT_TRUE(spec()->selected_shipping_option_error().empty());
 
+  // Call updateWith with option:1 now selected.
   std::vector<mojom::PaymentShippingOptionPtr> new_shipping_options;
   mojom::PaymentShippingOptionPtr new_option =
       mojom::PaymentShippingOption::New();
   new_option->id = "option:1";
-  new_option->selected = false;
-  shipping_options.push_back(std::move(new_option));
+  new_option->selected = true;
+  new_shipping_options.push_back(std::move(new_option));
   mojom::PaymentShippingOptionPtr new_option2 =
       mojom::PaymentShippingOption::New();
   new_option2->id = "option:2";
-  new_option2->selected = true;
+  new_option2->selected = false;
   new_shipping_options.push_back(std::move(new_option2));
   mojom::PaymentDetailsPtr new_details = mojom::PaymentDetails::New();
   new_details->shipping_options = std::move(new_shipping_options);
 
   spec()->UpdateWith(std::move(new_details));
+
+  EXPECT_EQ("option:1", spec()->selected_shipping_option()->id);
+  EXPECT_TRUE(spec()->selected_shipping_option_error().empty());
+}
+
+// Test that the last shipping option is selected, even in the case of
+// updateWith.
+TEST_F(PaymentRequestSpecTest, ShippingOptionsSelection_NoOptionsAtAll) {
+  // No options are provided at first.
+  mojom::PaymentOptionsPtr options = mojom::PaymentOptions::New();
+  options->request_shipping = true;
+  RecreateSpecWithOptionsAndDetails(std::move(options),
+                                    mojom::PaymentDetails::New());
+
+  // No option selected, but no error either (the flow just started and no
+  // address has been selected yet).
+  EXPECT_EQ(nullptr, spec()->selected_shipping_option());
+  EXPECT_TRUE(spec()->selected_shipping_option_error().empty());
+
+  // Call updateWith with still no options.
+  spec()->UpdateWith(mojom::PaymentDetails::New());
+
+  // Now it's more serious. No option selected, but there is a generic error.
+  EXPECT_EQ(nullptr, spec()->selected_shipping_option());
+  EXPECT_EQ(
+      l10n_util::GetStringUTF16(IDS_PAYMENTS_UNSUPPORTED_SHIPPING_ADDRESS),
+      spec()->selected_shipping_option_error());
+
+  // Call updateWith with still no options, but a customized error string.
+  mojom::PaymentDetailsPtr details = mojom::PaymentDetails::New();
+  details->error = "No can do shipping.";
+  spec()->UpdateWith(std::move(details));
+
+  // No option selected, but there is an error provided by the mercahnt.
+  EXPECT_EQ(nullptr, spec()->selected_shipping_option());
+  EXPECT_EQ(base::ASCIIToUTF16("No can do shipping."),
+            spec()->selected_shipping_option_error());
 }
 
 }  // namespace payments
diff --git a/components/security_state_strings.grdp b/components/security_state_strings.grdp
index d3580a9..8e94326f 100644
--- a/components/security_state_strings.grdp
+++ b/components/security_state_strings.grdp
@@ -4,6 +4,9 @@
   <message name="IDS_PRIVATE_USER_DATA_INPUT" desc="Summary phrase for a security problem where the site collects private user data on an insecure page." translateable="false">
     Private User Data Input
   </message>
+  <message name="IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION" desc="Description of a security problem where the site collects private user data on an insecure page, which results in an omnibox warning." translateable="false">
+    This page includes a password or credit card input over HTTP. A warning has been added to the URL bar.
+  </message>
   <message name="IDS_SAFEBROWSING_WARNING" desc="Summary phrase for a security problem where the site is deemed unsafe by the SafeBrowsing service." translateable="false">
     This page is dangerous (flagged by Google Safe Browsing).
   </message>
diff --git a/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.cc b/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.cc
index cfd968e..56cd2ba0 100644
--- a/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.cc
+++ b/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.cc
@@ -19,6 +19,10 @@
   url_to_threat_type_[url] = threat_type;
 }
 
+void FakeSafeBrowsingDatabaseManager::RemoveBlacklistedUrl(const GURL& url) {
+  url_to_threat_type_.erase(url);
+}
+
 void FakeSafeBrowsingDatabaseManager::SimulateTimeout() {
   simulate_timeout_ = true;
 }
@@ -53,6 +57,10 @@
     return;
   client->OnCheckBrowseUrlResult(url, url_to_threat_type_[url],
                                  safe_browsing::ThreatMetadata());
+  // Erase the client when a check is complete. Otherwise, it's possible
+  // subsequent clients that share an address with this one will DCHECK in
+  // CheckUrlForSubresourceFilter.
+  checks_.erase(client);
 }
 
 bool FakeSafeBrowsingDatabaseManager::CheckResourceUrl(const GURL& url,
diff --git a/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h b/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h
index f36c437..d216217 100644
--- a/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h
+++ b/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h
@@ -23,6 +23,7 @@
 
   void AddBlacklistedUrl(const GURL& url,
                          safe_browsing::SBThreatType threat_type);
+  void RemoveBlacklistedUrl(const GURL& url);
 
   void SimulateTimeout();
 
diff --git a/content/browser/media/session/audio_focus_delegate_default.cc b/content/browser/media/session/audio_focus_delegate_default.cc
index b1ae90f..586bbf3 100644
--- a/content/browser/media/session/audio_focus_delegate_default.cc
+++ b/content/browser/media/session/audio_focus_delegate_default.cc
@@ -42,7 +42,7 @@
 bool AudioFocusDelegateDefault::RequestAudioFocus(
     AudioFocusManager::AudioFocusType audio_focus_type) {
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableDefaultMediaSession)) {
+          switches::kEnableAudioFocus)) {
     return true;
   }
 
diff --git a/content/browser/media/session/audio_focus_delegate_default_browsertest.cc b/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
index b84d388..ed4ec737 100644
--- a/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
+++ b/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
@@ -15,7 +15,7 @@
 class AudioFocusDelegateDefaultBrowserTest : public ContentBrowserTest {
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(switches::kEnableDefaultMediaSession);
+    command_line->AppendSwitch(switches::kEnableAudioFocus);
   }
 
   void Run(WebContents* start_contents, WebContents* interrupt_contents) {
diff --git a/content/browser/media/session/audio_focus_manager_unittest.cc b/content/browser/media/session/audio_focus_manager_unittest.cc
index 6d476852..aa89b54 100644
--- a/content/browser/media/session/audio_focus_manager_unittest.cc
+++ b/content/browser/media/session/audio_focus_manager_unittest.cc
@@ -39,7 +39,7 @@
 
   void SetUp() override {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kEnableDefaultMediaSession);
+        switches::kEnableAudioFocus);
     rph_factory_.reset(new MockRenderProcessHostFactory());
     RenderProcessHostImpl::set_render_process_host_factory(rph_factory_.get());
     browser_context_.reset(new TestBrowserContext());
diff --git a/content/browser/media/session/media_session_controllers_manager.cc b/content/browser/media/session/media_session_controllers_manager.cc
index 48f1377..79bf0f1 100644
--- a/content/browser/media/session/media_session_controllers_manager.cc
+++ b/content/browser/media/session/media_session_controllers_manager.cc
@@ -17,7 +17,7 @@
   return true;
 #else
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kEnableDefaultMediaSession);
+      switches::kEnableAudioFocus);
 #endif
 }
 
diff --git a/content/browser/media/session/media_session_impl_visibility_browsertest.cc b/content/browser/media/session/media_session_impl_visibility_browsertest.cc
index 18dee99..a5ad0b02 100644
--- a/content/browser/media/session/media_session_impl_visibility_browsertest.cc
+++ b/content/browser/media/session/media_session_impl_visibility_browsertest.cc
@@ -99,7 +99,7 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(switches::kIgnoreAutoplayRestrictionsForTests);
 #if !defined(OS_ANDROID)
-    command_line->AppendSwitch(switches::kEnableDefaultMediaSession);
+    command_line->AppendSwitch(switches::kEnableAudioFocus);
 #endif  // !defined(OS_ANDROID)
 
     VisibilityTestData params = GetVisibilityTestData();
diff --git a/content/browser/media/session/pepper_playback_observer.cc b/content/browser/media/session/pepper_playback_observer.cc
index f854321..a60ba99 100644
--- a/content/browser/media/session/pepper_playback_observer.cc
+++ b/content/browser/media/session/pepper_playback_observer.cc
@@ -19,8 +19,8 @@
 
 bool ShouldDuckFlash() {
   return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-             switches::kEnableDefaultMediaSession) ==
-         switches::kEnableDefaultMediaSessionDuckFlash;
+             switches::kEnableAudioFocus) ==
+         switches::kEnableAudioFocusDuckFlash;
 }
 
 }  // anonymous namespace
diff --git a/content/browser/media/session/pepper_player_delegate.cc b/content/browser/media/session/pepper_player_delegate.cc
index b34fe57..a36a4c301 100644
--- a/content/browser/media/session/pepper_player_delegate.cc
+++ b/content/browser/media/session/pepper_player_delegate.cc
@@ -17,8 +17,8 @@
 
 bool ShouldDuckFlash() {
   return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-             switches::kEnableDefaultMediaSession) ==
-         switches::kEnableDefaultMediaSessionDuckFlash;
+             switches::kEnableAudioFocus) ==
+         switches::kEnableAudioFocusDuckFlash;
 }
 
 }  // anonymous namespace
diff --git a/extensions/browser/api/web_request/web_request_permissions.cc b/extensions/browser/api/web_request/web_request_permissions.cc
index 22dcaf58..033a0f11 100644
--- a/extensions/browser/api/web_request/web_request_permissions.cc
+++ b/extensions/browser/api/web_request/web_request_permissions.cc
@@ -7,6 +7,8 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "chromeos/login/login_state.h"
+#include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/resource_request_info.h"
 #include "extensions/browser/extension_navigation_ui_data.h"
 #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
@@ -45,11 +47,14 @@
 // Returns true if the URL is sensitive and requests to this URL must not be
 // modified/canceled by extensions, e.g. because it is targeted to the webstore
 // to check for updates, extension blacklisting, etc.
-bool IsSensitiveURL(const GURL& url) {
+bool IsSensitiveURL(const GURL& url,
+                    bool is_request_from_browser_or_webui_renderer) {
   // TODO(battre) Merge this, CanExtensionAccessURL and
   // PermissionsData::CanAccessPage into one function.
   bool sensitive_chrome_url = false;
-  const base::StringPiece& host = url.host_piece();
+  base::StringPiece host = url.host_piece();
+  while (host.ends_with("."))
+    host.remove_suffix(1u);
   const char kGoogleCom[] = "google.com";
   const char kClient[] = "clients";
   if (url.DomainIs(kGoogleCom)) {
@@ -57,23 +62,34 @@
     // This protects requests to several internal services such as sync,
     // extension update pings, captive portal detection, fraudulent certificate
     // reporting, autofill and others.
-    if (base::StartsWith(host, kClient, base::CompareCase::SENSITIVE)) {
-      bool match = true;
-      for (base::StringPiece::const_iterator
-               i = host.begin() + strlen(kClient),
-               end = host.end() - (strlen(kGoogleCom) + 1);
-           i != end; ++i) {
-        if (!isdigit(*i)) {
+    //
+    // These URLs are only protected for requests from the browser and webui
+    // renderers, not for requests from common renderers, because
+    // clients*.google.com are also used by websites.
+    if (is_request_from_browser_or_webui_renderer) {
+      base::StringPiece::size_type pos = host.rfind(kClient);
+      if (pos != base::StringPiece::npos) {
+        bool match = true;
+        if (pos > 0 && host[pos - 1] != '.') {
           match = false;
-          break;
+        } else {
+          for (base::StringPiece::const_iterator
+                   i = host.begin() + pos + strlen(kClient),
+                   end = host.end() - (strlen(kGoogleCom) + 1);
+               i != end; ++i) {
+            if (!isdigit(*i)) {
+              match = false;
+              break;
+            }
+          }
         }
+        sensitive_chrome_url = sensitive_chrome_url || match;
       }
-      sensitive_chrome_url = sensitive_chrome_url || match;
     }
-    // This protects requests to safe browsing, link doctor, and possibly
-    // others.
+
+    // Safebrowsing and Chrome Webstore URLs are always protected, i.e. also
+    // for requests from common renderers.
     sensitive_chrome_url = sensitive_chrome_url ||
-                           url.DomainIs("clients.google.com") ||
                            url.DomainIs("sb-ssl.google.com") ||
                            (url.DomainIs("chrome.google.com") &&
                             base::StartsWith(url.path_piece(), "/webstore",
@@ -88,8 +104,13 @@
     const extensions::InfoMap* extension_info_map,
     const net::URLRequest* request,
     extensions::ExtensionNavigationUIData* navigation_ui_data) {
-  // Hide requests from the Chrome WebStore App or signin process.
+  // Hide requests from the Chrome WebStore App, signin process and WebUI.
   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
+
+  // Requests from the browser and webui get special protection for
+  // clients*.google.com URLs.
+  bool is_request_from_browser = true;
+  bool is_request_from_webui_renderer = false;
   if (info) {
     int process_id = info->GetChildID();
     // Never hide requests from guest processes.
@@ -103,10 +124,17 @@
                                                    process_id)) {
       return true;
     }
+
+    is_request_from_browser = false;
+    is_request_from_webui_renderer =
+        content::ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
+            process_id);
   }
 
   const GURL& url = request->url();
-  return IsSensitiveURL(url) || !HasWebRequestScheme(url);
+  return IsSensitiveURL(
+             url, is_request_from_browser || is_request_from_webui_renderer) ||
+         !HasWebRequestScheme(url);
 }
 
 // static
diff --git a/extensions/browser/api/web_request/web_request_permissions.h b/extensions/browser/api/web_request/web_request_permissions.h
index f708355..ee6ba29 100644
--- a/extensions/browser/api/web_request/web_request_permissions.h
+++ b/extensions/browser/api/web_request/web_request_permissions.h
@@ -23,7 +23,8 @@
 }
 
 // Exposed for unit testing.
-bool IsSensitiveURL(const GURL& url);
+bool IsSensitiveURL(const GURL& url,
+                    bool is_request_from_browser_or_webui_renderer);
 
 // This class is used to test whether extensions may modify web requests.
 class WebRequestPermissions {
diff --git a/extensions/browser/api/web_request/web_request_permissions_unittest.cc b/extensions/browser/api/web_request/web_request_permissions_unittest.cc
index d8b212d..c872e90 100644
--- a/extensions/browser/api/web_request/web_request_permissions_unittest.cc
+++ b/extensions/browser/api/web_request/web_request_permissions_unittest.cc
@@ -12,28 +12,38 @@
 TEST(ExtensionWebRequestPermissions, IsSensitiveURL) {
   struct TestCase {
     const char* url;
-    bool is_sensitive;
+    bool is_sensitive_if_request_from_common_renderer;
+    bool is_sensitive_if_request_from_browser_or_webui_renderer;
   } cases[] = {
-      {"http://www.google.com", false},
-      {"http://www.example.com", false},
-      {"http://clients.google.com", true},
-      {"http://clients4.google.com", true},
-      {"http://clients9999.google.com", true},
-      {"http://clients9999..google.com", false},
-      {"http://clients9999.example.google.com", false},
-      {"http://clients.google.com.", true},
-      {"http://.clients.google.com.", true},
-      {"http://google.example.com", false},
-      {"http://www.example.com", false},
-      {"http://clients.google.com", true},
-      {"http://sb-ssl.google.com", true},
-      {"http://sb-ssl.random.google.com", false},
-      {"http://chrome.google.com", false},
-      {"http://chrome.google.com/webstore", true},
-      {"http://chrome.google.com/webstore?query", true},
+      {"http://www.google.com", false, false},
+      {"http://www.example.com", false, false},
+      {"http://clients.google.com", false, true},
+      {"http://clients4.google.com", false, true},
+      {"http://clients9999.google.com", false, true},
+      {"http://clients9999..google.com", false, false},
+      {"http://clients9999.example.google.com", false, false},
+      {"http://clients.google.com.", false, true},
+      {"http://.clients.google.com.", false, true},
+      {"http://google.example.com", false, false},
+      {"http://www.example.com", false, false},
+      {"http://clients.google.com", false, true},
+      {"http://sb-ssl.google.com", true, true},
+      {"http://sb-ssl.random.google.com", false, false},
+      {"http://chrome.google.com", false, false},
+      {"http://chrome.google.com/webstore", true, true},
+      {"http://chrome.google.com/webstore?query", true, true},
   };
   for (const TestCase& test : cases) {
-    EXPECT_EQ(test.is_sensitive, IsSensitiveURL(GURL(test.url))) << test.url;
+    EXPECT_EQ(
+        test.is_sensitive_if_request_from_common_renderer,
+        IsSensitiveURL(GURL(test.url),
+                       false /* is_request_from_browser_or_webui_renderer */))
+        << test.url;
+    EXPECT_EQ(
+        test.is_sensitive_if_request_from_browser_or_webui_renderer,
+        IsSensitiveURL(GURL(test.url),
+                       true /* is_request_from_browser_or_webui_renderer */))
+        << test.url;
   }
 }
 
diff --git a/ios/chrome/app/startup/setup_debugging.mm b/ios/chrome/app/startup/setup_debugging.mm
index 24ae2994..7fe86d7 100644
--- a/ios/chrome/app/startup/setup_debugging.mm
+++ b/ios/chrome/app/startup/setup_debugging.mm
@@ -33,6 +33,7 @@
   [whiteList addObject:@"glif-google-to-dots_28"];
   // TODO(crbug.com/721338): Add missing image.
   [whiteList addObject:@"voice_icon_keyboard_accessory"];
+  [whiteList addObject:@"voice_icon"];
 
   // The original implementation of [UIImage imageNamed:].
   // Called by the new implementation.
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index bdfcad6..bd7c3e1e 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -85,6 +85,14 @@
       UIEdgeInsetsMake(CGRectGetMaxY(self.toolbar.frame), 0, 0, 0);
 }
 
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:
+           (id<UIViewControllerTransitionCoordinator>)coordinator {
+  // We need to dismiss the ToolsMenu everytime the Toolbar frame changes
+  // (e.g. Size changes, rotation changes, etc.)
+  [self.dispatcher closeToolsMenu];
+}
+
 #pragma mark - SettingsActions
 
 - (void)showSettings:(id)sender {
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
index 50a9e6a7..7511cfd 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
@@ -65,6 +65,8 @@
   return self;
 }
 
+#pragma mark - View lifecyle
+
 - (void)viewDidLoad {
   self.view.backgroundColor = [UIColor lightGrayColor];
   [self addChildViewController:self.locationBarViewController
@@ -115,6 +117,14 @@
   ]];
 }
 
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:
+           (id<UIViewControllerTransitionCoordinator>)coordinator {
+  // We need to dismiss the ToolsMenu everytime the Toolbar frame changes
+  // (e.g. Size changes, rotation changes, etc.)
+  [self.dispatcher closeToolsMenu];
+}
+
 #pragma mark - Components Setup
 
 - (void)setUpToolbarButtons {
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 126b0d5..1011947 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -69,17 +69,16 @@
 #endif
 
 #if !defined(OS_ANDROID) || BUILDFLAG(ENABLE_PLUGINS)
-// Use a media session for each tabs in a way that two tabs can't play on top of
-// each other. This is different from the Media Session API as it is enabling a
-// default behaviour for the browser. The allowed values are: "" (empty),
-// |kEnableDefaultMediaSessionDuckFlash|.
-const char kEnableDefaultMediaSession[] = "enable-default-media-session";
+// Enable a internal audio focus management between tabs in such a way that two
+// tabs can't  play on top of each other.
+// The allowed values are: "" (empty) or |kEnableAudioFocusDuckFlash|.
+const char kEnableAudioFocus[] = "enable-audio-focus";
 #endif  // !defined(OS_ANDROID) || BUILDFLAG(ENABLE_PLUGINS)
 
 #if BUILDFLAG(ENABLE_PLUGINS)
-// This value is used as an option for |kEnableDefaultMediaSession|. Flash will
+// This value is used as an option for |kEnableAudioFocus|. Flash will
 // be ducked when losing audio focus.
-const char kEnableDefaultMediaSessionDuckFlash[] = "duck-flash";
+const char kEnableAudioFocusDuckFlash[] = "duck-flash";
 #endif  // BUILDFLAG(ENABLE_PLUGINS)
 
 #if BUILDFLAG(ENABLE_RUNTIME_MEDIA_RENDERER_SELECTION)
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index a14e0d2..4ff9c98 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -50,11 +50,11 @@
 #endif
 
 #if !defined(OS_ANDROID) || BUILDFLAG(ENABLE_PLUGINS)
-MEDIA_EXPORT extern const char kEnableDefaultMediaSession[];
+MEDIA_EXPORT extern const char kEnableAudioFocus[];
 #endif  // !defined(OS_ANDROID) || BUILDFLAG(ENABLE_PLUGINS)
 
 #if BUILDFLAG(ENABLE_PLUGINS)
-MEDIA_EXPORT extern const char kEnableDefaultMediaSessionDuckFlash[];
+MEDIA_EXPORT extern const char kEnableAudioFocusDuckFlash[];
 #endif  // BUILDFLAG(ENABLE_PLUGINS)
 
 #if BUILDFLAG(ENABLE_RUNTIME_MEDIA_RENDERER_SELECTION)
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index ca0e0ee..79fcdf7 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -3886,6 +3886,41 @@
   EXPECT_TRUE(keys_to_match.empty());
 }
 
+TEST_F(DiskCacheBackendTest, SimpleCacheIndexRecovery) {
+  // Make sure we can recover set of entries when the index was removed.
+  SetSimpleCacheMode();
+  InitCache();
+  std::set<std::string> key_pool;
+  ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool));
+
+  cache_.reset();
+
+  // Give it a chance to write out the index, so we can delete it (rather
+  // than have it write it after we delete it).
+  disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting();
+  base::RunLoop().RunUntilIdle();
+
+  base::FilePath index_path =
+      cache_path_.AppendASCII("index-dir").AppendASCII("the-real-index");
+  ASSERT_TRUE(base::DeleteFile(index_path, false));
+
+  DisableFirstCleanup();
+  InitCache();
+  // A bit surprising, but it calls it "NEWCACHE" if there was no index,
+  // even if it reconstructed non-zero things.
+  EXPECT_EQ(disk_cache::SimpleIndex::INITIALIZE_METHOD_NEWCACHE,
+            simple_cache_impl_->index()->init_method());
+
+  // Check that enumeration returns all entries.
+  std::set<std::string> keys_to_match(key_pool);
+  std::unique_ptr<TestIterator> iter = CreateIterator();
+  size_t count = 0;
+  ASSERT_TRUE(EnumerateAndMatchKeys(-1, iter.get(), &keys_to_match, &count));
+  iter.reset();
+  EXPECT_EQ(key_pool.size(), count);
+  EXPECT_TRUE(keys_to_match.empty());
+}
+
 // Tests that the enumerations are not affected by dooming an entry in the
 // middle.
 TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationWhileDoomed) {
diff --git a/net/spdy/core/spdy_framer.cc b/net/spdy/core/spdy_framer.cc
index cc4362e..51689299 100644
--- a/net/spdy/core/spdy_framer.cc
+++ b/net/spdy/core/spdy_framer.cc
@@ -17,7 +17,6 @@
 
 #include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
 #include "net/quic/platform/api/quic_flags.h"
@@ -254,7 +253,7 @@
   return GetFrameHeaderSize() + 8;
 }
 
-size_t SpdyFramer::GetHeadersMinimumSize() const  {
+size_t SpdyFramer::GetHeadersMinimumSize() const {
   // Size, in bytes, of a HEADERS frame not including the variable-length
   // header block.
   return GetFrameHeaderSize();
@@ -281,9 +280,9 @@
 
 size_t SpdyFramer::GetAltSvcMinimumSize() const {
   // Size, in bytes, of an ALTSVC frame not including the Field-Value and
-  // (optional) Origin fields, both of which can vary in length.  Note that this
-  // gives a lower bound on the frame size rather than a true minimum; the
-  // actual frame should always be larger than this.
+  // (optional) Origin fields, both of which can vary in length.  Note that
+  // this gives a lower bound on the frame size rather than a true minimum;
+  // the actual frame should always be larger than this.
   // Calculated as frame prefix + 2 (origin_len).
   return GetFrameHeaderSize() + 2;
 }
@@ -757,7 +756,7 @@
       }
       break;
     case SpdyFrameType::SETTINGS: {
-      // Make sure that we have an integral number of 8-byte key/value pairs,
+      // Make sure that we have an integral number of 8-byte key/value pairs.
       // Size of each key/value pair in bytes.
       if (current_frame_length_ < GetSettingsMinimumSize() ||
           (current_frame_length_ - GetFrameHeaderSize()) %
@@ -961,7 +960,8 @@
   CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
 }
 
-size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
+size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data,
+                                            size_t* len,
                                             size_t max_bytes) {
   size_t bytes_to_read = std::min(*len, max_bytes);
   if (bytes_to_read > 0) {
@@ -972,8 +972,7 @@
   return bytes_to_read;
 }
 
-size_t SpdyFramer::GetSerializedLength(
-    const SpdyHeaderBlock* headers) {
+size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock* headers) {
   const size_t num_name_value_pairs_size = sizeof(uint32_t);
   const size_t length_of_name_size = num_name_value_pairs_size;
   const size_t length_of_value_size = num_name_value_pairs_size;
@@ -994,8 +993,8 @@
   const size_t original_len = len;
 
   if (remaining_control_header_ > 0) {
-    size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
-                                                 remaining_control_header_);
+    size_t bytes_read =
+        UpdateCurrentFrameBuffer(&data, &len, remaining_control_header_);
     remaining_control_header_ -= bytes_read;
     remaining_data_length_ -= bytes_read;
   }
@@ -1301,8 +1300,8 @@
 
 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
   size_t original_len = len;
-  size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
-                                               remaining_data_length_);
+  size_t bytes_read =
+      UpdateCurrentFrameBuffer(&data, &len, remaining_data_length_);
   remaining_data_length_ -= bytes_read;
   if (remaining_data_length_ == 0) {
     SpdyFrameReader reader(current_frame_buffer_.data(),
@@ -1499,6 +1498,7 @@
     set_error(SPDY_INVALID_PADDING);
     return 0;
   }
+
   CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
   return original_len - len;
 }
@@ -1660,7 +1660,7 @@
 SpdyFramer::SpdyFrameIterator::~SpdyFrameIterator() {}
 
 size_t SpdyFramer::SpdyFrameIterator::NextFrame(ZeroCopyOutputBuffer* output) {
-  SpdyFrameWithHeaderBlockIR* frame_ir = GetIR();
+  const SpdyFrameWithHeaderBlockIR* frame_ir = GetIR();
   if (frame_ir == nullptr) {
     LOG(WARNING) << "frame_ir doesn't exist.";
     return false;
@@ -1694,15 +1694,14 @@
     }
   }
 
+  framer_->SetIsLastFrame(!has_next_frame_);
   if (is_first_frame_) {
     is_first_frame_ = false;
-    frame_ir->set_end_headers(!has_next_frame_);
     size_t free_bytes_before = output->BytesFree();
     bool ok = SerializeGivenEncoding(*encoding, output);
     return ok ? free_bytes_before - output->BytesFree() : 0;
   } else {
     SpdyContinuationIR continuation_ir(frame_ir->stream_id());
-    continuation_ir.set_end_headers(!has_next_frame_);
     continuation_ir.take_encoding(std::move(encoding));
     return framer_->SerializeContinuation(continuation_ir, output);
   }
@@ -1714,14 +1713,16 @@
 
 SpdyFramer::SpdyHeaderFrameIterator::SpdyHeaderFrameIterator(
     SpdyFramer* framer,
-    std::unique_ptr<SpdyHeadersIR> headers_ir)
+    std::unique_ptr<const SpdyHeadersIR> headers_ir)
     : SpdyFrameIterator(framer), headers_ir_(std::move(headers_ir)) {
   SetEncoder(headers_ir_.get());
+  GetFramer()->SetOverwriteLastFrame(true);
 }
 
 SpdyFramer::SpdyHeaderFrameIterator::~SpdyHeaderFrameIterator() {}
 
-SpdyFrameWithHeaderBlockIR* SpdyFramer::SpdyHeaderFrameIterator::GetIR() const {
+const SpdyFrameWithHeaderBlockIR* SpdyFramer::SpdyHeaderFrameIterator::GetIR()
+    const {
   return headers_ir_.get();
 }
 
@@ -1738,15 +1739,16 @@
 
 SpdyFramer::SpdyPushPromiseFrameIterator::SpdyPushPromiseFrameIterator(
     SpdyFramer* framer,
-    std::unique_ptr<SpdyPushPromiseIR> push_promise_ir)
+    std::unique_ptr<const SpdyPushPromiseIR> push_promise_ir)
     : SpdyFrameIterator(framer), push_promise_ir_(std::move(push_promise_ir)) {
   SetEncoder(push_promise_ir_.get());
+  GetFramer()->SetOverwriteLastFrame(true);
 }
 
 SpdyFramer::SpdyPushPromiseFrameIterator::~SpdyPushPromiseFrameIterator() {}
 
-SpdyFrameWithHeaderBlockIR* SpdyFramer::SpdyPushPromiseFrameIterator::GetIR()
-    const {
+const SpdyFrameWithHeaderBlockIR*
+SpdyFramer::SpdyPushPromiseFrameIterator::GetIR() const {
   return push_promise_ir_.get();
 }
 
@@ -1763,7 +1765,7 @@
 
 SpdyFramer::SpdyControlFrameIterator::SpdyControlFrameIterator(
     SpdyFramer* framer,
-    std::unique_ptr<SpdyFrameIR> frame_ir)
+    std::unique_ptr<const SpdyFrameIR> frame_ir)
     : framer_(framer), frame_ir_(std::move(frame_ir)) {}
 
 SpdyFramer::SpdyControlFrameIterator::~SpdyControlFrameIterator() {}
@@ -1779,10 +1781,10 @@
   return frame_ir_ != nullptr;
 }
 
-// TODO(yasong): remove all the down_casts.
+// TODO(yasong): remove all the static_casts.
 std::unique_ptr<SpdyFrameSequence> SpdyFramer::CreateIterator(
     SpdyFramer* framer,
-    std::unique_ptr<SpdyFrameIR> frame_ir) {
+    std::unique_ptr<const SpdyFrameIR> frame_ir) {
   std::unique_ptr<SpdyFrameSequence> result = nullptr;
   switch (frame_ir->frame_type()) {
     case SpdyFrameType::DATA: {
@@ -1791,20 +1793,20 @@
       break;
     }
     case SpdyFrameType::HEADERS: {
-      result = base::MakeUnique<SpdyHeaderFrameIterator>(
+      result = SpdyMakeUnique<SpdyHeaderFrameIterator>(
           framer,
-          base::WrapUnique(static_cast<SpdyHeadersIR*>(frame_ir.get())));
+          SpdyWrapUnique(static_cast<const SpdyHeadersIR*>(frame_ir.get())));
       break;
     }
     case SpdyFrameType::PUSH_PROMISE: {
-      result = base::MakeUnique<SpdyPushPromiseFrameIterator>(
-          framer,
-          base::WrapUnique(static_cast<SpdyPushPromiseIR*>(frame_ir.get())));
+      result = SpdyMakeUnique<SpdyPushPromiseFrameIterator>(
+          framer, SpdyWrapUnique(
+                      static_cast<const SpdyPushPromiseIR*>(frame_ir.get())));
       break;
     }
     default: {
-      result = base::MakeUnique<SpdyControlFrameIterator>(framer,
-                                                          std::move(frame_ir));
+      result =
+          SpdyMakeUnique<SpdyControlFrameIterator>(framer, std::move(frame_ir));
     }
   }
   return result;
@@ -2197,7 +2199,10 @@
   const SpdyString& encoding = continuation.encoding();
   size_t frame_size = GetContinuationMinimumSize() + encoding.size();
   SpdyFrameBuilder builder(frame_size);
-  uint8_t flags = continuation.end_headers() ? HEADERS_FLAG_END_HEADERS : 0;
+  uint8_t flags = ((overwrite_last_frame_ && is_last_frame_) ||
+                   (!overwrite_last_frame_ && continuation.end_headers()))
+                      ? HEADERS_FLAG_END_HEADERS
+                      : 0;
   builder.BeginNewFrame(*this, SpdyFrameType::CONTINUATION, flags,
                         continuation.stream_id());
   DCHECK_EQ(GetFrameHeaderSize(), builder.length());
@@ -2648,7 +2653,10 @@
   const SpdyString& encoding = continuation.encoding();
   size_t frame_size = GetContinuationMinimumSize() + encoding.size();
   SpdyFrameBuilder builder(frame_size, output);
-  uint8_t flags = continuation.end_headers() ? HEADERS_FLAG_END_HEADERS : 0;
+  uint8_t flags = ((overwrite_last_frame_ && is_last_frame_) ||
+                   (!overwrite_last_frame_ && continuation.end_headers()))
+                      ? HEADERS_FLAG_END_HEADERS
+                      : 0;
   bool ok = builder.BeginNewFrame(*this, SpdyFrameType::CONTINUATION, flags,
                                   continuation.stream_id(),
                                   frame_size - GetFrameHeaderSize());
@@ -2684,8 +2692,7 @@
   ok = ok &&
        builder.WriteUInt32(PackStreamDependencyValues(
            priority.exclusive(), priority.parent_stream_id())) &&
-       // Per RFC 7540 section 6.3, serialized weight value is actual value
-       // - 1.
+       // Per RFC 7540 section 6.3, serialized weight value is actual value - 1.
        builder.WriteUInt8(priority.weight() - 1);
   DCHECK_EQ(GetPrioritySize(), builder.length());
   return ok;
@@ -2793,9 +2800,12 @@
   if (header_ir.fin()) {
     flags |= CONTROL_FLAG_FIN;
   }
-  if (header_ir.end_headers()) {
+
+  if ((overwrite_last_frame_ && is_last_frame_) ||
+      (!overwrite_last_frame_ && header_ir.end_headers())) {
     flags |= HEADERS_FLAG_END_HEADERS;
   }
+
   if (header_ir.padded()) {
     flags |= HEADERS_FLAG_PADDED;
   }
@@ -2813,7 +2823,8 @@
     flags = flags | PUSH_PROMISE_FLAG_PADDED;
   }
 
-  if (push_promise_ir.end_headers()) {
+  if ((overwrite_last_frame_ && is_last_frame_) ||
+      (!overwrite_last_frame_ && push_promise_ir.end_headers())) {
     flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
   }
 
@@ -2836,8 +2847,8 @@
                 << FrameTypeToString(type);
   }
 
-  // Write all the padding payload and as much of the data payload as
-  // possible into the initial frame.
+  // Write all the padding payload and as much of the data payload as possible
+  // into the initial frame.
   size_t bytes_remaining = 0;
   bytes_remaining =
       hpack_encoding.size() -
diff --git a/net/spdy/core/spdy_framer.h b/net/spdy/core/spdy_framer.h
index 87c6959..02ee43f 100644
--- a/net/spdy/core/spdy_framer.h
+++ b/net/spdy/core/spdy_framer.h
@@ -396,7 +396,7 @@
   // Create a SpdyFrameSequence to serialize |frame_ir|.
   static std::unique_ptr<SpdyFrameSequence> CreateIterator(
       SpdyFramer* framer,
-      std::unique_ptr<SpdyFrameIR> frame_ir);
+      std::unique_ptr<const SpdyFrameIR> frame_ir);
 
   // Serialize a data frame.
   SpdySerializedFrame SerializeData(const SpdyDataIR& data) const;
@@ -593,12 +593,16 @@
   void SetEncoderHeaderTableDebugVisitor(
       std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
 
-  // For use in SpdyFramerDecoderAdapter implementations; returns a HPACK
+  // For use in SpdyFramerDecoderAdapter implementations; returns the HPACK
   // decoder to be used.
   HpackDecoderInterface* GetHpackDecoderForAdapter() {
     return GetHpackDecoder();
   }
 
+  void SetOverwriteLastFrame(bool value) { overwrite_last_frame_ = value; }
+  void SetIsLastFrame(bool value) { is_last_frame_ = value; }
+  bool ShouldOverwriteLastFrame() const { return overwrite_last_frame_; }
+
   // Returns the estimate of dynamically allocated memory in bytes.
   size_t EstimateMemoryUsage() const;
 
@@ -628,8 +632,9 @@
   // }
   class SPDY_EXPORT_PRIVATE SpdyFrameIterator : public SpdyFrameSequence {
    public:
-    // Creates an iterator with the provided framer. Does not take ownership of
-    // |framer|, |framer| must outlive this instance.
+    // Creates an iterator with the provided framer.
+    // Does not take ownership of |framer|.
+    // |framer| must outlive this instance.
     explicit SpdyFrameIterator(SpdyFramer* framer);
     ~SpdyFrameIterator() override;
 
@@ -645,13 +650,13 @@
     SpdyFrameIterator& operator=(const SpdyFrameIterator&) = delete;
 
    protected:
-    virtual SpdyFrameWithHeaderBlockIR* GetIR() const = 0;
+    virtual const SpdyFrameWithHeaderBlockIR* GetIR() const = 0;
     virtual size_t GetFrameSizeSansBlock() const = 0;
     virtual bool SerializeGivenEncoding(const SpdyString& encoding,
                                         ZeroCopyOutputBuffer* output) const = 0;
 
     SpdyFramer* GetFramer() const { return framer_; }
-    void SetEncoder(SpdyFrameWithHeaderBlockIR* ir) {
+    void SetEncoder(const SpdyFrameWithHeaderBlockIR* ir) {
       encoder_ =
           framer_->GetHpackEncoder()->EncodeHeaderSet(ir->header_block());
     }
@@ -673,17 +678,17 @@
    public:
     // Does not take ownership of |framer|. Take ownership of |headers_ir|.
     SpdyHeaderFrameIterator(SpdyFramer* framer,
-                            std::unique_ptr<SpdyHeadersIR> headers_ir);
+                            std::unique_ptr<const SpdyHeadersIR> headers_ir);
 
     ~SpdyHeaderFrameIterator() override;
 
    private:
-    SpdyFrameWithHeaderBlockIR* GetIR() const override;
+    const SpdyFrameWithHeaderBlockIR* GetIR() const override;
     size_t GetFrameSizeSansBlock() const override;
     bool SerializeGivenEncoding(const SpdyString& encoding,
                                 ZeroCopyOutputBuffer* output) const override;
 
-    const std::unique_ptr<SpdyHeadersIR> headers_ir_;
+    const std::unique_ptr<const SpdyHeadersIR> headers_ir_;
   };
 
   // Iteratively converts a SpdyPushPromiseIR (with a possibly huge
@@ -695,17 +700,17 @@
     // Does not take ownership of |framer|. Take ownership of |push_promise_ir|.
     SpdyPushPromiseFrameIterator(
         SpdyFramer* framer,
-        std::unique_ptr<SpdyPushPromiseIR> push_promise_ir);
+        std::unique_ptr<const SpdyPushPromiseIR> push_promise_ir);
 
     ~SpdyPushPromiseFrameIterator() override;
 
    private:
-    SpdyFrameWithHeaderBlockIR* GetIR() const override;
+    const SpdyFrameWithHeaderBlockIR* GetIR() const override;
     size_t GetFrameSizeSansBlock() const override;
     bool SerializeGivenEncoding(const SpdyString& encoding,
                                 ZeroCopyOutputBuffer* output) const override;
 
-    const std::unique_ptr<SpdyPushPromiseIR> push_promise_ir_;
+    const std::unique_ptr<const SpdyPushPromiseIR> push_promise_ir_;
   };
 
   // Converts a SpdyFrameIR into one Spdy frame (a sequence of length 1), and
@@ -713,7 +718,7 @@
   class SpdyControlFrameIterator : public SpdyFrameSequence {
    public:
     SpdyControlFrameIterator(SpdyFramer* framer,
-                             std::unique_ptr<SpdyFrameIR> frame_ir);
+                             std::unique_ptr<const SpdyFrameIR> frame_ir);
     ~SpdyControlFrameIterator() override;
 
     size_t NextFrame(ZeroCopyOutputBuffer* output) override;
@@ -722,7 +727,7 @@
 
    private:
     SpdyFramer* const framer_;
-    std::unique_ptr<SpdyFrameIR> frame_ir_;
+    std::unique_ptr<const SpdyFrameIR> frame_ir_;
   };
 
  private:
@@ -979,6 +984,14 @@
   // If true, then ProcessInput returns after processing a full frame,
   // rather than reading all available input.
   bool process_single_input_frame_ = false;
+
+  // TODO(yasong): Remove overwrite_last_frame_ and is_last_frame_ when we make
+  // Serialize<FrameType>() functions static and independent of SpdyFramer. And
+  // pass the last frame info in the arguments.
+  bool overwrite_last_frame_ = false;
+  // If the current frame to be serialized is the last frame. Will be valid iff
+  // overwrite_last_frame_ is true.
+  bool is_last_frame_ = false;
 };
 
 }  // namespace net
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 9d518367..ebef1dc 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -3257,8 +3257,6 @@
 
 crbug.com/701445 external/wpt/dom/events/EventListener-invoke-legacy.html [ Timeout Pass ]
 
-crbug.com/718394 virtual/enable_asmjs/http/tests/asmjs/asm-warnings.html [ NeedsRebaseline ]
-
 # When WebAssembly is exposed in V8 (soon), this test has the wrong number of expected Object.getOwnPropertyNames() for global object.
 
 crbug.com/681468 fast/forms/suggestion-picker/date-suggestion-picker-appearance-zoom125.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/media-capabilities/decodingInfo.html b/third_party/WebKit/LayoutTests/external/wpt/media-capabilities/decodingInfo.html
index a0e0d342..85acfe7f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/media-capabilities/decodingInfo.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/media-capabilities/decodingInfo.html
@@ -36,6 +36,131 @@
 }, "Test that decodingInfo rejects if the MediaConfiguration does not have a type");
 
 promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+  }));
+}, "Test that decodingInfo rejects if the configuration doesn't have an audio or video field");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    video: {
+      contentType: 'video/webm; codecs="vp9"',
+      width: 800,
+      height: 600,
+      bitrate: 3000,
+      framerate: -1,
+    },
+  }));
+}, "Test that decodingInfo rejects if the video configuration has a negative framerate");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    video: {
+      contentType: 'video/webm; codecs="vp9"',
+      width: 800,
+      height: 600,
+      bitrate: 3000,
+      framerate: 0,
+    },
+  }));
+}, "Test that decodingInfo rejects if the video configuration has a framerate set to 0");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    video: {
+      contentType: 'video/webm; codecs="vp9"',
+      width: 800,
+      height: 600,
+      bitrate: 3000,
+      framerate: Infinity,
+    },
+  }));
+}, "Test that decodingInfo rejects if the video configuration has a framerate set to Infinity");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    video: {
+      contentType: 'fgeoa',
+      width: 800,
+      height: 600,
+      bitrate: 3000,
+      framerate: 24,
+    },
+  }));
+}, "Test that decodingInfo rejects if the video configuration contentType doesn't parse");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    video: {
+      contentType: 'audio/fgeoa',
+      width: 800,
+      height: 600,
+      bitrate: 3000,
+      framerate: 24,
+    },
+  }));
+}, "Test that decodingInfo rejects if the video configuration contentType isn't of type video");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    video: {
+      contentType: 'video/webm; codecs="vp9"; foo="bar"',
+      width: 800,
+      height: 600,
+      bitrate: 3000,
+      framerate: 24,
+    },
+  }));
+}, "Test that decodingInfo rejects if the video configuration contentType has more than one parameter");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    video: {
+      contentType: 'video/webm; foo="bar"',
+      width: 800,
+      height: 600,
+      bitrate: 3000,
+      framerate: 24,
+    },
+  }));
+}, "Test that decodingInfo rejects if the video configuration contentType has one parameter that isn't codecs");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    audio: { contentType: 'fgeoa' },
+  }));
+}, "Test that decodingInfo rejects if the audio configuration contenType doesn't parse");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    audio: { contentType: 'video/fgeoa' },
+  }));
+}, "Test that decodingInfo rejects if the audio configuration contentType isn't of type audio");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    audio: { contentType: 'audio/webm; codecs="opus"; foo="bar"' },
+  }));
+}, "Test that decodingInfo rejects if the audio configuration contentType has more than one parameters");
+
+promise_test(t => {
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+    type: 'file',
+    audio: { contentType: 'audio/webm; foo="bar"' },
+  }));
+}, "Test that decodingInfo rejects if the audio configuration contentType has one parameter that isn't codecs");
+
+promise_test(t => {
   return navigator.mediaCapabilities.decodingInfo({
     type: 'file',
     video: minimalVideoConfiguration,
diff --git a/third_party/WebKit/LayoutTests/http/tests/css/remove-blocking-with-loading-import-expected.html b/third_party/WebKit/LayoutTests/http/tests/css/remove-blocking-with-loading-import-expected.html
new file mode 100644
index 0000000..cf3223f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/css/remove-blocking-with-loading-import-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<p>PASS</p>
diff --git a/third_party/WebKit/LayoutTests/http/tests/css/remove-blocking-with-loading-import.html b/third_party/WebKit/LayoutTests/http/tests/css/remove-blocking-with-loading-import.html
new file mode 100644
index 0000000..1b1d9a20
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/css/remove-blocking-with-loading-import.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script>
+  setTimeout(() => link.remove(), 0);
+</script>
+<link id="link" href="data:text/css,@import url(http://127.0.0.1:8000/css/resources/shared.css)" rel="stylesheet">
+<p>PASS</p>
diff --git a/third_party/WebKit/LayoutTests/media_capabilities/encodingInfo.html b/third_party/WebKit/LayoutTests/media_capabilities/encodingInfo.html
index cc9ffdb..554e8e2d 100644
--- a/third_party/WebKit/LayoutTests/media_capabilities/encodingInfo.html
+++ b/third_party/WebKit/LayoutTests/media_capabilities/encodingInfo.html
@@ -32,8 +32,10 @@
           assert_equals(isSupported, result.supported, mimeType + 'supported?');
           t.done();
         })
-        .catch(() => {
-          assert_unreached('encodingInfo() ' + mimeType);
+        .catch(e => {
+          assert_unreached('encodingInfo() failed with ' + e +
+                           ' using mimeType ' +  mimeType);
+          t.done();
         });
   });
 };
@@ -49,12 +51,12 @@
   [ 'video/webm;codecs=avc1', 'video/webm;codecs=avc1' ],
   // 'video/webm' supports audio codec specification, see
   // http://www.webmproject.org/docs/container/
-  [ 'video/webm;codecs=vp8,opus', 'video/webm;codecs=vp8,opus' ],
-  [ 'video/WEBM;codecs=VP8,OPUS', 'video/WEBM;codecs=VP8,OPUS' ],
-  [ 'video/webm;codecs=vp9,opus', 'video/webm;codecs=vp9,opus' ],
-  [ 'video/webm;codecs=vp8,vp9,opus', 'video/webm;codecs=vp8,vp9,opus' ],
-  [ 'video/webm;codecs=h264,opus', 'video/webm;codecs=h264,opus' ],
-  [ 'video/webm;codecs=h264,vp9,opus', 'video/webm;codecs=h264,vp9,opus' ],
+  [ 'video/webm;codecs="vp8,opus"', 'video/webm;codecs="vp8,opus"' ],
+  [ 'video/WEBM;codecs="VP8,OPUS"', 'video/WEBM;codecs="VP8,OPUS"' ],
+  [ 'video/webm;codecs="vp9,opus"', 'video/webm;codecs="vp9,opus"' ],
+  [ 'video/webm;codecs="vp8,vp9,opus"', 'video/webm;codecs="vp8,vp9,opus"' ],
+  [ 'video/webm;codecs="h264,opus"', 'video/webm;codecs="h264,opus"' ],
+  [ 'video/webm;codecs="h264,vp9,opus"', 'video/webm;codecs="h264,vp9,opus"' ],
   // https://matroska.org/technical/specs/notes.html#MIME
   [ 'video/x-matroska;codecs=vorbis', 'video/x-matroska;codecs=opus' ],
   [ 'audio/webm', 'audio/webm' ],
diff --git a/third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/asm-warnings-expected.txt b/third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/asm-warnings-expected.txt
deleted file mode 100644
index c9915986..0000000
--- a/third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/asm-warnings-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-CONSOLE WARNING: line 13: Invalid asm.js: Invalid type annotation - forbidden literal.
-CONSOLE WARNING: line 5: Invalid asm.js: Invalid initializer for foreign import - unrecognized annotation.
-
diff --git a/third_party/WebKit/Source/core/html/LinkStyle.cpp b/third_party/WebKit/Source/core/html/LinkStyle.cpp
index 37ae854..7da5475 100644
--- a/third_party/WebKit/Source/core/html/LinkStyle.cpp
+++ b/third_party/WebKit/Source/core/html/LinkStyle.cpp
@@ -402,11 +402,11 @@
 }
 
 void LinkStyle::OwnerRemoved() {
-  if (sheet_)
-    ClearSheet();
-
   if (StyleSheetIsLoading())
     RemovePendingSheet();
+
+  if (sheet_)
+    ClearSheet();
 }
 
 DEFINE_TRACE(LinkStyle) {
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
index c4dfc8a..ff4db4b8 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
@@ -441,12 +441,6 @@
    * @param {string} message
    */
   _sendProtocolMessage(message) {
-    var parsedMessage = JSON.parse(message);
-    if (parsedMessage['method'] === 'Emulation.setVisibleSize' ||
-        parsedMessage['method'] === 'Emulation.setDeviceMetricsOverride') {
-      this._dispatchProtocolMessage(JSON.stringify({id: parsedMessage['id'], result: {}}));
-      return;
-    }
     this._rawConnection.sendMessage(message);
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2_worker/Audits2Service.js b/third_party/WebKit/Source/devtools/front_end/audits2_worker/Audits2Service.js
index 1b8faf0..65dd354 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2_worker/Audits2Service.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits2_worker/Audits2Service.js
@@ -45,7 +45,7 @@
     });
 
     return Promise.resolve()
-        .then(_ => self.runLighthouseInWorker(this, params.url, {disableDeviceEmulation: true}, params.categoryIDs))
+        .then(_ => self.runLighthouseInWorker(this, params.url, {}, params.categoryIDs))
         .then(/** @type {!ReportRenderer.ReportJSON} */ result => {
           // Filter out artifacts except for screenshots in traces to minimize report size.
           var traces = result.artifacts.traces;
diff --git a/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp b/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
index 38f780f..c5088ac 100644
--- a/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
+++ b/third_party/WebKit/Source/modules/media_capabilities/MediaCapabilities.cpp
@@ -24,6 +24,62 @@
 
 namespace {
 
+constexpr const char* kApplicationMimeTypePrefix = "application/";
+constexpr const char* kAudioMimeTypePrefix = "audio/";
+constexpr const char* kVideoMimeTypePrefix = "video/";
+constexpr const char* kCodecsMimeTypeParam = "codecs";
+
+bool IsValidMimeType(const String& content_type, const String& prefix) {
+  ParsedContentType parsed_content_type(content_type,
+                                        ParsedContentType::Mode::kStrict);
+  if (!parsed_content_type.IsValid())
+    return false;
+
+  if (!parsed_content_type.MimeType().StartsWith(prefix) &&
+      !parsed_content_type.MimeType().StartsWith(kApplicationMimeTypePrefix)) {
+    return false;
+  }
+
+  if (parsed_content_type.ParameterCount() > 1)
+    return false;
+
+  if (parsed_content_type.ParameterCount() == 1 &&
+      parsed_content_type.ParameterValueForName(kCodecsMimeTypeParam)
+          .IsNull()) {
+    return false;
+  }
+
+  return true;
+}
+
+bool IsValidMediaConfiguration(const MediaConfiguration& configuration) {
+  return configuration.hasAudio() || configuration.hasVideo();
+}
+
+bool IsValidVideoConfiguration(const VideoConfiguration& configuration) {
+  DCHECK(configuration.hasContentType());
+
+  if (!IsValidMimeType(configuration.contentType(), kVideoMimeTypePrefix))
+    return false;
+
+  DCHECK(configuration.hasFramerate());
+  if (!std::isfinite(configuration.framerate()) ||
+      configuration.framerate() <= 0) {
+    return false;
+  }
+
+  return true;
+}
+
+bool IsValidAudioConfiguration(const AudioConfiguration& configuration) {
+  DCHECK(configuration.hasContentType());
+
+  if (!IsValidMimeType(configuration.contentType(), kAudioMimeTypePrefix))
+    return false;
+
+  return true;
+}
+
 WebAudioConfiguration ToWebAudioConfiguration(
     const AudioConfiguration& configuration) {
   WebAudioConfiguration web_configuration;
@@ -32,9 +88,7 @@
   DCHECK(configuration.hasContentType());
   ParsedContentType parsed_content_type(configuration.contentType(),
                                         ParsedContentType::Mode::kStrict);
-
-  // TODO(chcunningham): Throw TypeError for invalid input.
-  // DCHECK(parsed_content_type.IsValid());
+  DCHECK(parsed_content_type.IsValid());
 
   DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
   web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII();
@@ -62,9 +116,7 @@
   DCHECK(configuration.hasContentType());
   ParsedContentType parsed_content_type(configuration.contentType(),
                                         ParsedContentType::Mode::kStrict);
-
-  // TODO(chcunningham): Throw TypeError for invalid input.
-  // DCHECK(parsed_content_type.IsValid());
+  DCHECK(parsed_content_type.IsValid());
 
   DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
   web_configuration.mime_type = parsed_content_type.MimeType().LowerASCII();
@@ -86,9 +138,37 @@
 }
 
 WebMediaConfiguration ToWebMediaConfiguration(
-    const MediaConfiguration& configuration) {
+    const MediaDecodingConfiguration& configuration) {
   WebMediaConfiguration web_configuration;
 
+  // |type| is mandatory.
+  DCHECK(configuration.hasType());
+  if (configuration.type() == "file")
+    web_configuration.type = MediaConfigurationType::kFile;
+  else if (configuration.type() == "media-source")
+    web_configuration.type = MediaConfigurationType::kMediaSource;
+  else
+    NOTREACHED();
+
+  if (configuration.hasAudio()) {
+    web_configuration.audio_configuration =
+        ToWebAudioConfiguration(configuration.audio());
+  }
+
+  if (configuration.hasVideo()) {
+    web_configuration.video_configuration =
+        ToWebVideoConfiguration(configuration.video());
+  }
+
+  return web_configuration;
+}
+
+WebMediaConfiguration ToWebMediaConfiguration(
+    const MediaEncodingConfiguration& configuration) {
+  WebMediaConfiguration web_configuration;
+
+  // TODO(mcasas): parse and set the type for encoding.
+
   if (configuration.hasAudio()) {
     web_configuration.audio_configuration =
         ToWebAudioConfiguration(configuration.audio());
@@ -112,8 +192,29 @@
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   ScriptPromise promise = resolver->Promise();
 
-  // |type| is mandatory.
-  DCHECK(configuration.hasType());
+  if (!IsValidMediaConfiguration(configuration)) {
+    resolver->Reject(V8ThrowException::CreateTypeError(
+        script_state->GetIsolate(),
+        "The configuration dictionary has neither |video| nor |audio| "
+        "specified and needs at least one of them."));
+    return promise;
+  }
+
+  if (configuration.hasVideo() &&
+      !IsValidVideoConfiguration(configuration.video())) {
+    resolver->Reject(V8ThrowException::CreateTypeError(
+        script_state->GetIsolate(),
+        "The video configuration dictionary is not valid."));
+    return promise;
+  }
+
+  if (configuration.hasAudio() &&
+      !IsValidAudioConfiguration(configuration.audio())) {
+    resolver->Reject(V8ThrowException::CreateTypeError(
+        script_state->GetIsolate(),
+        "The audio configuration dictionary is not valid."));
+    return promise;
+  }
 
   Platform::Current()->MediaCapabilitiesClient()->DecodingInfo(
       ToWebMediaConfiguration(configuration),
@@ -129,14 +230,30 @@
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   ScriptPromise promise = resolver->Promise();
 
-  if (!configuration.hasVideo() && !configuration.hasAudio()) {
-    resolver->Reject(DOMException::Create(
-        kSyntaxError,
+  if (!IsValidMediaConfiguration(configuration)) {
+    resolver->Reject(V8ThrowException::CreateTypeError(
+        script_state->GetIsolate(),
         "The configuration dictionary has neither |video| nor |audio| "
         "specified and needs at least one of them."));
     return promise;
   }
 
+  if (configuration.hasVideo() &&
+      !IsValidVideoConfiguration(configuration.video())) {
+    resolver->Reject(V8ThrowException::CreateTypeError(
+        script_state->GetIsolate(),
+        "The video configuration dictionary is not valid."));
+    return promise;
+  }
+
+  if (configuration.hasAudio() &&
+      !IsValidAudioConfiguration(configuration.audio())) {
+    resolver->Reject(V8ThrowException::CreateTypeError(
+        script_state->GetIsolate(),
+        "The audio configuration dictionary is not valid."));
+    return promise;
+  }
+
   std::unique_ptr<WebMediaRecorderHandler> handler =
       Platform::Current()->CreateMediaRecorderHandler();
   if (!handler) {
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.h b/third_party/WebKit/Source/modules/webaudio/AudioNode.h
index f1079d6..7deea47 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.h
@@ -106,8 +106,8 @@
   // Do not release resources used by an audio rendering thread in dispose().
   virtual void Dispose();
 
-  // node() returns a valid object until dispose() is called.  This returns
-  // nullptr after dispose().  We must not call node() in an audio rendering
+  // GetNode() returns a valid object until dispose() is called.  This returns
+  // nullptr after dispose().  We must not call GetNode() in an audio rendering
   // thread.
   AudioNode* GetNode() const;
   // context() returns a valid object until the BaseAudioContext dies, and
@@ -259,8 +259,8 @@
   NodeType node_type_;
 
   // The owner AudioNode.  This untraced member is safe because dispose() is
-  // called before the AudioNode death, and it clears m_node.  Do not access
-  // m_node directly, use node() instead.
+  // called before the AudioNode death, and it clears |node_|.  Do not access
+  // |node_| directly, use GetNode() instead.
   // See http://crbug.com/404527 for the detail.
   UntracedMember<AudioNode> node_;
 
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 59f8d8d..82b6562 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1284,6 +1284,8 @@
     "scheduler/base/time_converter.h",
     "scheduler/base/time_domain.cc",
     "scheduler/base/time_domain.h",
+    "scheduler/base/trace_helper.cc",
+    "scheduler/base/trace_helper.h",
     "scheduler/base/virtual_time_domain.cc",
     "scheduler/base/virtual_time_domain.h",
     "scheduler/base/work_queue.cc",
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue.h
index 64c39a6..8ac280a 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue.h
@@ -37,6 +37,9 @@
     // Can be called on any thread
     // All methods but SetObserver, SetTimeDomain and GetTimeDomain can be
     // called on |queue|.
+    //
+    // TODO(altimin): Make it base::Optional<base::TimeTicks> to tell
+    // observer about cancellations.
     virtual void OnQueueNextWakeUpChanged(TaskQueue* queue,
                                           base::TimeTicks next_wake_up) = 0;
   };
@@ -162,7 +165,7 @@
 
   // Returns true if the queue has work that's ready to execute now.
   // NOTE: this must be called on the thread this TaskQueue was created by.
-  virtual bool HasPendingImmediateWork() const = 0;
+  virtual bool HasTaskToRunImmediately() const = 0;
 
   // Returns requested run time of next scheduled wake-up for a delayed task
   // which is not ready to run. If there are no such tasks or the queue is
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
index 5e5d7b74..2ead685 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
@@ -402,7 +402,7 @@
   return task_count;
 }
 
-bool TaskQueueImpl::HasPendingImmediateWork() const {
+bool TaskQueueImpl::HasTaskToRunImmediately() const {
   // Any work queue tasks count as immediate work.
   if (!main_thread_only().delayed_work_queue->Empty() ||
       !main_thread_only().immediate_work_queue->Empty()) {
@@ -821,8 +821,11 @@
     return;
 
   if (enable) {
-    if (HasPendingImmediateWork())
-      NotifyWakeUpChangedOnMainThread(base::TimeTicks());
+    if (HasPendingImmediateWork() && main_thread_only().observer) {
+      // Delayed work notification will be issued via time domain.
+      main_thread_only().observer->OnQueueNextWakeUpChanged(this,
+                                                            base::TimeTicks());
+    }
 
     ScheduleDelayedWorkInTimeDomain(main_thread_only().time_domain->Now());
 
@@ -899,14 +902,33 @@
   main_thread_only().time_domain->ScheduleDelayedWork(
       this, main_thread_only().delayed_incoming_queue.top().delayed_wake_up(),
       now);
-
-  NotifyWakeUpChangedOnMainThread(
-      main_thread_only().delayed_incoming_queue.top().delayed_run_time);
 }
 
-void TaskQueueImpl::NotifyWakeUpChangedOnMainThread(base::TimeTicks wake_up) {
-  if (main_thread_only().observer)
-    main_thread_only().observer->OnQueueNextWakeUpChanged(this, wake_up);
+void TaskQueueImpl::SetScheduledTimeDomainWakeUp(
+    base::Optional<base::TimeTicks> scheduled_time_domain_wake_up) {
+  main_thread_only().scheduled_time_domain_wake_up =
+      scheduled_time_domain_wake_up;
+
+  // If queue has immediate work an appropriate notification has already
+  // been issued.
+  if (!scheduled_time_domain_wake_up || !main_thread_only().observer ||
+      HasPendingImmediateWork())
+    return;
+
+  main_thread_only().observer->OnQueueNextWakeUpChanged(
+      this, scheduled_time_domain_wake_up.value());
+}
+
+bool TaskQueueImpl::HasPendingImmediateWork() {
+  // Any work queue tasks count as immediate work.
+  if (!main_thread_only().delayed_work_queue->Empty() ||
+      !main_thread_only().immediate_work_queue->Empty()) {
+    return true;
+  }
+
+  // Finally tasks on |immediate_incoming_queue| count as immediate work.
+  base::AutoLock lock(immediate_incoming_queue_lock_);
+  return !immediate_incoming_queue().empty();
 }
 
 }  // namespace internal
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
index dc36b1c..fc20922a 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
@@ -142,7 +142,7 @@
   bool IsQueueEnabled() const override;
   bool IsEmpty() const override;
   size_t GetNumberOfPendingTasks() const override;
-  bool HasPendingImmediateWork() const override;
+  bool HasTaskToRunImmediately() const override;
   base::Optional<base::TimeTicks> GetNextScheduledWakeUp() override;
   void SetQueuePriority(QueuePriority priority) override;
   QueuePriority GetQueuePriority() const override;
@@ -177,6 +177,18 @@
   void NotifyWillProcessTask(const base::PendingTask& pending_task);
   void NotifyDidProcessTask(const base::PendingTask& pending_task);
 
+  // Called by TimeDomain when the wake-up for this queue has changed.
+  // There is only one wake-up, new wake-up cancels any previous wake-ups.
+  // If |scheduled_time_domain_wake_up| is base::nullopt then the wake-up
+  // has been cancelled.
+  // Must be called from the main thread.
+  void SetScheduledTimeDomainWakeUp(
+      base::Optional<base::TimeTicks> scheduled_time_domain_wake_up);
+
+  // Check for available tasks in immediate work queues.
+  // Used to check if we need to generate notifications about delayed work.
+  bool HasPendingImmediateWork();
+
   WorkQueue* delayed_work_queue() {
     return main_thread_only().delayed_work_queue.get();
   }
@@ -202,16 +214,10 @@
   // any. Must be called from the main thread.
   base::Optional<DelayedWakeUp> WakeUpForDelayedWork(LazyNow* lazy_now);
 
-  base::TimeTicks scheduled_time_domain_wake_up() const {
+  base::Optional<base::TimeTicks> scheduled_time_domain_wake_up() const {
     return main_thread_only().scheduled_time_domain_wake_up;
   }
 
-  void set_scheduled_time_domain_wake_up(
-      base::TimeTicks scheduled_time_domain_wake_up) {
-    main_thread_only().scheduled_time_domain_wake_up =
-        scheduled_time_domain_wake_up;
-  }
-
   HeapHandle heap_handle() const { return main_thread_only().heap_handle; }
 
   void set_heap_handle(HeapHandle heap_handle) {
@@ -285,7 +291,7 @@
     int voter_refcount;
     base::trace_event::BlameContext* blame_context;  // Not owned.
     EnqueueOrder current_fence;
-    base::TimeTicks scheduled_time_domain_wake_up;
+    base::Optional<base::TimeTicks> scheduled_time_domain_wake_up;
   };
 
   ~TaskQueueImpl() override;
@@ -347,8 +353,6 @@
   // Schedules delayed work on time domain and calls the observer.
   void ScheduleDelayedWorkInTimeDomain(base::TimeTicks now);
 
-  void NotifyWakeUpChangedOnMainThread(base::TimeTicks wake_up);
-
   const base::PlatformThreadId thread_id_;
 
   mutable base::Lock any_thread_lock_;
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
index c240f08..97ad1c53 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
@@ -675,7 +675,7 @@
   DCHECK(main_thread_checker_.CalledOnValidThread());
   DCHECK(queue->IsQueueEnabled());
   // Only schedule DoWork if there's something to do.
-  if (queue->HasPendingImmediateWork() && !queue->BlockedByFence())
+  if (queue->HasTaskToRunImmediately() && !queue->BlockedByFence())
     MaybeScheduleImmediateWork(FROM_HERE);
 }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
index 68d0e53..0e1bec150 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
@@ -359,9 +359,9 @@
   Initialize(1u);
 
   std::vector<EnqueueOrder> run_order;
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
   runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
-  EXPECT_TRUE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
 
   // Move the task into the |immediate_work_queue|.
   EXPECT_TRUE(runners_[0]->immediate_work_queue()->Empty());
@@ -370,12 +370,12 @@
   voter->SetQueueEnabled(false);
   test_task_runner_->RunUntilIdle();
   EXPECT_FALSE(runners_[0]->immediate_work_queue()->Empty());
-  EXPECT_TRUE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
 
   // Run the task, making the queue empty.
   voter->SetQueueEnabled(true);
   test_task_runner_->RunUntilIdle();
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
 }
 
 TEST_F(TaskQueueManagerTest, HasPendingImmediateWork_DelayedTask) {
@@ -385,18 +385,18 @@
   base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10));
   runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order),
                                delay);
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
   now_src_->Advance(delay);
-  EXPECT_TRUE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
 
   // Move the task into the |delayed_work_queue|.
   WakeUpReadyDelayedQueues(LazyNow(now_src_.get()));
   EXPECT_FALSE(runners_[0]->delayed_work_queue()->Empty());
-  EXPECT_TRUE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
 
   // Run the task, making the queue empty.
   test_task_runner_->RunUntilIdle();
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
 }
 
 TEST_F(TaskQueueManagerTest, DelayedTaskPosting) {
@@ -407,7 +407,7 @@
   runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order),
                                delay);
   EXPECT_EQ(delay, test_task_runner_->DelayToNextTaskTime());
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
   EXPECT_TRUE(run_order.empty());
 
   // The task doesn't run before the delay has completed.
@@ -417,7 +417,7 @@
   // After the delay has completed, the task runs normally.
   test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(1));
   EXPECT_THAT(run_order, ElementsAre(1));
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
 }
 
 bool MessageLoopTaskCounter(size_t* count) {
@@ -551,7 +551,7 @@
   EXPECT_FALSE(test_task_runner_->HasPendingTasks());
 
   // However polling still works.
-  EXPECT_TRUE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
 
   // After removing the fence the task runs normally.
   runners_[0]->RemoveFence();
@@ -1134,34 +1134,34 @@
 TEST_F(TaskQueueManagerTest, HasPendingImmediateWork) {
   Initialize(1u);
 
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
   runners_[0]->PostTask(FROM_HERE, base::Bind(NullTask));
-  EXPECT_TRUE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
 
   test_task_runner_->RunUntilIdle();
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
 }
 
 TEST_F(TaskQueueManagerTest, HasPendingImmediateWork_DelayedTasks) {
   Initialize(1u);
 
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
   runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(NullTask),
                                base::TimeDelta::FromMilliseconds(12));
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
 
   // Move time forwards until just before the delayed task should run.
   now_src_->Advance(base::TimeDelta::FromMilliseconds(10));
   WakeUpReadyDelayedQueues(LazyNow(now_src_.get()));
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
 
   // Force the delayed task onto the work queue.
   now_src_->Advance(base::TimeDelta::FromMilliseconds(2));
   WakeUpReadyDelayedQueues(LazyNow(now_src_.get()));
-  EXPECT_TRUE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
 
   test_task_runner_->RunUntilIdle();
-  EXPECT_FALSE(runners_[0]->HasPendingImmediateWork());
+  EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
 }
 
 void ExpensiveTestTask(int value,
@@ -1748,12 +1748,14 @@
   std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
       runners_[0]->CreateQueueEnabledVoter();
   voter->SetQueueEnabled(false);
+  Mock::VerifyAndClearExpectations(&observer);
 
   // When a queue has been enabled, we may get a notification if the
   // TimeDomain's next scheduled wake-up has changed.
   EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(),
                                                  start_time + delay1s));
   voter->SetQueueEnabled(true);
+  Mock::VerifyAndClearExpectations(&observer);
 
   // Tidy up.
   runners_[0]->UnregisterTaskQueue();
@@ -1813,6 +1815,42 @@
   runners_[1]->UnregisterTaskQueue();
 }
 
+TEST_F(TaskQueueManagerTest, TaskQueueObserver_DelayedWorkWhichCanRunNow) {
+  // This test checks that when delayed work becomes available
+  // the notification still fires. This usually happens when time advances
+  // and task becomes available in the middle of the scheduling code.
+  // For this test we rely on the fact that notification dispatching code
+  // is the same in all conditions and just change a time domain to
+  // trigger notification.
+
+  Initialize(1u);
+
+  base::TimeDelta delay1s(base::TimeDelta::FromSeconds(1));
+  base::TimeDelta delay10s(base::TimeDelta::FromSeconds(10));
+
+  MockTaskQueueObserver observer;
+  runners_[0]->SetObserver(&observer);
+
+  // We should get a notification when a delayed task is posted on an empty
+  // queue.
+  EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _));
+  runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay1s);
+  Mock::VerifyAndClearExpectations(&observer);
+
+  std::unique_ptr<TimeDomain> mock_time_domain =
+      base::MakeUnique<RealTimeDomain>();
+  manager_->RegisterTimeDomain(mock_time_domain.get());
+
+  now_src_->Advance(delay10s);
+
+  EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _));
+  runners_[0]->SetTimeDomain(mock_time_domain.get());
+  Mock::VerifyAndClearExpectations(&observer);
+
+  // Tidy up.
+  runners_[0]->UnregisterTaskQueue();
+}
+
 class CancelableTask {
  public:
   explicit CancelableTask(base::TickClock* clock)
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
index bdf885b..66b7bae 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
@@ -41,7 +41,7 @@
   // We only want to store a single wake-up per queue, so we need to remove any
   // previously registered wake up for |queue|.
   if (queue->heap_handle().IsValid()) {
-    DCHECK_NE(queue->scheduled_time_domain_wake_up(), base::TimeTicks());
+    DCHECK(queue->scheduled_time_domain_wake_up());
 
     // O(log n)
     delayed_wake_up_queue_.ChangeKey(queue->heap_handle(), {wake_up, queue});
@@ -50,7 +50,7 @@
     delayed_wake_up_queue_.insert({wake_up, queue});
   }
 
-  queue->set_scheduled_time_domain_wake_up(wake_up.time);
+  queue->SetScheduledTimeDomainWakeUp(wake_up.time);
 
   // If |queue| is the first wake-up then request the wake-up.
   if (delayed_wake_up_queue_.Min().queue == queue)
@@ -65,7 +65,7 @@
   if (!queue->heap_handle().IsValid())
     return;
 
-  DCHECK_NE(queue->scheduled_time_domain_wake_up(), base::TimeTicks());
+  DCHECK(queue->scheduled_time_domain_wake_up());
   DCHECK(!delayed_wake_up_queue_.empty());
   base::TimeTicks prev_first_wake_up =
       delayed_wake_up_queue_.Min().wake_up.time;
@@ -95,11 +95,11 @@
     if (next_wake_up) {
       // O(log n)
       delayed_wake_up_queue_.ReplaceMin({*next_wake_up, queue});
-      queue->set_scheduled_time_domain_wake_up(next_wake_up->time);
+      queue->SetScheduledTimeDomainWakeUp(next_wake_up->time);
     } else {
       // O(log n)
       delayed_wake_up_queue_.Pop();
-      DCHECK_EQ(queue->scheduled_time_domain_wake_up(), base::TimeTicks());
+      DCHECK(!queue->scheduled_time_domain_wake_up());
     }
   }
 }
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h
index 6f1abcf..19cec2d 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h
@@ -135,8 +135,8 @@
       DCHECK(queue->heap_handle().IsValid());
       queue->set_heap_handle(HeapHandle());
 
-      DCHECK_NE(queue->scheduled_time_domain_wake_up(), base::TimeTicks());
-      queue->set_scheduled_time_domain_wake_up(base::TimeTicks());
+      DCHECK(queue->scheduled_time_domain_wake_up());
+      queue->SetScheduledTimeDomainWakeUp(base::nullopt);
     }
   };
 
diff --git a/third_party/WebKit/Source/platform/scheduler/base/trace_helper.cc b/third_party/WebKit/Source/platform/scheduler/base/trace_helper.cc
new file mode 100644
index 0000000..5fbb9f7
--- /dev/null
+++ b/third_party/WebKit/Source/platform/scheduler/base/trace_helper.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 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.
+
+#include "platform/scheduler/base/trace_helper.h"
+
+#include "base/format_macros.h"
+#include "base/strings/stringprintf.h"
+
+namespace blink {
+namespace scheduler {
+namespace trace_helper {
+
+std::string PointerToString(const void* pointer) {
+  return base::StringPrintf(
+      "0x%" PRIx64,
+      static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
+}
+
+}  // namespace trace_helper
+}  // namespace scheduler
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/base/trace_helper.h b/third_party/WebKit/Source/platform/scheduler/base/trace_helper.h
new file mode 100644
index 0000000..8f8fd26
--- /dev/null
+++ b/third_party/WebKit/Source/platform/scheduler/base/trace_helper.h
@@ -0,0 +1,20 @@
+// Copyright 2017 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.
+
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TRACE_HELPER_H
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TRACE_HELPER_H
+
+#include <string>
+
+namespace blink {
+namespace scheduler {
+
+namespace trace_helper {
+std::string PointerToString(const void* pointer);
+};
+
+}  // namespace scheduler
+}  // namespace blink
+
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TRACE_HELPER_H
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc
index 0ce84fa..b61f373 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc
@@ -96,7 +96,7 @@
   if (long_idle_period_duration >=
       base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) {
     *next_long_idle_period_delay_out = long_idle_period_duration;
-    if (!idle_queue_->HasPendingImmediateWork()) {
+    if (!idle_queue_->HasTaskToRunImmediately()) {
       return IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED;
     } else if (long_idle_period_duration == max_long_idle_period_duration) {
       return IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE;
@@ -248,7 +248,7 @@
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
                "UpdateLongIdlePeriodStateAfterIdleTask");
 
-  if (!idle_queue_->HasPendingImmediateWork()) {
+  if (!idle_queue_->HasTaskToRunImmediately()) {
     // If there are no more idle tasks then pause long idle period ticks until a
     // new idle task is posted.
     state_.UpdateState(IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED,
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/cpu_time_budget_pool.cc b/third_party/WebKit/Source/platform/scheduler/renderer/cpu_time_budget_pool.cc
index 96eb942..dc86aa7 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/cpu_time_budget_pool.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/cpu_time_budget_pool.cc
@@ -6,26 +6,15 @@
 
 #include <cstdint>
 
-#include "base/format_macros.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
-#include "base/strings/stringprintf.h"
+#include "platform/scheduler/base/trace_helper.h"
 #include "platform/scheduler/renderer/task_queue_throttler.h"
 
 namespace blink {
 namespace scheduler {
 
-namespace {
-
-std::string PointerToId(void* pointer) {
-  return base::StringPrintf(
-      "0x%" PRIx64,
-      static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
-}
-
-}  // namespace
-
 CPUTimeBudgetPool::CPUTimeBudgetPool(
     const char* name,
     BudgetPoolController* budget_pool_controller,
@@ -153,7 +142,7 @@
 
   state->BeginArray("task_queues");
   for (TaskQueue* queue : associated_task_queues_) {
-    state->AppendString(PointerToId(queue));
+    state->AppendString(trace_helper::PointerToString(queue));
   }
   state->EndArray();
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
index c7e246c..168aca3 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -9,7 +9,6 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
@@ -19,6 +18,7 @@
 #include "platform/scheduler/base/task_queue_impl.h"
 #include "platform/scheduler/base/task_queue_selector.h"
 #include "platform/scheduler/base/time_converter.h"
+#include "platform/scheduler/base/trace_helper.h"
 #include "platform/scheduler/base/virtual_time_domain.h"
 #include "platform/scheduler/child/scheduler_tqm_delegate.h"
 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
@@ -77,12 +77,6 @@
                  "RendererScheduler.BackgroundRendererLoad", load_percentage);
 }
 
-std::string PointerToId(void* pointer) {
-  return base::StringPrintf(
-      "0x%" PRIx64,
-      static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
-}
-
 }  // namespace
 
 RendererSchedulerImpl::RendererSchedulerImpl(
@@ -870,7 +864,7 @@
     case UseCase::MAIN_THREAD_GESTURE:
     case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING:
     case UseCase::SYNCHRONIZED_GESTURE:
-      return compositor_task_queue_->HasPendingImmediateWork() ||
+      return compositor_task_queue_->HasTaskToRunImmediately() ||
              GetMainThreadOnly().touchstart_expected_soon;
 
     case UseCase::TOUCHSTART:
@@ -1517,7 +1511,8 @@
   state->BeginDictionary("web_view_schedulers");
   for (WebViewSchedulerImpl* web_view_scheduler :
        GetMainThreadOnly().web_view_schedulers) {
-    state->BeginDictionaryWithCopiedName(PointerToId(web_view_scheduler));
+    state->BeginDictionaryWithCopiedName(
+        trace_helper::PointerToString(web_view_scheduler));
     web_view_scheduler->AsValueInto(state.get());
     state->EndDictionary();
   }
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
index 1c3cd00b..dd0bacca 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
@@ -6,13 +6,12 @@
 
 #include <cstdint>
 
-#include "base/format_macros.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
-#include "base/strings/stringprintf.h"
 #include "platform/WebFrameScheduler.h"
 #include "platform/scheduler/base/real_time_domain.h"
+#include "platform/scheduler/base/trace_helper.h"
 #include "platform/scheduler/child/scheduler_tqm_delegate.h"
 #include "platform/scheduler/renderer/budget_pool.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
@@ -26,7 +25,7 @@
 
 base::Optional<base::TimeTicks> NextTaskRunTime(LazyNow* lazy_now,
                                                 TaskQueue* queue) {
-  if (queue->HasPendingImmediateWork())
+  if (queue->HasTaskToRunImmediately())
     return lazy_now->Now();
   return queue->GetNextScheduledWakeUp();
 }
@@ -64,12 +63,6 @@
   return std::max(a.value(), b.value());
 }
 
-std::string PointerToId(void* pointer) {
-  return base::StringPrintf(
-      "0x%" PRIx64,
-      static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
-}
-
 }  // namespace
 
 TaskQueueThrottler::TaskQueueThrottler(
@@ -441,7 +434,8 @@
 
   state->BeginDictionary("queue_details");
   for (const auto& map_entry : queue_details_) {
-    state->BeginDictionaryWithCopiedName(PointerToId(map_entry.first));
+    state->BeginDictionaryWithCopiedName(
+        trace_helper::PointerToString(map_entry.first));
 
     state->SetInteger("throttling_ref_count",
                       map_entry.second.throttling_ref_count);
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/wake_up_budget_pool.cc b/third_party/WebKit/Source/platform/scheduler/renderer/wake_up_budget_pool.cc
index f58039a..9d9274c 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/wake_up_budget_pool.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/wake_up_budget_pool.cc
@@ -6,23 +6,12 @@
 
 #include <cstdint>
 
-#include "base/format_macros.h"
-#include "base/strings/stringprintf.h"
+#include "platform/scheduler/base/trace_helper.h"
 #include "platform/scheduler/renderer/task_queue_throttler.h"
 
 namespace blink {
 namespace scheduler {
 
-namespace {
-
-std::string PointerToId(void* pointer) {
-  return base::StringPrintf(
-      "0x%" PRIx64,
-      static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
-}
-
-}  // namespace
-
 WakeUpBudgetPool::WakeUpBudgetPool(const char* name,
                                    BudgetPoolController* budget_pool_controller,
                                    base::TimeTicks now)
@@ -109,7 +98,7 @@
 
   state->BeginArray("task_queues");
   for (TaskQueue* queue : associated_task_queues_) {
-    state->AppendString(PointerToId(queue));
+    state->AppendString(trace_helper::PointerToString(queue));
   }
   state->EndArray();
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
index 70e18c2..3dce41cf 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
@@ -4,10 +4,10 @@
 
 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
 
-#include "base/strings/stringprintf.h"
 #include "base/trace_event/blame_context.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/scheduler/base/real_time_domain.h"
+#include "platform/scheduler/base/trace_helper.h"
 #include "platform/scheduler/base/virtual_time_domain.h"
 #include "platform/scheduler/child/web_task_runner_impl.h"
 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
@@ -19,15 +19,6 @@
 
 namespace blink {
 namespace scheduler {
-namespace {
-
-std::string PointerToId(void* pointer) {
-  return base::StringPrintf(
-      "0x%" PRIx64,
-      static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
-}
-
-}  // namespace
 
 WebFrameSchedulerImpl::ActiveConnectionHandleImpl::ActiveConnectionHandleImpl(
     WebFrameSchedulerImpl* frame_scheduler)
@@ -238,22 +229,26 @@
   state->SetBoolean("cross_origin", cross_origin_);
   if (loading_task_queue_) {
     state->SetString("loading_task_queue",
-                     PointerToId(loading_task_queue_.get()));
+                     trace_helper::PointerToString(loading_task_queue_.get()));
   }
   if (timer_task_queue_)
-    state->SetString("timer_task_queue", PointerToId(timer_task_queue_.get()));
+    state->SetString("timer_task_queue",
+                     trace_helper::PointerToString(timer_task_queue_.get()));
   if (unthrottled_task_queue_) {
-    state->SetString("unthrottled_task_queue",
-                     PointerToId(unthrottled_task_queue_.get()));
+    state->SetString(
+        "unthrottled_task_queue",
+        trace_helper::PointerToString(unthrottled_task_queue_.get()));
   }
   if (suspendable_task_queue_) {
-    state->SetString("suspendable_task_queue",
-                     PointerToId(suspendable_task_queue_.get()));
+    state->SetString(
+        "suspendable_task_queue",
+        trace_helper::PointerToString(suspendable_task_queue_.get()));
   }
   if (blame_context_) {
     state->BeginDictionary("blame_context");
-    state->SetString(
-        "id_ref", PointerToId(reinterpret_cast<void*>(blame_context_->id())));
+    state->SetString("id_ref",
+                     trace_helper::PointerToString(
+                         reinterpret_cast<void*>(blame_context_->id())));
     state->SetString("scope", blame_context_->scope());
     state->EndDictionary();
   }
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc
index fefee3e..f6b9706 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc
@@ -8,6 +8,7 @@
 #include "base/strings/stringprintf.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/WebFrameScheduler.h"
+#include "platform/scheduler/base/trace_helper.h"
 #include "platform/scheduler/base/virtual_time_domain.h"
 #include "platform/scheduler/child/scheduler_tqm_delegate.h"
 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
@@ -84,12 +85,6 @@
   return base::TimeDelta::FromSecondsD(initial_budget);
 }
 
-std::string PointerToId(void* pointer) {
-  return base::StringPrintf(
-      "0x%" PRIx64,
-      static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
-}
-
 }  // namespace
 
 WebViewSchedulerImpl::WebViewSchedulerImpl(
@@ -328,7 +323,8 @@
 
   state->BeginDictionary("frame_schedulers");
   for (WebFrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
-    state->BeginDictionaryWithCopiedName(PointerToId(frame_scheduler));
+    state->BeginDictionaryWithCopiedName(
+        trace_helper::PointerToString(frame_scheduler));
     frame_scheduler->AsValueInto(state);
     state->EndDictionary();
   }
diff --git a/tools/binary_size/README.md b/tools/binary_size/README.md
index 42d7372..19bf7f3 100644
--- a/tools/binary_size/README.md
+++ b/tools/binary_size/README.md
@@ -3,11 +3,11 @@
 These currently focus on Android and Linux platforms. However, some great tools
 for Windows exist and are documented here:
 
-https://www.chromium.org/developers/windows-binary-sizes
+ * https://www.chromium.org/developers/windows-binary-sizes
 
 There is also a dedicated mailing-list for binary size discussions:
 
-https://groups.google.com/a/chromium.org/forum/#!forum/binary-size
+ * https://groups.google.com/a/chromium.org/forum/#!forum/binary-size
 
 [TOC]
 
@@ -19,10 +19,8 @@
 ### How it Works
 
 1. Builds multiple revisions using release GN args.
-
-  * Default is to build just two revisions (before & after commit)
-  * Rather than building, can fetch build artifacts from perf bots (`--cloud`)
-
+   * Default is to build just two revisions (before & after commit)
+   * Rather than building, can fetch build artifacts from perf bots (`--cloud`)
 1. Measures all outputs using `resource_size.py` and `supersize`.
 1. Saves & displays a breakdown of the difference in binary sizes.
 
@@ -31,11 +29,11 @@
     # Build and diff HEAD^ and HEAD.
     tools/binary_size/diagnose_bloat.py HEAD -v
 
-    # Diff OTHERREV and REV using downloaded build artifacts.
-    tools/binary_size/diagnose_bloat.py REV --reference-rev OTHERREV --cloud -v
+    # Diff BEFORE_REV and AFTER_REV using build artifacts downloaded from perf bots.
+    tools/binary_size/diagnose_bloat.py AFTER_REV --reference-rev BEFORE_REV --cloud -v
 
-    # Build and diff all contiguous revs in range OTHERREV..REV for src/v8.
-    tools/binary_size/diagnose_bloat.py REV --reference-rev OTHERREV --subrepo v8 --all -v
+    # Build and diff all contiguous revs in range BEFORE_REV..AFTER_REV for src/v8.
+    tools/binary_size/diagnose_bloat.py AFTER_REV --reference-rev BEFORE_REV --subrepo v8 --all -v
 
     # Display detailed usage info (there are many options).
     tools/binary_size/diagnose_bloat.py -h
@@ -46,7 +44,11 @@
 Supports Android and Linux (although Linux
 [has issues](https://bugs.chromium.org/p/chromium/issues/detail?id=717550)).
 
-`.size` files are archived on perf bots as well as on official builders.
+`.size` files are archived on perf builders so that regressions can be quickly
+analyzed (via `diagnose_bloat.py --cloud`).
+
+`.size` files are archived on official builders so that symbols can be diff'ed
+between milestones.
 
 ### Technical Details
 
@@ -62,52 +64,50 @@
 #### How are Symbols Collected?
 
 1. Symbol list is Extracted from linker `.map` file.
-
-  * Map files contain some unique pieces of information, such as
-    `** merge strings` entries, and the odd unnamed symbol (which map at least
-    lists a `.o` path).
-
+   * Map files contain some unique pieces of information, such as
+     `** merge strings` entries, and the odd unnamed symbol (which map at least
+     lists a `.o` path).
 1. `.o` files are mapped to `.cc` files by parsing `.ninja` files.
-
-  * This means that `.h` files are never listed as sources. No information about
-    inlined symbols is gathered.
-
+   * This means that `.h` files are never listed as sources. No information about
+     inlined symbols is gathered.
 1. Symbol aliases (when multiple symbols share an address) are collected from
    debug information via `nm elf-file`.
-
-  * Aliases have the same address and size, but report their `.pss` as
-     `.size / .num_aliases`.
-
+   * Aliases have the same address and size, but report their `.pss` as
+      `.size / .num_aliases`.
 1. Paths for shared symbols (those found in multiple `.o` files) are collected
    by running `nm` on every `.o` file.
-
-  * Shared symbols do not store the complete list of `.o` files. Instead, the
-    common ancestor is computed and stored as the path (along with a
-    `{shared}/count` suffix).
+   * Shared symbols do not store the complete list of `.o` files. Instead, the
+     common ancestor is computed and stored as the path (along with a
+     `{shared}/count` suffix).
 
 #### What Other Processing Happens?
 
 1. Path normalization:
-
-  * Prefixes are removed: `out/Release/`, `gen/`, `obj/`
-  * Archive names made more pathy: `foo/bar.a(baz.o)` -> `foo/bar.a/baz.o`
+   * Prefixes are removed: `out/Release/`, `gen/`, `obj/`
+   * Archive names made more pathy: `foo/bar.a(baz.o)` -> `foo/bar.a/baz.o`
 
 1. Name normalization:
-
-  * `(anonymous::)` is removed from names.
-  * `vtable for FOO` -> `Foo [vtable]`
-  * Names split into: `name`, `template_name`, `full_name`
+   * `(anonymous::)` is removed from names.
+   * `vtable for FOO` -> `Foo [vtable]`
+   * Names split into: `name`, `template_name`, `full_name`
 
 1. Clustering
-
-  * Compiler optimizations can cause a symbol to be broken into multiple smaller
-    symbols. Clustering puts them back together.
+   * Compiler optimizations can cause a symbol to be broken into multiple
+     smaller symbols. Clustering puts them back together.
 
 1. Diffing
+   * Some heuristics for matching up before/after symbols.
 
-  * Some heuristics for matching up before/after symbols.
+#### Is Super Size a Generic Tool?
 
-### Usage: `archive`
+No. Most of the logic is would could work for any ELF executable. However, being
+a generic tool is not a goal. Some examples of existing Chrome-specific logic:
+
+ * Assumes `.ninja` build rules are available.
+ * Heuristic for locating `.so` given `.apk`.
+ * Roadmap includes `.pak` file analysis.
+
+### Usage: archive
 
 Collect size information and dump it into a `.size` file.
 
@@ -127,7 +127,7 @@
     ninja -C out/Release -j 1000 chrome
     tools/binary_size/supersize archive chrome.size --elf-file out/Release/chrome -v
 
-### Usage: `html_report`
+### Usage: html_report
 
 Creates an interactive size breakdown (by source path) as a stand-alone html
 report.
@@ -137,7 +137,7 @@
     tools/binary_size/supersize html_report chrome.size --report-dir size-report -v
     xdg-open size-report/index.html
 
-### Usage: `console`
+### Usage: console
 
 Starts a Python interpreter where you can run custom queries.
 
@@ -149,7 +149,7 @@
     # Enters a Python REPL (it will print more guidance).
     tools/binary_size/supersize console chrome.size
 
-### Usage: `diff`
+### Usage: diff
 
 A convenience command equivalent to: `console before.size after.size --query='Print(Diff(size_info1, size_info2))'`
 
@@ -163,30 +163,22 @@
 
 1. [Better Linux support](https://bugs.chromium.org/p/chromium/issues/detail?id=717550) (clang+lld+lto vs gcc+gold).
 1. More `archive` features:
-
-  * Find out more about 0xffffffffffffffff addresses, and why such large
-    gaps exist after them. ([crbug/709050](https://bugs.chromium.org/p/chromium/issues/detail?id=709050))
-  * Collect .pak file information (using .o.whitelist files)
-  * Collect java symbol information
-  * Collect .apk entry information
-
+    * Find out more about 0xffffffffffffffff addresses, and why such large
+      gaps exist after them. ([crbug/709050](https://bugs.chromium.org/p/chromium/issues/detail?id=709050))
+    * Collect .pak file information (using .o.whitelist files)
+    * Collect java symbol information
+    * Collect .apk entry information
 1. More `console` features:
-
-  * CSV output (for pasting into a spreadsheet).
-  * Add `SplitByName()` - Like `GroupByName()`, but recursive.
-  * A canned query, that does what ShowGlobals does (as described in [Windows Binary Sizes](https://www.chromium.org/developers/windows-binary-sizes)).
-  * Show symbol counts by bucket size.
-
-    * 3 symbols < 64 bytes. 10 symbols < 128, 3 < 256, 5 < 512, 0 < 1024, 3 < 2048
-
+   * CSV output (for pasting into a spreadsheet).
+   * Add `SplitByName()` - Like `GroupByName()`, but recursive.
+   * A canned query, that does what ShowGlobals does (as described in [Windows Binary Sizes](https://www.chromium.org/developers/windows-binary-sizes)).
+   * Show symbol counts by bucket size.
+     * 3 symbols < 64 bytes. 10 symbols < 128, 3 < 256, 5 < 512, 0 < 1024, 3 < 2048
 1. More `html_report` features:
-
-  * Able to render size diffs (tint negative size red).
-  * Break down by other groupings (Create from result of `SplitByName()`)
-  * Render as simple tree view rather than 2d boxes
-
+   * Able to render size diffs (tint negative size red).
+   * Break down by other groupings (Create from result of `SplitByName()`)
+   * Render as simple tree view rather than 2d boxes
 1. Integrate with `resource_sizes.py` so that it tracks size of major
    components separately: chrome vs blink vs skia vs v8.
 1. Add dependency graph info, perhaps just on a per-file basis.
-
-  * No idea how to do this, but Windows can do it via `tools\win\linker_verbose_tracking.py`
+   * No idea how to do this, but Windows can do it via `tools\win\linker_verbose_tracking.py`
diff --git a/tools/gritsettings/translation_expectations.pyl b/tools/gritsettings/translation_expectations.pyl
index 0ddd39d00..8fc2ff1 100644
--- a/tools/gritsettings/translation_expectations.pyl
+++ b/tools/gritsettings/translation_expectations.pyl
@@ -57,6 +57,7 @@
     "files": [
       "android_webview/java/strings/android_webview_strings.grd",
       "chrome/android/java/strings/android_chrome_strings.grd",
+      "chrome/android/webapk/strings/android_webapk_strings.grd",
       "content/public/android/java/strings/android_content_strings.grd",
       "ui/android/java/strings/android_ui_strings.grd",
     ],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b5c057f7..982d45e 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -21217,6 +21217,7 @@
   <int value="-1880355454" label="disable-topchrome-md"/>
   <int value="-1876881908"
       label="disable-infobar-for-protected-media-identifier"/>
+  <int value="-1875383510" label="UseGoogleLocalNtp:disabled"/>
   <int value="-1874908826" label="enable-instant-search-clicks"/>
   <int value="-1874141108" label="NewOmniboxAnswerTypes:enabled"/>
   <int value="-1872989945" label="enable-webview-based-signin"/>
@@ -21305,6 +21306,7 @@
   <int value="-1559789642" label="RunAllFlashInAllowMode:enabled"/>
   <int value="-1557527869" label="LoadingWithMojo:disabled"/>
   <int value="-1553477903" label="ash-disable-text-filtering-in-overview-mode"/>
+  <int value="-1549871007" label="OneGoogleBarOnLocalNtp:disabled"/>
   <int value="-1546903171" label="enable-touch-drag-drop"/>
   <int value="-1544248549" label="ArcUseAuthEndpoint:enabled"/>
   <int value="-1543316040"
@@ -21981,6 +21983,7 @@
   <int value="1081546525" label="ash-enable-docked-windows"/>
   <int value="1087235172" label="file-manager-enable-new-audio-player"/>
   <int value="1090377940" label="enable-quic-https"/>
+  <int value="1094506652" label="UseGoogleLocalNtp:enabled"/>
   <int value="1095061640" label="enable-prominent-url-app-flow"/>
   <int value="1098823967" label="ash-enable-window-cycle-ui"/>
   <int value="1104948452" label="manual-enhanced-bookmarks-optout"/>
@@ -22121,6 +22124,7 @@
   <int value="1511161758" label="BackgroundLoader:enabled"/>
   <int value="1515196403" label="fast-user-switching"/>
   <int value="1517863401" label="history-entry-requires-user-gesture"/>
+  <int value="1538690515" label="OneGoogleBarOnLocalNtp:enabled"/>
   <int value="1541723759" label="ServiceWorkerNavigationPreload:disabled"/>
   <int value="1548776701" label="AllBookmarks:disabled"/>
   <int value="1548942246" label="PassiveDocumentEventListeners:disabled"/>
@@ -22262,6 +22266,7 @@
       label="enable-supervised-user-managed-bookmarks-folder"/>
   <int value="2079672348" label="ExperimentalKeyboardLockUI:disabled"/>
   <int value="2085438501" label="ChromeHome:enabled"/>
+  <int value="2089897928" label="enable-audio-focus"/>
   <int value="2093235103" label="default-tile-width"/>
   <int value="2097048479" label="disable-auto-hiding-toolbar-threshold"/>
   <int value="2098714203" label="enable-generic-sensors"/>
diff --git a/tools/perf/docs/apk_size_regressions.md b/tools/perf/docs/apk_size_regressions.md
index a196e80..8e60f241 100644
--- a/tools/perf/docs/apk_size_regressions.md
+++ b/tools/perf/docs/apk_size_regressions.md
@@ -1,86 +1,126 @@
 # How to Deal with Android Size Alerts
 
-*Not all alerts should not have a bug created for them. Please read on...*
+ >
+ > Not all alerts should not have a bug created for them. Please read on...
+ >
 
-### If the alert is for "other lib size" or "Unknown files size":
- * File a bug against agrieve@ to fix
-   [resource_sizes.py](https://cs.chromium.org/chromium/src/build/android/resource_sizes.py).
- * ...or fix it yourself. This script will output the list of unknown
-   filenames.
+[TOC]
 
-### If the alert is a downstream size alert (aka, for Monochrome.apk):
+## Step 1: Identify the Commit
+
+### MonochromePublic.apk Alerts (Single Commit)
+
+ * Zoom in on the graph to make sure the alert is not
+   [off-by-one](https://github.com/catapult-project/catapult/issues/3444)
+   * Replace `&num_points=XXXX` with `&rev=COMMIT_POSITION` in the URL.
+   * It will be obvious from this whether or not the point is off. Use the
+     "nudge" feature to correct it when this happens.
+
+### MonochromePublic.apk Alerts (Multiple Commits or Rolls)
+
+ * Bisects [will not help you](https://bugs.chromium.org/p/chromium/issues/detail?id=678338).
+ * File a bug using template in Step 2.
+ * If you can afford to run a fire-and-forget command locally, use a
+   [local Android checkout](https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md)
+   along with [`//tools/binary_size/diagnose_bloat.py`](https://chromium.googlesource.com/chromium/src/+/master/tools/binary_size/README.md)
+   to build all commits locally and find the culprit.
+
+**Example:**
+
+     tools/binary_size/diagnose_bloat.py AFTER_REV --reference-rev BEFORE_REV --subrepo v8 --all
+
+### Monochrome.apk Alerts
+
  * The regression most likely already occurred in the upstream
    MonochromePublic.apk target. Look at the
-   [upstream graphs](https://chromeperf.appspot.com/report?sid=cfc29eed1238fd38fb5e6cf83bdba6c619be621b606e03e5dfc2e99db14c418b&num_points=1500)
-   to find the culprit & de-dupe with upstream alerts.
+   [graph of Monochrome.apk and MonochromePublic.apk overlaid](https://chromeperf.appspot.com/report?sid=cfc29eed1238fd38fb5e6cf83bdba6c619be621b606e03e5dfc2e99db14c418b&num_points=1500)
+   to find the culprit and de-dupe with upstream alert.
  * If no upstream regression was found, look through the downstream commits
    within the given date range to find the culprit.
     * Via `git log --format=fuller` (be sure to look at `CommitDate` and not
       `AuthorDate`)
+ * If the culprit is not obvious, follow the steps from the "multiple commits"
+   section above, filing a bug and running `diagnose_bloat.py`
+   (with `--subrepo=clank`).
 
-### If the alert is for a roll, or has multiple commits listed:
- * Use a bisect to try and determine a more precise commit.
-    * Except don't. Bisects for these alerts [are currently broken](https://bugs.chromium.org/p/chromium/issues/detail?id=678338).
-    * Until this is fixed, just file a bug and assign to agrieve@.
+## Step 2: File Bug or Silence Alert
 
-### What to do once the commit is identified:
- * If the code seems to justify the size increase:
-    * Annotate the code review with the following (replacing **bold** parts):
-       > FYI - this added **20kb** to Chrome on Android. No action is required
-       > (unless you can think of an obvious way to reduce the overhead).
-       >
-       > Link to size graph:
-[https://chromeperf.appspot.com/report?sid=cfc29eed1238fd38fb5e6cf83bdba6c619be621b606e03e5dfc2e99db14c418b&rev=**440074**](https://chromeperf.appspot.com/report?sid=cfc29eed1238fd38fb5e6cf83bdba6c619be621b606e03e5dfc2e99db14c418b&rev=440074)
- * If the code might not justify the size increase:
-    * File a bug and assign to the author to follow-up.
-        * Change the bug's title from X% to XXkb
-        * Paste in link to commit or review URL that is at fault.
-        * Paste in link to [https://chromium.googlesource.com/chromium/src/+/master/tools/perf/docs/apk_size_regressions.md#Debugging-Apk-Size-Increase](https://chromium.googlesource.com/chromium/src/+/master/tools/perf/docs/apk_size_regressions.md#Debugging-Apk-Size-Increase).
-        * Remove label: `Restrict-View-Google`
-        * TODO(agrieve): [https://github.com/catapult-project/catapult/issues/3150](Change bug template to match these instructions)
+If the code seems to justify the size increase:
+
+ * Annotate the code review with the following (replacing **bold** parts):
+    > FYI - this added **20kb** to Chrome on Android. No action is required
+    > (unless you can think of an obvious way to reduce the overhead).
+    >
+    > Link to size graph:
+[https://chromeperf.appspot.com/report?sid=a097e74b1aa288511afb4cb616efe0f95ba4d347ad61d5e835072f23450938ba&rev=**440074**](https://chromeperf.appspot.com/report?sid=cfc29eed1238fd38fb5e6cf83bdba6c619be621b606e03e5dfc2e99db14c418b&rev=440074)
+ * Silence the alert.
+
+
+If the code might not justify the size increase:
+
+ * File a bug (TODO:
+[Make this template automatic](https://github.com/catapult-project/catapult/issues/3150)).
+    * Change the bug's title from `X%` to `XXkb`
+    * Remove label: `Restrict-View-Google`
+    * Assign to commit author
+    * Set description to (replacing **bold** parts):
+      > Alert caused by "**First line of commit message**"
+      >
+      > Commit: **abc123abc123abc123abc123abc123abc123abcd**
+      >
+      > Link to size graph:
+[https://chromeperf.appspot.com/report?sid=a097e74b1aa288511afb4cb616efe0f95ba4d347ad61d5e835072f23450938ba&rev=**440074**](https://chromeperf.appspot.com/report?sid=cfc29eed1238fd38fb5e6cf83bdba6c619be621b606e03e5dfc2e99db14c418b&rev=440074)
+      >
+      >
+      > How to debug this size regressions is documented at:
+https://chromium.googlesource.com/chromium/src/+/master/tools/perf/docs/apk_size_regressions.md#Debugging-Apk-Size-Increase
 
 # Debugging Apk Size Increase
 
-## Step 1: Identify where the extra bytes came from
+## Step 1: Identify what Grew
 
-Figure out which file within the .apk increased by looking at the size graphs
-showing the breakdowns.
+Figure out which file within the `.apk` increased (native library, dex, pak
+resources, etc) by looking at the breakdown in the size graphs linked to in the
+bug (if it was not linked in the bug, see above).
 
- * Refer to the chromeperf link that should have been posted to your code
-   review (see above).
- * Alternatively, refer to [go/chrome-binary-size](https://goto.google.com/chrome-binary-size) (*googler only*).
+## Step 2: Analyze
 
-## Step 2: Reproduce build results locally
+### Growth is from Translations
 
-### Option 1: Build Locally
- 1. Follow the normal [Android build instructions](https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md).
- 1. Ensure you're using the same GN args as the bots by looking at the `generate_build_files` step of the build:
-    * https://luci-logdog.appspot.com/v/?s=chrome%2Fbb%2Fchromium.perf%2FAndroid_Builder%2F**134505**%2F%2B%2Frecipes%2Fsteps%2Fgenerate_build_files%2F0%2Fstdout
- 3. Save artifacts you'll need for diffing:
+ * There is likely nothing that can be done. Translations are expensive.
+ * Close as `Won't Fix`.
 
-```shell
-    mv out/Release/lib.unstripped out/Release/lib.unstripped.withchange
-    mv out/Release/apks out/Release/apks.withchange
-```
+### Growth is from Images
 
-### Option 2: Download artifacts from perf jobs (Googlers only)**
- 1. Replace the bolded part of the following URL with the git commit hash:
-  [https://storage.cloud.google.com/chrome-perf/Android%20Builder/full-build-linux_**HASH**.zip](https://storage.cloud.google.com/chrome-perf/Android%20Builder/full-build-linux_**HASH**.zip)
+  * Would [a VectorDrawable](https://codereview.chromium.org/2857893003/) be better?
+  * If it's lossy, consider [using webp](https://codereview.chromium.org/2615243002/).
+  * Ensure you've optimized with
+    [tools/resources/optimize-png-files.sh](https://cs.chromium.org/chromium/src/tools/resources/optimize-png-files.sh).
+  * There is some [Googler-specific guidance](https://goto.google.com/clank/engineering/best-practices/adding-image-assets) as well.
 
-## Step 3: Analyze
+### Growth is from Native Code
 
- * If the growth is from native code:
-    * Refer to techniques used in [crbug.com/681991](https://bugs.chromium.org/p/chromium/issues/detail?id=681991)
-      and [crbug.com/680973](https://bugs.chromium.org/p/chromium/issues/detail?id=680973).
- * If the growth is from java code:
-    * Use [tools/android/dexdiffer/dexdiffer.py](https://cs.chromium.org/chromium/src/tools/android/dexdiffer/dexdiffer.py).
-        * This currently just shows a list of symbols added / removed rather than
-          taking into account method body sizes.
-        * Enhancements to this tool tracked at
-          [crbug/678044](https://bugs.chromium.org/p/chromium/issues/detail?id=678044).
- * If the growth is from images, ensure they are optimized:
-    * Would it be smaller as a VectorDrawable?
-    * If it's lossy, consider using webp.
-    * Ensure you've optimized with
-      [tools/resources/optimize-png-files.sh](https://cs.chromium.org/chromium/src/tools/resources/optimize-png-files.sh).
-    * There is some [Googler-specific guidance](https://goto.google.com/clank/engineering/best-practices/adding-image-assets) as well.
+ * Use [//tools/binary_size/diagnose_bloat.py](https://chromium.googlesource.com/chromium/src/+/master/tools/binary_size/README.md)
+to show a diff of ELF symbols.
+ * Paste the diff into the bug.
+ * If the diff looks reasonable, close as `Won't Fix`.
+ * Otherwise, try to refactor a bit (e.g.
+ [move code out of templates](https://bugs.chromium.org/p/chromium/issues/detail?id=716393)).
+
+### Growth is from Java code
+
+ * Use [tools/android/dexdiffer/dexdiffer.py](https://cs.chromium.org/chromium/src/tools/android/dexdiffer/dexdiffer.py).
+    * This currently just shows a list of symbols added / removed rather than
+      taking into account method body sizes.
+    * Enhancements to this tool tracked at
+      [crbug/678044](https://bugs.chromium.org/p/chromium/issues/detail?id=678044).
+
+### Growth is from "other lib size" or "Unknown files size"
+
+ * File a bug against agrieve@ to fix
+   [resource_sizes.py](https://cs.chromium.org/chromium/src/build/android/resource_sizes.py).
+ * ...or fix it yourself. This script will output the list of unknown filenames.
+
+### You Would Like Assistance
+
+ * Feel free to email [binary-size@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/binary-size).