diff --git a/DEPS b/DEPS
index 7b4fe455a..34bc573f 100644
--- a/DEPS
+++ b/DEPS
@@ -133,11 +133,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'aefecad7c0d2c29c147a05ea385a2ad855cbbc20',
+  'skia_revision': '69600007e278d1bd3fed1df28a6dd9cb9ed23f20',
   # 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': '4181d035d41f0831644d836f5ebe6c81efbec3e5',
+  'v8_revision': '1eab45067108b961de4117fde9584b3099e428e3',
   # 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.
@@ -149,7 +149,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '1b8cd2d9ce2c0c0cc0213da6eab7d8d47bef4ab3',
+  'swiftshader_revision': 'f3b57974620dc86f8040123b55c9c9788c79b0e0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -196,7 +196,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'f8e231582d6aa491266c06cfaa7b81cd15aa3dfa',
+  'catapult_revision': '0a33de82760c4a3f8cb7089d5817cdea2b674291',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -440,7 +440,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '651b6470f437cdc51bb97f285b213d1520bc7201',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'd4fdb374214cfe2010d167338affd3fa9e67263c',
       'condition': 'checkout_ios',
   },
 
@@ -786,7 +786,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '04600b4f26bdd5534788d437d0f82a5a47d97deb',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e5c289fde0a115ef91448242729d61b4f7174517',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1128,7 +1128,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '34e6c9d3d1b6a30263b13ac18b782c79e66f9825',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'eff66d82dc0de2b3cd3cb8af3b5689b88fd2ba7e',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1299,7 +1299,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a0f51b2e123f39c9ff12e621b0b47dd28dd64424',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'd841ea6b586a81065f78d3eae7ab82c505cda1d8',
+    Var('webrtc_git') + '/src.git' + '@' + '35816cc9a150ad6a350bc18e8fe759f501fa3f73',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1340,7 +1340,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@798a5f3dda67bf4cfa914cec4d3463c90f37d336',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@fa2d5d1b4ecfb9c097ee6dd91654fd8317084cca',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
index 964c20a..83eec58 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
@@ -109,16 +109,10 @@
             setCookieWithJavaScript(jsCookieName, "value");
             if (acceptCookieValue) {
                 waitForCookie(url);
-                String cookie = mCookieManager.getCookie(url);
-                String message =
-                        "WebView should set cookies from JavaScript (with setAcceptCookie enabled)";
-                Assert.assertNotNull(message, cookie);
-                validateCookies(cookie, jsCookieName);
+                assertHasCookies(url);
+                validateCookies(url, jsCookieName);
             } else {
-                String message =
-                        "WebView should not set cookies via JavaScript (with setAcceptCookie "
-                        + "disabled)";
-                Assert.assertNull(message, mCookieManager.getCookie(url));
+                assertNoCookies(url);
             }
 
             final List<Pair<String, String>> responseHeaders =
@@ -131,16 +125,10 @@
                     mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
             if (acceptCookieValue) {
                 waitForCookie(url);
-                String cookie = mCookieManager.getCookie(url);
-                String message =
-                        "WebView should set cookies from JavaScript (with setAcceptCookie enabled)";
-                Assert.assertNotNull(message, cookie);
-                validateCookies(cookie, jsCookieName, headerCookieName);
+                assertHasCookies(url);
+                validateCookies(url, jsCookieName, headerCookieName);
             } else {
-                String message =
-                        "WebView should not set cookies from headers (with setAcceptCookie "
-                        + "disabled)";
-                Assert.assertNull(message, mCookieManager.getCookie(url));
+                assertNoCookies(url);
             }
         } finally {
             webServer.shutdown();
@@ -165,7 +153,7 @@
     @MediumTest
     @Feature({"AndroidWebView", "Privacy"})
     public void testAcceptCookie_falseDoNotSendCookies() throws Throwable {
-        mCookieManager.setAcceptCookie(false);
+        blockAllCookies();
         AwActivityTestRule.enableJavaScriptOnUiThread(mAwContents);
 
         EmbeddedTestServer embeddedTestServer = EmbeddedTestServer.createAndStartServer(
@@ -175,9 +163,8 @@
             String cookieName = "java-test";
             mCookieManager.setCookie(url, cookieName + "=should-not-work");
 
-            String cookie = mCookieManager.getCookie(url);
-            Assert.assertNotNull(
-                    "Setting cookies should still affect the CookieManager itself", cookie);
+            // Setting cookies should still affect the CookieManager itself
+            assertHasCookies(url);
 
             mActivityTestRule.loadUrlSync(
                     mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
@@ -215,9 +202,8 @@
             mActivityTestRule.loadUrlSync(
                     mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
             waitForCookie(url);
-            String cookie = mCookieManager.getCookie(url);
-            Assert.assertNotNull(cookie);
-            validateCookies(cookie, "httponly", "strictsamesite", "laxsamesite");
+            assertHasCookies(url);
+            validateCookies(url, "httponly", "strictsamesite", "laxsamesite");
         } finally {
             webServer.shutdown();
         }
@@ -243,10 +229,11 @@
     @MediumTest
     @Feature({"AndroidWebView", "Privacy"})
     public void testRemoveAllCookies() throws Exception {
-        mCookieManager.setCookie("http://www.example.com", "name=test");
-        Assert.assertTrue(mCookieManager.hasCookies());
+        final String cookieUrl = "http://www.example.com";
+        mCookieManager.setCookie(cookieUrl, "name=test");
+        assertHasCookies(cookieUrl);
         mCookieManager.removeAllCookies();
-        Assert.assertFalse(mCookieManager.hasCookies());
+        assertNoCookies();
     }
 
     @Test
@@ -274,7 +261,7 @@
         String url = "http://www.example.com";
         String cookie = "name=test";
         mCookieManager.setCookie(url, cookie);
-        Assert.assertEquals(cookie, mCookieManager.getCookie(url));
+        assertCookieEquals(cookie, url);
     }
 
     @Test
@@ -288,8 +275,8 @@
         String differentSubdomainUrl = "http://different.sub.example.com";
         String cookie = "name=test";
         mCookieManager.setCookie(url, cookie);
-        Assert.assertEquals(cookie, mCookieManager.getCookie(sameSubdomainUrl));
-        Assert.assertNull(mCookieManager.getCookie(differentSubdomainUrl));
+        assertCookieEquals(cookie, sameSubdomainUrl);
+        assertNoCookies(differentSubdomainUrl);
     }
 
     @Test
@@ -300,8 +287,8 @@
         String differentSubdomainUrl = "http://different.sub.example.com";
         String cookie = "name=test";
         mCookieManager.setCookie(url, cookie + "; doMaIN \t  =.example.com");
-        Assert.assertEquals(cookie, mCookieManager.getCookie(url));
-        Assert.assertEquals(cookie, mCookieManager.getCookie(differentSubdomainUrl));
+        assertCookieEquals(cookie, url);
+        assertCookieEquals(cookie, differentSubdomainUrl);
     }
 
     @Test
@@ -313,8 +300,8 @@
         String differentSubdomainUrl = "http://different.sub.example.com";
         String cookie = "name=test";
         mCookieManager.setCookie(url, cookie + ";");
-        Assert.assertEquals(cookie, mCookieManager.getCookie(sameSubdomainUrl));
-        Assert.assertNull(mCookieManager.getCookie(differentSubdomainUrl));
+        assertCookieEquals(cookie, sameSubdomainUrl);
+        assertNoCookies(differentSubdomainUrl);
     }
 
     @Test
@@ -325,7 +312,7 @@
         String secureUrl = "https://www.example.com";
         String cookie = "name=test";
         mCookieManager.setCookie(url, cookie + ";secure");
-        Assert.assertEquals(cookie, mCookieManager.getCookie(secureUrl));
+        assertCookieEquals(cookie, secureUrl);
     }
 
     @Test
@@ -350,7 +337,7 @@
         setCookieOnUiThread(url, cookie, callback);
         callback.getOnResultHelper().waitForCallback(callCount);
         Assert.assertTrue(callback.getValue());
-        Assert.assertEquals(cookie, mCookieManager.getCookie(url));
+        assertCookieEquals(cookie, url);
     }
 
     @Test
@@ -366,16 +353,14 @@
         setCookieOnUiThread(brokenUrl, cookie, callback);
         callback.getOnResultHelper().waitForCallback(callCount);
         Assert.assertFalse("Cookie should not be set for bad URLs", callback.getValue());
-        Assert.assertNull("getCookie should be null if cookie hasn't been set",
-                mCookieManager.getCookie(brokenUrl));
+        assertNoCookies(brokenUrl);
     }
 
     @Test
     @MediumTest
     @Feature({"AndroidWebView", "Privacy"})
     public void testSetCookieNullCallback() throws Throwable {
-        mCookieManager.setAcceptCookie(true);
-        Assert.assertTrue(mCookieManager.acceptCookie());
+        allowFirstPartyCookies();
 
         final String url = "http://www.example.com";
         final String cookie = "name=test";
@@ -383,7 +368,7 @@
         mCookieManager.setCookie(url, cookie, null);
 
         AwActivityTestRule.pollInstrumentationThread(() -> mCookieManager.hasCookies());
-        Assert.assertEquals(cookie, mCookieManager.getCookie(url));
+        assertCookieEquals(cookie, url);
     }
 
     @Test
@@ -482,7 +467,7 @@
         final String cookie = "cookie1=peter";
 
         mCookieManager.setCookie(url, makeExpiringCookie(cookie, -1));
-        Assert.assertNull(mCookieManager.getCookie(url));
+        assertNoCookies(url);
     }
 
     @Test
@@ -539,15 +524,10 @@
         // 127.0.0.1 which count (both in theory and pratice) as having different origins.
         TestWebServer webServer = TestWebServer.start();
         try {
-            // Turn global allow on.
-            mCookieManager.setAcceptCookie(true);
-            Assert.assertTrue(mCookieManager.acceptCookie());
+            allowFirstPartyCookies();
+            blockThirdPartyCookies(mAwContents);
 
-            // When third party cookies are disabled...
-            mAwContents.getSettings().setAcceptThirdPartyCookies(false);
-            Assert.assertFalse(mAwContents.getSettings().getAcceptThirdPartyCookies());
-
-            // ...we can't set third party cookies.
+            // We can't set third party cookies.
             // First on the third party server we create a url which tries to set a cookie.
             String cookieUrl = toThirdPartyUrl(
                     makeCookieUrl(webServer, "/cookie_1.js", "test1", "value1"));
@@ -555,22 +535,72 @@
             String url = makeScriptLinkUrl(webServer, "/content_1.html", cookieUrl);
             mActivityTestRule.loadUrlSync(
                     mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
-            Assert.assertNull(mCookieManager.getCookie(cookieUrl));
+            assertNoCookies(cookieUrl);
 
-            // When third party cookies are enabled...
-            mAwContents.getSettings().setAcceptThirdPartyCookies(true);
-            Assert.assertTrue(mAwContents.getSettings().getAcceptThirdPartyCookies());
+            allowThirdPartyCookies(mAwContents);
 
-            // ...we can set third party cookies.
+            // We can set third party cookies.
             cookieUrl = toThirdPartyUrl(
                     makeCookieUrl(webServer, "/cookie_2.js", "test2", "value2"));
             url = makeScriptLinkUrl(webServer, "/content_2.html", cookieUrl);
             mActivityTestRule.loadUrlSync(
                     mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
             waitForCookie(cookieUrl);
-            String cookie = mCookieManager.getCookie(cookieUrl);
-            Assert.assertNotNull(cookie);
-            validateCookies(cookie, "test2");
+            assertHasCookies(cookieUrl);
+            validateCookies(cookieUrl, "test2");
+        } finally {
+            webServer.shutdown();
+        }
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"AndroidWebView", "Privacy"})
+    public void testThirdPartyCookie_redirectFromThirdToFirst() throws Throwable {
+        TestWebServer webServer = TestWebServer.start();
+        try {
+            allowFirstPartyCookies();
+            blockThirdPartyCookies(mAwContents);
+
+            // Load a page with a third-party resource. The resource URL redirects to a new URL
+            // (which is first-party relative to the main frame). The final resource URL should
+            // successfully set its cookies (because it's first-party).
+            String resourcePath = "/cookie_1.js";
+            String firstPartyCookieUrl = makeCookieUrl(webServer, resourcePath, "test1", "value1");
+            String thirdPartyRedirectUrl = toThirdPartyUrl(
+                    webServer.setRedirect("/redirect_cookie_1.js", firstPartyCookieUrl));
+            String contentUrl =
+                    makeScriptLinkUrl(webServer, "/content_1.html", thirdPartyRedirectUrl);
+            mActivityTestRule.loadUrlSync(
+                    mAwContents, mContentsClient.getOnPageFinishedHelper(), contentUrl);
+            assertCookieEquals("test1=value1", firstPartyCookieUrl);
+        } finally {
+            webServer.shutdown();
+        }
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"AndroidWebView", "Privacy"})
+    public void testThirdPartyCookie_redirectFromFirstPartyToThird() throws Throwable {
+        TestWebServer webServer = TestWebServer.start();
+        try {
+            allowFirstPartyCookies();
+            blockThirdPartyCookies(mAwContents);
+
+            // Load a page with a first-party resource. The resource URL redirects to a new URL
+            // (which is third-party relative to the main frame). The final resource URL should be
+            // unable to set cookies (because it's third-party).
+            String resourcePath = "/cookie_2.js";
+            String thirdPartyCookieUrl =
+                    toThirdPartyUrl(makeCookieUrl(webServer, resourcePath, "test2", "value2"));
+            String firstPartyRedirectUrl =
+                    webServer.setRedirect("/redirect_cookie_2.js", thirdPartyCookieUrl);
+            String contentUrl =
+                    makeScriptLinkUrl(webServer, "/content_2.html", firstPartyRedirectUrl);
+            mActivityTestRule.loadUrlSync(
+                    mAwContents, mContentsClient.getOnPageFinishedHelper(), contentUrl);
+            assertNoCookies(thirdPartyCookieUrl);
         } finally {
             webServer.shutdown();
         }
@@ -611,11 +641,8 @@
     @MediumTest
     @Feature({"AndroidWebView", "Privacy"})
     public void testCookieForWebSocketHandshake_thirdParty_enabled() throws Throwable {
-        // Allow all cookies
-        mCookieManager.setAcceptCookie(true);
-        Assert.assertTrue(mCookieManager.acceptCookie());
-        mAwContents.getSettings().setAcceptThirdPartyCookies(true);
-        Assert.assertTrue(mAwContents.getSettings().getAcceptThirdPartyCookies());
+        allowFirstPartyCookies();
+        allowThirdPartyCookies(mAwContents);
         String cookieKey = "test1";
         String cookieValue = "value1";
         Assert.assertEquals(cookieKey + "=" + cookieValue,
@@ -626,11 +653,8 @@
     @MediumTest
     @Feature({"AndroidWebView", "Privacy"})
     public void testCookieForWebSocketHandshake_thirdParty_disabled() throws Throwable {
-        // Allow cookies but disable 3P cookies
-        mCookieManager.setAcceptCookie(true);
-        Assert.assertTrue(mCookieManager.acceptCookie());
-        mAwContents.getSettings().setAcceptThirdPartyCookies(false);
-        Assert.assertFalse(mAwContents.getSettings().getAcceptThirdPartyCookies());
+        allowFirstPartyCookies();
+        blockThirdPartyCookies(mAwContents);
         String cookieKey = "test1";
         String cookieValue = "value1";
         Assert.assertNull("Should not set 3P cookie when 3P cookie settings are disabled",
@@ -641,9 +665,8 @@
     @MediumTest
     @Feature({"AndroidWebView", "Privacy"})
     public void testCookieForWebSocketHandshake_firstParty_enabled() throws Throwable {
-        // Allow all cookies
-        mCookieManager.setAcceptCookie(true);
-        Assert.assertTrue(mCookieManager.acceptCookie());
+        allowFirstPartyCookies();
+        allowThirdPartyCookies(mAwContents);
         String cookieKey = "test1";
         String cookieValue = "value1";
         Assert.assertEquals(cookieKey + "=" + cookieValue,
@@ -654,9 +677,7 @@
     @MediumTest
     @Feature({"AndroidWebView", "Privacy"})
     public void testCookieForWebSocketHandshake_firstParty_disabled() throws Throwable {
-        // Disallow all cookies
-        mCookieManager.setAcceptCookie(false);
-        Assert.assertFalse(mCookieManager.acceptCookie());
+        blockAllCookies();
         String cookieKey = "test1";
         String cookieValue = "value1";
         Assert.assertNull("Should not set 1P cookie when 1P cookie settings are disabled",
@@ -736,21 +757,15 @@
             ThirdPartyCookiesTestHelper thirdParty =
                     new ThirdPartyCookiesTestHelper(webServer);
 
-            mCookieManager.setAcceptCookie(true);
-            Assert.assertTrue(mCookieManager.acceptCookie());
+            allowFirstPartyCookies();
+            blockThirdPartyCookies(thirdParty.getAwContents());
 
-            // When third party cookies are disabled...
-            thirdParty.getSettings().setAcceptThirdPartyCookies(false);
-            Assert.assertFalse(thirdParty.getSettings().getAcceptThirdPartyCookies());
-
-            // ...we can't set third party cookies.
+            // We can't set third party cookies.
             thirdParty.assertThirdPartyIFrameCookieResult("1", false);
 
-            // When third party cookies are enabled...
-            thirdParty.getSettings().setAcceptThirdPartyCookies(true);
-            Assert.assertTrue(thirdParty.getSettings().getAcceptThirdPartyCookies());
+            allowThirdPartyCookies(thirdParty.getAwContents());
 
-            // ...we can set third party cookies.
+            // We can set third party cookies.
             thirdParty.assertThirdPartyIFrameCookieResult("2", true);
         } finally {
             webServer.shutdown();
@@ -763,36 +778,33 @@
     public void testThirdPartyCookiesArePerWebview() throws Throwable {
         TestWebServer webServer = TestWebServer.start();
         try {
-            mCookieManager.setAcceptCookie(true);
+            allowFirstPartyCookies();
             mCookieManager.removeAllCookies();
-            Assert.assertTrue(mCookieManager.acceptCookie());
             Assert.assertFalse(mCookieManager.hasCookies());
 
             ThirdPartyCookiesTestHelper helperOne = new ThirdPartyCookiesTestHelper(webServer);
             ThirdPartyCookiesTestHelper helperTwo = new ThirdPartyCookiesTestHelper(webServer);
 
-            helperOne.getSettings().setAcceptThirdPartyCookies(false);
-            helperTwo.getSettings().setAcceptThirdPartyCookies(false);
-            Assert.assertFalse(helperOne.getSettings().getAcceptThirdPartyCookies());
-            Assert.assertFalse(helperTwo.getSettings().getAcceptThirdPartyCookies());
+            blockThirdPartyCookies(helperOne.getAwContents());
+            blockThirdPartyCookies(helperTwo.getAwContents());
             helperOne.assertThirdPartyIFrameCookieResult("1", false);
             helperTwo.assertThirdPartyIFrameCookieResult("2", false);
 
-            helperTwo.getSettings().setAcceptThirdPartyCookies(true);
-            Assert.assertFalse(helperOne.getSettings().getAcceptThirdPartyCookies());
-            Assert.assertTrue(helperTwo.getSettings().getAcceptThirdPartyCookies());
+            allowThirdPartyCookies(helperTwo.getAwContents());
+            Assert.assertFalse("helperOne's third-party cookie setting should be unaffected",
+                    helperOne.getSettings().getAcceptThirdPartyCookies());
             helperOne.assertThirdPartyIFrameCookieResult("3", false);
             helperTwo.assertThirdPartyIFrameCookieResult("4", true);
 
-            helperOne.getSettings().setAcceptThirdPartyCookies(true);
-            Assert.assertTrue(helperOne.getSettings().getAcceptThirdPartyCookies());
-            Assert.assertTrue(helperTwo.getSettings().getAcceptThirdPartyCookies());
+            allowThirdPartyCookies(helperOne.getAwContents());
+            Assert.assertTrue("helperTwo's third-party cookie setting shoudl be unaffected",
+                    helperTwo.getSettings().getAcceptThirdPartyCookies());
             helperOne.assertThirdPartyIFrameCookieResult("5", true);
             helperTwo.assertThirdPartyIFrameCookieResult("6", true);
 
-            helperTwo.getSettings().setAcceptThirdPartyCookies(false);
-            Assert.assertTrue(helperOne.getSettings().getAcceptThirdPartyCookies());
-            Assert.assertFalse(helperTwo.getSettings().getAcceptThirdPartyCookies());
+            blockThirdPartyCookies(helperTwo.getAwContents());
+            Assert.assertTrue("helperOne's third-party cookie setting should be unaffected",
+                    helperOne.getSettings().getAcceptThirdPartyCookies());
             helperOne.assertThirdPartyIFrameCookieResult("7", true);
             helperTwo.assertThirdPartyIFrameCookieResult("8", false);
         } finally {
@@ -877,11 +889,10 @@
                     mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
 
             if (expectedResult) {
-                String cookie = mCookieManager.getCookie(cookieUrl);
-                Assert.assertNotNull(cookie);
-                validateCookies(cookie, key);
+                assertHasCookies(cookieUrl);
+                validateCookies(cookieUrl, key);
             } else {
-                Assert.assertNull(mCookieManager.getCookie(cookieUrl));
+                assertNoCookies(cookieUrl);
             }
 
             // Clear the cookies.
@@ -954,7 +965,8 @@
         AwActivityTestRule.pollInstrumentationThread(() -> mCookieManager.getCookie(url) != null);
     }
 
-    private void validateCookies(String responseCookie, String... expectedCookieNames) {
+    private void validateCookies(String url, String... expectedCookieNames) {
+        final String responseCookie = mCookieManager.getCookie(url);
         String[] cookies = responseCookie.split(";");
         // Convert to sets, since Set#equals() hooks in nicely with assertEquals()
         Set<String> foundCookieNamesSet = new HashSet<String>();
@@ -977,4 +989,105 @@
         date.setTime(date.getTime() + millisecondsTillExpiry);
         return cookie + "; expires=" + date.toGMTString();
     }
+
+    /**
+     * Asserts there are no cookies set for the given URL. This makes no assertions about other
+     * URLs.
+     *
+     * @param cookieUrl the URL for which we expect no cookies to be set.
+     */
+    private void assertNoCookies(final String cookieUrl) throws Exception {
+        String msg = "Expected to not see cookies for '" + cookieUrl + "'";
+        Assert.assertNull(msg, mCookieManager.getCookie(cookieUrl));
+    }
+
+    /**
+     * Asserts there are no cookies set at all.
+     */
+    private void assertNoCookies() throws Exception {
+        String msg = "Expected to CookieManager to have no cookies";
+        Assert.assertFalse(msg, mCookieManager.hasCookies());
+    }
+
+    /**
+     * Asserts there are cookies set for the given URL.
+     *
+     * @param cookieUrl the URL for which to check for cookies.
+     */
+    private void assertHasCookies(final String cookieUrl) throws Exception {
+        String msg = "Expected CookieManager to have cookies for '" + cookieUrl
+                + "' but it has no cookies";
+        Assert.assertTrue(msg, mCookieManager.hasCookies());
+        msg = "Expected getCookie to return non-null for '" + cookieUrl + "'";
+        Assert.assertNotNull(msg, mCookieManager.getCookie(cookieUrl));
+    }
+
+    /**
+     * Asserts the cookie key/value pair for a given URL. Note: {@code cookieKeyValuePair} must
+     * exactly match the expected {@link AwCookieManager#getCookie()} output, which may return
+     * multiple key-value pairs.
+     *
+     * @param cookieKeyValuePair the expected key/value pair.
+     * @param cookieUrl the URL to check cookies for.
+     */
+    private void assertCookieEquals(final String cookieKeyValuePair, final String cookieUrl)
+            throws Exception {
+        assertHasCookies(cookieUrl);
+        String msg = "Unexpected cookie key/value pair";
+        Assert.assertEquals(msg, cookieKeyValuePair, mCookieManager.getCookie(cookieUrl));
+    }
+
+    /**
+     * Allow third-party cookies for the given {@link AwContents}. This checks the return value of
+     * {@link AwCookieManager#getAcceptThirdPartyCookies}. This also checks the value of {@link
+     * AwCookieManager#acceptCookie}, since it doesn't make sense to turn on third-party cookies if
+     * all cookies have been blocked.
+     *
+     * @param awContents the AwContents for which to allow third-party cookies.
+     * @throws IllegalStateException if cookies are already blocked globally.
+     */
+    private void allowThirdPartyCookies(AwContents awContents) throws Exception {
+        if (!mCookieManager.acceptCookie()) {
+            throw new IllegalStateException("It doesn't make sense to allow third-party cookies if "
+                    + "cookies have already been globally blocked.");
+        }
+        awContents.getSettings().setAcceptThirdPartyCookies(true);
+        String msg = "getAcceptThirdPartyCookies() should return true after "
+                + "setAcceptThirdPartyCookies(true)";
+        Assert.assertTrue(msg, awContents.getSettings().getAcceptThirdPartyCookies());
+    }
+
+    /**
+     * Block third-party cookies for the given {@link AwContents}. This checks the return value of
+     * {@link AwCookieManager#getAcceptThirdPartyCookies}.
+     *
+     * @param awContents the AwContents for which to block third-party cookies.
+     */
+    private void blockThirdPartyCookies(AwContents awContents) throws Exception {
+        awContents.getSettings().setAcceptThirdPartyCookies(false);
+        String msg = "getAcceptThirdPartyCookies() should return false after "
+                + "setAcceptThirdPartyCookies(false)";
+        Assert.assertFalse(msg, awContents.getSettings().getAcceptThirdPartyCookies());
+    }
+
+    /**
+     * Allow first-party cookies globally. This affects all {@link AwContents}, and this does not
+     * affect the third-party cookie settings for any {@link AwContents}. This checks the return
+     * value of {@link AwCookieManager#acceptCookie}.
+     */
+    private void allowFirstPartyCookies() throws Exception {
+        mCookieManager.setAcceptCookie(true);
+        String msg = "acceptCookie() should return true after setAcceptCookie(true)";
+        Assert.assertTrue(msg, mCookieManager.acceptCookie());
+    }
+
+    /**
+     * Block all cookies for all {@link AwContents}. This blocks both first-party and third-party
+     * cookies. This checks the return value of {@link AwCookieManager#acceptCookie}.
+     */
+    private void blockAllCookies() throws Exception {
+        mCookieManager.setAcceptCookie(false);
+        String msg = "acceptCookie() should return false after setAcceptCookie(false)";
+        Assert.assertFalse(msg, mCookieManager.acceptCookie());
+    }
 }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 276d370..7e4acc4 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1407,10 +1407,13 @@
     ":dbus_service_files",
   ]
 
-  # Ash should not depend upon content at all.
   assert_no_deps = [
+    # Ash should not depend upon content at all.
     "//content/public/browser",
     "//content/public/common",
+
+    # //ui/base/idle depends on SessionManagerClient so disallow it.
+    "//ui/base/idle",
   ]
 
   allow_circular_includes_from = [
diff --git a/ash/DEPS b/ash/DEPS
index 7b40fb2..029e03c 100644
--- a/ash/DEPS
+++ b/ash/DEPS
@@ -62,9 +62,8 @@
   "+chromeos/dbus/dbus_thread_manager.h",
   "+chromeos/dbus/fake_power_manager_client.h",
   "+chromeos/dbus/hammerd",
+  "+chromeos/dbus/power",
   "+chromeos/dbus/power_manager",
-  "+chromeos/dbus/power_manager_client.h",
-  "+chromeos/dbus/power_policy_controller.h",
   "+chromeos/dbus/shill_device_client.h",
   "+chromeos/dbus/system_clock",
   # TODO(jamescook): Eliminate this. http://crbug.com/644355
@@ -77,6 +76,9 @@
   "+chromeos/strings",
   "+chromeos/system",
 
+  # ui/base/idle depends on SessionManagerClient so disallow it.
+  "-ui/base/idle"
+
   # InputMethodManager lives in the browser process. Use ImeController.
   "-ui/base/ime/chromeos/input_method_manager.h"
 
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index a4e9835..e47e4fe1 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -74,7 +74,7 @@
 #include "base/system/sys_info.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/user_manager/user_type.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/accelerators/accelerator_manager.h"
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc
index 2486a75..59210e29 100644
--- a/ash/accessibility/accessibility_controller_unittest.cc
+++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -19,7 +19,7 @@
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/prefs/pref_service.h"
 #include "ui/keyboard/keyboard_util.h"
 #include "ui/message_center/message_center.h"
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc
index 00676b51..e2df65f 100644
--- a/ash/app_list/views/app_list_item_view.cc
+++ b/ash/app_list/views/app_list_item_view.cc
@@ -713,17 +713,16 @@
     Button::OnGestureEvent(event);
 }
 
-bool AppListItemView::GetTooltipText(const gfx::Point& p,
-                                     base::string16* tooltip) const {
+base::string16 AppListItemView::GetTooltipText(const gfx::Point& p) const {
   // Use the label to generate a tooltip, so that it will consider its text
   // truncation in making the tooltip. We do not want the label itself to have a
   // tooltip, so we only temporarily enable it to get the tooltip text from the
   // label, then disable it again.
   title_->SetHandlesTooltips(true);
   title_->SetTooltipText(tooltip_text_);
-  bool handled = title_->GetTooltipText(p, tooltip);
+  base::string16 tooltip = title_->GetTooltipText(p);
   title_->SetHandlesTooltips(false);
-  return handled;
+  return tooltip;
 }
 
 void AppListItemView::OnDraggedViewEnter() {
diff --git a/ash/app_list/views/app_list_item_view.h b/ash/app_list/views/app_list_item_view.h
index e2dba2e8..c647b23a 100644
--- a/ash/app_list/views/app_list_item_view.h
+++ b/ash/app_list/views/app_list_item_view.h
@@ -111,8 +111,7 @@
   void OnGestureEvent(ui::GestureEvent* event) override;
 
   // views::View overrides:
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
 
   // When a dragged view enters this view, a preview circle is shown for
   // non-folder item while the icon is enlarged for folder item. When a
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc
index eae815d..36fd66a3 100644
--- a/ash/app_list/views/apps_grid_view_unittest.cc
+++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -417,14 +417,12 @@
   AppListItem* item = model_->CreateAndAddItem("Item with short name");
   model_->SetItemNameAndShortName(item, expected_tooltip, expected_text);
 
-  base::string16 actual_tooltip;
   AppListItemView* item_view = GetItemViewAt(0);
   ASSERT_TRUE(item_view);
   const views::Label* title_label = item_view->title();
-  EXPECT_TRUE(item_view->GetTooltipText(title_label->bounds().CenterPoint(),
-                                        &actual_tooltip));
-  EXPECT_EQ(expected_tooltip, base::UTF16ToUTF8(actual_tooltip));
-  EXPECT_EQ(expected_text, base::UTF16ToUTF8(title_label->text()));
+  EXPECT_EQ(base::ASCIIToUTF16(expected_tooltip),
+            item_view->GetTooltipText(title_label->bounds().CenterPoint()));
+  EXPECT_EQ(base::ASCIIToUTF16(expected_text), title_label->text());
 }
 
 TEST_F(AppsGridViewTest, ItemLabelNoShortName) {
@@ -434,13 +432,12 @@
   AppListItem* item = model_->CreateAndAddItem(title);
   model_->SetItemNameAndShortName(item, title, "");
 
-  base::string16 actual_tooltip;
   AppListItemView* item_view = GetItemViewAt(0);
   ASSERT_TRUE(item_view);
   const views::Label* title_label = item_view->title();
-  EXPECT_FALSE(title_label->GetTooltipText(title_label->bounds().CenterPoint(),
-                                           &actual_tooltip));
-  EXPECT_EQ(title, base::UTF16ToUTF8(title_label->text()));
+  EXPECT_TRUE(
+      title_label->GetTooltipText(title_label->bounds().CenterPoint()).empty());
+  EXPECT_EQ(base::ASCIIToUTF16(title), title_label->text());
 }
 
 TEST_P(AppsGridViewTest, ScrollSequenceHandledByAppListView) {
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc
index 306d08d..ca342bb2 100644
--- a/ash/app_list/views/search_result_tile_item_view.cc
+++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -607,16 +607,16 @@
                    AppListConfig::instance().search_tile_height());
 }
 
-bool SearchResultTileItemView::GetTooltipText(const gfx::Point& p,
-                                              base::string16* tooltip) const {
+base::string16 SearchResultTileItemView::GetTooltipText(
+    const gfx::Point& p) const {
   // Use the label to generate a tooltip, so that it will consider its text
   // truncation in making the tooltip. We do not want the label itself to have a
   // tooltip, so we only temporarily enable it to get the tooltip text from the
   // label, then disable it again.
   title_->SetHandlesTooltips(true);
-  bool handled = title_->GetTooltipText(p, tooltip);
+  base::string16 tooltip = title_->GetTooltipText(p);
   title_->SetHandlesTooltips(false);
-  return handled;
+  return tooltip;
 }
 
 }  // namespace app_list
diff --git a/ash/app_list/views/search_result_tile_item_view.h b/ash/app_list/views/search_result_tile_item_view.h
index 52139ae..c34fbfe 100644
--- a/ash/app_list/views/search_result_tile_item_view.h
+++ b/ash/app_list/views/search_result_tile_item_view.h
@@ -100,8 +100,7 @@
   void Layout() override;
   const char* GetClassName() const override;
   gfx::Size CalculatePreferredSize() const override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
 
   AppListViewDelegate* const view_delegate_;           // Owned by AppListView.
   PaginationModel* const pagination_model_;            // Owned by AppsGridView.
diff --git a/ash/ash_service.cc b/ash/ash_service.cc
index ad2fbb32..89bcc69 100644
--- a/ash/ash_service.cc
+++ b/ash/ash_service.cc
@@ -18,7 +18,7 @@
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/hammerd/hammerd_client.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/system_clock/system_clock_client.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_handler.h"
@@ -162,9 +162,17 @@
 
   // TODO(jamescook): Initialize real audio handler.
   chromeos::CrasAudioHandler::InitializeForTesting();
-  chromeos::HammerdClient::Initialize(bus);
+
+  // TODO(estade/stevenjb): Modify PowerManagerClient to use InitializeFake.
   chromeos::PowerManagerClient::Initialize(bus);
-  chromeos::SystemClockClient::Initialize(bus);
+
+  if (bus) {
+    chromeos::HammerdClient::Initialize(bus);
+    chromeos::SystemClockClient::Initialize(bus);
+  } else {
+    chromeos::HammerdClient::InitializeFake();
+    chromeos::SystemClockClient::InitializeFake();
+  }
 
   chromeos::PowerPolicyController::Initialize(
       chromeos::PowerManagerClient::Get());
diff --git a/ash/dbus/DEPS b/ash/dbus/DEPS
index c4c77ff..5ea2f34 100644
--- a/ash/dbus/DEPS
+++ b/ash/dbus/DEPS
@@ -1,6 +1,4 @@
 include_rules = [
   "+chromeos/dbus/services",
-  # TODO(stevenjb): Eliminate this, https://crbug.com/644350.
-  "+chromeos/dbus/session_manager_client.h",
   "+dbus",
 ]
diff --git a/ash/dbus/ash_dbus_services.cc b/ash/dbus/ash_dbus_services.cc
index e2590dd..05ed967 100644
--- a/ash/dbus/ash_dbus_services.cc
+++ b/ash/dbus/ash_dbus_services.cc
@@ -10,7 +10,6 @@
 #include "ash/shell.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/services/cros_dbus_service.h"
-#include "chromeos/dbus/session_manager_client.h"
 #include "dbus/object_path.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
@@ -41,12 +40,6 @@
           std::make_unique<UrlHandlerServiceProvider>()));
 }
 
-void AshDBusServices::EmitAshInitialized() {
-  chromeos::DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->EmitAshInitialized();
-}
-
 AshDBusServices::~AshDBusServices() {
   display_service_.reset();
   liveness_service_.reset();
diff --git a/ash/dbus/ash_dbus_services.h b/ash/dbus/ash_dbus_services.h
index f0408b8d..3e39e10 100644
--- a/ash/dbus/ash_dbus_services.h
+++ b/ash/dbus/ash_dbus_services.h
@@ -22,10 +22,6 @@
   AshDBusServices();
   ~AshDBusServices();
 
-  // Emit ash-initialized upstart signal to start Chrome OS tasks that expect
-  // that ash is listening to D-Bus signals they emit.
-  void EmitAshInitialized();
-
  private:
   std::unique_ptr<chromeos::CrosDBusService> display_service_;
   std::unique_ptr<chromeos::CrosDBusService> liveness_service_;
diff --git a/ash/detachable_base/detachable_base_handler.h b/ash/detachable_base/detachable_base_handler.h
index a8d482f..b7a9884 100644
--- a/ash/detachable_base/detachable_base_handler.h
+++ b/ash/detachable_base/detachable_base_handler.h
@@ -19,7 +19,7 @@
 #include "base/optional.h"
 #include "base/scoped_observer.h"
 #include "chromeos/dbus/hammerd/hammerd_client.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 class PrefRegistrySimple;
 class PrefService;
diff --git a/ash/detachable_base/detachable_base_handler_unittest.cc b/ash/detachable_base/detachable_base_handler_unittest.cc
index 12c736ca..1edee9a 100644
--- a/ash/detachable_base/detachable_base_handler_unittest.cc
+++ b/ash/detachable_base/detachable_base_handler_unittest.cc
@@ -14,8 +14,8 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
 #include "chromeos/dbus/hammerd/fake_hammerd_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/account_id/account_id.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -85,7 +85,7 @@
 
   // testing::Test:
   void SetUp() override {
-    chromeos::HammerdClient::Initialize(nullptr /* bus */);
+    chromeos::HammerdClient::InitializeFake();
     hammerd_client_ = chromeos::FakeHammerdClient::Get();
 
     chromeos::PowerManagerClient::Initialize();
diff --git a/ash/detachable_base/detachable_base_notification_controller_unittest.cc b/ash/detachable_base/detachable_base_notification_controller_unittest.cc
index af48a9e..805646f 100644
--- a/ash/detachable_base/detachable_base_notification_controller_unittest.cc
+++ b/ash/detachable_base/detachable_base_notification_controller_unittest.cc
@@ -14,7 +14,7 @@
 #include "ash/test/ash_test_base.h"
 #include "base/macros.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/user_type.h"
 #include "ui/message_center/message_center.h"
diff --git a/ash/display/projecting_observer.cc b/ash/display/projecting_observer.cc
index a27952a7..fc3f509 100644
--- a/ash/display/projecting_observer.cc
+++ b/ash/display/projecting_observer.cc
@@ -7,7 +7,7 @@
 #include "ash/shell.h"
 #include "base/logging.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/display/types/display_snapshot.h"
 
 namespace ash {
diff --git a/ash/display/projecting_observer_unittest.cc b/ash/display/projecting_observer_unittest.cc
index bdae9f40..543f4ff 100644
--- a/ash/display/projecting_observer_unittest.cc
+++ b/ash/display/projecting_observer_unittest.cc
@@ -7,7 +7,7 @@
 #include <memory>
 #include <vector>
 
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/manager/fake_display_snapshot.h"
 
diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc
index 8431fa1..33ea235c 100644
--- a/ash/extended_desktop_unittest.cc
+++ b/ash/extended_desktop_unittest.cc
@@ -732,7 +732,8 @@
 }
 
 TEST_F(ExtendedDesktopTest, OpenSystemTray) {
-  UpdateDisplay("500x600,600x400");
+  // Two displays side by side and both are high enough for tray bubble.
+  UpdateDisplay("500x600,600x700");
   ASSERT_FALSE(IsBubbleShown());
 
   ui::test::EventGenerator* event_generator = GetEventGenerator();
@@ -743,9 +744,17 @@
   event_generator->ClickLeftButton();
   EXPECT_TRUE(IsBubbleShown());
 
+  // Verifies that the bubble is within the primary display.
+  const gfx::Rect& primary_display_bounds = GetPrimaryDisplay().bounds();
+  const gfx::Rect& tray_bubble_bounds =
+      GetPrimaryUnifiedSystemTray()->GetBubbleBoundsInScreen();
+  EXPECT_TRUE(primary_display_bounds.Contains(tray_bubble_bounds))
+      << "primary display bounds=" << primary_display_bounds.ToString()
+      << ", tray bubble bounds=" << tray_bubble_bounds.ToString();
+
   UpdateDisplay("500x600");
   EXPECT_TRUE(IsBubbleShown());
-  UpdateDisplay("500x600,600x400");
+  UpdateDisplay("500x600,600x700");
   EXPECT_TRUE(IsBubbleShown());
 
   // Closes the tray and again makes sure that adding/removing displays doesn't
@@ -757,7 +766,7 @@
 
   UpdateDisplay("500x600");
   EXPECT_FALSE(IsBubbleShown());
-  UpdateDisplay("500x600,600x400");
+  UpdateDisplay("500x600,600x700");
   EXPECT_FALSE(IsBubbleShown());
 }
 
diff --git a/ash/host/ash_window_tree_host_init_params.h b/ash/host/ash_window_tree_host_init_params.h
index c68d8fee..07006e03 100644
--- a/ash/host/ash_window_tree_host_init_params.h
+++ b/ash/host/ash_window_tree_host_init_params.h
@@ -23,7 +23,6 @@
   bool mirroring_unified = false;
   int64_t display_id = 0;
   float device_scale_factor = 0.0f;
-  float ui_scale_factor = 0.0f;
 };
 
 }  // namespace ash
diff --git a/ash/lock_screen_action/lock_screen_note_display_state_handler_unittest.cc b/ash/lock_screen_action/lock_screen_note_display_state_handler_unittest.cc
index 398f072..c21de05 100644
--- a/ash/lock_screen_action/lock_screen_note_display_state_handler_unittest.cc
+++ b/ash/lock_screen_action/lock_screen_note_display_state_handler_unittest.cc
@@ -22,7 +22,7 @@
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "services/ws/public/cpp/input_devices/input_device_client_test_api.h"
 #include "ui/events/devices/stylus_state.h"
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 4d0a6ed..65fd9ff 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -417,13 +417,17 @@
     observer.SetAvatarForUser(account_id, avatar);
 }
 
-void LoginScreenController::SetAuthEnabledForUser(
+void LoginScreenController::EnableAuthForUser(const AccountId& account_id) {
+  if (DataDispatcher())
+    DataDispatcher()->EnableAuthForUser(account_id);
+}
+
+void LoginScreenController::DisableAuthForUser(
     const AccountId& account_id,
-    bool is_enabled,
-    base::Optional<base::Time> auth_reenabled_time) {
+    ash::mojom::AuthDisabledDataPtr auth_disabled_data) {
   if (DataDispatcher()) {
-    DataDispatcher()->SetAuthEnabledForUser(account_id, is_enabled,
-                                            auth_reenabled_time);
+    DataDispatcher()->DisableAuthForUser(account_id,
+                                         std::move(auth_disabled_data));
   }
 }
 
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h
index ffba8952..bce52a0f 100644
--- a/ash/login/login_screen_controller.h
+++ b/ash/login/login_screen_controller.h
@@ -138,10 +138,10 @@
                                    bool successful) override;
   void SetAvatarForUser(const AccountId& account_id,
                         mojom::UserAvatarPtr avatar) override;
-  void SetAuthEnabledForUser(
+  void EnableAuthForUser(const AccountId& account_id) override;
+  void DisableAuthForUser(
       const AccountId& account_id,
-      bool is_enabled,
-      base::Optional<base::Time> auth_reenabled_time) override;
+      ash::mojom::AuthDisabledDataPtr auth_disabled_data) override;
   void HandleFocusLeavingLockScreenApps(bool reverse) override;
   void SetSystemInfo(bool show_if_hidden,
                      const std::string& os_version_label_text,
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index a858769..47946d7f 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -766,31 +766,42 @@
   big_view->auth_user()->NotifyFingerprintAuthResult(success);
 }
 
-void LockContentsView::OnAuthEnabledForUserChanged(
-    const AccountId& user,
-    bool enabled,
-    const base::Optional<base::Time>& auth_reenabled_time) {
+void LockContentsView::OnAuthEnabledForUser(const AccountId& user) {
   LockContentsView::UserState* state = FindStateForUser(user);
   if (!state) {
-    LOG(ERROR) << "Unable to find user when changing auth enabled state to "
-               << enabled;
+    LOG(ERROR) << "Unable to find user when enabling auth.";
     return;
   }
 
-  DCHECK(enabled || auth_reenabled_time);
-  state->disable_auth = !enabled;
+  state->disable_auth = false;
   disable_lock_screen_note_ = state->disable_auth;
   OnLockScreenNoteStateChanged(
-      disable_lock_screen_note_
-          ? mojom::TrayActionState::kNotAvailable
-          : Shell::Get()->tray_action()->GetLockScreenNoteState());
+      Shell::Get()->tray_action()->GetLockScreenNoteState());
+
+  LoginBigUserView* big_user =
+      TryToFindBigUser(user, true /*require_auth_active*/);
+  if (big_user && big_user->auth_user())
+    LayoutAuth(big_user, nullptr /*opt_to_hide*/, true /*animate*/);
+}
+
+void LockContentsView::OnAuthDisabledForUser(
+    const AccountId& user,
+    const ash::mojom::AuthDisabledDataPtr& auth_disabled_data) {
+  LockContentsView::UserState* state = FindStateForUser(user);
+  if (!state) {
+    LOG(ERROR) << "Unable to find user when disabling auth";
+    return;
+  }
+
+  state->disable_auth = true;
+  disable_lock_screen_note_ = state->disable_auth;
+  OnLockScreenNoteStateChanged(mojom::TrayActionState::kNotAvailable);
 
   LoginBigUserView* big_user =
       TryToFindBigUser(user, true /*require_auth_active*/);
   if (big_user && big_user->auth_user()) {
     LayoutAuth(big_user, nullptr /*opt_to_hide*/, true /*animate*/);
-    if (auth_reenabled_time)
-      big_user->auth_user()->SetAuthReenabledTime(auth_reenabled_time.value());
+    big_user->auth_user()->SetAuthDisabledMessage(auth_disabled_data);
   }
 }
 
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index c5435d7..42bbbbd 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -20,12 +20,13 @@
 #include "ash/login/ui/login_tooltip_view.h"
 #include "ash/login/ui/non_accessible_view.h"
 #include "ash/public/cpp/system_tray_focus_observer.h"
+#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/session/session_observer.h"
 #include "base/macros.h"
 #include "base/optional.h"
 #include "base/scoped_observer.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "ui/display/display_observer.h"
 #include "ui/display/screen.h"
 #include "ui/keyboard/keyboard_controller.h"
@@ -148,10 +149,10 @@
                                  mojom::FingerprintState state) override;
   void OnFingerprintAuthResult(const AccountId& account_id,
                                bool success) override;
-  void OnAuthEnabledForUserChanged(
+  void OnAuthEnabledForUser(const AccountId& user) override;
+  void OnAuthDisabledForUser(
       const AccountId& user,
-      bool enabled,
-      const base::Optional<base::Time>& auth_reenabled_time) override;
+      const ash::mojom::AuthDisabledDataPtr& auth_disabled_data) override;
   void OnLockScreenNoteStateChanged(mojom::TrayActionState state) override;
   void OnTapToUnlockEnabledForUserChanged(const AccountId& user,
                                           bool enabled) override;
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc
index 453e57e..c534740 100644
--- a/ash/login/ui/lock_contents_view_unittest.cc
+++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -25,6 +25,7 @@
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/scrollable_users_list_view.h"
 #include "ash/login/ui/views_utils.h"
+#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/public/interfaces/tray_action.mojom.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
@@ -35,7 +36,7 @@
 #include "ash/tray_action/tray_action.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/manager/display_manager.h"
@@ -1764,23 +1765,28 @@
   EXPECT_FALSE(pin_view->visible());
   EXPECT_FALSE(disabled_auth_message->visible());
   // Setting auth disabled will hide the password field and show the message.
-  DataDispatcher()->SetAuthEnabledForUser(
-      kFirstUserAccountId, false,
-      base::Time::Now() + base::TimeDelta::FromHours(8));
+  DataDispatcher()->DisableAuthForUser(
+      kFirstUserAccountId,
+      ash::mojom::AuthDisabledData::New(
+          ash::mojom::AuthDisabledReason::TIME_WINDOW_LIMIT,
+          base::Time::Now() + base::TimeDelta::FromHours(8),
+          base::TimeDelta::FromHours(1)));
   EXPECT_FALSE(password_view->visible());
   EXPECT_FALSE(pin_view->visible());
   EXPECT_TRUE(disabled_auth_message->visible());
   // Setting auth enabled will hide the message and show the password field.
-  DataDispatcher()->SetAuthEnabledForUser(kFirstUserAccountId, true,
-                                          base::nullopt);
+  DataDispatcher()->EnableAuthForUser(kFirstUserAccountId);
   EXPECT_TRUE(password_view->visible());
   EXPECT_FALSE(pin_view->visible());
   EXPECT_FALSE(disabled_auth_message->visible());
 
   // Set auth disabled again.
-  DataDispatcher()->SetAuthEnabledForUser(
-      kFirstUserAccountId, false,
-      base::Time::Now() + base::TimeDelta::FromHours(8));
+  DataDispatcher()->DisableAuthForUser(
+      kFirstUserAccountId,
+      ash::mojom::AuthDisabledData::New(
+          ash::mojom::AuthDisabledReason::TIME_WINDOW_LIMIT,
+          base::Time::Now() + base::TimeDelta::FromHours(8),
+          base::TimeDelta::FromHours(1)));
   EXPECT_FALSE(password_view->visible());
   EXPECT_FALSE(pin_view->visible());
   EXPECT_TRUE(disabled_auth_message->visible());
@@ -1790,8 +1796,7 @@
   EXPECT_FALSE(pin_view->visible());
   EXPECT_TRUE(disabled_auth_message->visible());
   // Set auth enabled again. Both password field and PIN keyboard are shown.
-  DataDispatcher()->SetAuthEnabledForUser(kFirstUserAccountId, true,
-                                          base::nullopt);
+  DataDispatcher()->EnableAuthForUser(kFirstUserAccountId);
   EXPECT_TRUE(password_view->visible());
   EXPECT_TRUE(pin_view->visible());
   EXPECT_FALSE(disabled_auth_message->visible());
@@ -1817,25 +1822,29 @@
 
   EXPECT_TRUE(note_action_button->visible());
   // Setting auth disabled hides the note action button.
-  DataDispatcher()->SetAuthEnabledForUser(
-      kFirstUserAccountId, false,
-      base::Time::Now() + base::TimeDelta::FromHours(8));
+  DataDispatcher()->DisableAuthForUser(
+      kFirstUserAccountId,
+      ash::mojom::AuthDisabledData::New(
+          ash::mojom::AuthDisabledReason::TIME_WINDOW_LIMIT,
+          base::Time::Now() + base::TimeDelta::FromHours(8),
+          base::TimeDelta::FromHours(1)));
   EXPECT_FALSE(note_action_button->visible());
   // Setting auth enabled shows the note action button.
-  DataDispatcher()->SetAuthEnabledForUser(kFirstUserAccountId, true,
-                                          base::nullopt);
+  DataDispatcher()->EnableAuthForUser(kFirstUserAccountId);
   EXPECT_TRUE(note_action_button->visible());
 
   // Set auth disabled again.
-  DataDispatcher()->SetAuthEnabledForUser(
-      kFirstUserAccountId, false,
-      base::Time::Now() + base::TimeDelta::FromHours(8));
+  DataDispatcher()->DisableAuthForUser(
+      kFirstUserAccountId,
+      ash::mojom::AuthDisabledData::New(
+          ash::mojom::AuthDisabledReason::TIME_WINDOW_LIMIT,
+          base::Time::Now() + base::TimeDelta::FromHours(8),
+          base::TimeDelta::FromHours(1)));
   EXPECT_FALSE(note_action_button->visible());
   // Set the lock screen note state to |kNotAvailable| while the note action
   // button is hidden.
   tray_action->UpdateLockScreenNoteState(mojom::TrayActionState::kNotAvailable);
-  DataDispatcher()->SetAuthEnabledForUser(kFirstUserAccountId, true,
-                                          base::nullopt);
+  DataDispatcher()->EnableAuthForUser(kFirstUserAccountId);
   // The note action button remains hidden after setting auth enabled.
   EXPECT_FALSE(note_action_button->visible());
 }
@@ -1857,9 +1866,12 @@
   LoginUserView* user_view = auth_test_api.user_view();
 
   // The message is visible after disabling auth and it receives initial focus.
-  DataDispatcher()->SetAuthEnabledForUser(
-      kFirstUserAccountId, false,
-      base::Time::Now() + base::TimeDelta::FromHours(8));
+  DataDispatcher()->DisableAuthForUser(
+      kFirstUserAccountId,
+      ash::mojom::AuthDisabledData::New(
+          ash::mojom::AuthDisabledReason::TIME_WINDOW_LIMIT,
+          base::Time::Now() + base::TimeDelta::FromHours(8),
+          base::TimeDelta::FromHours(1)));
   EXPECT_TRUE(disabled_auth_message->visible());
   EXPECT_TRUE(HasFocusInAnyChildView(disabled_auth_message));
   // Tabbing from the message will move focus to the user view.
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc
index c6f55348..491f158 100644
--- a/ash/login/ui/lock_debug_view.cc
+++ b/ash/login/ui/lock_debug_view.cc
@@ -350,15 +350,39 @@
         debug_users_[user_index].account_id);
   }
 
+  // Updates |auth_disabled_reason_| with the next enum value in a cyclic
+  // manner.
+  void UpdateAuthDisabledReason() {
+    switch (auth_disabled_reason_) {
+      case mojom::AuthDisabledReason::TIME_LIMIT_OVERRIDE:
+        auth_disabled_reason_ = mojom::AuthDisabledReason::TIME_USAGE_LIMIT;
+        break;
+      case mojom::AuthDisabledReason::TIME_USAGE_LIMIT:
+        auth_disabled_reason_ = mojom::AuthDisabledReason::TIME_WINDOW_LIMIT;
+        break;
+      case mojom::AuthDisabledReason::TIME_WINDOW_LIMIT:
+        auth_disabled_reason_ = mojom::AuthDisabledReason::TIME_LIMIT_OVERRIDE;
+        break;
+    }
+  }
+
   // Toggle the unlock allowed state for the user at |user_index|.
   void ToggleAuthEnabledForUserIndex(size_t user_index) {
     DCHECK(user_index >= 0 && user_index < debug_users_.size());
     UserMetadata& user = debug_users_[user_index];
     user.enable_auth = !user.enable_auth;
-    debug_dispatcher_.SetAuthEnabledForUser(
-        user.account_id, user.enable_auth,
-        base::Time::Now() + base::TimeDelta::FromHours(user_index) +
-            base::TimeDelta::FromHours(8));
+    if (user.enable_auth) {
+      debug_dispatcher_.EnableAuthForUser(user.account_id);
+    } else {
+      debug_dispatcher_.DisableAuthForUser(
+          user.account_id,
+          mojom::AuthDisabledData::New(
+              auth_disabled_reason_,
+              base::Time::Now() + base::TimeDelta::FromHours(user_index) +
+                  base::TimeDelta::FromHours(8),
+              base::TimeDelta::FromMinutes(15)));
+      UpdateAuthDisabledReason();
+    }
   }
 
   // Convert user type to regular user or public account for the user at
@@ -502,6 +526,11 @@
   // Called when a new user list has been received.
   base::RepeatingClosure on_users_received_;
 
+  // When auth is disabled, this property is used to define the reason, which
+  // customizes the UI accordingly.
+  mojom::AuthDisabledReason auth_disabled_reason_ =
+      mojom::AuthDisabledReason::TIME_LIMIT_OVERRIDE;
+
   DISALLOW_COPY_AND_ASSIGN(DebugDataDispatcherTransformer);
 };
 
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc
index 1900b679..6e092a7 100644
--- a/ash/login/ui/login_auth_user_view.cc
+++ b/ash/login/ui/login_auth_user_view.cc
@@ -26,6 +26,7 @@
 #include "ash/system/toast/toast_manager.h"
 #include "ash/wallpaper/wallpaper_controller.h"
 #include "base/bind.h"
+#include "base/i18n/time_formatting.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/timer/timer.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -42,6 +43,7 @@
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/interpolated_transform.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/vector_icon_types.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/button/label_button.h"
@@ -79,6 +81,9 @@
 constexpr SkColor kDisabledAuthMessageBubbleColor =
     SkColorSetRGB(0x20, 0x21, 0x24);
 
+// Date time format containing only the day of the week, for example: "Tuesday".
+constexpr char kDayOfWeekOnlyTimeFormat[] = "EEEE";
+
 constexpr int kFingerprintIconSizeDp = 32;
 constexpr int kResetToDefaultIconDelayMs = 1300;
 constexpr int kFingerprintIconTopSpacingDp = 20;
@@ -88,8 +93,8 @@
 constexpr int kFingerprintFailedAnimationDurationMs = 700;
 constexpr int kFingerprintFailedAnimationNumFrames = 45;
 
-constexpr int kDisabledAuthMessageVerticalBorderDp = 14;
-constexpr int kDisabledAuthMessageHorizontalBorderDp = 0;
+constexpr int kDisabledAuthMessageVerticalBorderDp = 16;
+constexpr int kDisabledAuthMessageHorizontalBorderDp = 16;
 constexpr int kDisabledAuthMessageChildrenSpacingDp = 4;
 constexpr int kDisabledAuthMessageWidthDp = 204;
 constexpr int kDisabledAuthMessageHeightDp = 98;
@@ -218,6 +223,101 @@
   DISALLOW_COPY_AND_ASSIGN(FingerprintLabel);
 };
 
+// The content needed to render the disabled auth message view.
+struct LockScreenMessage {
+  base::string16 title;
+  base::string16 content;
+  const gfx::VectorIcon* icon;
+};
+
+// Returns the message used when the device was locked due to a time window
+// limit.
+LockScreenMessage GetWindowLimitMessage(const base::Time& unlock_time) {
+  LockScreenMessage message;
+  message.title = l10n_util::GetStringUTF16(IDS_ASH_LOGIN_TIME_FOR_BED_MESSAGE);
+
+  base::Time local_midnight = base::Time::Now().LocalMidnight();
+  const std::string time_of_day = TimeOfDay::FromTime(unlock_time).ToString();
+
+  if (unlock_time < local_midnight + base::TimeDelta::FromDays(1)) {
+    // Unlock time is today.
+    message.content = l10n_util::GetStringFUTF16(
+        IDS_ASH_LOGIN_COME_BACK_MESSAGE, base::UTF8ToUTF16(time_of_day));
+  } else if (unlock_time < local_midnight + base::TimeDelta::FromDays(2)) {
+    // Unlock time is tomorrow.
+    message.content =
+        l10n_util::GetStringFUTF16(IDS_ASH_LOGIN_COME_BACK_TOMORROW_MESSAGE,
+                                   base::UTF8ToUTF16(time_of_day));
+  } else {
+    message.content = l10n_util::GetStringFUTF16(
+        IDS_ASH_LOGIN_COME_BACK_DAY_OF_WEEK_MESSAGE,
+        base::TimeFormatWithPattern(unlock_time, kDayOfWeekOnlyTimeFormat),
+        base::UTF8ToUTF16(time_of_day));
+  }
+  message.icon = &kLockScreenTimeLimitMoonIcon;
+  return message;
+}
+
+// Returns the message used when the device was locked due to a time usage
+// limit.
+LockScreenMessage GetUsageLimitMessage(const base::TimeDelta& used_time) {
+  LockScreenMessage message;
+
+  // 1 minute is used instead of 0, because the device is used for a few
+  // milliseconds before locking.
+  if (used_time < base::TimeDelta::FromMinutes(1)) {
+    // The device was locked all day.
+    message.title = l10n_util::GetStringUTF16(IDS_ASH_LOGIN_TAKE_BREAK_MESSAGE);
+    message.content =
+        l10n_util::GetStringUTF16(IDS_ASH_LOGIN_LOCKED_ALL_DAY_MESSAGE);
+  } else {
+    // The usage limit is over.
+    message.title = l10n_util::GetStringUTF16(IDS_ASH_LOGIN_TIME_IS_UP_MESSAGE);
+
+    // TODO(933973): Stop displaying the hours part of the string when duration
+    // is less than 1 hour. Example: change "0 hours, 7 minutes" to "7 minutes".
+    base::string16 used_time_string;
+    if (!base::TimeDurationFormat(
+            used_time, base::DurationFormatWidth::DURATION_WIDTH_WIDE,
+            &used_time_string)) {
+      LOG(ERROR) << "Failed to generate time duration string.";
+      return message;
+    }
+
+    message.content = l10n_util::GetStringFUTF16(
+        IDS_ASH_LOGIN_SCREEN_TIME_USED_MESSAGE, used_time_string);
+  }
+  message.icon = &kLockScreenTimeLimitTimerIcon;
+  return message;
+}
+
+// Returns the message used when the device was locked due to a time limit
+// override.
+LockScreenMessage GetOverrideMessage() {
+  LockScreenMessage message;
+  message.title =
+      l10n_util::GetStringUTF16(IDS_ASH_LOGIN_TIME_FOR_A_BREAK_MESSAGE);
+  message.content =
+      l10n_util::GetStringUTF16(IDS_ASH_LOGIN_MANUAL_LOCK_MESSAGE);
+  message.icon = &kLockScreenTimeLimitLockIcon;
+  return message;
+}
+
+LockScreenMessage GetLockScreenMessage(mojom::AuthDisabledReason lock_reason,
+                                       const base::Time& unlock_time,
+                                       const base::TimeDelta& used_time) {
+  switch (lock_reason) {
+    case mojom::AuthDisabledReason::TIME_WINDOW_LIMIT:
+      return GetWindowLimitMessage(unlock_time);
+    case mojom::AuthDisabledReason::TIME_USAGE_LIMIT:
+      return GetUsageLimitMessage(used_time);
+    case mojom::AuthDisabledReason::TIME_LIMIT_OVERRIDE:
+      return GetOverrideMessage();
+    default:
+      NOTREACHED();
+  }
+}
+
 }  // namespace
 
 // Consists of fingerprint icon view and a label.
@@ -351,12 +451,13 @@
     SetPreferredSize(
         gfx::Size(kDisabledAuthMessageWidthDp, kDisabledAuthMessageHeightDp));
     SetFocusBehavior(FocusBehavior::ALWAYS);
-    views::ImageView* alarm_clock_icon = new views::ImageView();
-    alarm_clock_icon->SetPreferredSize(gfx::Size(
-        kDisabledAuthMessageIconSizeDp, kDisabledAuthMessageIconSizeDp));
-    alarm_clock_icon->SetImage(
-        gfx::CreateVectorIcon(kLockScreenTimeLimitAlarmIcon, SK_ColorWHITE));
-    AddChildView(alarm_clock_icon);
+    message_icon_ = new views::ImageView();
+    message_icon_->SetPreferredSize(gfx::Size(kDisabledAuthMessageIconSizeDp,
+                                              kDisabledAuthMessageIconSizeDp));
+    message_icon_->SetImage(
+        gfx::CreateVectorIcon(kLockScreenTimeLimitMoonIcon,
+                              kDisabledAuthMessageIconSizeDp, SK_ColorWHITE));
+    AddChildView(message_icon_);
 
     auto decorate_label = [](views::Label* label) {
       label->SetSubpixelRenderingEnabled(false);
@@ -364,9 +465,9 @@
       label->SetEnabledColor(SK_ColorWHITE);
       label->SetFocusBehavior(FocusBehavior::ALWAYS);
     };
-    message_title_ = new views::Label(
-        l10n_util::GetStringUTF16(IDS_ASH_LOGIN_TAKE_BREAK_MESSAGE),
-        views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY);
+    message_title_ =
+        new views::Label(base::string16(), views::style::CONTEXT_LABEL,
+                         views::style::STYLE_PRIMARY);
     message_title_->SetFontList(
         gfx::FontList().Derive(kDisabledAuthMessageTitleFontSizeDeltaDp,
                                gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM));
@@ -380,18 +481,22 @@
         gfx::FontList().Derive(kDisabledAuthMessageContentsFontSizeDeltaDp,
                                gfx::Font::NORMAL, gfx::Font::Weight::NORMAL));
     decorate_label(message_contents_);
+    message_contents_->SetMultiLine(true);
     AddChildView(message_contents_);
   }
 
   ~DisabledAuthMessageView() override = default;
 
-  // Set the time when auth will be reenabled. It will be included in the
-  // message.
-  void SetAuthReenabledTime(const base::Time& auth_reenabled_time) {
-    const std::string time_of_day =
-        TimeOfDay::FromTime(auth_reenabled_time).ToString();
-    message_contents_->SetText(l10n_util::GetStringFUTF16(
-        IDS_ASH_LOGIN_COME_BACK_MESSAGE, base::UTF8ToUTF16(time_of_day)));
+  // Set the parameters needed to render the message.
+  void SetAuthDisabledMessage(
+      const ash::mojom::AuthDisabledDataPtr& auth_disabled_data) {
+    LockScreenMessage message = GetLockScreenMessage(
+        auth_disabled_data->reason, auth_disabled_data->auth_reenabled_time,
+        auth_disabled_data->device_used_time);
+    message_icon_->SetImage(gfx::CreateVectorIcon(
+        *message.icon, kDisabledAuthMessageIconSizeDp, SK_ColorWHITE));
+    message_title_->SetText(message.title);
+    message_contents_->SetText(message.content);
     Layout();
   }
 
@@ -415,6 +520,7 @@
  private:
   views::Label* message_title_;
   views::Label* message_contents_;
+  views::ImageView* message_icon_;
 
   DISALLOW_COPY_AND_ASSIGN(DisabledAuthMessageView);
 };
@@ -842,9 +948,10 @@
   fingerprint_view_->NotifyFingerprintAuthResult(success);
 }
 
-void LoginAuthUserView::SetAuthReenabledTime(
-    const base::Time& auth_reenabled_time) {
-  disabled_auth_message_->SetAuthReenabledTime(auth_reenabled_time);
+void LoginAuthUserView::SetAuthDisabledMessage(
+    const ash::mojom::AuthDisabledDataPtr& auth_disabled_data) {
+  disabled_auth_message_->SetAuthDisabledMessage(auth_disabled_data);
+  Layout();
 }
 
 const mojom::LoginUserInfoPtr& LoginAuthUserView::current_user() const {
diff --git a/ash/login/ui/login_auth_user_view.h b/ash/login/ui/login_auth_user_view.h
index 6db9cb6e..28cf0f1 100644
--- a/ash/login/ui/login_auth_user_view.h
+++ b/ash/login/ui/login_auth_user_view.h
@@ -12,12 +12,13 @@
 #include "ash/login/ui/login_password_view.h"
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/non_accessible_view.h"
+#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/public/interfaces/user_info.mojom.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/scoped_observer.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
 
@@ -127,9 +128,10 @@
   // Called to show a fingerprint authentication attempt result.
   void NotifyFingerprintAuthResult(bool success);
 
-  // Set the time when auth will be reenabled. It will be included in the
-  // message shown to user when auth method is |AUTH_DISABLED|.
-  void SetAuthReenabledTime(const base::Time& auth_reenabled_time);
+  // Set the parameters needed to render the message that is shown to user when
+  // auth method is |AUTH_DISABLED|.
+  void SetAuthDisabledMessage(
+      const ash::mojom::AuthDisabledDataPtr& auth_disabled_data);
 
   const mojom::LoginUserInfoPtr& current_user() const;
 
diff --git a/ash/login/ui/login_auth_user_view_unittest.cc b/ash/login/ui/login_auth_user_view_unittest.cc
index a1ae362..9ec94124 100644
--- a/ash/login/ui/login_auth_user_view_unittest.cc
+++ b/ash/login/ui/login_auth_user_view_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/test/event_generator.h"
diff --git a/ash/login/ui/login_data_dispatcher.cc b/ash/login/ui/login_data_dispatcher.cc
index 85366e1..375f0ab 100644
--- a/ash/login/ui/login_data_dispatcher.cc
+++ b/ash/login/ui/login_data_dispatcher.cc
@@ -23,10 +23,12 @@
     const AccountId& account_id,
     bool successful) {}
 
-void LoginDataDispatcher::Observer::OnAuthEnabledForUserChanged(
+void LoginDataDispatcher::Observer::OnAuthEnabledForUser(
+    const AccountId& user) {}
+
+void LoginDataDispatcher::Observer::OnAuthDisabledForUser(
     const AccountId& user,
-    bool enabled,
-    const base::Optional<base::Time>& auth_reenabled_time) {}
+    const mojom::AuthDisabledDataPtr& auth_disabled_data) {}
 
 void LoginDataDispatcher::Observer::OnTapToUnlockEnabledForUserChanged(
     const AccountId& user,
@@ -114,13 +116,16 @@
     observer.OnFingerprintAuthResult(account_id, successful);
 }
 
-void LoginDataDispatcher::SetAuthEnabledForUser(
+void LoginDataDispatcher::EnableAuthForUser(const AccountId& account_id) {
+  for (auto& observer : observers_)
+    observer.OnAuthEnabledForUser(account_id);
+}
+
+void LoginDataDispatcher::DisableAuthForUser(
     const AccountId& account_id,
-    bool is_enabled,
-    base::Optional<base::Time> auth_reenabled_time) {
+    ash::mojom::AuthDisabledDataPtr auth_disabled_data) {
   for (auto& observer : observers_) {
-    observer.OnAuthEnabledForUserChanged(account_id, is_enabled,
-                                         auth_reenabled_time);
+    observer.OnAuthDisabledForUser(account_id, auth_disabled_data);
   }
 }
 
diff --git a/ash/login/ui/login_data_dispatcher.h b/ash/login/ui/login_data_dispatcher.h
index dea9a9f..41dcdc4 100644
--- a/ash/login/ui/login_data_dispatcher.h
+++ b/ash/login/ui/login_data_dispatcher.h
@@ -11,6 +11,7 @@
 
 #include "ash/ash_export.h"
 #include "ash/detachable_base/detachable_base_pairing_status.h"
+#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/public/interfaces/login_user_info.mojom.h"
 #include "ash/public/interfaces/tray_action.mojom.h"
 #include "base/macros.h"
@@ -57,12 +58,15 @@
     virtual void OnFingerprintAuthResult(const AccountId& account_id,
                                          bool successful);
 
-    // Called when auth should be enabled or disabled for |user|. By default,
-    // auth should be enabled.
-    virtual void OnAuthEnabledForUserChanged(
+    // Called when auth should be enabled for |user|. By default, auth should be
+    // enabled.
+    virtual void OnAuthEnabledForUser(const AccountId& user);
+
+    // Called when auth should be disabled for |user|. By default, auth should
+    // be enabled.
+    virtual void OnAuthDisabledForUser(
         const AccountId& user,
-        bool enabled,
-        const base::Optional<base::Time>& auth_reenabled_time);
+        const ash::mojom::AuthDisabledDataPtr& auth_disabled_data);
 
     // Called when the given user can click their pod to unlock.
     virtual void OnTapToUnlockEnabledForUserChanged(const AccountId& user,
@@ -139,9 +143,9 @@
                            mojom::FingerprintState state);
   void NotifyFingerprintAuthResult(const AccountId& account_id,
                                    bool successful);
-  void SetAuthEnabledForUser(const AccountId& account_id,
-                             bool is_enabled,
-                             base::Optional<base::Time> auth_reenabled_time);
+  void EnableAuthForUser(const AccountId& account_id);
+  void DisableAuthForUser(const AccountId& account_id,
+                          ash::mojom::AuthDisabledDataPtr auth_disabled_data);
   void SetTapToUnlockEnabledForUser(const AccountId& user, bool enabled);
   void SetForceOnlineSignInForUser(const AccountId& user);
   void SetLockScreenNoteState(mojom::TrayActionState state);
diff --git a/ash/media/media_controller.h b/ash/media/media_controller.h
index 16a706e7..6fbeafc 100644
--- a/ash/media/media_controller.h
+++ b/ash/media/media_controller.h
@@ -73,6 +73,8 @@
   void MediaSessionActionsChanged(
       const std::vector<media_session::mojom::MediaSessionAction>& actions)
       override;
+  void MediaSessionChanged(
+      const base::Optional<base::UnguessableToken>& request_id) override {}
 
  private:
   friend class MediaSessionAcceleratorTest;
diff --git a/ash/media/media_notification_controller.h b/ash/media/media_notification_controller.h
index 27d4f28..1b3776f 100644
--- a/ash/media/media_notification_controller.h
+++ b/ash/media/media_notification_controller.h
@@ -39,8 +39,6 @@
       media_session::mojom::AudioFocusRequestStatePtr session) override;
   void OnFocusLost(
       media_session::mojom::AudioFocusRequestStatePtr session) override;
-  void OnActiveSessionChanged(
-      media_session::mojom::AudioFocusRequestStatePtr session) override {}
 
   void SetView(const std::string& id, MediaNotificationView* view);
 
diff --git a/ash/media/media_notification_item.h b/ash/media/media_notification_item.h
index 1ede1f94..d6080d1 100644
--- a/ash/media/media_notification_item.h
+++ b/ash/media/media_notification_item.h
@@ -39,6 +39,8 @@
   void MediaSessionActionsChanged(
       const std::vector<media_session::mojom::MediaSessionAction>& actions)
       override;
+  void MediaSessionChanged(
+      const base::Optional<base::UnguessableToken>& request_id) override {}
 
   // media_session::mojom::MediaControllerImageObserver:
   void MediaControllerImageChanged(
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc
index a866cfb7..f845d24f 100644
--- a/ash/public/cpp/ash_pref_names.cc
+++ b/ash/public/cpp/ash_pref_names.cc
@@ -347,6 +347,16 @@
 // Whether the user is allowed to disconnect and configure VPN connections.
 const char kVpnConfigAllowed[] = "vpn_config_allowed";
 
+// A boolean pref that indicates whether power peak shift is enabled.
+const char kDevicePowerPeakShiftEnabled[] = "ash.power.peak_shift_enabled";
+// An integer pref that specifies the power peak shift battery threshold in
+// percent.
+const char kDevicePowerPeakShiftBatteryThreshold[] =
+    "ash.power.peak_shift_battery_threshold";
+// A dictionary pref that specifies the power peak shift day configs.
+// For details see "DevicePowerPeakShiftDayConfig" in policy_templates.json.
+const char kDevicePowerPeakShiftDayConfig[] = "ash.power.peak_shift_day_config";
+
 // NOTE: New prefs should start with the "ash." prefix. Existing prefs moved
 // into this file should not be renamed, since they may be synced.
 
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h
index 1ffbcccf..5e142f7 100644
--- a/ash/public/cpp/ash_pref_names.h
+++ b/ash/public/cpp/ash_pref_names.h
@@ -136,6 +136,10 @@
 
 ASH_PUBLIC_EXPORT extern const char kVpnConfigAllowed[];
 
+ASH_PUBLIC_EXPORT extern const char kDevicePowerPeakShiftEnabled[];
+ASH_PUBLIC_EXPORT extern const char kDevicePowerPeakShiftBatteryThreshold[];
+ASH_PUBLIC_EXPORT extern const char kDevicePowerPeakShiftDayConfig[];
+
 }  // namespace prefs
 
 }  // namespace ash
diff --git a/ash/public/interfaces/login_screen.mojom b/ash/public/interfaces/login_screen.mojom
index 923832c..9d2bcc8 100644
--- a/ash/public/interfaces/login_screen.mojom
+++ b/ash/public/interfaces/login_screen.mojom
@@ -51,6 +51,32 @@
   HIDDEN = 10,
 };
 
+// Reason why the auth is disabled. This is used to personalize the UI.
+enum AuthDisabledReason {
+  // Auth is disabled because the device is locked by a time limit override.
+  TIME_LIMIT_OVERRIDE,
+
+  // Auth is disabled because the user has reached their daily usage limit on
+  // the device.
+  TIME_USAGE_LIMIT,
+
+  // Auth is disabled because the device is within a locked time window.
+  TIME_WINDOW_LIMIT,
+};
+
+// The data needed to customize the lock screen when auth is disabled.
+struct AuthDisabledData {
+  // Reason why auth is disabled.
+  AuthDisabledReason reason;
+
+  // A future time when auth will be enabled. This value is for display purpose
+  // only, auth won't be automatically enabled when this time is reached.
+  mojo_base.mojom.Time auth_reenabled_time;
+
+  // The amount of time that the user used this device.
+  mojo_base.mojom.TimeDelta device_used_time;
+};
+
 // Allows clients (e.g. the browser process) to send messages to the ash
 // login/lock/user-add screens.
 interface LoginScreen {
@@ -134,19 +160,17 @@
   // login screen may already be visible.
   SetAvatarForUser(signin.mojom.AccountId account_id, UserAvatar avatar);
 
-  // Called when auth should be enabled or disabled for the given user. When
-  // auth is disabled, the user cannot unlock the device. Auth is enabled by
-  // default.
+  // Called when auth should be enabled for the given user. When auth is
+  // disabled, the user cannot unlock the device. Auth is enabled by default.
   // |account_id|:            The account id of the user in the user pod.
-  // |is_enabled|:            True if auth is enabled.
-  // |auth_reenabled_time|:   A future time when auth will be enabled. Must be
-  //                          non-null if |is_enabled| is false. This value is
-  //                          for display purpose only and the client should be
-  //                          responsible for calling this method again with
-  //                          is_enabled == true when the time reaches.
-  SetAuthEnabledForUser(signin.mojom.AccountId account_id,
-                        bool is_enabled,
-                        mojo_base.mojom.Time? auth_reenabled_time);
+  EnableAuthForUser(signin.mojom.AccountId account_id);
+
+  // Called when auth should be disabled for the given user. When auth is
+  // disabled, the user cannot unlock the device. Auth is enabled by default.
+  // |account_id|:            The account id of the user in the user pod.
+  // |auth_disabled_data|:    The data needed to customize the lock screen UI.
+  DisableAuthForUser(signin.mojom.AccountId account_id,
+                      AuthDisabledData auth_disabled_data);
 
   // Called when focus is reported to be leaving a lock screen app window.
   // Requests focus to be handed off to the next suitable widget.
diff --git a/ash/public/interfaces/session_controller.mojom b/ash/public/interfaces/session_controller.mojom
index 0720245..ac791dd 100644
--- a/ash/public/interfaces/session_controller.mojom
+++ b/ash/public/interfaces/session_controller.mojom
@@ -206,6 +206,10 @@
 
   // Show the multi-profile login UI to add another user to this session.
   ShowMultiProfileLogin();
+
+  // Emits the ash-initialized upstart signal to start Chrome OS tasks that
+  // expect that Ash is listening to D-Bus signals they emit.
+  EmitAshInitialized();
 };
 
 // Interface for ash to notify client of sessions status for a specific
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn
index bcbbf0a..41ccb12 100644
--- a/ash/resources/vector_icons/BUILD.gn
+++ b/ash/resources/vector_icons/BUILD.gn
@@ -39,7 +39,9 @@
     "lock_screen_dropdown.icon",
     "lock_screen_fingerprint.icon",
     "lock_screen_fingerprint_success.icon",
-    "lock_screen_time_limit_alarm.icon",
+    "lock_screen_time_limit_lock.icon",
+    "lock_screen_time_limit_moon.icon",
+    "lock_screen_time_limit_timer.icon",
     "login_screen_button_dropdown.icon",
     "login_screen_menu_dropdown.icon",
     "login_screen_enterprise.icon",
diff --git a/ash/resources/vector_icons/lock_screen_time_limit_alarm.icon b/ash/resources/vector_icons/lock_screen_time_limit_alarm.icon
deleted file mode 100644
index a9f51a1..0000000
--- a/ash/resources/vector_icons/lock_screen_time_limit_alarm.icon
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 18,
-MOVE_TO, 16.5f, 4.29f,
-LINE_TO, 13.05f, 1.4f,
-LINE_TO, 12.08f, 2.54f,
-LINE_TO, 15.53f, 5.44f,
-LINE_TO, 16.5f, 4.29f,
-CLOSE,
-MOVE_TO, 5.91f, 2.54f,
-LINE_TO, 4.95f, 1.4f,
-LINE_TO, 1.5f, 4.28f,
-LINE_TO, 2.47f, 5.43f,
-LINE_TO, 5.91f, 2.54f,
-CLOSE,
-MOVE_TO, 9.38f, 6,
-LINE_TO, 8.25f, 6,
-LINE_TO, 8.25f, 10.5f,
-LINE_TO, 11.81f, 12.64f,
-LINE_TO, 12.38f, 11.72f,
-LINE_TO, 9.38f, 9.94f,
-LINE_TO, 9.38f, 6,
-CLOSE,
-MOVE_TO, 9, 3,
-CUBIC_TO, 5.27f, 3, 2.25f, 6.02f, 2.25f, 9.75f,
-CUBIC_TO, 2.25f, 13.48f, 5.27f, 16.5f, 9, 16.5f,
-CUBIC_TO, 12.73f, 16.5f, 15.75f, 13.48f, 15.75f, 9.75f,
-CUBIC_TO, 15.75f, 6.02f, 12.73f, 3, 9, 3,
-CLOSE,
-MOVE_TO, 9, 15,
-CUBIC_TO, 6.1f, 15, 3.75f, 12.65f, 3.75f, 9.75f,
-CUBIC_TO, 3.75f, 6.85f, 6.1f, 4.5f, 9, 4.5f,
-CUBIC_TO, 11.9f, 4.5f, 14.25f, 6.85f, 14.25f, 9.75f,
-CUBIC_TO, 14.25f, 12.65f, 11.9f, 15, 9, 15,
-CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_time_limit_lock.icon b/ash/resources/vector_icons/lock_screen_time_limit_lock.icon
new file mode 100644
index 0000000..053a28663
--- /dev/null
+++ b/ash/resources/vector_icons/lock_screen_time_limit_lock.icon
@@ -0,0 +1,32 @@
+// Copyright 2019 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.
+
+MOVE_TO, 36, 16,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, -4,
+R_CUBIC_TO, 0, -5.52f, -4.48f, -10, -10, -10,
+CUBIC_TO_SHORTHAND, 14, 6.48f, 14, 12,
+R_V_LINE_TO, 4,
+R_H_LINE_TO, -2,
+R_CUBIC_TO, -2.21f, 0, -4, 1.79f, -4, 4,
+R_V_LINE_TO, 20,
+R_CUBIC_TO, 0, 2.21f, 1.79f, 4, 4, 4,
+R_H_LINE_TO, 24,
+R_CUBIC_TO, 2.21f, 0, 4, -1.79f, 4, -4,
+V_LINE_TO, 20,
+R_CUBIC_TO, 0, -2.21f, -1.79f, -4, -4, -4,
+CLOSE,
+MOVE_TO, 24, 34,
+R_CUBIC_TO, -2.21f, 0, -4, -1.79f, -4, -4,
+R_CUBIC_TO, 0, -2.21f, 1.79f, -4, 4, -4,
+R_CUBIC_TO, 2.21f, 0, 4, 1.79f, 4, 4,
+R_CUBIC_TO, 0, 2.21f, -1.79f, 4, -4, 4,
+CLOSE,
+R_MOVE_TO, 6.2f, -18,
+H_LINE_TO, 17.8f,
+R_V_LINE_TO, -4,
+R_CUBIC_TO, 0, -3.42f, 2.78f, -6.2f, 6.2f, -6.2f,
+R_CUBIC_TO, 3.42f, 0, 6.2f, 2.78f, 6.2f, 6.2f,
+R_V_LINE_TO, 4,
+CLOSE
\ No newline at end of file
diff --git a/ash/resources/vector_icons/lock_screen_time_limit_moon.icon b/ash/resources/vector_icons/lock_screen_time_limit_moon.icon
new file mode 100644
index 0000000..3392fffe
--- /dev/null
+++ b/ash/resources/vector_icons/lock_screen_time_limit_moon.icon
@@ -0,0 +1,37 @@
+// Copyright 2019 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.
+
+MOVE_TO, 20, 15,
+R_CUBIC_TO, 0, -4, 1.25f, -7.75f, 3.25f, -11,
+CUBIC_TO, 12.5f, 4.5f, 4, 13.25f, 4, 24,
+R_CUBIC_TO, 0, 11, 9, 20, 20, 20,
+R_CUBIC_TO, 7, 0, 13, -3.5f, 16.75f, -9,
+CUBIC_TO, 29, 35, 20, 26.25f, 20, 15,
+CLOSE,
+MOVE_TO, 23.25f, 4,
+R_LINE_TO, -0.31f, 0.27f,
+CUBIC_TO, 21.12f, 7.4f, 20, 10.96f, 20, 14.75f,
+R_CUBIC_TO, 0, 0.04f, 0, 0.07f, 0, 0.11f,
+CUBIC_TO, 20.03f, 10.91f, 21.27f, 7.21f, 23.25f, 4,
+CLOSE,
+MOVE_TO, 40.4f, 35.25f,
+R_CUBIC_TO, -3.77f, 5.21f, -9.61f, 8.5f, -16.4f, 8.5f,
+R_CUBIC_TO, -10.96f, 0, -19.93f, -8.93f, -20, -19.88f,
+R_CUBIC_TO, 0, 0.04f, 0, 0.08f, 0, 0.13f,
+R_CUBIC_TO, 0, 11, 9, 20, 20, 20,
+R_CUBIC_TO, 7, 0, 13, -3.5f, 16.75f, -9,
+LINE_TO, 40.4f, 35.25f,
+CLOSE,
+MOVE_TO, 20, 15.11f,
+R_CUBIC_TO, 0, 0.05f, 0, 0.09f, 0, 0.14f,
+R_CUBIC_TO, 0, 11.14f, 8.82f, 19.82f, 20.4f, 19.99f,
+LINE_TO, 40.75f, 35,
+CUBIC_TO, 29.04f, 35, 20.06f, 26.31f, 20, 15.11f,
+CLOSE,
+MOVE_TO, 23.25f, 4,
+CUBIC_TO, 12.5f, 4.5f, 4, 13.25f, 4, 24,
+R_CUBIC_TO, 0, 0.04f, 0, 0.08f, 0, 0.12f,
+R_CUBIC_TO, 0.07f, -10.59f, 8.38f, -19.2f, 18.94f, -19.85f,
+LINE_TO, 23.25f, 4,
+CLOSE
\ No newline at end of file
diff --git a/ash/resources/vector_icons/lock_screen_time_limit_timer.icon b/ash/resources/vector_icons/lock_screen_time_limit_timer.icon
new file mode 100644
index 0000000..2b4af138
--- /dev/null
+++ b/ash/resources/vector_icons/lock_screen_time_limit_timer.icon
@@ -0,0 +1,32 @@
+// Copyright 2019 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.
+
+MOVE_TO, 30, 2,
+H_LINE_TO, 18,
+R_V_LINE_TO, 4,
+R_H_LINE_TO, 12,
+V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, -8, 26,
+R_H_LINE_TO, 4,
+V_LINE_TO, 16,
+R_H_LINE_TO, -4,
+R_V_LINE_TO, 12,
+CLOSE,
+R_MOVE_TO, 16.05f, -13.23f,
+R_LINE_TO, 2.85f, -2.85f,
+R_CUBIC_TO, -0.86f, -1.03f, -1.8f, -1.97f, -2.83f, -2.83f,
+R_LINE_TO, -2.85f, 2.85f,
+CUBIC_TO, 32.15f, 9.48f, 28.24f, 8, 23.99f, 8,
+CUBIC_TO, 14.04f, 8, 6, 16.06f, 6, 26,
+R_CUBIC_TO, 0, 9.94f, 8.04f, 18, 17.99f, 18,
+CUBIC_TO_SHORTHAND, 42, 35.94f, 42, 26,
+R_CUBIC_TO, 0, -4.25f, -1.48f, -8.15f, -3.95f, -11.23f,
+CLOSE,
+MOVE_TO, 24, 40,
+R_CUBIC_TO, -7.73f, 0, -14, -6.27f, -14, -14,
+R_CUBIC_TO, 0, -7.73f, 6.27f, -14, 14, -14,
+R_CUBIC_TO, 7.73f, 0, 14, 6.27f, 14, 14,
+R_CUBIC_TO, 0, 7.73f, -6.27f, 14, -14, 14,
+CLOSE
diff --git a/ash/session/session_controller.cc b/ash/session/session_controller.cc
index a4ea7f9..efa4f2f 100644
--- a/ash/session/session_controller.cc
+++ b/ash/session/session_controller.cc
@@ -260,6 +260,11 @@
     client_->ShowMultiProfileLogin();
 }
 
+void SessionController::EmitAshInitialized() {
+  if (client_)
+    client_->EmitAshInitialized();
+}
+
 PrefService* SessionController::GetSigninScreenPrefService() const {
   return signin_screen_prefs_.get();
 }
diff --git a/ash/session/session_controller.h b/ash/session/session_controller.h
index a71d9979..e530938f 100644
--- a/ash/session/session_controller.h
+++ b/ash/session/session_controller.h
@@ -154,6 +154,9 @@
   // Show the multi-profile login UI to add another user to this session.
   void ShowMultiProfileLogin();
 
+  // Forwards EmitAshInitialized to |client_|.
+  void EmitAshInitialized();
+
   // Returns the PrefService used at the signin screen, which is tied to an
   // incognito profile in chrome and is valid until the browser exits.
   PrefService* GetSigninScreenPrefService() const;
diff --git a/ash/session/test_session_controller_client.cc b/ash/session/test_session_controller_client.cc
index 1e783be..e45f5e5 100644
--- a/ash/session/test_session_controller_client.cc
+++ b/ash/session/test_session_controller_client.cc
@@ -246,4 +246,6 @@
 
 void TestSessionControllerClient::ShowMultiProfileLogin() {}
 
+void TestSessionControllerClient::EmitAshInitialized() {}
+
 }  // namespace ash
diff --git a/ash/session/test_session_controller_client.h b/ash/session/test_session_controller_client.h
index 07cfb39..12e3610 100644
--- a/ash/session/test_session_controller_client.h
+++ b/ash/session/test_session_controller_client.h
@@ -91,6 +91,7 @@
   void SwitchActiveUser(const AccountId& account_id) override;
   void CycleActiveUser(CycleUserDirection direction) override;
   void ShowMultiProfileLogin() override;
+  void EmitAshInitialized() override;
 
  private:
   SessionController* const controller_;
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc
index 14b9c50..e73e94b 100644
--- a/ash/shelf/shelf.cc
+++ b/ash/shelf/shelf.cc
@@ -308,12 +308,13 @@
   switch (alignment_) {
     case SHELF_ALIGNMENT_BOTTOM:
     case SHELF_ALIGNMENT_BOTTOM_LOCKED:
-      return gfx::Rect(base::i18n::IsRTL() ? work_area.x() : work_area.right(),
-                       work_area.bottom(), 0, 0);
+      return gfx::Rect(
+          base::i18n::IsRTL() ? work_area.x() : work_area.right() - 1,
+          work_area.bottom() - 1, 0, 0);
     case SHELF_ALIGNMENT_LEFT:
-      return gfx::Rect(work_area.x(), work_area.bottom(), 0, 0);
+      return gfx::Rect(work_area.x(), work_area.bottom() - 1, 0, 0);
     case SHELF_ALIGNMENT_RIGHT:
-      return gfx::Rect(work_area.right(), work_area.bottom(), 0, 0);
+      return gfx::Rect(work_area.right() - 1, work_area.bottom() - 1, 0, 0);
   }
   NOTREACHED();
   return gfx::Rect();
diff --git a/ash/shell.cc b/ash/shell.cc
index d70fc4f..d5ce14fd 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -173,7 +173,7 @@
 #include "base/task/task_traits.h"
 #include "base/trace_event/trace_event.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/system/devicemode.h"
 #include "components/exo/file_helper.h"
 #include "components/prefs/pref_registry_simple.h"
@@ -406,6 +406,7 @@
   WallpaperController::RegisterLocalStatePrefs(registry);
   BluetoothPowerController::RegisterLocalStatePrefs(registry);
   DetachableBaseHandler::RegisterPrefs(registry);
+  PowerPrefs::RegisterLocalStatePrefs(registry);
   // Note: DisplayPrefs are registered in chrome in AshShellInit::RegisterPrefs
   // (see comment there for details).
   if (for_test)
@@ -1277,15 +1278,10 @@
 
   // Initialize the D-Bus thread and services for ash.
   ash_dbus_services_ = std::make_unique<AshDBusServices>();
+
   // By this point ash shell should have initialized its D-Bus signal
-  // listeners, so emit ash-initialized upstart signal to start Chrome OS tasks
-  // that expect that ash is listening to D-Bus signals they emit. For example,
-  // hammerd, which handles detachable base state, communicates the base state
-  // purely by emitting D-Bus signals, and thus has to be run whenever ash is
-  // started so ash (DetachableBaseHandler in particular) gets the proper view
-  // of the current detachable base state.
-  // TODO(stevenjb): Move this and other D-Bus dependencies to AshDBusServices.
-  ash_dbus_services_->EmitAshInitialized();
+  // listeners, so inform the session manager that Ash is initialized.
+  session_controller_->EmitAshInitialized();
 }
 
 void Shell::InitializeDisplayManager() {
diff --git a/ash/shell/content/client/shell_browser_main_parts.cc b/ash/shell/content/client/shell_browser_main_parts.cc
index 9381479..548a75a 100644
--- a/ash/shell/content/client/shell_browser_main_parts.cc
+++ b/ash/shell/content/client/shell_browser_main_parts.cc
@@ -33,7 +33,7 @@
 #include "base/time/time.h"
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "components/exo/file_helper.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/ash/shutdown_controller.cc b/ash/shutdown_controller.cc
index 90717139..17b704ed4 100644
--- a/ash/shutdown_controller.cc
+++ b/ash/shutdown_controller.cc
@@ -14,7 +14,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace ash {
diff --git a/ash/system/audio/display_speaker_controller.h b/ash/system/audio/display_speaker_controller.h
index 51e2051..0ef60332 100644
--- a/ash/system/audio/display_speaker_controller.h
+++ b/ash/system/audio/display_speaker_controller.h
@@ -6,7 +6,7 @@
 #define ASH_SYSTEM_AUDIO_DISPLAY_SPEAKER_CONTROLLER_H_
 
 #include "base/macros.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/display/display_observer.h"
 
 namespace ash {
diff --git a/ash/system/brightness/brightness_controller_chromeos.cc b/ash/system/brightness/brightness_controller_chromeos.cc
index 4007f92e..2d84ab39 100644
--- a/ash/system/brightness/brightness_controller_chromeos.cc
+++ b/ash/system/brightness/brightness_controller_chromeos.cc
@@ -8,8 +8,8 @@
 
 #include "base/metrics/user_metrics.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "ui/base/accelerators/accelerator.h"
 
 namespace ash {
diff --git a/ash/system/keyboard_brightness/keyboard_brightness_controller.cc b/ash/system/keyboard_brightness/keyboard_brightness_controller.cc
index e62ba7a..11f3ff51 100644
--- a/ash/system/keyboard_brightness/keyboard_brightness_controller.cc
+++ b/ash/system/keyboard_brightness/keyboard_brightness_controller.cc
@@ -6,7 +6,7 @@
 
 #include "base/metrics/user_metrics.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/base/accelerators/accelerator.h"
 
 using base::RecordAction;
diff --git a/ash/system/network/network_tray_view.cc b/ash/system/network/network_tray_view.cc
index 70dd7a6..cc446e4e 100644
--- a/ash/system/network/network_tray_view.cc
+++ b/ash/system/network/network_tray_view.cc
@@ -65,12 +65,8 @@
   return GetLocalBounds().Contains(point) ? this : nullptr;
 }
 
-bool NetworkTrayView::GetTooltipText(const gfx::Point& p,
-                                     base::string16* tooltip) const {
-  if (connection_status_tooltip_.empty())
-    return false;
-  *tooltip = connection_status_tooltip_;
-  return true;
+base::string16 NetworkTrayView::GetTooltipText(const gfx::Point& p) const {
+  return connection_status_tooltip_;
 }
 
 void NetworkTrayView::NetworkIconChanged() {
diff --git a/ash/system/network/network_tray_view.h b/ash/system/network/network_tray_view.h
index d188f401..82d3efd 100644
--- a/ash/system/network/network_tray_view.h
+++ b/ash/system/network/network_tray_view.h
@@ -44,8 +44,7 @@
   // views::View:
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
 
   // network_icon::AnimationObserver:
   void NetworkIconChanged() override;
diff --git a/ash/system/night_light/night_light_controller.h b/ash/system/night_light/night_light_controller.h
index dd01ee03..3916e13 100644
--- a/ash/system/night_light/night_light_controller.h
+++ b/ash/system/night_light/night_light_controller.h
@@ -15,7 +15,7 @@
 #include "base/observer_list.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "ui/aura/env_observer.h"
diff --git a/ash/system/power/backlights_forced_off_setter.h b/ash/system/power/backlights_forced_off_setter.h
index 7db451b..431f342 100644
--- a/ash/system/power/backlights_forced_off_setter.h
+++ b/ash/system/power/backlights_forced_off_setter.h
@@ -13,7 +13,7 @@
 #include "base/observer_list.h"
 #include "base/optional.h"
 #include "base/scoped_observer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace ash {
 
diff --git a/ash/system/power/backlights_forced_off_setter_unittest.cc b/ash/system/power/backlights_forced_off_setter_unittest.cc
index 248e1fdd9..b165a5f 100644
--- a/ash/system/power/backlights_forced_off_setter_unittest.cc
+++ b/ash/system/power/backlights_forced_off_setter_unittest.cc
@@ -15,7 +15,7 @@
 #include "ash/touch/touch_devices_controller.h"
 #include "base/macros.h"
 #include "base/scoped_observer.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "services/ws/public/cpp/input_devices/input_device_client_test_api.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/test/touch_transform_controller_test_api.h"
diff --git a/ash/system/power/notification_reporter.cc b/ash/system/power/notification_reporter.cc
index 09f339c..90123a6 100644
--- a/ash/system/power/notification_reporter.cc
+++ b/ash/system/power/notification_reporter.cc
@@ -4,7 +4,7 @@
 
 #include "ash/system/power/notification_reporter.h"
 
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/public/cpp/notification.h"
 #include "ui/message_center/public/cpp/notification_types.h"
diff --git a/ash/system/power/notification_reporter_unittest.cc b/ash/system/power/notification_reporter_unittest.cc
index 30f3ef5..9a597d4 100644
--- a/ash/system/power/notification_reporter_unittest.cc
+++ b/ash/system/power/notification_reporter_unittest.cc
@@ -11,7 +11,7 @@
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "ui/message_center/fake_message_center.h"
 #include "ui/message_center/public/cpp/notification.h"
 
diff --git a/ash/system/power/peripheral_battery_notifier.h b/ash/system/power/peripheral_battery_notifier.h
index 82e08fd..3df371c 100644
--- a/ash/system/power/peripheral_battery_notifier.h
+++ b/ash/system/power/peripheral_battery_notifier.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/tick_clock.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 
 namespace ash {
diff --git a/ash/system/power/power_button_controller.h b/ash/system/power/power_button_controller.h
index 09bc2f1..5ae260b 100644
--- a/ash/system/power/power_button_controller.h
+++ b/ash/system/power/power_button_controller.h
@@ -15,7 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/display/manager/display_configurator.h"
 
 namespace base {
diff --git a/ash/system/power/power_button_controller_unittest.cc b/ash/system/power/power_button_controller_unittest.cc
index 0bcab3b..aee4209bc 100644
--- a/ash/system/power/power_button_controller_unittest.cc
+++ b/ash/system/power/power_button_controller_unittest.cc
@@ -27,7 +27,7 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/display/test/display_manager_test_api.h"
diff --git a/ash/system/power/power_button_display_controller.h b/ash/system/power/power_button_display_controller.h
index 88475ef..e193b28 100644
--- a/ash/system/power/power_button_display_controller.h
+++ b/ash/system/power/power_button_display_controller.h
@@ -13,7 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observer.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/events/devices/input_device_event_observer.h"
 #include "ui/events/event_handler.h"
 
diff --git a/ash/system/power/power_button_screenshot_controller_unittest.cc b/ash/system/power/power_button_screenshot_controller_unittest.cc
index be0fbae..a52421cb 100644
--- a/ash/system/power/power_button_screenshot_controller_unittest.cc
+++ b/ash/system/power/power_button_screenshot_controller_unittest.cc
@@ -15,7 +15,7 @@
 #include "ash/test_screenshot_delegate.h"
 #include "ash/wm/lock_state_controller_test_api.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "ui/events/event.h"
 
 namespace ash {
diff --git a/ash/system/power/power_button_test_base.cc b/ash/system/power/power_button_test_base.cc
index 2a78c90..61fe61c 100644
--- a/ash/system/power/power_button_test_base.cc
+++ b/ash/system/power/power_button_test_base.cc
@@ -17,7 +17,7 @@
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/events/event.h"
 #include "ui/events/test/event_generator.h"
 
diff --git a/ash/system/power/power_event_observer.h b/ash/system/power/power_event_observer.h
index 5af8d94..0f1a0b0 100644
--- a/ash/system/power/power_event_observer.h
+++ b/ash/system/power/power_event_observer.h
@@ -12,7 +12,7 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace ui {
 class CompositorObserver;
diff --git a/ash/system/power/power_event_observer_unittest.cc b/ash/system/power/power_event_observer_unittest.cc
index f7077aa..a0a7c32 100644
--- a/ash/system/power/power_event_observer_unittest.cc
+++ b/ash/system/power/power_event_observer_unittest.cc
@@ -17,8 +17,8 @@
 #include "ash/wm/test_session_state_animator.h"
 #include "base/time/time.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/compositor/compositor.h"
diff --git a/ash/system/power/power_prefs.cc b/ash/system/power/power_prefs.cc
index 6397937..92c0840 100644
--- a/ash/system/power/power_prefs.cc
+++ b/ash/system/power/power_prefs.cc
@@ -13,8 +13,8 @@
 #include "base/callback.h"
 #include "base/time/default_tick_clock.h"
 #include "chromeos/constants/chromeos_features.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
-#include "chromeos/dbus/power_policy_controller.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_registry.h"
@@ -146,6 +146,16 @@
 }
 
 // static
+void PowerPrefs::RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterBooleanPref(prefs::kDevicePowerPeakShiftEnabled, false,
+                                PrefRegistry::PUBLIC);
+  registry->RegisterIntegerPref(prefs::kDevicePowerPeakShiftBatteryThreshold,
+                                -1, PrefRegistry::PUBLIC);
+  registry->RegisterDictionaryPref(prefs::kDevicePowerPeakShiftDayConfig,
+                                   PrefRegistry::PUBLIC);
+}
+
+// static
 void PowerPrefs::RegisterSigninProfilePrefs(PrefRegistrySimple* registry,
                                             bool for_test) {
   RegisterProfilePrefs(registry, for_test);
diff --git a/ash/system/power/power_prefs.h b/ash/system/power/power_prefs.h
index 76d0db27..e66071a3 100644
--- a/ash/system/power/power_prefs.h
+++ b/ash/system/power/power_prefs.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/scoped_observer.h"
 #include "base/time/tick_clock.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 class PrefChangeRegistrar;
 class PrefRegistrySimple;
@@ -37,6 +37,10 @@
              chromeos::PowerManagerClient* power_manager_client);
   ~PowerPrefs() override;
 
+  // Registers power prefs with default values applicable to the local state
+  // prefs.
+  static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+
   // Registers power prefs with default values applicable to the signin prefs.
   static void RegisterSigninProfilePrefs(PrefRegistrySimple* registry,
                                          bool for_test = false);
diff --git a/ash/system/power/power_prefs_unittest.cc b/ash/system/power/power_prefs_unittest.cc
index 097ab1a..0ba6010 100644
--- a/ash/system/power/power_prefs_unittest.cc
+++ b/ash/system/power/power_prefs_unittest.cc
@@ -17,9 +17,9 @@
 #include "ash/test/ash_test_base.h"
 #include "base/macros.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
-#include "chromeos/dbus/power_policy_controller.h"
 #include "components/prefs/pref_service.h"
 
 using session_manager::SessionState;
diff --git a/ash/system/power/power_status.cc b/ash/system/power/power_status.cc
index 082b203..7fe8f83 100644
--- a/ash/system/power/power_status.cc
+++ b/ash/system/power/power_status.cc
@@ -17,7 +17,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/time_format.h"
 #include "ui/display/display.h"
diff --git a/ash/system/power/power_status.h b/ash/system/power/power_status.h
index 1e63fb3..e9eec524 100644
--- a/ash/system/power/power_status.h
+++ b/ash/system/power/power_status.h
@@ -14,8 +14,8 @@
 #include "base/optional.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "ui/gfx/image/image_skia.h"
 
 namespace gfx {
diff --git a/ash/system/power/power_status_unittest.cc b/ash/system/power/power_status_unittest.cc
index 2021bd2..f6cde88 100644
--- a/ash/system/power/power_status_unittest.cc
+++ b/ash/system/power/power_status_unittest.cc
@@ -9,7 +9,7 @@
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/gfx/image/image.h"
diff --git a/ash/system/power/tray_power.cc b/ash/system/power/tray_power.cc
index 7268112..0b37a2a 100644
--- a/ash/system/power/tray_power.cc
+++ b/ash/system/power/tray_power.cc
@@ -69,12 +69,8 @@
   return GetLocalBounds().Contains(point) ? this : nullptr;
 }
 
-bool PowerTrayView::GetTooltipText(const gfx::Point& p,
-                                   base::string16* tooltip) const {
-  if (tooltip_.empty())
-    return false;
-  *tooltip = tooltip_;
-  return true;
+base::string16 PowerTrayView::GetTooltipText(const gfx::Point& p) const {
+  return tooltip_;
 }
 
 void PowerTrayView::OnPowerStatusChanged() {
diff --git a/ash/system/power/tray_power.h b/ash/system/power/tray_power.h
index 8c230bd8..2b199652 100644
--- a/ash/system/power/tray_power.h
+++ b/ash/system/power/tray_power.h
@@ -28,8 +28,7 @@
   gfx::Size CalculatePreferredSize() const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
 
   // PowerStatus::Observer:
   void OnPowerStatusChanged() override;
diff --git a/ash/system/power/video_activity_notifier.cc b/ash/system/power/video_activity_notifier.cc
index f98f0354..582d5940 100644
--- a/ash/system/power/video_activity_notifier.cc
+++ b/ash/system/power/video_activity_notifier.cc
@@ -7,7 +7,7 @@
 #include "ash/session/session_controller.h"
 #include "ash/shell.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace ash {
 namespace {
diff --git a/ash/system/power/video_activity_notifier_unittest.cc b/ash/system/power/video_activity_notifier_unittest.cc
index 04ff159..cd9ce87a 100644
--- a/ash/system/power/video_activity_notifier_unittest.cc
+++ b/ash/system/power/video_activity_notifier_unittest.cc
@@ -10,7 +10,7 @@
 #include "ash/wm/video_detector.h"
 #include "base/macros.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 
 namespace ash {
 
diff --git a/ash/system/unified/feature_pod_button.cc b/ash/system/unified/feature_pod_button.cc
index d1e94355..4d072b6 100644
--- a/ash/system/unified/feature_pod_button.cc
+++ b/ash/system/unified/feature_pod_button.cc
@@ -95,9 +95,7 @@
 
 void FeaturePodIconButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   ImageButton::GetAccessibleNodeData(node_data);
-  base::string16 name;
-  GetTooltipText(gfx::Point(), &name);
-  node_data->SetName(name);
+  node_data->SetName(GetTooltipText(gfx::Point()));
   node_data->role = ax::mojom::Role::kToggleButton;
   node_data->SetCheckedState(toggled_ ? ax::mojom::CheckedState::kTrue
                                       : ax::mojom::CheckedState::kFalse);
diff --git a/ash/system/unified/unified_slider_bubble_controller.cc b/ash/system/unified/unified_slider_bubble_controller.cc
index 3d71cf5a..bd87cbf 100644
--- a/ash/system/unified/unified_slider_bubble_controller.cc
+++ b/ash/system/unified/unified_slider_bubble_controller.cc
@@ -168,7 +168,11 @@
   init_params.anchor_view = nullptr;
   init_params.anchor_mode = TrayBubbleView::AnchorMode::kRect;
   init_params.anchor_rect = tray_->shelf()->GetSystemTrayAnchorRect();
-  init_params.insets = gfx::Insets(kUnifiedMenuPadding, kUnifiedMenuPadding);
+  // Decrease bottom and right insets to compensate for the adjustment of
+  // the respective edges in Shelf::GetSystemTrayAnchorRect().
+  init_params.insets =
+      gfx::Insets(kUnifiedMenuPadding, kUnifiedMenuPadding,
+                  kUnifiedMenuPadding - 1, kUnifiedMenuPadding - 1);
   init_params.corner_radius = kUnifiedTrayCornerRadius;
   init_params.has_shadow = false;
 
diff --git a/ash/system/unified/unified_system_tray_bubble.cc b/ash/system/unified/unified_system_tray_bubble.cc
index 115ede03..b9478d5 100644
--- a/ash/system/unified/unified_system_tray_bubble.cc
+++ b/ash/system/unified/unified_system_tray_bubble.cc
@@ -78,7 +78,11 @@
   init_params.anchor_view = nullptr;
   init_params.anchor_mode = TrayBubbleView::AnchorMode::kRect;
   init_params.anchor_rect = tray->shelf()->GetSystemTrayAnchorRect();
-  init_params.insets = gfx::Insets(kUnifiedMenuPadding, kUnifiedMenuPadding);
+  // Decrease bottom and right insets to compensate for the adjustment of
+  // the respective edges in Shelf::GetSystemTrayAnchorRect().
+  init_params.insets =
+      gfx::Insets(kUnifiedMenuPadding, kUnifiedMenuPadding,
+                  kUnifiedMenuPadding - 1, kUnifiedMenuPadding - 1);
   init_params.corner_radius = kUnifiedTrayCornerRadius;
   init_params.has_shadow = false;
   init_params.show_by_click = show_by_click;
diff --git a/ash/system/unified/unified_system_tray_model.h b/ash/system/unified/unified_system_tray_model.h
index a5691ee..1dbc17a 100644
--- a/ash/system/unified/unified_system_tray_model.h
+++ b/ash/system/unified/unified_system_tray_model.h
@@ -7,7 +7,7 @@
 
 #include "ash/ash_export.h"
 #include "base/observer_list.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace ash {
 
diff --git a/ash/system/unified/unified_system_tray_test_api.cc b/ash/system/unified/unified_system_tray_test_api.cc
index 0e2f1647..81a5476 100644
--- a/ash/system/unified/unified_system_tray_test_api.cc
+++ b/ash/system/unified/unified_system_tray_test_api.cc
@@ -105,11 +105,9 @@
 void UnifiedSystemTrayTestApi::GetBubbleViewTooltip(
     int view_id,
     GetBubbleViewTooltipCallback cb) {
-  base::string16 tooltip;
   views::View* view = GetBubbleView(view_id);
-  if (view)
-    view->GetTooltipText(gfx::Point(), &tooltip);
-  std::move(cb).Run(tooltip);
+  std::move(cb).Run(view ? view->GetTooltipText(gfx::Point())
+                         : base::string16());
 }
 
 void UnifiedSystemTrayTestApi::GetBubbleLabelText(
diff --git a/ash/system/unified/unified_system_tray_unittest.cc b/ash/system/unified/unified_system_tray_unittest.cc
index cb2d025..bcb40720 100644
--- a/ash/system/unified/unified_system_tray_unittest.cc
+++ b/ash/system/unified/unified_system_tray_unittest.cc
@@ -7,7 +7,10 @@
 #include "ash/system/status_area_widget.h"
 #include "ash/system/status_area_widget_test_helper.h"
 #include "ash/system/unified/unified_slider_bubble_controller.h"
+#include "ash/system/unified/unified_system_tray_bubble.h"
 #include "ash/test/ash_test_base.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
 
 namespace ash {
 
@@ -27,6 +30,10 @@
         ->slider_bubble_controller_->slider_type_;
   }
 
+  UnifiedSystemTrayBubble* GetUnifiedSystemTrayBubble() {
+    return GetPrimaryUnifiedSystemTray()->bubble_.get();
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(UnifiedSystemTrayTest);
 };
@@ -52,4 +59,26 @@
   EXPECT_FALSE(status->ShouldShowShelf());
 }
 
+TEST_F(UnifiedSystemTrayTest, ShowBubble_MultipleDisplays_OpenedOnSameDisplay) {
+  // Initialize two displays with 800x800 resolution.
+  UpdateDisplay("400+400-800x600,1220+400-800x600");
+  auto* screen = display::Screen::GetScreen();
+  EXPECT_EQ(2, screen->GetNumDisplays());
+
+  // The tray bubble for each display should be opened on the same display.
+  // See crbug.com/937420.
+  for (int i = 0; i < screen->GetNumDisplays(); ++i) {
+    auto* system_tray = GetPrimaryUnifiedSystemTray();
+    system_tray->ShowBubble(true /* show_by_click */);
+    const gfx::Rect& primary_display_bounds = GetPrimaryDisplay().bounds();
+    const gfx::Rect& tray_bubble_bounds =
+        GetPrimaryUnifiedSystemTray()->GetBubbleBoundsInScreen();
+    EXPECT_TRUE(primary_display_bounds.Contains(tray_bubble_bounds))
+        << "primary display bounds=" << primary_display_bounds.ToString()
+        << ", tray bubble bounds=" << tray_bubble_bounds.ToString();
+
+    SwapPrimaryDisplay();
+  }
+}
+
 }  // namespace ash
diff --git a/ash/system/unified/user_chooser_view.cc b/ash/system/unified/user_chooser_view.cc
index 8f8cf90..74887ba2 100644
--- a/ash/system/unified/user_chooser_view.cc
+++ b/ash/system/unified/user_chooser_view.cc
@@ -249,14 +249,13 @@
     capture_icon_->set_tooltip_text(l10n_util::GetStringUTF16(res_id));
 }
 
-bool UserItemButton::GetTooltipText(const gfx::Point& p,
-                                    base::string16* tooltip) const {
+base::string16 UserItemButton::GetTooltipText(const gfx::Point& p) const {
   // If both of them are full shown, hide the tooltip.
   if (name_->GetPreferredSize().width() <= name_->width() &&
       email_->GetPreferredSize().width() <= email_->width()) {
-    return false;
+    return base::string16();
   }
-  return views::Button::GetTooltipText(p, tooltip);
+  return views::Button::GetTooltipText(p);
 }
 
 void UserItemButton::ButtonPressed(views::Button* sender,
diff --git a/ash/system/unified/user_chooser_view.h b/ash/system/unified/user_chooser_view.h
index ec2d5db0..757f7e5 100644
--- a/ash/system/unified/user_chooser_view.h
+++ b/ash/system/unified/user_chooser_view.h
@@ -35,8 +35,7 @@
   void SetCaptureState(mojom::MediaCaptureState capture_states);
 
   // views::Button:
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
 
   // views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc
index 113ce77..8822df0d 100644
--- a/ash/test/ash_test_base.cc
+++ b/ash/test/ash_test_base.cc
@@ -35,7 +35,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/user_names.h"
 #include "mojo/public/cpp/bindings/map.h"
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 14de605..c9fd4506e 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -32,7 +32,7 @@
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/hammerd/hammerd_client.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "components/discardable_memory/public/interfaces/discardable_shared_memory_manager.mojom.h"
@@ -161,8 +161,7 @@
   if (!chromeos::DBusThreadManager::IsInitialized()) {
     chromeos::DBusThreadManager::Initialize(
         chromeos::DBusThreadManager::kShared);
-    chromeos::HammerdClient::Initialize(
-        chromeos::DBusThreadManager::Get()->GetSystemBus());
+    chromeos::HammerdClient::InitializeFake();
     dbus_thread_manager_initialized_ = true;
   }
 
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc
index 3672184..03f6f934 100644
--- a/ash/wallpaper/wallpaper_view.cc
+++ b/ash/wallpaper/wallpaper_view.cc
@@ -12,7 +12,9 @@
 #include "ash/shell.h"
 #include "ash/wallpaper/wallpaper_controller.h"
 #include "ash/wallpaper/wallpaper_widget_controller.h"
+#include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "cc/paint/render_surface_filters.h"
 #include "ui/aura/window.h"
 #include "ui/display/display.h"
 #include "ui/display/manager/display_manager.h"
@@ -91,6 +93,10 @@
           ->tablet_mode_controller()
           ->IsTabletModeWindowManagerEnabled()) {
     alpha = kTabletModeWallpaperAlpha;
+  } else if (Shell::Get()->overview_controller()->IsSelecting()) {
+    // Overview mode will apply its own brightness filter on a downscaled image,
+    // so color with full opacity here.
+    alpha = 255;
   }
 
   return SkColorSetA(darken_color, alpha);
@@ -107,6 +113,16 @@
 
 WallpaperView::~WallpaperView() = default;
 
+void WallpaperView::RepaintBlurAndOpacity(int repaint_blur,
+                                          float repaint_opacity) {
+  if (repaint_blur_ == repaint_blur && repaint_opacity_ == repaint_opacity)
+    return;
+
+  repaint_blur_ = repaint_blur;
+  repaint_opacity_ = repaint_opacity;
+  SchedulePaint();
+}
+
 void WallpaperView::OnPaint(gfx::Canvas* canvas) {
   // Scale the image while maintaining the aspect ratio, cropping as necessary
   // to fill the wallpaper. Ideally the image should be larger than the largest
@@ -149,13 +165,10 @@
                                                  horizontal_ratio));
       }
 
-      gfx::Rect wallpaper_cropped_rect(0, 0, wallpaper.width(),
-                                       wallpaper.height());
+      gfx::Rect wallpaper_cropped_rect(wallpaper.size());
       wallpaper_cropped_rect.ClampToCenteredSize(cropped_size);
-      canvas->DrawImageInt(
-          wallpaper, wallpaper_cropped_rect.x(), wallpaper_cropped_rect.y(),
-          wallpaper_cropped_rect.width(), wallpaper_cropped_rect.height(), 0, 0,
-          width(), height(), true, flags);
+      DrawWallpaper(wallpaper, wallpaper_cropped_rect, gfx::Rect(size()), flags,
+                    canvas);
       break;
     }
     case WALLPAPER_LAYOUT_TILE: {
@@ -166,21 +179,19 @@
     }
     case WALLPAPER_LAYOUT_STRETCH: {
       // This is generally not recommended as it may show artifacts.
-      canvas->DrawImageInt(wallpaper, 0, 0, wallpaper.width(),
-                           wallpaper.height(), 0, 0, width(), height(), true,
-                           flags);
+      DrawWallpaper(wallpaper, gfx::Rect(wallpaper.size()), gfx::Rect(size()),
+                    flags, canvas);
       break;
     }
     case WALLPAPER_LAYOUT_CENTER: {
-      float image_scale = canvas->image_scale();
-      gfx::Rect wallpaper_rect(0, 0, wallpaper.width() / image_scale,
-                               wallpaper.height() / image_scale);
+      const float image_scale = canvas->image_scale();
       // Simply centered and not scaled (but may be clipped).
-      canvas->DrawImageInt(
-          wallpaper, 0, 0, wallpaper.width(), wallpaper.height(),
-          (width() - wallpaper_rect.width()) / 2,
-          (height() - wallpaper_rect.height()) / 2, wallpaper_rect.width(),
-          wallpaper_rect.height(), true, flags);
+      gfx::Rect wallpaper_rect = gfx::ScaleToRoundedRect(
+          gfx::Rect(wallpaper.size()), 1.f / image_scale);
+      wallpaper_rect.set_x((width() - wallpaper_rect.width()) / 2);
+      wallpaper_rect.set_y((height() - wallpaper_rect.height()) / 2);
+      DrawWallpaper(wallpaper, gfx::Rect(wallpaper.size()), wallpaper_rect,
+                    flags, canvas);
       break;
     }
     default: {
@@ -200,6 +211,59 @@
   Shell::Get()->ShowContextMenu(point, source_type);
 }
 
+void WallpaperView::DrawWallpaper(const gfx::ImageSkia& wallpaper,
+                                  const gfx::Rect& src,
+                                  const gfx::Rect& dst,
+                                  const cc::PaintFlags& flags,
+                                  gfx::Canvas* canvas) {
+  if (repaint_blur_ == 0 && repaint_opacity_ == 1.f) {
+    canvas->DrawImageInt(wallpaper, src.x(), src.y(), src.width(), src.height(),
+                         dst.x(), dst.y(), dst.width(), dst.height(),
+                         /*filter=*/true, flags);
+    return;
+  }
+
+  // The amount we downsample the original image by before applying filters to
+  // improve performance.
+  constexpr float quality = 0.3f;
+  float blur = repaint_blur_ * quality;
+  gfx::Rect quality_adjusted_rect = gfx::ScaleToEnclosingRect(dst, quality);
+
+  // Create the blur and brightness filter to apply to the downsampled image.
+  cc::PaintFlags filter_flags;
+  cc::FilterOperations operations;
+  operations.Append(
+      cc::FilterOperation::CreateBrightnessFilter(repaint_opacity_));
+  operations.Append(cc::FilterOperation::CreateBlurFilter(
+      blur, SkBlurImageFilter::kClamp_TileMode));
+  sk_sp<cc::PaintFilter> filter = cc::RenderSurfaceFilters::BuildImageFilter(
+      operations, gfx::SizeF(dst.size()), gfx::Vector2dF());
+  filter_flags.setImageFilter(filter);
+
+  gfx::Canvas downsampled_canvas(quality_adjusted_rect.size(),
+                                 /*image_scale=*/1.f,
+                                 /*is_opaque=*/false);
+  downsampled_canvas.sk_canvas()->saveLayer(nullptr, &filter_flags);
+  downsampled_canvas.DrawImageInt(
+      wallpaper, src.x(), src.y(), src.width(), src.height(), 0, 0,
+      quality_adjusted_rect.width(), quality_adjusted_rect.height(), true);
+  downsampled_canvas.sk_canvas()->restore();
+
+  // Draw the downsampled and filtered image onto |canvas|. Draw a inseted
+  // version of the image to avoid drawing a blackish border caused by the blur
+  // filter. This is what we do on the login screen as well.
+  // TODO(sammiequon): Investigate if we can cache the small image and apply
+  // additional blur and opacity when painting or maybe store the small image
+  // with blur and color then transform.
+  gfx::ImageSkia filtered_wallpaper =
+      gfx::ImageSkia::CreateFrom1xBitmap(downsampled_canvas.GetBitmap());
+  canvas->DrawImageInt(filtered_wallpaper, blur, blur,
+                       quality_adjusted_rect.width() - 2 * blur,
+                       quality_adjusted_rect.height() - 2 * blur, dst.x(),
+                       dst.y(), dst.width(), dst.height(),
+                       /*filter=*/true, flags);
+}  // namespace ash
+
 views::Widget* CreateWallpaperWidget(aura::Window* root_window,
                                      int container_id,
                                      WallpaperView** out_wallpaper_view) {
diff --git a/ash/wallpaper/wallpaper_view.h b/ash/wallpaper/wallpaper_view.h
index 7b4e9c8..fdebe91 100644
--- a/ash/wallpaper/wallpaper_view.h
+++ b/ash/wallpaper/wallpaper_view.h
@@ -19,6 +19,9 @@
   WallpaperView();
   ~WallpaperView() override;
 
+  // Schedules a repaint of the wallpaper with blur and opacity changes.
+  void RepaintBlurAndOpacity(int repaint_blur, float repaint_opacity);
+
  private:
   friend class WallpaperControllerTest;
 
@@ -31,6 +34,20 @@
                                   const gfx::Point& point,
                                   ui::MenuSourceType source_type) override;
 
+  // Helper to draw the wallpaper.
+  void DrawWallpaper(const gfx::ImageSkia& wallpaper,
+                     const gfx::Rect& src,
+                     const gfx::Rect& dst,
+                     const cc::PaintFlags& flags,
+                     gfx::Canvas* canvas);
+
+  // These are used by overview mode to animate the blur and opacity on the
+  // wallpaper. If |repaint_blur_| is not 0 and |repaint_opacity_| is not 1, the
+  // wallpaper will be downsampled and a blur and brightness filter will be
+  // applied. It is downsampled to increase performance.
+  int repaint_blur_ = 0;
+  float repaint_opacity_ = 1.f;
+
   DISALLOW_COPY_AND_ASSIGN(WallpaperView);
 };
 
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc
index 1a78300..208eaf2 100644
--- a/ash/wm/lock_state_controller_unittest.cc
+++ b/ash/wm/lock_state_controller_unittest.cc
@@ -25,7 +25,7 @@
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "ui/display/manager/display_configurator.h"
 #include "ui/display/manager/fake_display_snapshot.h"
 #include "ui/display/types/display_constants.h"
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc
index 6bbe587b6..d05d446a 100644
--- a/ash/wm/overview/overview_controller.cc
+++ b/ash/wm/overview/overview_controller.cc
@@ -13,6 +13,7 @@
 #include "ash/session/session_controller.h"
 #include "ash/shell.h"
 #include "ash/wallpaper/wallpaper_controller.h"
+#include "ash/wallpaper/wallpaper_view.h"
 #include "ash/wallpaper/wallpaper_widget_controller.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_constants.h"
@@ -86,10 +87,11 @@
 
 }  // namespace
 
-// Class that handles of blurring wallpaper upon entering and exiting overview
-// mode. Blurs the wallpaper automatically if the wallpaper is not visible
-// prior to entering overview mode (covered by a window), otherwise animates
-// the blur.
+// Class that handles of blurring and dimming wallpaper upon entering and
+// exiting overview mode. Blurs the wallpaper automatically if the wallpaper is
+// not visible prior to entering overview mode (covered by a window), otherwise
+// animates the blur and dim.
+// TODO(sammiequon): Rename since this dims as well now.
 class OverviewController::OverviewBlurController
     : public ui::CompositorAnimationObserver,
       public aura::WindowObserver {
@@ -163,7 +165,7 @@
     // Animate only to even numbers to reduce the load.
     int ivalue = static_cast<int>(value * kWallpaperBlurSigma) / 2 * 2;
     for (aura::Window* root : roots_to_animate_)
-      ApplyBlur(root, ivalue);
+      ApplyBlurAndOpacity(root, ivalue);
   }
 
   // aura::WindowObserver:
@@ -175,10 +177,17 @@
       roots_to_animate_.erase(it);
   }
 
-  void ApplyBlur(aura::Window* root, float blur_sigma) {
-    RootWindowController::ForWindow(root)
-        ->wallpaper_widget_controller()
-        ->SetWallpaperBlur(blur_sigma);
+  void ApplyBlurAndOpacity(aura::Window* root, int value) {
+    DCHECK_GE(value, 0);
+    DCHECK_LE(value, 10);
+    const float opacity =
+        gfx::Tween::FloatValueBetween(value / 10.0, 1.f, kShieldOpacity);
+    auto* wallpaper_widget_controller =
+        RootWindowController::ForWindow(root)->wallpaper_widget_controller();
+    if (wallpaper_widget_controller->wallpaper_view()) {
+      wallpaper_widget_controller->wallpaper_view()->RepaintBlurAndOpacity(
+          value, opacity);
+    }
   }
 
   // Called when the wallpaper is to be changed. Checks to see which root
@@ -210,19 +219,15 @@
         DCHECK(overview_session);
         OverviewGrid* grid = overview_session->GetGridWithRootWindow(root);
         bool should_animate = grid && grid->ShouldAnimateWallpaper();
-        float blur_sigma = RootWindowController::ForWindow(root)
-                               ->wallpaper_widget_controller()
-                               ->GetWallpaperBlur();
-        if (should_animate && animate_only &&
-            blur_sigma != kWallpaperBlurSigma) {
+        if (should_animate && animate_only) {
           root->AddObserver(this);
           roots_to_animate_.push_back(root);
           continue;
         }
         if (should_animate == animate_only)
-          ApplyBlur(root, value);
+          ApplyBlurAndOpacity(root, value);
       } else {
-        ApplyBlur(root, value);
+        ApplyBlurAndOpacity(root, value);
       }
     }
 
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index bcd5a66..119d363 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -11,7 +11,6 @@
 #include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/shelf_types.h"
 #include "ash/public/cpp/shell_window_ids.h"
-#include "ash/public/cpp/wallpaper_types.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/public/cpp/window_state_type.h"
 #include "ash/root_window_controller.h"
@@ -21,8 +20,6 @@
 #include "ash/shelf/shelf_constants.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
-#include "ash/wallpaper/wallpaper_controller.h"
-#include "ash/wallpaper/wallpaper_widget_controller.h"
 #include "ash/wm/desks/desks_bar_view.h"
 #include "ash/wm/overview/cleanup_animation_observer.h"
 #include "ash/wm/overview/drop_target_view.h"
@@ -50,8 +47,6 @@
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/compositor_extra/shadow.h"
-#include "ui/gfx/color_analysis.h"
-#include "ui/gfx/color_utils.h"
 #include "ui/gfx/geometry/safe_integer_conversions.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/views/background.h"
@@ -65,9 +60,6 @@
 namespace ash {
 namespace {
 
-// The color and opacity of the screen shield in overview.
-constexpr SkColor kShieldColor = SkColorSetARGB(255, 0, 0, 0);
-
 // The color and opacity of the overview selector.
 constexpr SkColor kWindowSelectionColor = SkColorSetARGB(36, 255, 255, 255);
 
@@ -75,10 +67,6 @@
 constexpr int kWindowSelectionRadius = 9;
 constexpr int kWindowSelectionShadowElevation = 24;
 
-// The base color which is mixed with the dark muted color from wallpaper to
-// form the shield widgets color.
-constexpr SkColor kShieldBaseColor = SkColorSetARGB(179, 0, 0, 0);
-
 // Windows are not allowed to get taller than this.
 constexpr int kMaxHeight = 512;
 
@@ -195,16 +183,6 @@
 class OverviewGrid::ShieldView : public views::View {
  public:
   ShieldView() {
-    background_view_ = new views::View();
-    background_view_->SetPaintToLayer(ui::LAYER_SOLID_COLOR);
-    background_view_->layer()->SetColor(kShieldBaseColor);
-    background_view_->layer()->SetOpacity(
-        !Shell::Get()
-                ->tablet_mode_controller()
-                ->IsTabletModeWindowManagerEnabled()
-            ? kShieldOpacity
-            : 0.f);
-
     label_ = new views::Label(
         l10n_util::GetStringUTF16(IDS_ASH_OVERVIEW_NO_RECENT_ITEMS),
         views::style::CONTEXT_LABEL);
@@ -226,7 +204,6 @@
     label_container_->layer()->SetOpacity(kNoItemsIndicatorBackgroundOpacity);
     label_container_->SetVisible(false);
 
-    AddChildView(background_view_);
     AddChildView(label_container_);
   }
 
@@ -246,10 +223,6 @@
     desks_bar_view_->Init();
   }
 
-  void SetBackgroundColor(SkColor color) {
-    background_view_->layer()->SetColor(color);
-  }
-
   void SetLabelVisibility(bool visible) {
     label_container_->SetVisible(visible);
   }
@@ -277,7 +250,6 @@
  protected:
   // views::View:
   void Layout() override {
-    background_view_->SetBoundsRect(GetLocalBounds());
     UpdateDesksBarBounds();
   }
 
@@ -328,7 +300,6 @@
   }
 
   // Owned by views heirarchy.
-  views::View* background_view_ = nullptr;
   RoundedRectView* label_container_ = nullptr;
   views::Label* label_ = nullptr;
   DesksBarView* desks_bar_view_ = nullptr;
@@ -434,22 +405,6 @@
 
 OverviewGrid::~OverviewGrid() = default;
 
-// static
-SkColor OverviewGrid::GetShieldColor() {
-  SkColor shield_color = kShieldColor;
-  // Extract the dark muted color from the wallpaper and mix it with
-  // |kShieldBaseColor|. Just use |kShieldBaseColor| if the dark muted color
-  // could not be extracted.
-  SkColor dark_muted_color =
-      Shell::Get()->wallpaper_controller()->GetProminentColor(
-          color_utils::ColorProfile());
-  if (dark_muted_color != ash::kInvalidWallpaperColor) {
-    shield_color =
-        color_utils::GetResultingPaintColor(kShieldBaseColor, dark_muted_color);
-  }
-  return shield_color;
-}
-
 void OverviewGrid::Shutdown() {
   ScreenRotationAnimator::GetForRootWindow(root_window_)->RemoveObserver(this);
 
@@ -1322,9 +1277,11 @@
   shield_view_ = new ShieldView();
   shield_widget_->SetContentsView(shield_view_);
   shield_view_->MaybeInitVirtualDesksBar();
-  shield_view_->SetBackgroundColor(GetShieldColor());
   shield_view_->SetGridBounds(bounds_);
 
+  // TODO(sammiequon): The shield widget is not anymore in most cases. Remove
+  // the shield widget and put the cannot snap widget and desks bar into their
+  // own widgets.
   if (animate) {
     shield_widget_->SetOpacity(initial_opacity);
     ScopedOverviewAnimationSettings settings(OVERVIEW_ANIMATION_SHIELD_FADE,
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h
index e1c14b4a..dc8f5574 100644
--- a/ash/wm/overview/overview_grid.h
+++ b/ash/wm/overview/overview_grid.h
@@ -61,9 +61,6 @@
                const gfx::Rect& bounds_in_screen);
   ~OverviewGrid() override;
 
-  // Returns the shield color that is used to darken the background of the grid.
-  static SkColor GetShieldColor();
-
   // Exits overview mode, fading out the |shield_widget_| if necessary.
   void Shutdown();
 
diff --git a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
index 4cac448..7e3a482 100644
--- a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
+++ b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
@@ -7,14 +7,15 @@
 #include <vector>
 
 #include "ash/home_screen/home_screen_controller.h"
+#include "ash/public/cpp/wallpaper_types.h"
 #include "ash/root_window_controller.h"
 #include "ash/scoped_animation_disabler.h"
 #include "ash/shell.h"
+#include "ash/wallpaper/wallpaper_controller.h"
 #include "ash/wallpaper/wallpaper_widget_controller.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_constants.h"
 #include "ash/wm/overview/overview_controller.h"
-#include "ash/wm/overview/overview_grid.h"
 #include "ash/wm/overview/overview_utils.h"
 #include "ash/wm/splitview/split_view_constants.h"
 #include "ash/wm/tablet_mode/tablet_mode_window_state.h"
@@ -23,6 +24,8 @@
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/display/screen.h"
+#include "ui/gfx/color_analysis.h"
+#include "ui/gfx/color_utils.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/coordinate_conversion.h"
 
@@ -40,6 +43,29 @@
 // window after drag ends and do not try to merge it back into source window.
 constexpr float kFlingToStayAsNewWindowThreshold = 2000.f;
 
+// The color and opacity of the screen shield.
+constexpr SkColor kShieldColor = SkColorSetARGB(255, 0, 0, 0);
+
+// The base color which is mixed with the dark muted color from wallpaper to
+// form the shield widgets color.
+constexpr SkColor kShieldBaseColor = SkColorSetARGB(179, 0, 0, 0);
+
+// Returns the shield color that is used to darken the background.
+SkColor GetShieldColor() {
+  SkColor shield_color = kShieldColor;
+  // Extract the dark muted color from the wallpaper and mix it with
+  // |kShieldBaseColor|. Just use |kShieldBaseColor| if the dark muted color
+  // could not be extracted.
+  SkColor dark_muted_color =
+      Shell::Get()->wallpaper_controller()->GetProminentColor(
+          color_utils::ColorProfile());
+  if (dark_muted_color != ash::kInvalidWallpaperColor) {
+    shield_color =
+        color_utils::GetResultingPaintColor(kShieldBaseColor, dark_muted_color);
+  }
+  return shield_color;
+}
+
 // The class to observe the source window's bounds change animation. It's used
 // to prevent the dragged window to merge back into the source window during
 // dragging. Only when the source window restores to its maximized window size,
@@ -147,7 +173,8 @@
     // Hide the home launcher if it's enabled during dragging.
     Shell::Get()->home_screen_controller()->OnWindowDragStarted();
 
-    // Blurs the wallpaper background.
+    // TODO: Do dimming and blurring in wallpaper to avoid creating another
+    // fullscreen widget. Blurs the wallpaper background.
     RootWindowController::ForWindow(root_window)
         ->wallpaper_widget_controller()
         ->SetWallpaperBlur(kWallpaperBlurSigma);
@@ -162,7 +189,7 @@
     widget_window->SetBounds(bounds);
     views::View* shield_view = new views::View();
     shield_view->SetPaintToLayer(ui::LAYER_SOLID_COLOR);
-    shield_view->layer()->SetColor(OverviewGrid::GetShieldColor());
+    shield_view->layer()->SetColor(GetShieldColor());
     shield_view->layer()->SetOpacity(kShieldOpacity);
     shield_widget_->SetContentsView(shield_view);
   }
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc
index e6bac9f8..61b3ed3 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller.cc
+++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -25,7 +25,7 @@
 #include "base/metrics/user_metrics.h"
 #include "base/time/default_tick_clock.h"
 #include "base/time/tick_clock.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/display/display.h"
 #include "ui/display/manager/display_manager.h"
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.h b/ash/wm/tablet_mode/tablet_mode_controller.h
index 71a56fc..3cf5de5 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller.h
+++ b/ash/wm/tablet_mode/tablet_mode_controller.h
@@ -22,7 +22,7 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
 #include "ui/aura/window_occlusion_tracker.h"
diff --git a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
index 90c50ef..fa38de8 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
@@ -31,7 +31,7 @@
 #include "base/test/metrics/user_action_tester.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "services/ws/public/cpp/input_devices/input_device_client_test_api.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/test/test_window_delegate.h"
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 6379ad9..c00e7ad 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -551,6 +551,8 @@
     "power_monitor/power_monitor_source.cc",
     "power_monitor/power_monitor_source.h",
     "power_monitor/power_observer.h",
+    "process/environment_internal.cc",
+    "process/environment_internal.h",
     "process/internal_linux.cc",
     "process/internal_linux.h",
     "process/kill.cc",
@@ -2458,6 +2460,7 @@
     "path_service_unittest.cc",
     "pickle_unittest.cc",
     "power_monitor/power_monitor_unittest.cc",
+    "process/environment_internal_unittest.cc",
     "process/launch_unittest_win.cc",
     "process/memory_unittest.cc",
     "process/memory_unittest_mac.h",
diff --git a/base/environment.cc b/base/environment.cc
index 3113fe2d..8e3afd89 100644
--- a/base/environment.cc
+++ b/base/environment.cc
@@ -4,10 +4,6 @@
 
 #include "base/environment.h"
 
-#include <stddef.h>
-
-#include <vector>
-
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
@@ -101,25 +97,6 @@
   }
 };
 
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-// Parses a null-terminated input string of an environment block. The key is
-// placed into the given string, and the total length of the line, including
-// the terminating null, is returned.
-size_t ParseEnvLine(const NativeEnvironmentString::value_type* input,
-                    NativeEnvironmentString* key) {
-  // Skip to the equals or end of the string, this is the key.
-  size_t cur = 0;
-  while (input[cur] && input[cur] != '=')
-    cur++;
-  *key = NativeEnvironmentString(&input[0], cur);
-
-  // Now just skip to the end of the string.
-  while (input[cur])
-    cur++;
-  return cur + 1;
-}
-#endif
-
 }  // namespace
 
 namespace env_vars {
@@ -143,57 +120,4 @@
   return GetVar(variable_name, nullptr);
 }
 
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-
-std::unique_ptr<char* []> AlterEnvironment(const char* const* const env,
-                                           const EnvironmentMap& changes) {
-  std::string value_storage;  // Holds concatenated null-terminated strings.
-  std::vector<size_t> result_indices;  // Line indices into value_storage.
-
-  // First build up all of the unchanged environment strings. These are
-  // null-terminated of the form "key=value".
-  std::string key;
-  for (size_t i = 0; env[i]; i++) {
-    size_t line_length = ParseEnvLine(env[i], &key);
-
-    // Keep only values not specified in the change vector.
-    auto found_change = changes.find(key);
-    if (found_change == changes.end()) {
-      result_indices.push_back(value_storage.size());
-      value_storage.append(env[i], line_length);
-    }
-  }
-
-  // Now append all modified and new values.
-  for (const auto& i : changes) {
-    if (!i.second.empty()) {
-      result_indices.push_back(value_storage.size());
-      value_storage.append(i.first);
-      value_storage.push_back('=');
-      value_storage.append(i.second);
-      value_storage.push_back(0);
-    }
-  }
-
-  size_t pointer_count_required =
-      result_indices.size() + 1 +  // Null-terminated array of pointers.
-      (value_storage.size() + sizeof(char*) - 1) / sizeof(char*);  // Buffer.
-  std::unique_ptr<char* []> result(new char*[pointer_count_required]);
-
-  // The string storage goes after the array of pointers.
-  char* storage_data = reinterpret_cast<char*>(
-      &result.get()[result_indices.size() + 1]);
-  if (!value_storage.empty())
-    memcpy(storage_data, value_storage.data(), value_storage.size());
-
-  // Fill array of pointers at the beginning of the result.
-  for (size_t i = 0; i < result_indices.size(); i++)
-    result[i] = &storage_data[result_indices[i]];
-  result[result_indices.size()] = 0;  // Null terminator.
-
-  return result;
-}
-
-#endif  // OS_POSIX || OS_FUCHSIA
-
 }  // namespace base
diff --git a/base/environment.h b/base/environment.h
index 37288e8..85206f8 100644
--- a/base/environment.h
+++ b/base/environment.h
@@ -38,42 +38,24 @@
   // Syntactic sugar for GetVar(variable_name, nullptr);
   virtual bool HasVar(StringPiece variable_name);
 
-  // Returns true on success, otherwise returns false.
+  // Returns true on success, otherwise returns false. This method should not
+  // be called in a multi-threaded process.
   virtual bool SetVar(StringPiece variable_name,
                       const std::string& new_value) = 0;
 
-  // Returns true on success, otherwise returns false.
+  // Returns true on success, otherwise returns false. This method should not
+  // be called in a multi-threaded process.
   virtual bool UnSetVar(StringPiece variable_name) = 0;
 };
 
-
 #if defined(OS_WIN)
-
-typedef string16 NativeEnvironmentString;
-typedef std::map<NativeEnvironmentString, NativeEnvironmentString>
-    EnvironmentMap;
-
+using NativeEnvironmentString = string16;
+using EnvironmentMap =
+    std::map<NativeEnvironmentString, NativeEnvironmentString>;
 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
-
-typedef std::string NativeEnvironmentString;
-typedef std::map<NativeEnvironmentString, NativeEnvironmentString>
-    EnvironmentMap;
-
-// Returns a modified environment vector constructed from the given environment
-// and the list of changes given in |changes|. Each key in the environment is
-// matched against the first element of the pairs. In the event of a match, the
-// value is replaced by the second of the pair, unless the second is empty, in
-// which case the key-value is removed.
-//
-// This Posix version takes and returns a Posix-style environment block, which
-// is a null-terminated list of pointers to null-terminated strings. The
-// returned array will have appended to it the storage for the array itself so
-// there is only one pointer to manage, but this means that you can't copy the
-// array without keeping the original around.
-BASE_EXPORT std::unique_ptr<char* []> AlterEnvironment(
-    const char* const* env,
-    const EnvironmentMap& changes);
-
+using NativeEnvironmentString = std::string;
+using EnvironmentMap =
+    std::map<NativeEnvironmentString, NativeEnvironmentString>;
 #endif
 
 }  // namespace base
diff --git a/base/environment_unittest.cc b/base/environment_unittest.cc
index 1746b95..f7387d4 100644
--- a/base/environment_unittest.cc
+++ b/base/environment_unittest.cc
@@ -99,44 +99,4 @@
   EXPECT_FALSE(env->HasVar(kFooUpper));
 }
 
-#if !defined(OS_WIN)
-
-TEST_F(EnvironmentTest, AlterEnvironment) {
-  const char* const empty[] = {nullptr};
-  const char* const a2[] = {"A=2", nullptr};
-  EnvironmentMap changes;
-  std::unique_ptr<char* []> e;
-
-  e = AlterEnvironment(empty, changes);
-  EXPECT_TRUE(e[0] == nullptr);
-
-  changes["A"] = "1";
-  e = AlterEnvironment(empty, changes);
-  EXPECT_EQ(std::string("A=1"), e[0]);
-  EXPECT_TRUE(e[1] == nullptr);
-
-  changes.clear();
-  changes["A"] = std::string();
-  e = AlterEnvironment(empty, changes);
-  EXPECT_TRUE(e[0] == nullptr);
-
-  changes.clear();
-  e = AlterEnvironment(a2, changes);
-  EXPECT_EQ(std::string("A=2"), e[0]);
-  EXPECT_TRUE(e[1] == nullptr);
-
-  changes.clear();
-  changes["A"] = "1";
-  e = AlterEnvironment(a2, changes);
-  EXPECT_EQ(std::string("A=1"), e[0]);
-  EXPECT_TRUE(e[1] == nullptr);
-
-  changes.clear();
-  changes["A"] = std::string();
-  e = AlterEnvironment(a2, changes);
-  EXPECT_TRUE(e[0] == nullptr);
-}
-
-#endif
-
 }  // namespace base
diff --git a/base/process/environment_internal.cc b/base/process/environment_internal.cc
new file mode 100644
index 0000000..2be296ef
--- /dev/null
+++ b/base/process/environment_internal.cc
@@ -0,0 +1,128 @@
+// Copyright 2019 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 "base/process/environment_internal.h"
+
+#include <stddef.h>
+
+#include <vector>
+
+namespace base {
+namespace internal {
+
+namespace {
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA) || defined(OS_WIN)
+// Parses a null-terminated input string of an environment block. The key is
+// placed into the given string, and the total length of the line, including
+// the terminating null, is returned.
+size_t ParseEnvLine(const NativeEnvironmentString::value_type* input,
+                    NativeEnvironmentString* key) {
+  // Skip to the equals or end of the string, this is the key.
+  size_t cur = 0;
+  while (input[cur] && input[cur] != '=')
+    cur++;
+  *key = NativeEnvironmentString(&input[0], cur);
+
+  // Now just skip to the end of the string.
+  while (input[cur])
+    cur++;
+  return cur + 1;
+}
+#endif
+
+}  // namespace
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+
+std::unique_ptr<char* []> AlterEnvironment(const char* const* const env,
+                                           const EnvironmentMap& changes) {
+  std::string value_storage;  // Holds concatenated null-terminated strings.
+  std::vector<size_t> result_indices;  // Line indices into value_storage.
+
+  // First build up all of the unchanged environment strings. These are
+  // null-terminated of the form "key=value".
+  std::string key;
+  for (size_t i = 0; env[i]; i++) {
+    size_t line_length = ParseEnvLine(env[i], &key);
+
+    // Keep only values not specified in the change vector.
+    auto found_change = changes.find(key);
+    if (found_change == changes.end()) {
+      result_indices.push_back(value_storage.size());
+      value_storage.append(env[i], line_length);
+    }
+  }
+
+  // Now append all modified and new values.
+  for (const auto& i : changes) {
+    if (!i.second.empty()) {
+      result_indices.push_back(value_storage.size());
+      value_storage.append(i.first);
+      value_storage.push_back('=');
+      value_storage.append(i.second);
+      value_storage.push_back(0);
+    }
+  }
+
+  size_t pointer_count_required =
+      result_indices.size() + 1 +  // Null-terminated array of pointers.
+      (value_storage.size() + sizeof(char*) - 1) / sizeof(char*);  // Buffer.
+  std::unique_ptr<char*[]> result(new char*[pointer_count_required]);
+
+  // The string storage goes after the array of pointers.
+  char* storage_data =
+      reinterpret_cast<char*>(&result.get()[result_indices.size() + 1]);
+  if (!value_storage.empty())
+    memcpy(storage_data, value_storage.data(), value_storage.size());
+
+  // Fill array of pointers at the beginning of the result.
+  for (size_t i = 0; i < result_indices.size(); i++)
+    result[i] = &storage_data[result_indices[i]];
+  result[result_indices.size()] = 0;  // Null terminator.
+
+  return result;
+}
+
+#elif defined(OS_WIN)
+
+NativeEnvironmentString AlterEnvironment(const wchar_t* env,
+                                         const EnvironmentMap& changes) {
+  NativeEnvironmentString result;
+
+  // First build up all of the unchanged environment strings.
+  const wchar_t* ptr = env;
+  while (*ptr) {
+    string16 key;
+    size_t line_length = ParseEnvLine(ptr, &key);
+
+    // Keep only values not specified in the change vector.
+    if (changes.find(key) == changes.end()) {
+      result.append(ptr, line_length);
+    }
+    ptr += line_length;
+  }
+
+  // Now append all modified and new values.
+  for (const auto& i : changes) {
+    // Windows environment blocks cannot handle keys or values with NULs.
+    CHECK_EQ(string16::npos, i.first.find(static_cast<wchar_t>(0)));
+    CHECK_EQ(string16::npos, i.second.find(static_cast<wchar_t>(0)));
+    if (!i.second.empty()) {
+      result += i.first;
+      result.push_back('=');
+      result += i.second;
+      result.push_back('\0');
+    }
+  }
+
+  // Add the terminating NUL.
+  result.push_back('\0');
+  return result;
+}
+
+#endif  // OS_POSIX || OS_FUCHSIA
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/process/environment_internal.h b/base/process/environment_internal.h
new file mode 100644
index 0000000..31338f132
--- /dev/null
+++ b/base/process/environment_internal.h
@@ -0,0 +1,52 @@
+// Copyright 2019 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.
+
+// This file contains internal routines that are called by other files in
+// base/process/.
+
+#ifndef BASE_PROCESS_ENVIRONMENT_INTERNAL_H_
+#define BASE_PROCESS_ENVIRONMENT_INTERNAL_H_
+
+#include <memory>
+
+#include "base/environment.h"
+#include "build/build_config.h"
+
+namespace base {
+namespace internal {
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+// Returns a modified environment vector constructed from the given environment
+// and the list of changes given in |changes|. Each key in the environment is
+// matched against the first element of the pairs. In the event of a match, the
+// value is replaced by the second of the pair, unless the second is empty, in
+// which case the key-value is removed.
+//
+// This POSIX version takes and returns a POSIX-style environment block, which
+// is a null-terminated list of pointers to null-terminated strings. The
+// returned array will have appended to it the storage for the array itself so
+// there is only one pointer to manage, but this means that you can't copy the
+// array without keeping the original around.
+BASE_EXPORT std::unique_ptr<char*[]> AlterEnvironment(
+    const char* const* env,
+    const EnvironmentMap& changes);
+#elif defined(OS_WIN)
+// Returns a modified environment vector constructed from the given environment
+// and the list of changes given in |changes|. Each key in the environment is
+// matched against the first element of the pairs. In the event of a match, the
+// value is replaced by the second of the pair, unless the second is empty, in
+// which case the key-value is removed.
+//
+// This Windows version takes and returns a Windows-style environment block,
+// which is a string containing several null-terminated strings followed by an
+// extra terminating null character. So, e.g., the environment A=1 B=2 is
+// represented as L"A=1\0B=2\0\0".
+BASE_EXPORT NativeEnvironmentString
+AlterEnvironment(const wchar_t* env, const EnvironmentMap& changes);
+#endif  // OS_*
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_PROCESS_ENVIRONMENT_INTERNAL_H_
diff --git a/base/process/environment_internal_unittest.cc b/base/process/environment_internal_unittest.cc
new file mode 100644
index 0000000..67617da
--- /dev/null
+++ b/base/process/environment_internal_unittest.cc
@@ -0,0 +1,161 @@
+// Copyright 2019 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 "base/process/environment_internal.h"
+
+#include <memory>
+#include <vector>
+
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+using EnvironmentInternalTest = PlatformTest;
+
+namespace base {
+namespace internal {
+
+#if defined(OS_WIN)
+
+namespace {
+void ExpectEnvironmentBlock(const std::vector<string16>& vars,
+                            const string16& block) {
+  string16 expected;
+  for (const auto& var : vars) {
+    expected += var;
+    expected.push_back('\0');
+  }
+  expected.push_back('\0');
+  EXPECT_EQ(expected, block);
+}
+}  // namespace
+
+TEST_F(EnvironmentInternalTest, AlterEnvironment) {
+  const wchar_t empty[] = {'\0'};
+  const wchar_t a2[] = {'A', '=', '2', '\0', '\0'};
+  const wchar_t a2b3[] = {'A', '=', '2', '\0', 'B', '=', '3', '\0', '\0'};
+  EnvironmentMap changes;
+  NativeEnvironmentString e;
+
+  e = AlterEnvironment(empty, changes);
+  ExpectEnvironmentBlock({}, e);
+
+  changes[L"A"] = L"1";
+  e = AlterEnvironment(empty, changes);
+  ExpectEnvironmentBlock({L"A=1"}, e);
+
+  changes.clear();
+  changes[L"A"] = string16();
+  e = AlterEnvironment(empty, changes);
+  ExpectEnvironmentBlock({}, e);
+
+  changes.clear();
+  e = AlterEnvironment(a2, changes);
+  ExpectEnvironmentBlock({L"A=2"}, e);
+
+  changes.clear();
+  changes[L"A"] = L"1";
+  e = AlterEnvironment(a2, changes);
+  ExpectEnvironmentBlock({L"A=1"}, e);
+
+  changes.clear();
+  changes[L"A"] = string16();
+  e = AlterEnvironment(a2, changes);
+  ExpectEnvironmentBlock({}, e);
+
+  changes.clear();
+  changes[L"A"] = string16();
+  changes[L"B"] = string16();
+  e = AlterEnvironment(a2b3, changes);
+  ExpectEnvironmentBlock({}, e);
+
+  changes.clear();
+  changes[L"A"] = string16();
+  e = AlterEnvironment(a2b3, changes);
+  ExpectEnvironmentBlock({L"B=3"}, e);
+
+  changes.clear();
+  changes[L"B"] = string16();
+  e = AlterEnvironment(a2b3, changes);
+  ExpectEnvironmentBlock({L"A=2"}, e);
+
+  changes.clear();
+  changes[L"A"] = L"1";
+  changes[L"C"] = L"4";
+  e = AlterEnvironment(a2b3, changes);
+  // AlterEnvironment() currently always puts changed entries at the end.
+  ExpectEnvironmentBlock({L"B=3", L"A=1", L"C=4"}, e);
+}
+
+#else  // !OS_WIN
+
+TEST_F(EnvironmentInternalTest, AlterEnvironment) {
+  const char* const empty[] = {nullptr};
+  const char* const a2[] = {"A=2", nullptr};
+  const char* const a2b3[] = {"A=2", "B=3", nullptr};
+  EnvironmentMap changes;
+  std::unique_ptr<char*[]> e;
+
+  e = AlterEnvironment(empty, changes);
+  EXPECT_TRUE(e[0] == nullptr);
+
+  changes["A"] = "1";
+  e = AlterEnvironment(empty, changes);
+  EXPECT_EQ(std::string("A=1"), e[0]);
+  EXPECT_TRUE(e[1] == nullptr);
+
+  changes.clear();
+  changes["A"] = std::string();
+  e = AlterEnvironment(empty, changes);
+  EXPECT_TRUE(e[0] == nullptr);
+
+  changes.clear();
+  e = AlterEnvironment(a2, changes);
+  EXPECT_EQ(std::string("A=2"), e[0]);
+  EXPECT_TRUE(e[1] == nullptr);
+
+  changes.clear();
+  changes["A"] = "1";
+  e = AlterEnvironment(a2, changes);
+  EXPECT_EQ(std::string("A=1"), e[0]);
+  EXPECT_TRUE(e[1] == nullptr);
+
+  changes.clear();
+  changes["A"] = std::string();
+  e = AlterEnvironment(a2, changes);
+  EXPECT_TRUE(e[0] == nullptr);
+
+  changes.clear();
+  changes["A"] = std::string();
+  changes["B"] = std::string();
+  e = AlterEnvironment(a2b3, changes);
+  EXPECT_TRUE(e[0] == nullptr);
+
+  changes.clear();
+  changes["A"] = std::string();
+  e = AlterEnvironment(a2b3, changes);
+  EXPECT_EQ(std::string("B=3"), e[0]);
+  EXPECT_TRUE(e[1] == nullptr);
+
+  changes.clear();
+  changes["B"] = std::string();
+  e = AlterEnvironment(a2b3, changes);
+  EXPECT_EQ(std::string("A=2"), e[0]);
+  EXPECT_TRUE(e[1] == nullptr);
+
+  changes.clear();
+  changes["A"] = "1";
+  changes["C"] = "4";
+  e = AlterEnvironment(a2b3, changes);
+  EXPECT_EQ(std::string("B=3"), e[0]);
+  // AlterEnvironment() currently always puts changed entries at the end.
+  EXPECT_EQ(std::string("A=1"), e[1]);
+  EXPECT_EQ(std::string("C=4"), e[2]);
+  EXPECT_TRUE(e[3] == nullptr);
+}
+
+#endif  // OS_WIN
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/process/launch.h b/base/process/launch.h
index 5b84b16..c4da984 100644
--- a/base/process/launch.h
+++ b/base/process/launch.h
@@ -165,20 +165,22 @@
   // the launched process if the current process has such permission.
   bool grant_foreground_privilege = false;
 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
-  // Set/unset environment variables. These are applied on top of the parent
-  // process environment.  Empty (the default) means to inherit the same
-  // environment. See AlterEnvironment().
-  EnvironmentMap environ;
-
-  // Clear the environment for the new process before processing changes from
-  // |environ|.
-  bool clear_environ = false;
-
   // Remap file descriptors according to the mapping of src_fd->dest_fd to
   // propagate FDs into the child process.
   FileHandleMappingVector fds_to_remap;
 #endif  // defined(OS_WIN)
 
+#if defined(OS_WIN) || defined(OS_POSIX) || defined(OS_FUCHSIA)
+  // Set/unset environment variables. These are applied on top of the parent
+  // process environment.  Empty (the default) means to inherit the same
+  // environment. See internal::AlterEnvironment().
+  EnvironmentMap environment;
+
+  // Clear the environment for the new process before processing changes from
+  // |environment|.
+  bool clear_environment = false;
+#endif  // OS_WIN || OS_POSIX || OS_FUCHSIA
+
 #if defined(OS_LINUX)
   // If non-zero, start the process using clone(), using flags as provided.
   // Unlike in clone, clone_flags may not contain a custom termination signal
diff --git a/base/process/launch_fuchsia.cc b/base/process/launch_fuchsia.cc
index 3e840cdf..34cbaad7 100644
--- a/base/process/launch_fuchsia.cc
+++ b/base/process/launch_fuchsia.cc
@@ -19,6 +19,7 @@
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/process/environment_internal.h"
 #include "base/scoped_generic.h"
 
 namespace base {
@@ -140,13 +141,13 @@
     argv_cstr.push_back(arg.c_str());
   argv_cstr.push_back(nullptr);
 
-  // Determine the environment to pass to the new process.
-  // If |clear_environ|, |environ| or |current_directory| are set then we
+  // Determine the environment to pass to the new process. If
+  // |clear_environment|, |environment| or |current_directory| are set then we
   // construct a new (possibly empty) environment, otherwise we let fdio_spawn()
   // clone the caller's environment into the new process.
   uint32_t spawn_flags = FDIO_SPAWN_CLONE_LDSVC | options.spawn_flags;
 
-  EnvironmentMap environ_modifications = options.environ;
+  EnvironmentMap environ_modifications = options.environment;
   if (!options.current_directory.empty()) {
     environ_modifications["PWD"] = options.current_directory.value();
   } else {
@@ -158,9 +159,11 @@
   std::unique_ptr<char* []> new_environ;
   if (!environ_modifications.empty()) {
     char* const empty_environ = nullptr;
-    char* const* old_environ = options.clear_environ ? &empty_environ : environ;
-    new_environ = AlterEnvironment(old_environ, environ_modifications);
-  } else if (!options.clear_environ) {
+    char* const* old_environ =
+        options.clear_environment ? &empty_environ : environ;
+    new_environ =
+        internal::AlterEnvironment(old_environ, environ_modifications);
+  } else if (!options.clear_environment) {
     spawn_flags |= FDIO_SPAWN_CLONE_ENVIRON;
   }
 
diff --git a/base/process/launch_mac.cc b/base/process/launch_mac.cc
index a72c9f1..7b3e3bda 100644
--- a/base/process/launch_mac.cc
+++ b/base/process/launch_mac.cc
@@ -16,6 +16,7 @@
 #include "base/logging.h"
 #include "base/mac/availability.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/process/environment_internal.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/trace_event/trace_event.h"
@@ -230,10 +231,13 @@
     argv_cstr.push_back(const_cast<char*>(arg.c_str()));
   argv_cstr.push_back(nullptr);
 
-  std::unique_ptr<char* []> owned_environ;
-  char** new_environ = options.clear_environ ? nullptr : *_NSGetEnviron();
-  if (!options.environ.empty()) {
-    owned_environ = AlterEnvironment(new_environ, options.environ);
+  std::unique_ptr<char*[]> owned_environ;
+  char* empty_environ = nullptr;
+  char** new_environ =
+      options.clear_environment ? &empty_environ : *_NSGetEnviron();
+  if (!options.environment.empty()) {
+    owned_environ =
+        internal::AlterEnvironment(new_environ, options.environment);
     new_environ = owned_environ.get();
   }
 
diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc
index fa2c0e9..a81a031b 100644
--- a/base/process/launch_posix.cc
+++ b/base/process/launch_posix.cc
@@ -35,6 +35,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/process/environment_internal.h"
 #include "base/process/process.h"
 #include "base/process/process_metrics.h"
 #include "base/strings/stringprintf.h"
@@ -300,10 +301,10 @@
   std::unique_ptr<char* []> new_environ;
   char* const empty_environ = nullptr;
   char* const* old_environ = GetEnvironment();
-  if (options.clear_environ)
+  if (options.clear_environment)
     old_environ = &empty_environ;
-  if (!options.environ.empty())
-    new_environ = AlterEnvironment(old_environ, options.environ);
+  if (!options.environment.empty())
+    new_environ = internal::AlterEnvironment(old_environ, options.environment);
 
   sigset_t full_sigset;
   sigfillset(&full_sigset);
@@ -439,7 +440,7 @@
       fd_shuffle2.push_back(InjectionArc(value.first, value.second, false));
     }
 
-    if (!options.environ.empty() || options.clear_environ)
+    if (!options.environment.empty() || options.clear_environment)
       SetEnvironment(new_environ.get());
 
     // fd_shuffle1 is mutated by this call because it cannot malloc.
diff --git a/base/process/launch_win.cc b/base/process/launch_win.cc
index a045d2dd..7fb71d8 100644
--- a/base/process/launch_win.cc
+++ b/base/process/launch_win.cc
@@ -21,6 +21,7 @@
 #include "base/debug/stack_trace.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
+#include "base/process/environment_internal.h"
 #include "base/process/kill.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -288,6 +289,10 @@
       return Process();
     }
 
+    // Environment options are not implemented for use with |as_user|.
+    DCHECK(!options.clear_environment);
+    DCHECK(options.environment.empty());
+
     BOOL launched = CreateProcessAsUser(
         options.as_user, nullptr, as_writable_wcstr(writable_cmdline), nullptr,
         nullptr, inherit_handles, flags, enviroment_block, current_directory,
@@ -299,11 +304,32 @@
       return Process();
     }
   } else {
+    wchar_t* new_environment = nullptr;
+    string16 env_storage;
+    if (options.clear_environment || !options.environment.empty()) {
+      if (options.clear_environment) {
+        static const wchar_t kEmptyEnvironment[] = {0};
+        env_storage =
+            internal::AlterEnvironment(kEmptyEnvironment, options.environment);
+      } else {
+        wchar_t* old_environment = GetEnvironmentStrings();
+        if (!old_environment) {
+          DPLOG(ERROR);
+          return Process();
+        }
+        env_storage =
+            internal::AlterEnvironment(old_environment, options.environment);
+        FreeEnvironmentStrings(old_environment);
+      }
+      new_environment = const_cast<wchar_t*>(env_storage.data());
+      flags |= CREATE_UNICODE_ENVIRONMENT;
+    }
+
     if (!CreateProcess(nullptr, as_writable_wcstr(writable_cmdline), nullptr,
-                       nullptr, inherit_handles, flags, nullptr,
+                       nullptr, inherit_handles, flags, new_environment,
                        current_directory, startup_info, &temp_process_info)) {
-      DPLOG(ERROR) << "Command line:" << std::endl << UTF16ToUTF8(cmdline)
-                   << std::endl;
+      DPLOG(ERROR) << "Command line:" << std::endl
+                   << UTF16ToUTF8(cmdline) << std::endl;
       return Process();
     }
   }
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc
index b08292b..55aa192 100644
--- a/base/process/process_util_unittest.cc
+++ b/base/process/process_util_unittest.cc
@@ -1213,96 +1213,6 @@
 
 #endif  // defined(OS_FUCHSIA)
 
-namespace {
-
-std::string TestLaunchProcess(const std::vector<std::string>& args,
-                              const EnvironmentMap& env_changes,
-                              const bool clear_environ,
-                              const int clone_flags) {
-  int fds[2];
-  PCHECK(pipe(fds) == 0);
-
-  LaunchOptions options;
-  options.wait = true;
-  options.environ = env_changes;
-  options.clear_environ = clear_environ;
-  options.fds_to_remap.emplace_back(fds[1], 1);
-#if defined(OS_LINUX)
-  options.clone_flags = clone_flags;
-#else
-  CHECK_EQ(0, clone_flags);
-#endif  // defined(OS_LINUX)
-  EXPECT_TRUE(LaunchProcess(args, options).IsValid());
-  PCHECK(IGNORE_EINTR(close(fds[1])) == 0);
-
-  char buf[512];
-  const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
-
-  PCHECK(IGNORE_EINTR(close(fds[0])) == 0);
-
-  return std::string(buf, n);
-}
-
-const char kLargeString[] =
-    "0123456789012345678901234567890123456789012345678901234567890123456789"
-    "0123456789012345678901234567890123456789012345678901234567890123456789"
-    "0123456789012345678901234567890123456789012345678901234567890123456789"
-    "0123456789012345678901234567890123456789012345678901234567890123456789"
-    "0123456789012345678901234567890123456789012345678901234567890123456789"
-    "0123456789012345678901234567890123456789012345678901234567890123456789"
-    "0123456789012345678901234567890123456789012345678901234567890123456789";
-
-}  // namespace
-
-TEST_F(ProcessUtilTest, LaunchProcess) {
-  const int no_clone_flags = 0;
-  const bool no_clear_environ = false;
-  const char kBaseTest[] = "BASE_TEST";
-  const std::vector<std::string> kPrintEnvCommand = {test_helper_path_.value(),
-                                                     "-e", kBaseTest};
-
-  EnvironmentMap env_changes;
-  env_changes[kBaseTest] = "bar";
-  EXPECT_EQ("bar", TestLaunchProcess(kPrintEnvCommand, env_changes,
-                                     no_clear_environ, no_clone_flags));
-  env_changes.clear();
-
-  EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */));
-  EXPECT_EQ("testing", TestLaunchProcess(kPrintEnvCommand, env_changes,
-                                         no_clear_environ, no_clone_flags));
-
-  env_changes[kBaseTest] = std::string();
-  EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
-                                  no_clear_environ, no_clone_flags));
-
-  env_changes[kBaseTest] = "foo";
-  EXPECT_EQ("foo", TestLaunchProcess(kPrintEnvCommand, env_changes,
-                                     no_clear_environ, no_clone_flags));
-
-  env_changes.clear();
-  EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */));
-  EXPECT_EQ(std::string(kLargeString),
-            TestLaunchProcess(kPrintEnvCommand, env_changes, no_clear_environ,
-                              no_clone_flags));
-
-  env_changes[kBaseTest] = "wibble";
-  EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
-                                        no_clear_environ, no_clone_flags));
-
-#if defined(OS_LINUX)
-  // Test a non-trival value for clone_flags.
-  EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
-                                        no_clear_environ, CLONE_FS));
-
-  EXPECT_EQ("wibble",
-            TestLaunchProcess(kPrintEnvCommand, env_changes,
-                              true /* clear_environ */, no_clone_flags));
-  env_changes.clear();
-  EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
-                                  true /* clear_environ */, no_clone_flags));
-#endif  // defined(OS_LINUX)
-}
-
 // There's no such thing as a parent process id on Fuchsia.
 #if !defined(OS_FUCHSIA)
 TEST_F(ProcessUtilTest, GetParentProcessId) {
@@ -1351,7 +1261,119 @@
 }
 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
 
-#endif  // !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#endif  // defined(OS_POSIX) || defined(OS_FUCHSIA)
+
+namespace {
+
+std::string TestLaunchProcess(const CommandLine& cmdline,
+                              const EnvironmentMap& env_changes,
+                              const bool clear_environment,
+                              const int clone_flags) {
+  LaunchOptions options;
+  options.wait = true;
+  options.environment = env_changes;
+  options.clear_environment = clear_environment;
+
+#if defined(OS_WIN)
+  HANDLE read_handle, write_handle;
+  PCHECK(CreatePipe(&read_handle, &write_handle, nullptr, 0));
+  File read_pipe(read_handle);
+  File write_pipe(write_handle);
+  options.stdin_handle = INVALID_HANDLE_VALUE;
+  options.stdout_handle = write_handle;
+  options.stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
+  options.handles_to_inherit.push_back(write_handle);
+#else
+  int fds[2];
+  PCHECK(pipe(fds) == 0);
+  File read_pipe(fds[0]);
+  File write_pipe(fds[1]);
+  options.fds_to_remap.emplace_back(fds[1], STDOUT_FILENO);
+#endif  // defined(OS_WIN)
+
+#if defined(OS_LINUX)
+  options.clone_flags = clone_flags;
+#else
+  CHECK_EQ(0, clone_flags);
+#endif  // defined(OS_LINUX)
+
+  EXPECT_TRUE(LaunchProcess(cmdline, options).IsValid());
+  write_pipe.Close();
+
+  char buf[512];
+  int n = read_pipe.ReadAtCurrentPos(buf, sizeof(buf));
+#if defined(OS_WIN)
+  // Closed pipes fail with ERROR_BROKEN_PIPE on Windows, rather than
+  // successfully reporting EOF.
+  if (n < 0 && GetLastError() == ERROR_BROKEN_PIPE) {
+    n = 0;
+  }
+#endif  // OS_WIN
+  PCHECK(n >= 0);
+
+  return std::string(buf, n);
+}
+
+const char kLargeString[] =
+    "0123456789012345678901234567890123456789012345678901234567890123456789"
+    "0123456789012345678901234567890123456789012345678901234567890123456789"
+    "0123456789012345678901234567890123456789012345678901234567890123456789"
+    "0123456789012345678901234567890123456789012345678901234567890123456789"
+    "0123456789012345678901234567890123456789012345678901234567890123456789"
+    "0123456789012345678901234567890123456789012345678901234567890123456789"
+    "0123456789012345678901234567890123456789012345678901234567890123456789";
+
+}  // namespace
+
+TEST_F(ProcessUtilTest, LaunchProcess) {
+  const int no_clone_flags = 0;
+  const bool no_clear_environ = false;
+  const FilePath::CharType kBaseTest[] = FILE_PATH_LITERAL("BASE_TEST");
+  const CommandLine kPrintEnvCommand(CommandLine::StringVector(
+      {test_helper_path_.value(), FILE_PATH_LITERAL("-e"), kBaseTest}));
+  std::unique_ptr<Environment> env = Environment::Create();
+
+  EnvironmentMap env_changes;
+  env_changes[kBaseTest] = FILE_PATH_LITERAL("bar");
+  EXPECT_EQ("bar", TestLaunchProcess(kPrintEnvCommand, env_changes,
+                                     no_clear_environ, no_clone_flags));
+  env_changes.clear();
+
+  EXPECT_TRUE(env->SetVar("BASE_TEST", "testing"));
+  EXPECT_EQ("testing", TestLaunchProcess(kPrintEnvCommand, env_changes,
+                                         no_clear_environ, no_clone_flags));
+
+  env_changes[kBaseTest] = FilePath::StringType();
+  EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
+                                  no_clear_environ, no_clone_flags));
+
+  env_changes[kBaseTest] = FILE_PATH_LITERAL("foo");
+  EXPECT_EQ("foo", TestLaunchProcess(kPrintEnvCommand, env_changes,
+                                     no_clear_environ, no_clone_flags));
+
+  env_changes.clear();
+  EXPECT_TRUE(env->SetVar("BASE_TEST", kLargeString));
+  EXPECT_EQ(std::string(kLargeString),
+            TestLaunchProcess(kPrintEnvCommand, env_changes, no_clear_environ,
+                              no_clone_flags));
+
+  env_changes[kBaseTest] = FILE_PATH_LITERAL("wibble");
+  EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
+                                        no_clear_environ, no_clone_flags));
+
+#if defined(OS_LINUX)
+  // Test a non-trival value for clone_flags.
+  EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
+                                        no_clear_environ, CLONE_FS));
+#endif  // defined(OS_LINUX)
+
+  EXPECT_EQ("wibble",
+            TestLaunchProcess(kPrintEnvCommand, env_changes,
+                              true /* clear_environ */, no_clone_flags));
+  env_changes.clear();
+  EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
+                                  true /* clear_environ */, no_clone_flags));
+}
 
 #if defined(OS_LINUX)
 MULTIPROCESS_TEST_MAIN(CheckPidProcess) {
diff --git a/base/profiler/win32_stack_frame_unwinder.cc b/base/profiler/win32_stack_frame_unwinder.cc
index fdf4885..d642ae0 100644
--- a/base/profiler/win32_stack_frame_unwinder.cc
+++ b/base/profiler/win32_stack_frame_unwinder.cc
@@ -78,7 +78,18 @@
 
 Win32StackFrameUnwinder::~Win32StackFrameUnwinder() {}
 
-bool Win32StackFrameUnwinder::TryUnwind(
+bool Win32StackFrameUnwinder::TryUnwind(CONTEXT* context,
+                                        const ModuleCache::Module* module) {
+  bool result =
+      TryUnwindImpl(unwind_functions_.get(), at_top_frame_, context, module);
+  at_top_frame_ = false;
+  return result;
+}
+
+// static
+bool Win32StackFrameUnwinder::TryUnwindImpl(
+    UnwindFunctions* unwind_functions,
+    bool at_top_frame,
     CONTEXT* context,
     // The module parameter, while not directly used, is still passed because it
     // represents an implicit dependency for this function. Having the Module
@@ -94,19 +105,16 @@
   ULONG64 image_base;
   // Try to look up unwind metadata for the current function.
   PRUNTIME_FUNCTION runtime_function =
-      unwind_functions_->LookupFunctionEntry(ContextPC(context), &image_base);
+      unwind_functions->LookupFunctionEntry(ContextPC(context), &image_base);
   DCHECK_EQ(module->GetBaseAddress(), image_base);
 
   if (runtime_function) {
-    unwind_functions_->VirtualUnwind(image_base, ContextPC(context),
-                                     runtime_function, context);
-    at_top_frame_ = false;
+    unwind_functions->VirtualUnwind(image_base, ContextPC(context),
+                                    runtime_function, context);
     return true;
   }
 
-  if (at_top_frame_) {
-    at_top_frame_ = false;
-
+  if (at_top_frame) {
     // This is a leaf function (i.e. a function that neither calls a function,
     // nor allocates any stack space itself).
 #if defined(ARCH_CPU_X86_64)
@@ -141,6 +149,6 @@
 
 Win32StackFrameUnwinder::Win32StackFrameUnwinder(
     std::unique_ptr<UnwindFunctions> unwind_functions)
-    : at_top_frame_(true), unwind_functions_(std::move(unwind_functions)) {}
+    : unwind_functions_(std::move(unwind_functions)) {}
 
 }  // namespace base
diff --git a/base/profiler/win32_stack_frame_unwinder.h b/base/profiler/win32_stack_frame_unwinder.h
index 94b186e..0fe08e8 100644
--- a/base/profiler/win32_stack_frame_unwinder.h
+++ b/base/profiler/win32_stack_frame_unwinder.h
@@ -72,13 +72,17 @@
   bool TryUnwind(CONTEXT* context, const ModuleCache::Module* module);
 
  private:
+  static bool TryUnwindImpl(UnwindFunctions* unwind_functions,
+                            bool at_top_frame,
+                            CONTEXT* context,
+                            const ModuleCache::Module* module);
+
   // This function is for internal and test purposes only.
   Win32StackFrameUnwinder(std::unique_ptr<UnwindFunctions> unwind_functions);
   friend class Win32StackFrameUnwinderTest;
 
   // State associated with each stack unwinding.
-  bool at_top_frame_;
-  bool unwind_info_present_for_all_frames_;
+  bool at_top_frame_ = true;
 
   std::unique_ptr<UnwindFunctions> unwind_functions_;
 
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
index b0985f6..8e3172f 100644
--- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc
+++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -44,6 +44,7 @@
 #include "base/test/trace_event_analyzer.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
 #include "base/trace_event/blame_context.h"
 #include "build/build_config.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -3871,8 +3872,8 @@
       base::Passed(std::make_unique<RunOnDestructionHelper>(std::move(task))));
 }
 
-base::OnceClosure PostOnDestructon(scoped_refptr<TestTaskQueue> task_queue,
-                                   base::OnceClosure task) {
+base::OnceClosure PostOnDestruction(scoped_refptr<TestTaskQueue> task_queue,
+                                    base::OnceClosure task) {
   return RunOnDestruction(base::BindOnce(
       [](base::OnceClosure task, scoped_refptr<TestTaskQueue> task_queue) {
         task_queue->task_runner()->PostTask(FROM_HERE, std::move(task));
@@ -3899,7 +3900,7 @@
                      [](scoped_refptr<TestTaskQueue> task_queue,
                         WaitableEvent* test_executed) {
                        task_queue->task_runner()->PostTask(
-                           FROM_HERE, PostOnDestructon(
+                           FROM_HERE, PostOnDestruction(
                                           task_queue, base::BindOnce([]() {})));
                        test_executed->Signal();
                      },
@@ -3933,11 +3934,11 @@
   bool run = false;
   task_queue->task_runner()->PostTask(
       FROM_HERE,
-      PostOnDestructon(
+      PostOnDestruction(
           task_queue,
-          PostOnDestructon(task_queue,
-                           RunOnDestruction(base::BindOnce(
-                               [](bool* run) { *run = true; }, &run)))));
+          PostOnDestruction(task_queue,
+                            RunOnDestruction(base::BindOnce(
+                                [](bool* run) { *run = true; }, &run)))));
 
   DestroySequenceManager();
 
@@ -4616,6 +4617,22 @@
   debug::SetCrashKeyImplementation(nullptr);
 }
 
+TEST_P(SequenceManagerTest, CrossQueueTaskPostingWhenQueueDeleted) {
+  MockTask task;
+  auto queue_1 = CreateTaskQueue();
+  auto queue_2 = CreateTaskQueue();
+
+  EXPECT_CALL(task, Run).Times(1);
+
+  queue_1->task_runner()->PostDelayedTask(
+      FROM_HERE, PostOnDestruction(queue_2, task.Get()),
+      TimeDelta::FromMinutes(1));
+
+  queue_1->ShutdownTaskQueue();
+
+  FastForwardUntilNoTasksRemain();
+}
+
 }  // namespace sequence_manager_impl_unittest
 }  // namespace internal
 }  // namespace sequence_manager
diff --git a/base/task/sequence_manager/task_queue.cc b/base/task/sequence_manager/task_queue.cc
index 1debbd9..34df1e55 100644
--- a/base/task/sequence_manager/task_queue.cc
+++ b/base/task/sequence_manager/task_queue.cc
@@ -155,11 +155,10 @@
 
 void TaskQueue::ShutdownTaskQueue() {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
-  base::internal::AutoSchedulerLock lock(impl_lock_);
   if (!impl_)
     return;
   if (!sequence_manager_) {
-    impl_.reset();
+    TakeTaskQueueImpl().reset();
     return;
   }
   impl_->SetBlameContext(nullptr);
@@ -329,6 +328,7 @@
 }
 
 std::unique_ptr<internal::TaskQueueImpl> TaskQueue::TakeTaskQueueImpl() {
+  base::internal::AutoSchedulerLock lock(impl_lock_);
   DCHECK(impl_);
   return std::move(impl_);
 }
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py
index 18e3faa..2aec4de 100755
--- a/build/android/gyp/proguard.py
+++ b/build/android/gyp/proguard.py
@@ -69,6 +69,9 @@
                     help='Minimum Android API level compatibility.')
   parser.add_option('--verbose', '-v', action='store_true',
                     help='Print all proguard output')
+  parser.add_option(
+      '--repackage-classes',
+      help='Unique package name given to an asynchronously proguarded module')
 
   options, _ = parser.parse_args(args)
 
@@ -155,9 +158,12 @@
   for config_file in options.proguard_configs:
     cmd += ['--pg-conf', config_file]
 
-  if options.apply_mapping:
+  if options.apply_mapping or options.repackage_classes:
     with open(tmp_config_path, 'w') as f:
-      f.write('-applymapping ' + options.apply_mapping)
+      if options.apply_mapping:
+        f.write('-applymapping \'%s\'\n' % (options.apply_mapping))
+      if options.repackage_classes:
+        f.write('-repackageclasses \'%s\'\n' % (options.repackage_classes))
     cmd += ['--pg-conf', tmp_config_path]
 
   if options.min_api:
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 98f909c..f3ae7cf 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -1184,6 +1184,13 @@
           args += invoker.proguard_args
         }
 
+        if (defined(invoker.repackage_classes)) {
+          args += [
+            "--repackage-classes",
+            "${invoker.repackage_classes}",
+          ]
+        }
+
         if (_proguarding_with_r8 && defined(invoker.min_sdk_version)) {
           args += [
             "--min-api",
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 8ebf456..bf4dfa0 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -4013,10 +4013,13 @@
 
     if (defined(invoker.extra_modules)) {
       _module_count = 0
-
-      # Prevent "unused variable".
       not_needed([ "_module_count" ])
 
+      # Define unique package for each async proguarding run.
+      _async_package_number = 1
+
+      not_needed([ "_async_package_number" ])
+
       foreach(_module, invoker.extra_modules) {
         _module_count += 1
         assert(defined(_module.name),
@@ -4054,6 +4057,7 @@
               proguard_mapping_path = _async_proguard_mapping_path
               forward_variables_from(invoker, [ "proguard_jar_path" ])
               build_config = _module.build_config
+              repackage_classes = "ap${_async_package_number}"
 
               deps = [
                 _module.module_target,
@@ -4062,6 +4066,7 @@
               output = _dex_zip
             }
             _module.async_dex_target = _async_dex_target
+            _async_package_number += 1
           }
 
           _async_modules += [ _module ]
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index d36df5f..d54752d 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-644d5b59c0682caf40ef946b411fa699a9d95cdc
\ No newline at end of file
+4a56f4ef93ff9a4556ceedf77b29b898aee8cecd
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 643ebc4..6877fa88 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-e34cc49eab53073ada98d13d2991fa6b92ddebd6
\ No newline at end of file
+fa8802142b8e9bab857b2c4fa19c44b3a3d17369
\ No newline at end of file
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index 78bf8c39..8104307 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -51,10 +51,8 @@
                         [ target_os ],
                         "value")
 
-  # TODO(https://crbug.com/904400): Re-enable this check once hermetic toolchain
-  # runs on latest macOS release [Mojave].
-  # assert(_result != 2,
-  #        "Do not allow building targets with the default" +
-  #            "hermetic toolchain if the minimum OS version is not met.")
+  assert(_result != 2,
+         "Do not allow building targets with the default" +
+             "hermetic toolchain if the minimum OS version is not met.")
   use_system_xcode = _result != 1
 }
diff --git a/chrome/android/java/res/drawable-v21/popup_bg_bottom_tinted.xml b/chrome/android/java/res/drawable-v21/popup_bg_bottom_tinted.xml
new file mode 100644
index 0000000..c8dff0c
--- /dev/null
+++ b/chrome/android/java/res/drawable-v21/popup_bg_bottom_tinted.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 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. -->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/popup_bg_bottom"
+    android:tint="@color/popup_bg_color"
+    android:tintMode="multiply" />
\ No newline at end of file
diff --git a/chrome/android/java/res/drawable/popup_bg_bottom_tinted.xml b/chrome/android/java/res/drawable/popup_bg_bottom_tinted.xml
new file mode 100644
index 0000000..5ce85ed
--- /dev/null
+++ b/chrome/android/java/res/drawable/popup_bg_bottom_tinted.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 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. -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:ignore="UnusedResources">
+    <item android:drawable="@drawable/popup_bg_bottom" />
+    <item>
+        <shape>
+            <corners android:radius="4dp" />
+            <solid android:color="@color/popup_bg_color" />
+        </shape>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
index 34c10f8b..a3e1f61 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
@@ -30,6 +30,7 @@
 import org.chromium.chrome.browser.feedback.FeedbackReporter;
 import org.chromium.chrome.browser.feedback.FeedbackSource;
 import org.chromium.chrome.browser.feedback.FeedbackSourceProvider;
+import org.chromium.chrome.browser.firstrun.FreIntentCreator;
 import org.chromium.chrome.browser.gsa.GSAHelper;
 import org.chromium.chrome.browser.help.HelpAndFeedback;
 import org.chromium.chrome.browser.historyreport.AppIndexingReporter;
@@ -389,4 +390,18 @@
         }
         return ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED;
     }
+
+    /**
+     * Returns a new {@link FreIntentCreator} instance.
+     */
+    public FreIntentCreator createFreIntentCreator() {
+        return new FreIntentCreator();
+    }
+
+    /**
+     * @return true if the webAppIntent has been intercepted.
+     */
+    public boolean interceptWebAppIntent(Intent intent, ChromeActivity activity) {
+        return false;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
index 69059143..6f5cf55 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
@@ -107,7 +107,7 @@
         mPopup = new ListPopupWindow(context, null, 0, R.style.NavigationPopupDialog);
         mPopup.setOnDismissListener(this::onDismiss);
         mPopup.setBackgroundDrawable(ApiCompatibilityUtils.getDrawable(resources,
-                anchorToBottom ? R.drawable.popup_bg_bottom : R.drawable.popup_bg_tinted));
+                anchorToBottom ? R.drawable.popup_bg_bottom_tinted : R.drawable.popup_bg_tinted));
         mPopup.setModal(true);
         mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
         mPopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java b/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java
index 05d668f..cc5c620 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java
@@ -81,7 +81,7 @@
             // Do not pass in wrappedCallback because this is a short-circuit reschedule. For UMA
             // purposes, tasks are started when runWithNative is called and does not consider
             // short-circuit reschedules such as this.
-            PostTask.postTask(UiThreadTaskTraits.DEFAULT, buildRescheduleRunnable(callback));
+            PostTask.postTask(UiThreadTaskTraits.BOOTSTRAP, buildRescheduleRunnable(callback));
             return true;
         }
 
@@ -120,14 +120,14 @@
     protected final void runWithNative(final Context context,
             final Runnable startWithNativeRunnable, final Runnable rescheduleRunnable) {
         if (isNativeLoaded()) {
-            PostTask.postTask(UiThreadTaskTraits.DEFAULT, startWithNativeRunnable);
+            PostTask.postTask(UiThreadTaskTraits.BOOTSTRAP, startWithNativeRunnable);
             return;
         }
 
         final BrowserParts parts = new EmptyBrowserParts() {
             @Override
             public void finishNativeInitialization() {
-                PostTask.postTask(UiThreadTaskTraits.DEFAULT, startWithNativeRunnable);
+                PostTask.postTask(UiThreadTaskTraits.BOOTSTRAP, startWithNativeRunnable);
             }
             @Override
             public boolean startServiceManagerOnly() {
@@ -135,11 +135,11 @@
             }
             @Override
             public void onStartupFailure() {
-                PostTask.postTask(UiThreadTaskTraits.DEFAULT, rescheduleRunnable);
+                PostTask.postTask(UiThreadTaskTraits.BOOTSTRAP, rescheduleRunnable);
             }
         };
 
-        PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() {
+        PostTask.postTask(UiThreadTaskTraits.BOOTSTRAP, new Runnable() {
             @Override
             public void run() {
                 // If task was stopped before we got here, don't start native initialization.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
index 60bfe0b..b353df5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
@@ -28,6 +28,7 @@
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder.DelegatedNotificationSmallIconFallback;
 import org.chromium.chrome.browser.notifications.NotificationBuilderBase;
+import org.chromium.chrome.browser.notifications.NotificationMetadata;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
 
 import java.util.List;
@@ -77,7 +78,10 @@
         mConnection.execute(scope, new Origin(scope).toString(), service -> {
             fallbackToIconFromServiceIfNecessary(builder, service);
 
-            Notification notification = builder.build();
+            NotificationMetadata metadata = new NotificationMetadata(
+                    NotificationUmaTracker.SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES,
+                    platformTag, platformId);
+            Notification notification = builder.build(metadata).getNotification();
 
             service.notify(platformTag, platformId, notification, channelDisplayName);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
index 6b2eefcd..1e2a76a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -6,23 +6,19 @@
 
 import android.accounts.Account;
 import android.app.Activity;
-import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
-import android.content.res.TypedArray;
 import android.net.Uri;
 import android.os.Bundle;
 import android.text.TextUtils;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.ApplicationStatus;
 import org.chromium.base.CommandLine;
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.LaunchIntentDispatcher;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
@@ -33,11 +29,9 @@
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
-import org.chromium.chrome.browser.webapps.WebappLauncherActivity;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.ChildAccountStatus;
 import org.chromium.components.signin.ChromeSigninController;
-import org.chromium.ui.base.DeviceFormFactor;
 
 import java.util.List;
 
@@ -51,7 +45,6 @@
  * }.start();
  */
 public abstract class FirstRunFlowSequencer  {
-    private static final int FIRST_RUN_EXPERIENCE_REQUEST_CODE = 101;
     private static final String TAG = "firstrun";
 
     private final Activity mActivity;
@@ -265,80 +258,6 @@
     }
 
     /**
-     * @return A generic intent to show the First Run Activity.
-     * @param context                        The context.
-     * @param fromIntent                     The intent that was used to launch Chrome.
-     * @param intentToLaunchAfterFreComplete The intent to launch when the user completes the FRE.
-     * @param requiresBroadcast              Whether the relaunch intent must be broadcasted.
-     */
-    private static Intent createGenericFirstRunIntent(Context context, Intent fromIntent,
-            Intent intentToLaunchAfterFreComplete, boolean requiresBroadcast) {
-        Intent intent = new Intent();
-        intent.setClassName(context, FirstRunActivity.class.getName());
-        intent.putExtra(FirstRunActivity.EXTRA_COMING_FROM_CHROME_ICON,
-                TextUtils.equals(fromIntent.getAction(), Intent.ACTION_MAIN));
-        intent.putExtra(FirstRunActivity.EXTRA_CHROME_LAUNCH_INTENT_IS_CCT,
-                LaunchIntentDispatcher.isCustomTabIntent(fromIntent));
-        addPendingIntent(context, intent, intentToLaunchAfterFreComplete, requiresBroadcast);
-
-        // Copy extras bundle from intent which was used to launch Chrome. Copying the extras
-        // enables the FirstRunActivity to locate the associated CustomTabsSession (if there
-        // is one) and to notify the connection of whether the FirstRunActivity was completed.
-        Bundle fromIntentExtras = fromIntent.getExtras();
-        if (fromIntentExtras != null) {
-            Bundle copiedFromExtras = new Bundle(fromIntentExtras);
-            intent.putExtra(FirstRunActivity.EXTRA_CHROME_LAUNCH_INTENT_EXTRAS, copiedFromExtras);
-        }
-
-        return intent;
-    }
-
-    /**
-     * Returns an intent to show the lightweight first run activity.
-     * @param context                        The context.
-     * @param fromIntent                     The intent that was used to launch Chrome.
-     * @param associatedAppName              The id of the application associated with the activity
-     *                                       being launched.
-     * @param intentToLaunchAfterFreComplete The intent to launch when the user completes the FRE.
-     * @param requiresBroadcast              Whether the relaunch intent must be broadcasted.
-     */
-    private static Intent createLightweightFirstRunIntent(Context context, Intent fromIntent,
-            String associatedAppName, Intent intentToLaunchAfterFreComplete,
-            boolean requiresBroadcast) {
-        Intent intent = new Intent();
-        intent.setClassName(context, LightweightFirstRunActivity.class.getName());
-        if (associatedAppName != null) {
-            intent.putExtra(
-                    LightweightFirstRunActivity.EXTRA_ASSOCIATED_APP_NAME, associatedAppName);
-        }
-        addPendingIntent(context, intent, intentToLaunchAfterFreComplete, requiresBroadcast);
-        return intent;
-    }
-
-    /**
-     * Adds fromIntent as a PendingIntent to the firstRunIntent. This should be used to add a
-     * PendingIntent that will be sent when first run is completed.
-     *
-     * @param context                        The context that corresponds to the Intent.
-     * @param firstRunIntent                 The intent that will be used to start first run.
-     * @param intentToLaunchAfterFreComplete The intent to launch when the user completes the FRE.
-     * @param requiresBroadcast              Whether or not the fromIntent must be broadcasted.
-     */
-    private static void addPendingIntent(Context context, Intent firstRunIntent,
-            Intent intentToLaunchAfterFreComplete, boolean requiresBroadcast) {
-        PendingIntent pendingIntent = null;
-        int pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT;
-        if (requiresBroadcast) {
-            pendingIntent = PendingIntent.getBroadcast(context, FIRST_RUN_EXPERIENCE_REQUEST_CODE,
-                    intentToLaunchAfterFreComplete, pendingIntentFlags);
-        } else {
-            pendingIntent = PendingIntent.getActivity(context, FIRST_RUN_EXPERIENCE_REQUEST_CODE,
-                    intentToLaunchAfterFreComplete, pendingIntentFlags);
-        }
-        firstRunIntent.putExtra(FirstRunActivity.EXTRA_FRE_COMPLETE_LAUNCH_INTENT, pendingIntent);
-    }
-
-    /**
      * Tries to launch the First Run Experience.  If the Activity was launched with the wrong Intent
      * flags, we first relaunch it to make sure it runs in its own task, then trigger First Run.
      *
@@ -362,42 +281,12 @@
 
         Log.d(TAG, "Redirecting user through FRE.");
         if ((fromIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
-            boolean isVrIntent = VrModuleProvider.getIntentDelegate().isVrIntent(fromIntent);
-            boolean isGenericFreActive = checkIsGenericFreActive();
-
-            Intent intentToLaunchAfterFreComplete = fromIntent;
-            String associatedAppNameForLightweightFre = null;
-            WebappLauncherActivity.FreParams webApkFreParams =
-                    WebappLauncherActivity.slowGenerateFreParamsIfIntentIsForWebApk(fromIntent);
-            if (webApkFreParams != null) {
-                intentToLaunchAfterFreComplete =
-                        webApkFreParams.getIntentToLaunchAfterFreComplete();
-                associatedAppNameForLightweightFre = webApkFreParams.webApkShortName();
-            }
-
-            // Launch the Generic First Run Experience if it was previously active.
-            Intent freIntent = null;
-            if (preferLightweightFre && !isGenericFreActive) {
-                freIntent = createLightweightFirstRunIntent(caller, fromIntent,
-                        associatedAppNameForLightweightFre, intentToLaunchAfterFreComplete,
-                        requiresBroadcast);
-            } else {
-                freIntent = createGenericFirstRunIntent(
-                        caller, fromIntent, intentToLaunchAfterFreComplete, requiresBroadcast);
-
-                if (shouldSwitchToTabbedMode(caller)) {
-                    freIntent.setClass(caller, TabbedModeFirstRunActivity.class);
-
-                    // We switched to TabbedModeFRE. We need to disable animation on the original
-                    // intent, to make transition seamless.
-                    intentToLaunchAfterFreComplete = new Intent(intentToLaunchAfterFreComplete);
-                    intentToLaunchAfterFreComplete.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
-                    addPendingIntent(
-                            caller, freIntent, intentToLaunchAfterFreComplete, requiresBroadcast);
-                }
-            }
+            FreIntentCreator intentCreator = AppHooks.get().createFreIntentCreator();
+            Intent freIntent = intentCreator.create(
+                    caller, fromIntent, requiresBroadcast, preferLightweightFre);
 
             if (!(caller instanceof Activity)) freIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            boolean isVrIntent = VrModuleProvider.getIntentDelegate().isVrIntent(fromIntent);
             if (isVrIntent) {
                 freIntent =
                         VrModuleProvider.getIntentDelegate().setupVrFreIntent(caller, freIntent);
@@ -414,42 +303,4 @@
         }
         return true;
     }
-
-    /** Returns whether the generic FRE is active. */
-    private static boolean checkIsGenericFreActive() {
-        for (Activity activity : ApplicationStatus.getRunningActivities()) {
-            // TabbedModeFirstRunActivity extends FirstRunActivity. LightweightFirstRunActivity
-            // does not.
-            if (activity instanceof FirstRunActivity) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * On tablets, where FRE activity is a dialog, transitions from fillscreen activities
-     * (the ones that use Theme.Chromium.TabbedMode, e.g. ChromeTabbedActivity) look ugly, because
-     * when FRE is started from CTA.onCreate(), currently running animation for CTA window
-     * is aborted. This is perceived as a flash of white and doesn't look good.
-     *
-     * To solve this, we added TabbedMode FRE activity, which has the same window background
-     * as Theme.Chromium.TabbedMode activities, but shows content in a FRE-like dialog.
-     *
-     * This function returns whether to use the TabbedModeFRE.
-     */
-    private static boolean shouldSwitchToTabbedMode(Context caller) {
-        // Caller must be an activity.
-        if (!(caller instanceof Activity)) return false;
-
-        // We must be on a tablet (where FRE is a dialog).
-        if (!DeviceFormFactor.isNonMultiDisplayContextOnTablet(caller)) return false;
-
-        // Caller must use a theme with @drawable/window_background (the same background
-        // used by TabbedModeFRE).
-        TypedArray a = caller.obtainStyledAttributes(new int[] {android.R.attr.windowBackground});
-        int backgroundResourceId = a.getResourceId(0 /* index */, 0);
-        a.recycle();
-        return (backgroundResourceId == R.drawable.window_background);
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FreIntentCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FreIntentCreator.java
new file mode 100644
index 0000000..a799660
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FreIntentCreator.java
@@ -0,0 +1,183 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.firstrun;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import org.chromium.base.ApplicationStatus;
+import org.chromium.chrome.browser.AppHooks;
+import org.chromium.chrome.browser.LaunchIntentDispatcher;
+import org.chromium.chrome.browser.webapps.WebappLauncherActivity;
+import org.chromium.ui.base.DeviceFormFactor;
+
+/**
+ * This class makes a decision what FRE type to launch and creates a corresponding intent. Should be
+ * instantiated using {@link AppHooks#createFreIntentCreator}.
+ */
+public class FreIntentCreator {
+    private static final int FIRST_RUN_EXPERIENCE_REQUEST_CODE = 101;
+
+    /**
+     * Creates an intent to launch the First Run Experience.
+     *
+     * @param caller               Activity instance that is requesting the first run.
+     * @param fromIntent           Intent used to launch the caller.
+     * @param requiresBroadcast    Whether or not the Intent triggers a BroadcastReceiver.
+     * @param preferLightweightFre Whether to prefer the Lightweight First Run Experience.
+     * @return Intent to launch First Run Experience.
+     */
+    public Intent create(Context caller, Intent fromIntent, boolean requiresBroadcast,
+            boolean preferLightweightFre) {
+        Intent intentToLaunchAfterFreComplete = fromIntent;
+        String associatedAppNameForLightweightFre = null;
+        WebappLauncherActivity.FreParams webApkFreParams =
+                WebappLauncherActivity.slowGenerateFreParamsIfIntentIsForWebApk(fromIntent);
+        if (webApkFreParams != null) {
+            intentToLaunchAfterFreComplete = webApkFreParams.getIntentToLaunchAfterFreComplete();
+            associatedAppNameForLightweightFre = webApkFreParams.webApkShortName();
+        }
+
+        // Launch the Generic First Run Experience if it was previously active.
+        boolean isGenericFreActive = checkIsGenericFreActive();
+        if (preferLightweightFre && !isGenericFreActive) {
+            return createLightweightFirstRunIntent(caller, fromIntent,
+                    associatedAppNameForLightweightFre, intentToLaunchAfterFreComplete,
+                    requiresBroadcast);
+        } else {
+            Intent freIntent = createGenericFirstRunIntent(
+                    caller, fromIntent, intentToLaunchAfterFreComplete, requiresBroadcast);
+
+            if (shouldSwitchToTabbedMode(caller)) {
+                freIntent.setClass(caller, TabbedModeFirstRunActivity.class);
+
+                // We switched to TabbedModeFRE. We need to disable animation on the original
+                // intent, to make transition seamless.
+                intentToLaunchAfterFreComplete = new Intent(intentToLaunchAfterFreComplete);
+                intentToLaunchAfterFreComplete.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
+                addPendingIntent(
+                        caller, freIntent, intentToLaunchAfterFreComplete, requiresBroadcast);
+            }
+            return freIntent;
+        }
+    }
+
+    /**
+     * Returns an intent to show the lightweight first run activity.
+     * @param context                        The context.
+     * @param fromIntent                     The intent that was used to launch Chrome.
+     * @param associatedAppName              The id of the application associated with the activity
+     *                                       being launched.
+     * @param intentToLaunchAfterFreComplete The intent to launch when the user completes the FRE.
+     * @param requiresBroadcast              Whether the relaunch intent must be broadcasted.
+     */
+    private static Intent createLightweightFirstRunIntent(Context context, Intent fromIntent,
+            String associatedAppName, Intent intentToLaunchAfterFreComplete,
+            boolean requiresBroadcast) {
+        Intent intent = new Intent();
+        intent.setClassName(context, LightweightFirstRunActivity.class.getName());
+        if (associatedAppName != null) {
+            intent.putExtra(
+                    LightweightFirstRunActivity.EXTRA_ASSOCIATED_APP_NAME, associatedAppName);
+        }
+        addPendingIntent(context, intent, intentToLaunchAfterFreComplete, requiresBroadcast);
+        return intent;
+    }
+
+    /**
+     * @return A generic intent to show the First Run Activity.
+     * @param context                        The context.
+     * @param fromIntent                     The intent that was used to launch Chrome.
+     * @param intentToLaunchAfterFreComplete The intent to launch when the user completes the FRE.
+     * @param requiresBroadcast              Whether the relaunch intent must be broadcasted.
+     */
+    private static Intent createGenericFirstRunIntent(Context context, Intent fromIntent,
+            Intent intentToLaunchAfterFreComplete, boolean requiresBroadcast) {
+        Intent intent = new Intent();
+        intent.setClassName(context, FirstRunActivity.class.getName());
+        intent.putExtra(FirstRunActivity.EXTRA_COMING_FROM_CHROME_ICON,
+                TextUtils.equals(fromIntent.getAction(), Intent.ACTION_MAIN));
+        intent.putExtra(FirstRunActivity.EXTRA_CHROME_LAUNCH_INTENT_IS_CCT,
+                LaunchIntentDispatcher.isCustomTabIntent(fromIntent));
+        addPendingIntent(context, intent, intentToLaunchAfterFreComplete, requiresBroadcast);
+
+        // Copy extras bundle from intent which was used to launch Chrome. Copying the extras
+        // enables the FirstRunActivity to locate the associated CustomTabsSession (if there
+        // is one) and to notify the connection of whether the FirstRunActivity was completed.
+        Bundle fromIntentExtras = fromIntent.getExtras();
+        if (fromIntentExtras != null) {
+            Bundle copiedFromExtras = new Bundle(fromIntentExtras);
+            intent.putExtra(FirstRunActivity.EXTRA_CHROME_LAUNCH_INTENT_EXTRAS, copiedFromExtras);
+        }
+
+        return intent;
+    }
+
+    /**
+     * Adds fromIntent as a PendingIntent to the firstRunIntent. This should be used to add a
+     * PendingIntent that will be sent when first run is completed.
+     *
+     * @param context                        The context that corresponds to the Intent.
+     * @param firstRunIntent                 The intent that will be used to start first run.
+     * @param intentToLaunchAfterFreComplete The intent to launch when the user completes the FRE.
+     * @param requiresBroadcast              Whether or not the fromIntent must be broadcasted.
+     */
+    private static void addPendingIntent(Context context, Intent firstRunIntent,
+            Intent intentToLaunchAfterFreComplete, boolean requiresBroadcast) {
+        PendingIntent pendingIntent = null;
+        int pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT;
+        if (requiresBroadcast) {
+            pendingIntent = PendingIntent.getBroadcast(context, FIRST_RUN_EXPERIENCE_REQUEST_CODE,
+                    intentToLaunchAfterFreComplete, pendingIntentFlags);
+        } else {
+            pendingIntent = PendingIntent.getActivity(context, FIRST_RUN_EXPERIENCE_REQUEST_CODE,
+                    intentToLaunchAfterFreComplete, pendingIntentFlags);
+        }
+        firstRunIntent.putExtra(FirstRunActivity.EXTRA_FRE_COMPLETE_LAUNCH_INTENT, pendingIntent);
+    }
+
+    /** Returns whether the generic FRE is active. */
+    private static boolean checkIsGenericFreActive() {
+        for (Activity activity : ApplicationStatus.getRunningActivities()) {
+            // TabbedModeFirstRunActivity extends FirstRunActivity. LightweightFirstRunActivity
+            // does not.
+            if (activity instanceof FirstRunActivity) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * On tablets, where FRE activity is a dialog, transitions from fillscreen activities
+     * (the ones that use Theme.Chromium.TabbedMode, e.g. ChromeTabbedActivity) look ugly, because
+     * when FRE is started from CTA.onCreate(), currently running animation for CTA window
+     * is aborted. This is perceived as a flash of white and doesn't look good.
+     *
+     * To solve this, we added TabbedMode FRE activity, which has the same window background
+     * as Theme.Chromium.TabbedMode activities, but shows content in a FRE-like dialog.
+     *
+     * This function returns whether to use the TabbedModeFRE.
+     */
+    private static boolean shouldSwitchToTabbedMode(Context caller) {
+        // Caller must be an activity.
+        if (!(caller instanceof Activity)) return false;
+
+        // We must be on a tablet (where FRE is a dialog).
+        if (!DeviceFormFactor.isNonMultiDisplayContextOnTablet(caller)) return false;
+
+        // Caller must use a theme with @drawable/window_background (the same background
+        // used by TabbedModeFRE).
+        TypedArray a = caller.obtainStyledAttributes(new int[] {android.R.attr.windowBackground});
+        int backgroundResourceId = a.getResourceId(0 /* index */, 0);
+        a.recycle();
+        return (backgroundResourceId == org.chromium.chrome.R.drawable.window_background);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotification.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotification.java
index 6324ed20..12a5e750 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotification.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotification.java
@@ -13,7 +13,7 @@
     private final Notification mNotification;
     private final NotificationMetadata mNotificationMetadata;
 
-    ChromeNotification(Notification notification, NotificationMetadata metadata) {
+    public ChromeNotification(Notification notification, NotificationMetadata metadata) {
         assert notification != null;
         assert metadata != null;
         mNotification = notification;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java
index 4e2bd2f..cfd66cc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java
@@ -99,7 +99,7 @@
 
     ChromeNotificationBuilder setCategory(String category);
 
-    Notification buildWithBigContentView(RemoteViews bigView);
+    ChromeNotification buildWithBigContentView(RemoteViews bigView);
 
     ChromeNotification buildWithBigTextStyle(String bigText);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java
index 6a185de..1199a5d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java
@@ -6,7 +6,6 @@
 
 import static org.chromium.chrome.browser.util.ViewUtils.dpToPx;
 
-import android.app.Notification;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -84,7 +83,7 @@
     }
 
     @Override
-    public Notification build() {
+    public ChromeNotification build(NotificationMetadata metadata) {
         // A note about RemoteViews and updating notifications. When a notification is passed to the
         // {@code NotificationManager} with the same tag and id as a previous notification, an
         // in-place update will be performed. In that case, the actions of all new
@@ -140,8 +139,8 @@
         // API level of methods you call on the builder.
         // TODO(crbug.com/697104) We should probably use a Compat builder.
         ChromeNotificationBuilder builder =
-                NotificationBuilderFactory.createChromeNotificationBuilder(
-                        false /* preferCompat */, mChannelId, mRemotePackageForBuilderContext);
+                NotificationBuilderFactory.createChromeNotificationBuilder(false /* preferCompat */,
+                        mChannelId, mRemotePackageForBuilderContext, metadata);
         builder.setTicker(mTickerText);
         builder.setContentIntent(mContentIntent);
         builder.setDeleteIntent(mDeleteIntent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java
index 448f7273..39e6295 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilder.java
@@ -327,13 +327,15 @@
 
     @Override
     @SuppressWarnings("deprecation")
-    public Notification buildWithBigContentView(RemoteViews view) {
+    public ChromeNotification buildWithBigContentView(RemoteViews view) {
+        assert mMetadata != null;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            return mBuilder.setCustomBigContentView(view).build();
+            return new ChromeNotification(
+                    mBuilder.setCustomBigContentView(view).build(), mMetadata);
         } else {
             Notification notification = mBuilder.build();
             notification.bigContentView = view;
-            return notification;
+            return new ChromeNotification(notification, mMetadata);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java
index b0e3639..bba758ca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java
@@ -130,8 +130,8 @@
      */
     @Nullable protected String mRemotePackageForBuilderContext;
 
-    protected PendingIntent mContentIntent;
-    protected PendingIntent mDeleteIntent;
+    protected PendingIntentProvider mContentIntent;
+    protected PendingIntentProvider mDeleteIntent;
     protected List<Action> mActions = new ArrayList<>(MAX_AUTHOR_PROVIDED_ACTION_BUTTONS);
     protected Action mSettingsAction;
     protected int mDefaults;
@@ -152,7 +152,7 @@
     /**
      * Combines all of the options that have been set and returns a new Notification object.
      */
-    public abstract Notification build();
+    public abstract ChromeNotification build(NotificationMetadata metadata);
 
     /**
      * Sets the title text of the notification.
@@ -300,7 +300,7 @@
     /**
      * Sets the PendingIntent to send when the notification is clicked.
      */
-    public NotificationBuilderBase setContentIntent(@Nullable PendingIntent intent) {
+    public NotificationBuilderBase setContentIntent(@Nullable PendingIntentProvider intent) {
         mContentIntent = intent;
         return this;
     }
@@ -309,7 +309,7 @@
      * Sets the PendingIntent to send when the notification is cleared by the user directly from the
      * notification panel.
      */
-    public NotificationBuilderBase setDeleteIntent(@Nullable PendingIntent intent) {
+    public NotificationBuilderBase setDeleteIntent(@Nullable PendingIntentProvider intent) {
         mDeleteIntent = intent;
         return this;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java
index 38d9841d..0fa040c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java
@@ -273,8 +273,9 @@
     }
 
     @Override
-    public Notification buildWithBigContentView(RemoteViews view) {
-        return mBuilder.setCustomBigContentView(view).build();
+    public ChromeNotification buildWithBigContentView(RemoteViews view) {
+        assert mMetadata != null;
+        return new ChromeNotification(mBuilder.setCustomBigContentView(view).build(), mMetadata);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
index 96177d5..bb78e66 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -321,9 +321,9 @@
      *        the notification is not associated with a WebAPK.
      * @param actionIndex The zero-based index of the action button, or -1 if not applicable.
      */
-    private PendingIntent makePendingIntent(Context context, String action, String notificationId,
-            String origin, String scopeUrl, String profileId, boolean incognito,
-            String webApkPackage, int actionIndex) {
+    private PendingIntentProvider makePendingIntent(Context context, String action,
+            String notificationId, String origin, String scopeUrl, String profileId,
+            boolean incognito, String webApkPackage, int actionIndex) {
         Uri intentData = makeIntentData(notificationId, origin, actionIndex);
         Intent intent = new Intent(action, intentData);
         intent.setClass(context, NotificationService.Receiver.class);
@@ -346,7 +346,7 @@
             intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         }
 
-        return PendingIntent.getBroadcast(
+        return PendingIntentProvider.getBroadcast(
                 context, PENDING_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
     }
 
@@ -529,10 +529,10 @@
         Context context = ContextUtils.getApplicationContext();
         Resources res = context.getResources();
 
-        PendingIntent clickIntent = makePendingIntent(context,
+        PendingIntentProvider clickIntent = makePendingIntent(context,
                 NotificationConstants.ACTION_CLICK_NOTIFICATION, notificationId, origin, scopeUrl,
                 profileId, incognito, webApkPackage, -1 /* actionIndex */);
-        PendingIntent closeIntent = makePendingIntent(context,
+        PendingIntentProvider closeIntent = makePendingIntent(context,
                 NotificationConstants.ACTION_CLOSE_NOTIFICATION, notificationId, origin, scopeUrl,
                 profileId, incognito, webApkPackage, -1 /* actionIndex */);
 
@@ -562,7 +562,7 @@
         }
 
         for (int actionIndex = 0; actionIndex < actions.length; actionIndex++) {
-            PendingIntent intent = makePendingIntent(context,
+            PendingIntentProvider intent = makePendingIntent(context,
                     NotificationConstants.ACTION_CLICK_NOTIFICATION, notificationId, origin,
                     scopeUrl, profileId, incognito, webApkPackage, actionIndex);
             ActionInfo action = actions[actionIndex];
@@ -571,9 +571,10 @@
             Bitmap actionIcon = hasImage ? null : action.icon;
             if (action.type == NotificationActionType.TEXT) {
                 notificationBuilder.addTextAction(
-                        actionIcon, action.title, intent, action.placeholder);
+                        actionIcon, action.title, intent.getPendingIntent(), action.placeholder);
             } else {
-                notificationBuilder.addButtonAction(actionIcon, action.title, intent);
+                notificationBuilder.addButtonAction(
+                        actionIcon, action.title, intent.getPendingIntent());
             }
         }
 
@@ -618,10 +619,13 @@
             notificationBuilder.addSettingsAction(
                     settingsIconId, settingsTitle, pendingSettingsIntent);
 
-            Notification notification = notificationBuilder.build();
-            mNotificationManager.notify(notificationId, PLATFORM_ID, notification);
+            ChromeNotification notification = notificationBuilder.build(new NotificationMetadata(
+                    NotificationUmaTracker.SystemNotificationType.SITES,
+                    notificationId /* notificationTag */, PLATFORM_ID /* notificationId */));
+            mNotificationManager.notify(notification);
             NotificationUmaTracker.getInstance().onNotificationShown(
-                    NotificationUmaTracker.SystemNotificationType.SITES, notification);
+                    NotificationUmaTracker.SystemNotificationType.SITES,
+                    notification.getNotification());
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java
index 3dc01a01..2bce469 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java
@@ -20,13 +20,13 @@
     }
 
     @Override
-    public Notification build() {
+    public ChromeNotification build(NotificationMetadata metadata) {
         // Note: this is not a NotificationCompat builder so be mindful of the
         // API level of methods you call on the builder.
         // TODO(crbug.com/697104) We should probably use a Compat builder.
         ChromeNotificationBuilder builder =
-                NotificationBuilderFactory.createChromeNotificationBuilder(
-                        false /* preferCompat */, mChannelId, mRemotePackageForBuilderContext);
+                NotificationBuilderFactory.createChromeNotificationBuilder(false /* preferCompat */,
+                        mChannelId, mRemotePackageForBuilderContext, metadata);
 
         builder.setContentTitle(mTitle);
         builder.setContentText(mBody);
@@ -66,6 +66,6 @@
             // Public versions only supported since L, and createPublicNotification requires L+.
             builder.setPublicVersion(createPublicNotification(mContext));
         }
-        return builder.build();
+        return builder.buildChromeNotification();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSetting.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSetting.java
index b18b298..26168fa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSetting.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSetting.java
@@ -29,12 +29,7 @@
     public static String toString(@ContentSettingValues int value) {
         assert ContentSettingValues.DEFAULT == 0;
         assert ContentSettingValues.NUM_SETTINGS == STRING_VALUES.length;
-
-        for (int i = 0; i < ContentSettingValues.NUM_SETTINGS; ++i) {
-            if (i == value) return STRING_VALUES[i];
-        }
-        assert false;
-        return "";
+        return STRING_VALUES[value];
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java
index 98c1986..c43b700 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java
@@ -669,9 +669,6 @@
                                 mShouldShowConfirmationPageWhenAttachedToWindow = true;
                             }
                         }
-
-                        @Override
-                        public void onSystemAccountsChanged() {}
                     });
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
index 211e5b9..633e4f2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
@@ -436,9 +436,6 @@
                         if (mDestroyed) return;
                         runStateMachineAndSignin(settingsClicked);
                     }
-
-                    @Override
-                    public void onSystemAccountsChanged() {}
                 };
         accountTrackerService.addSystemAccountsSeededListener(listener);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
index 85453be..41b3cc6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -186,7 +186,7 @@
         if (accountsChanged) {
             // Account details have changed so inform the token service that credentials
             // should now be available.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
         }
 
         if (mProfileSyncService != null && AndroidSyncSettings.get().isSyncEnabled()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
index e0fb454..9734304 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
@@ -362,7 +362,11 @@
         tabState.parentId = tab.getParentId();
         tabState.timestampMillis = tab.getTimestampMillis();
         tabState.tabLaunchTypeAtCreation = tab.getLaunchTypeAtInitialTabCreation();
-        tabState.themeColor = TabThemeColorHelper.getColor(tab);
+        // Don't save the actual default theme color because it could change on night mode state
+        // changed.
+        tabState.themeColor = TabThemeColorHelper.isDefaultColorUsed(tab)
+                ? TabState.UNSPECIFIED_THEME_COLOR
+                : TabThemeColorHelper.getColor(tab);
         tabState.rootId = tab.getRootId();
         return tabState;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java
index 0c961654..231b73a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java
@@ -18,6 +18,8 @@
 import org.chromium.base.Log;
 import org.chromium.chrome.browser.metrics.WebApkUma;
 import org.chromium.chrome.browser.notifications.NotificationBuilderBase;
+import org.chromium.chrome.browser.notifications.NotificationMetadata;
+import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
 import org.chromium.webapk.lib.client.WebApkServiceConnectionManager;
 import org.chromium.webapk.lib.runtime_library.IWebApkApi;
 
@@ -95,8 +97,12 @@
                         channelName = ContextUtils.getApplicationContext().getString(
                                 org.chromium.chrome.R.string.webapk_notification_channel_name);
                     }
-                    api.notifyNotificationWithChannel(
-                            platformTag, platformID, notificationBuilder.build(), channelName);
+                    NotificationMetadata metadata = new NotificationMetadata(
+                            NotificationUmaTracker.SystemNotificationType.WEBAPK, platformTag,
+                            platformID);
+
+                    api.notifyNotificationWithChannel(platformTag, platformID,
+                            notificationBuilder.build(metadata).getNotification(), channelName);
                 }
                 WebApkUma.recordNotificationPermissionStatus(notificationPermissionEnabled);
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 11cd4a3..d6b81bcf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -33,6 +33,7 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.SingleTabActivity;
 import org.chromium.chrome.browser.WarmupManager;
@@ -155,6 +156,8 @@
     protected void onNewIntent(Intent intent) {
         if (intent == null) return;
 
+        if (AppHooks.get().interceptWebAppIntent(intent, this)) return;
+
         super.onNewIntent(intent);
 
         WebappInfo newWebappInfo = popWebappInfo(WebappInfo.idFromIntent(intent));
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index ed22cb4..5169993 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -731,6 +731,7 @@
   "java/src/org/chromium/chrome/browser/firstrun/FirstRunView.java",
   "java/src/org/chromium/chrome/browser/firstrun/FirstRunViewPager.java",
   "java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java",
+  "java/src/org/chromium/chrome/browser/firstrun/FreIntentCreator.java",
   "java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java",
   "java/src/org/chromium/chrome/browser/firstrun/SigninFirstRunFragment.java",
   "java/src/org/chromium/chrome/browser/firstrun/TabbedModeFirstRunActivity.java",
@@ -1841,6 +1842,11 @@
     "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java",
     "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageTopLayout.java",
     "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabObserver.java",
+    "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java",
+    "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java",
+    "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarProperties.java",
+    "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarView.java",
+    "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarViewBinder.java",
   ]
 } else {
   chrome_java_sources += [ "touchless/fallback/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java" ]
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java
index f109e0e..5851d84 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java
@@ -47,6 +47,9 @@
  */
 @RunWith(BaseJUnit4ClassRunner.class)
 public class CustomNotificationBuilderTest {
+    private static final String NOTIFICATION_TAG = "TestNotificationTag";
+    private static final int NOTIFICATION_ID = 99;
+
     @Rule
     public NativeLibraryTestRule mActivityTestRule = new NativeLibraryTestRule();
 
@@ -63,8 +66,8 @@
     public void testSetAll() {
         Context context = InstrumentationRegistry.getTargetContext();
 
-        PendingIntent contentIntent = createIntent(context, "Content");
-        PendingIntent deleteIntent = createIntent(context, "Delete");
+        PendingIntentProvider contentIntent = createIntent(context, "Content");
+        PendingIntentProvider deleteIntent = createIntent(context, "Delete");
 
         Bitmap smallIcon =
                 BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_chrome);
@@ -72,25 +75,26 @@
         Bitmap largeIcon = createIcon(Color.RED);
         Bitmap actionIcon = createIcon(Color.WHITE);
 
-        Notification notification = new CustomNotificationBuilder(context)
-                                            .setSmallIconId(R.drawable.ic_chrome)
-                                            .setLargeIcon(largeIcon)
-                                            .setTitle("title")
-                                            .setBody("body")
-                                            .setOrigin("origin")
-                                            .setChannelId(ChannelDefinitions.ChannelId.SITES)
-                                            .setTicker("ticker")
-                                            .setDefaults(Notification.DEFAULT_ALL)
-                                            .setVibrate(new long[] {100L})
-                                            .setContentIntent(contentIntent)
-                                            .setDeleteIntent(deleteIntent)
-                                            .addButtonAction(actionIcon, "button",
-                                                    createIntent(context, "ActionButtonOne"))
-                                            .addButtonAction(actionIcon, "button",
-                                                    createIntent(context, "ActionButtonTwo"))
-                                            .addSettingsAction(0 /* iconId */, "settings",
-                                                    createIntent(context, "SettingsButton"))
-                                            .build();
+        NotificationBuilderBase builder =
+                new CustomNotificationBuilder(context)
+                        .setSmallIconId(R.drawable.ic_chrome)
+                        .setLargeIcon(largeIcon)
+                        .setTitle("title")
+                        .setBody("body")
+                        .setOrigin("origin")
+                        .setChannelId(ChannelDefinitions.ChannelId.SITES)
+                        .setTicker("ticker")
+                        .setDefaults(Notification.DEFAULT_ALL)
+                        .setVibrate(new long[] {100L})
+                        .setContentIntent(contentIntent)
+                        .setDeleteIntent(deleteIntent)
+                        .addButtonAction(actionIcon, "button",
+                                createIntent(context, "ActionButtonOne").getPendingIntent())
+                        .addButtonAction(actionIcon, "button",
+                                createIntent(context, "ActionButtonTwo").getPendingIntent())
+                        .addSettingsAction(0 /* iconId */, "settings",
+                                createIntent(context, "SettingsButton").getPendingIntent());
+        Notification notification = buildNotification(builder);
 
         assertSmallNotificationIconAsExpected(context, notification, smallIcon);
         assertLargeNotificationIconAsExpected(context, notification, largeIcon);
@@ -114,8 +118,6 @@
         Assert.assertEquals(Notification.DEFAULT_ALL, notification.defaults);
         Assert.assertEquals(1, notification.vibrate.length);
         Assert.assertEquals(100L, notification.vibrate[0]);
-        Assert.assertSame(contentIntent, notification.contentIntent);
-        Assert.assertSame(deleteIntent, notification.deleteIntent);
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             // Notification.publicVersion was added in Android L.
@@ -144,9 +146,9 @@
     @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228")
     public void testZeroActionButtons() {
         Context context = InstrumentationRegistry.getTargetContext();
-        Notification notification = new CustomNotificationBuilder(context)
-                                            .setChannelId(ChannelDefinitions.ChannelId.SITES)
-                                            .build();
+        NotificationBuilderBase builder = new CustomNotificationBuilder(context).setChannelId(
+                ChannelDefinitions.ChannelId.SITES);
+        Notification notification = buildNotification(builder);
         View bigView = notification.bigContentView.apply(context, new LinearLayout(context));
         ArrayList<View> buttons = new ArrayList<>();
         bigView.findViewsWithText(buttons, "button", View.FIND_VIEWS_WITH_TEXT);
@@ -163,21 +165,23 @@
     @DisableIf.Build(sdk_is_greater_than = 23, message = "crbug.com/779228")
     public void testMaxActionButtons() {
         Context context = InstrumentationRegistry.getTargetContext();
-        NotificationBuilderBase builder = new CustomNotificationBuilder(context)
-                                                  .setChannelId(ChannelDefinitions.ChannelId.SITES)
-                                                  .addButtonAction(null /* iconBitmap */, "button",
-                                                          createIntent(context, "ActionButtonOne"))
-                                                  .addButtonAction(null /* iconBitmap */, "button",
-                                                          createIntent(context, "ActionButtonTwo"));
+        NotificationBuilderBase builder =
+                new CustomNotificationBuilder(context)
+                        .setChannelId(ChannelDefinitions.ChannelId.SITES)
+                        .addButtonAction(null /* iconBitmap */, "button",
+                                createIntent(context, "ActionButtonOne").getPendingIntent())
+                        .addButtonAction(null /* iconBitmap */, "button",
+                                createIntent(context, "ActionButtonTwo").getPendingIntent());
         try {
-            builder.addButtonAction(
-                    null /* iconBitmap */, "button", createIntent(context, "ActionButtonThree"));
+            builder.addButtonAction(null /* iconBitmap */, "button",
+                    createIntent(context, "ActionButtonThree").getPendingIntent());
             Assert.fail(
                     "This statement should not be reached as the previous statement should throw.");
         } catch (IllegalStateException e) {
             Assert.assertEquals("Cannot add more than 2 actions.", e.getMessage());
         }
-        Notification notification = builder.build();
+
+        Notification notification = buildNotification(builder);
         View bigView = notification.bigContentView.apply(context, new LinearLayout(context));
         ArrayList<View> buttons = new ArrayList<>();
         bigView.findViewsWithText(buttons, "button", View.FIND_VIEWS_WITH_TEXT);
@@ -194,12 +198,11 @@
 
         Bitmap largeIcon = createIcon(Color.RED);
 
-        Notification notification = new CustomNotificationBuilder(context)
-                                            .setChannelId(ChannelDefinitions.ChannelId.SITES)
-                                            .setLargeIcon(largeIcon)
-                                            .setSmallIconId(R.drawable.ic_chrome)
-                                            .build();
-
+        NotificationBuilderBase builder = new CustomNotificationBuilder(context)
+                                                  .setChannelId(ChannelDefinitions.ChannelId.SITES)
+                                                  .setLargeIcon(largeIcon)
+                                                  .setSmallIconId(R.drawable.ic_chrome);
+        Notification notification = buildNotification(builder);
         assertLargeNotificationIconAsExpected(context, notification, largeIcon);
     }
 
@@ -211,11 +214,11 @@
 
         Bitmap smallIcon = createIcon(Color.RED);
 
-        Notification notification = new CustomNotificationBuilder(context)
-                .setChannelId(ChannelDefinitions.ChannelId.SITES)
-                .setSmallIconForContent(smallIcon)
-                .setStatusBarIcon(smallIcon)
-                .build();
+        NotificationBuilderBase builder = new CustomNotificationBuilder(context)
+                                                  .setChannelId(ChannelDefinitions.ChannelId.SITES)
+                                                  .setSmallIconForContent(smallIcon)
+                                                  .setStatusBarIcon(smallIcon);
+        Notification notification = buildNotification(builder);
 
         // Note that small icon as a Bitmap should be present on pre-M, even though it can't
         // be shown in the status bar
@@ -229,12 +232,13 @@
         Context context = InstrumentationRegistry.getTargetContext();
         Bitmap actionIcon = createIcon(Color.RED);
 
-        Notification notification = new CustomNotificationBuilder(context)
-                .setChannelId(ChannelDefinitions.ChannelId.SITES)
-                .setSmallIconId(R.drawable.ic_chrome)
-                .addButtonAction(actionIcon, "button",
-                        createIntent(context, "ActionButton"))
-                .build();
+        NotificationBuilderBase builder =
+                new CustomNotificationBuilder(context)
+                        .setChannelId(ChannelDefinitions.ChannelId.SITES)
+                        .setSmallIconId(R.drawable.ic_chrome)
+                        .addButtonAction(actionIcon, "button",
+                                createIntent(context, "ActionButton").getPendingIntent());
+        Notification notification = buildNotification(builder);
 
         Bitmap whiteIcon = createIcon(Color.WHITE);
 
@@ -265,7 +269,7 @@
     public void testCharSequenceLimits() {
         Context context = InstrumentationRegistry.getTargetContext();
         int maxLength = CustomNotificationBuilder.MAX_CHARSEQUENCE_LENGTH;
-        Notification notification =
+        NotificationBuilderBase builder =
                 new CustomNotificationBuilder(context)
                         .setTitle(createString('a', maxLength + 1))
                         .setBody(createString('b', maxLength + 1))
@@ -273,8 +277,9 @@
                         .setChannelId(ChannelDefinitions.ChannelId.SITES)
                         .setTicker(createString('d', maxLength + 1))
                         .addButtonAction(null /* iconBitmap */, createString('e', maxLength + 1),
-                                createIntent(context, "ActionButtonOne"))
-                        .build();
+                                createIntent(context, "ActionButtonOne").getPendingIntent());
+        Notification notification = buildNotification(builder);
+
         View compactView = notification.contentView.apply(context, new LinearLayout(context));
         View bigView = notification.bigContentView.apply(context, new LinearLayout(context));
 
@@ -330,7 +335,7 @@
                         .setOrigin("https://www.google.com")
                         .setChannelId(ChannelDefinitions.ChannelId.SITES);
 
-        Notification notification = notificationBuilder.build();
+        Notification notification = buildNotification(notificationBuilder);
 
         Bitmap expectedIcon = NotificationBuilderBase.createIconGenerator(context.getResources())
                                       .generateIconForUrl("https://www.google.com");
@@ -350,7 +355,7 @@
                         .setChannelId(ChannelDefinitions.ChannelId.SITES)
                         .setLargeIcon(null);
 
-        Notification notification = notificationBuilder.build();
+        Notification notification = buildNotification(notificationBuilder);
 
         Bitmap expectedIcon = NotificationBuilderBase.createIconGenerator(context.getResources())
                                       .generateIconForUrl("https://www.chromium.org");
@@ -377,7 +382,7 @@
                         .setChannelId(ChannelDefinitions.ChannelId.SITES)
                         .addTextAction(null, "Action Title", null, "Placeholder");
 
-        Notification notification = notificationBuilder.build();
+        Notification notification = buildNotification(notificationBuilder);
 
         Assert.assertEquals(1, notification.actions.length);
         Assert.assertEquals("Action Title", notification.actions[0].title);
@@ -455,9 +460,9 @@
         return result;
     }
 
-    private static PendingIntent createIntent(Context context, String action) {
+    private static PendingIntentProvider createIntent(Context context, String action) {
         Intent intent = new Intent("CustomNotificationBuilderTest." + action);
-        return PendingIntent.getBroadcast(
+        return PendingIntentProvider.getBroadcast(
                 context, 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
     }
 
@@ -472,4 +477,11 @@
                 new int[] {color}, 1 /* width */, 1 /* height */, Bitmap.Config.ARGB_8888);
         return icon.copy(Bitmap.Config.ARGB_8888, true /* isMutable */);
     }
+
+    private static Notification buildNotification(NotificationBuilderBase builder) {
+        NotificationMetadata metadata =
+                new NotificationMetadata(NotificationUmaTracker.SystemNotificationType.SITES,
+                        NOTIFICATION_TAG, NOTIFICATION_ID);
+        return builder.build(metadata).getNotification();
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationBuilderBaseTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationBuilderBaseTest.java
index 7a2609d..1cd8105 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationBuilderBaseTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationBuilderBaseTest.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.notifications;
 
-import android.app.Notification;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -68,7 +67,7 @@
 
         NotificationBuilderBase notificationBuilder = new NotificationBuilderBase(resources) {
             @Override
-            public Notification build() {
+            public ChromeNotification build(NotificationMetadata metadata) {
                 return null;
             }
         };
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilderTest.java
index 40dc6bc..84bb1a49 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilderTest.java
@@ -44,6 +44,9 @@
  */
 @RunWith(BaseJUnit4ClassRunner.class)
 public class StandardNotificationBuilderTest {
+    private static final String NOTIFICATION_TAG = "TestNotificationTag";
+    private static final int NOTIFICATION_ID = 99;
+
     @Rule
     public NativeLibraryTestRule mActivityTestRule = new NativeLibraryTestRule();
 
@@ -55,7 +58,7 @@
     }
 
     private NotificationBuilderBase createAllOptionsBuilder(
-            PendingIntent[] outContentAndDeleteIntents) {
+            PendingIntentProvider[] outContentAndDeleteIntents) {
         if (outContentAndDeleteIntents == null || outContentAndDeleteIntents.length != 2) {
             throw new IllegalArgumentException();
         }
@@ -63,11 +66,11 @@
         Context context = InstrumentationRegistry.getTargetContext();
 
         Intent contentIntent = new Intent("contentIntent");
-        outContentAndDeleteIntents[0] = PendingIntent.getBroadcast(
+        outContentAndDeleteIntents[0] = PendingIntentProvider.getBroadcast(
                 context, 0 /* requestCode */, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
         Intent deleteIntent = new Intent("deleteIntent");
-        outContentAndDeleteIntents[1] = PendingIntent.getBroadcast(
+        outContentAndDeleteIntents[1] = PendingIntentProvider.getBroadcast(
                 context, 1 /* requestCode */, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
         Bitmap image = Bitmap.createBitmap(
@@ -100,13 +103,20 @@
                 .addSettingsAction(0 /* iconId */, "settings", null /* intent */);
     }
 
+    private Notification buildNotification(NotificationBuilderBase builder) {
+        NotificationMetadata metadata =
+                new NotificationMetadata(NotificationUmaTracker.SystemNotificationType.SITES,
+                        NOTIFICATION_TAG, NOTIFICATION_ID);
+        return builder.build(metadata).getNotification();
+    }
+
     @Test
     @SmallTest
     @Feature({"Browser", "Notifications"})
     public void testSetAll() {
-        PendingIntent[] contentAndDeleteIntents = new PendingIntent[2];
+        PendingIntentProvider[] contentAndDeleteIntents = new PendingIntentProvider[2];
         NotificationBuilderBase builder = createAllOptionsBuilder(contentAndDeleteIntents);
-        Notification notification = builder.build();
+        Notification notification = buildNotification(builder);
 
         Assert.assertEquals("title", NotificationTestUtil.getExtraTitle(notification));
         Assert.assertEquals("body", NotificationTestUtil.getExtraText(notification));
@@ -136,8 +146,6 @@
         Assert.assertEquals(Notification.DEFAULT_ALL, notification.defaults);
         Assert.assertEquals(1, notification.vibrate.length);
         Assert.assertEquals(100L, notification.vibrate[0]);
-        Assert.assertEquals(contentAndDeleteIntents[0], notification.contentIntent);
-        Assert.assertEquals(contentAndDeleteIntents[1], notification.deleteIntent);
         Notification.Action[] actions = NotificationTestUtil.getActions(notification);
         Assert.assertEquals(3, actions.length);
         Assert.assertEquals("button 1", NotificationTestUtil.getActionTitle(actions[0]));
@@ -163,10 +171,10 @@
     @SmallTest
     @Feature({"Browser", "Notifications"})
     public void testBigTextStyle() {
-        PendingIntent[] contentAndDeleteIntents = new PendingIntent[2];
+        PendingIntentProvider[] contentAndDeleteIntents = new PendingIntentProvider[2];
         NotificationBuilderBase builder = createAllOptionsBuilder(contentAndDeleteIntents);
         builder.setImage(null);
-        Notification notification = builder.build();
+        Notification notification = buildNotification(builder);
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             // EXTRA_TEMPLATE was added in Android L; style cannot be verified in earlier versions.
@@ -189,7 +197,7 @@
         notificationBuilder.setStatusBarIcon(bitmap);
         notificationBuilder.setChannelId(ChannelDefinitions.ChannelId.SITES);
 
-        Notification notification = notificationBuilder.build();
+        Notification notification = buildNotification(notificationBuilder);
 
         Bitmap result = NotificationTestUtil.getSmallIconFromNotification(context, notification);
 
@@ -204,7 +212,7 @@
             // Check using the same bitmap on another builder gives the same result.
             NotificationBuilderBase otherBuilder = new StandardNotificationBuilder(context);
             otherBuilder.setStatusBarIcon(bitmap).setChannelId(ChannelDefinitions.ChannelId.SITES);
-            Notification otherNotification = otherBuilder.build();
+            Notification otherNotification = buildNotification(otherBuilder);
             Assert.assertTrue(expected.sameAs(
                     NotificationTestUtil.getSmallIconFromNotification(context, otherNotification)));
         } else {
@@ -224,19 +232,19 @@
     public void testRenotifyWithCustomBadgeDoesNotCrash() {
         Context context = InstrumentationRegistry.getTargetContext();
 
-        Notification notification = new StandardNotificationBuilder(context)
-                                            .setChannelId(ChannelDefinitions.ChannelId.SITES)
-                                            .setSmallIconId(R.drawable.ic_chrome)
-                                            .build();
+        NotificationBuilderBase builder = new StandardNotificationBuilder(context)
+                                                  .setChannelId(ChannelDefinitions.ChannelId.SITES)
+                                                  .setSmallIconId(R.drawable.ic_chrome);
+        Notification notification = buildNotification(builder);
 
         Bitmap bitmap = Bitmap.createBitmap(new int[] {Color.BLUE}, 1, 1, Bitmap.Config.ARGB_8888);
 
-        Notification notificationWithBitmap =
+        NotificationBuilderBase otherBuilder =
                 new StandardNotificationBuilder(context)
                         .setChannelId(ChannelDefinitions.ChannelId.SITES)
                         .setSmallIconId(R.drawable.ic_chrome)
-                        .setStatusBarIcon(bitmap)
-                        .build();
+                        .setStatusBarIcon(bitmap);
+        Notification notificationWithBitmap = buildNotification(otherBuilder);
 
         NotificationManager notificationManager =
                 (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
@@ -257,7 +265,7 @@
                         .setChannelId(ChannelDefinitions.ChannelId.SITES)
                         .addTextAction(null, "Action Title", null, "Placeholder");
 
-        Notification notification = notificationBuilder.build();
+        Notification notification = buildNotification(notificationBuilder);
 
         Assert.assertEquals(1, notification.actions.length);
         Assert.assertEquals("Action Title", notification.actions[0].title);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java
index 5ef40ca..65633c8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java
@@ -86,7 +86,7 @@
     public void tearDown() {
         ThreadUtils.runOnUiThreadBlocking(() -> {
             mChromeSigninController.setSignedInAccountName(null);
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
         });
         SigninHelper.resetSharedPrefs();
         SigninTestUtil.resetSigninState();
@@ -129,10 +129,10 @@
 
     @Test
     @MediumTest
-    public void testValidateAccountsNoAccountsRegisteredAndNoSignedInUser() {
+    public void testUpdateAccountListNoAccountsRegisteredAndNoSignedInUser() {
         ThreadUtils.runOnUiThreadBlocking(() -> {
             // Run test.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
 
             // Ensure no calls have been made to the observer.
             Assert.assertEquals(0, mObserver.getAvailableCallCount());
@@ -143,12 +143,12 @@
 
     @Test
     @MediumTest
-    public void testValidateAccountsOneAccountsRegisteredAndNoSignedInUser() {
+    public void testUpdateAccountListOneAccountsRegisteredAndNoSignedInUser() {
         addAccount(TEST_ACCOUNT_HOLDER_1);
 
         ThreadUtils.runOnUiThreadBlocking(() -> {
             // Run test.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
 
             // Ensure no calls have been made to the observer.
             Assert.assertEquals(0, mObserver.getAvailableCallCount());
@@ -159,7 +159,7 @@
 
     @Test
     @MediumTest
-    public void testValidateAccountsOneAccountsRegisteredSignedIn() {
+    public void testUpdateAccountListOneAccountsRegisteredSignedIn() {
         addAccount(TEST_ACCOUNT_HOLDER_1);
 
         ThreadUtils.runOnUiThreadBlocking(() -> {
@@ -167,21 +167,15 @@
             mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
 
             // Run test.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
 
             // Ensure one call for the signed in account.
             Assert.assertEquals(1, mObserver.getAvailableCallCount());
             Assert.assertEquals(0, mObserver.getRevokedCallCount());
             Assert.assertEquals(0, mObserver.getLoadedCallCount());
 
-            // Validate again and make sure no new calls are made.
-            mOAuth2TokenService.validateAccounts(false);
-            Assert.assertEquals(1, mObserver.getAvailableCallCount());
-            Assert.assertEquals(0, mObserver.getRevokedCallCount());
-            Assert.assertEquals(0, mObserver.getLoadedCallCount());
-
-            // Validate again with force notifications and make sure one new calls is made.
-            mOAuth2TokenService.validateAccounts(true);
+            // Validate again and make sure one new call is made.
+            mOAuth2TokenService.updateAccountList();
             Assert.assertEquals(2, mObserver.getAvailableCallCount());
             Assert.assertEquals(0, mObserver.getRevokedCallCount());
             Assert.assertEquals(0, mObserver.getLoadedCallCount());
@@ -190,7 +184,7 @@
 
     @Test
     @MediumTest
-    public void testValidateAccountsSingleAccountWithoutChanges() {
+    public void testUpdateAccountListSingleAccountThenAddOne() {
         addAccount(TEST_ACCOUNT_HOLDER_1);
 
         ThreadUtils.runOnUiThreadBlocking(() -> {
@@ -198,30 +192,7 @@
             mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
 
             // Run one validation.
-            mOAuth2TokenService.validateAccounts(false);
-            Assert.assertEquals(1, mObserver.getAvailableCallCount());
-            Assert.assertEquals(0, mObserver.getRevokedCallCount());
-            Assert.assertEquals(0, mObserver.getLoadedCallCount());
-
-            // Re-run validation.
-            mOAuth2TokenService.validateAccounts(false);
-            Assert.assertEquals(1, mObserver.getAvailableCallCount());
-            Assert.assertEquals(0, mObserver.getRevokedCallCount());
-            Assert.assertEquals(0, mObserver.getLoadedCallCount());
-        });
-    }
-
-    @Test
-    @MediumTest
-    public void testValidateAccountsSingleAccountThenAddOne() {
-        addAccount(TEST_ACCOUNT_HOLDER_1);
-
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            // Mark user as signed in.
-            mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
-
-            // Run one validation.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
             Assert.assertEquals(1, mObserver.getAvailableCallCount());
             Assert.assertEquals(0, mObserver.getRevokedCallCount());
             Assert.assertEquals(0, mObserver.getLoadedCallCount());
@@ -232,8 +203,8 @@
 
         ThreadUtils.runOnUiThreadBlocking(() -> {
             // Re-run validation.
-            mOAuth2TokenService.validateAccounts(false);
-            Assert.assertEquals(2, mObserver.getAvailableCallCount());
+            mOAuth2TokenService.updateAccountList();
+            Assert.assertEquals(3, mObserver.getAvailableCallCount());
             Assert.assertEquals(0, mObserver.getRevokedCallCount());
             Assert.assertEquals(0, mObserver.getLoadedCallCount());
         });
@@ -241,7 +212,7 @@
 
     @Test
     @MediumTest
-    public void testValidateAccountsTwoAccountsThenRemoveOne() {
+    public void testUpdateAccountListTwoAccountsThenRemoveOne() {
         // Add accounts.
         addAccount(TEST_ACCOUNT_HOLDER_1);
         addAccount(TEST_ACCOUNT_HOLDER_2);
@@ -251,16 +222,18 @@
             mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
 
             // Run one validation.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
             Assert.assertEquals(2, mObserver.getAvailableCallCount());
+            Assert.assertEquals(0, mObserver.getRevokedCallCount());
+            Assert.assertEquals(0, mObserver.getLoadedCallCount());
         });
 
         removeAccount(TEST_ACCOUNT_HOLDER_2);
 
         ThreadUtils.runOnUiThreadBlocking(() -> {
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
 
-            Assert.assertEquals(2, mObserver.getAvailableCallCount());
+            Assert.assertEquals(3, mObserver.getAvailableCallCount());
             Assert.assertEquals(1, mObserver.getRevokedCallCount());
             Assert.assertEquals(0, mObserver.getLoadedCallCount());
         });
@@ -268,7 +241,7 @@
 
     @Test
     @MediumTest
-    public void testValidateAccountsTwoAccountsThenRemoveAll() {
+    public void testUpdateAccountListTwoAccountsThenRemoveAll() {
         // Add accounts.
         addAccount(TEST_ACCOUNT_HOLDER_1);
         addAccount(TEST_ACCOUNT_HOLDER_2);
@@ -277,8 +250,10 @@
             // Mark user as signed in.
             mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
 
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
             Assert.assertEquals(2, mObserver.getAvailableCallCount());
+            Assert.assertEquals(0, mObserver.getRevokedCallCount());
+            Assert.assertEquals(0, mObserver.getLoadedCallCount());
         });
 
         // Remove all.
@@ -287,7 +262,8 @@
 
         ThreadUtils.runOnUiThreadBlocking(() -> {
             // Re-validate and run checks.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
+            Assert.assertEquals(2, mObserver.getAvailableCallCount());
             Assert.assertEquals(2, mObserver.getRevokedCallCount());
             Assert.assertEquals(0, mObserver.getLoadedCallCount());
         });
@@ -296,7 +272,7 @@
     @Test
     @MediumTest
     @RetryOnFailure
-    public void testValidateAccountsTwoAccountsThenRemoveAllSignOut() {
+    public void testUpdateAccountListTwoAccountsThenRemoveAllSignOut() {
         // Add accounts.
         addAccount(TEST_ACCOUNT_HOLDER_1);
         addAccount(TEST_ACCOUNT_HOLDER_2);
@@ -305,8 +281,10 @@
             // Mark user as signed in.
             mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
 
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
             Assert.assertEquals(2, mObserver.getAvailableCallCount());
+            Assert.assertEquals(0, mObserver.getRevokedCallCount());
+            Assert.assertEquals(0, mObserver.getLoadedCallCount());
 
             // Remove all.
             mChromeSigninController.setSignedInAccountName(null);
@@ -317,7 +295,8 @@
 
         ThreadUtils.runOnUiThreadBlocking(() -> {
             // Re-validate and run checks.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
+            Assert.assertEquals(2, mObserver.getAvailableCallCount());
             Assert.assertEquals(2, mObserver.getRevokedCallCount());
             Assert.assertEquals(0, mObserver.getLoadedCallCount());
         });
@@ -325,7 +304,7 @@
 
     @Test
     @MediumTest
-    public void testValidateAccountsTwoAccountsRegisteredAndOneSignedIn() {
+    public void testUpdateAccountListTwoAccountsRegisteredAndOneSignedIn() {
         // Add accounts.
         addAccount(TEST_ACCOUNT_HOLDER_1);
         addAccount(TEST_ACCOUNT_HOLDER_2);
@@ -335,7 +314,7 @@
             mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
 
             // Run test.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
 
             // All accounts will be notified. It is up to the observer
             // to design if any action is needed.
@@ -347,13 +326,13 @@
 
     @Test
     @MediumTest
-    public void testValidateAccountsNoAccountsRegisteredButSignedIn() {
+    public void testUpdateAccountListNoAccountsRegisteredButSignedIn() {
         ThreadUtils.runOnUiThreadBlocking(() -> {
             // Mark user as signed in without setting up the account.
             mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
 
             // Run test.
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
 
             // Ensure no calls have been made to the observer.
             Assert.assertEquals(0, mObserver.getAvailableCallCount());
@@ -364,7 +343,7 @@
 
     @Test
     @MediumTest
-    public void testValidateAccountsFiresEventAtTheEnd() {
+    public void testUpdateAccountListFiresEventAtTheEnd() {
         ThreadUtils.runOnUiThreadBlocking(() -> {
             // Mark user as signed in without setting up the account.
             mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
@@ -377,7 +356,7 @@
             };
 
             mOAuth2TokenService.addObserver(ob);
-            mOAuth2TokenService.validateAccounts(false);
+            mOAuth2TokenService.updateAccountList();
         });
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
index d0d4468..08372dc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
@@ -126,8 +126,10 @@
      */
     @Test
     @MediumTest
-    @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
-    public void testInfoBarPresentWhenVrServicesOutdated() throws InterruptedException {
+    @XrActivityRestriction({XrActivityRestriction.SupportedActivity.CTA,
+            XrActivityRestriction.SupportedActivity.CCT})
+    public void
+    testInfoBarPresentWhenVrServicesOutdated() throws InterruptedException {
         infoBarTestHelper(VrCoreCompatibility.VR_OUT_OF_DATE);
     }
 
@@ -136,8 +138,10 @@
      */
     @Test
     @MediumTest
-    @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
-    public void testInfoBarPresentWhenVrServicesMissing() throws InterruptedException {
+    @XrActivityRestriction({XrActivityRestriction.SupportedActivity.CTA,
+            XrActivityRestriction.SupportedActivity.CCT})
+    public void
+    testInfoBarPresentWhenVrServicesMissing() throws InterruptedException {
         infoBarTestHelper(VrCoreCompatibility.VR_NOT_AVAILABLE);
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
index 3629dc25..13bce68 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
@@ -28,6 +28,7 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.notifications.ChromeNotification;
 import org.chromium.chrome.browser.notifications.NotificationBuilderBase;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
 
@@ -55,6 +56,9 @@
     @Mock
     private Bitmap mServiceSmallIconBitmap;
 
+    @Mock
+    private ChromeNotification mChromeNotification;
+
     private TrustedWebActivityClient mClient;
 
     @Before
@@ -71,6 +75,7 @@
         when(mService.getSmallIconId()).thenReturn(SERVICE_SMALL_ICON_ID);
         when(mService.getSmallIconBitmap()).thenReturn(mServiceSmallIconBitmap);
         when(mService.getComponentName()).thenReturn(new ComponentName(CLIENT_PACKAGE_NAME, ""));
+        when(mNotificationBuilder.build(any())).thenReturn(mChromeNotification);
 
         mClient = new TrustedWebActivityClient(mConnection, mRecorder, mNotificationUmaTracker);
     }
diff --git a/chrome/android/touchless/java/res/drawable/notouch_progress_bar_drawable.xml b/chrome/android/touchless/java/res/drawable/notouch_progress_bar_drawable.xml
new file mode 100644
index 0000000..200cd43
--- /dev/null
+++ b/chrome/android/touchless/java/res/drawable/notouch_progress_bar_drawable.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@android:id/background">
+        <shape>
+            <corners android:radius="16dp" />
+            <solid android:color="@android:color/white" />
+        </shape>
+    </item>
+
+    <item android:id="@android:id/progress">
+        <clip>
+            <shape>
+                <corners android:radius="16dp" />
+                <solid android:color="@color/notouch_progress_bar_foreground" />
+            </shape>
+        </clip>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/notouch_progress_bar_view.xml b/chrome/android/touchless/java/res/layout/notouch_progress_bar_view.xml
new file mode 100644
index 0000000..38983ef
--- /dev/null
+++ b/chrome/android/touchless/java/res/layout/notouch_progress_bar_view.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="180dp"
+    android:layout_height="32dp"
+    android:layout_marginTop="11dp">
+
+    <ProgressBar
+        android:id="@+id/notouch_progress_bar_view"
+        style="@android:style/Widget.ProgressBar.Horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:progressDrawable="@drawable/notouch_progress_bar_drawable" />
+
+    <TextView
+        android:id="@+id/notouch_url_text_view"
+        style="@style/TextAppearance.NoTouchProgressBar"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:ellipsize="start"
+        android:gravity="center"
+        android:paddingEnd="16dp"
+        android:paddingStart="16dp"
+        android:singleLine="true" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/values-v17/colors.xml b/chrome/android/touchless/java/res/values-v17/colors.xml
new file mode 100644
index 0000000..15effdb
--- /dev/null
+++ b/chrome/android/touchless/java/res/values-v17/colors.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 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. -->
+
+<resources>
+    <color name="notouch_progress_bar_foreground">@color/google_blue_50</color>
+    <color name="notouch_progress_bar_text">@color/modern_grey_800</color>
+</resources>
diff --git a/chrome/android/touchless/java/res/values-v17/styles.xml b/chrome/android/touchless/java/res/values-v17/styles.xml
new file mode 100644
index 0000000..61f80f2
--- /dev/null
+++ b/chrome/android/touchless/java/res/values-v17/styles.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 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. -->
+
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <style name="TextAppearance.NoTouchProgressBar">
+        <item name="android:textSize">14sp</item>
+        <item name="android:textColor">@color/notouch_progress_bar_text</item>
+    </style>
+</resources>
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
index 24c2f7d..78123322 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
@@ -7,9 +7,11 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.SystemClock;
+import android.view.KeyEvent;
 import android.view.ViewGroup;
 
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
 import org.chromium.chrome.browser.IntentHandler.TabOpenType;
@@ -20,6 +22,8 @@
 import org.chromium.chrome.browser.tab.TabBuilder;
 import org.chromium.chrome.browser.tab.TabRedirectHandler;
 import org.chromium.chrome.browser.tab.TabState;
+import org.chromium.chrome.browser.touchless.ui.progressbar.ProgressBarCoordinator;
+import org.chromium.chrome.browser.touchless.ui.progressbar.ProgressBarView;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.common.Referrer;
 import org.chromium.ui.base.PageTransition;
@@ -33,6 +37,9 @@
     // Time at which an intent was received and handled.
     private long mIntentHandlingTimeMs;
 
+    private ProgressBarView mProgressBarView;
+    private ProgressBarCoordinator mProgressBarCoordinator;
+
     /**
      * Internal class which performs the intent handling operations delegated by IntentHandler.
      */
@@ -106,6 +113,8 @@
     @Override
     public void initializeState() {
         super.initializeState();
+        mProgressBarCoordinator =
+                new ProgressBarCoordinator(getActivityTabProvider(), mProgressBarView);
 
         // By this point if we were going to restore a URL from savedInstanceState we would already
         // have done so.
@@ -181,8 +190,32 @@
     }
 
     @Override
+    protected void doLayoutInflation() {
+        super.doLayoutInflation();
+        ViewGroup coordinatorLayout = (ViewGroup) findViewById(R.id.coordinator);
+        mProgressBarView = new ProgressBarView(this);
+        coordinatorLayout.addView(mProgressBarView);
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (mProgressBarCoordinator != null) {
+            mProgressBarCoordinator.onKeyEvent();
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    @Override
     public void onStopWithNative() {
         super.onStopWithNative();
         getFullscreenManager().exitPersistentFullscreenMode();
     }
+
+    @Override
+    protected void onDestroyInternal() {
+        super.onDestroyInternal();
+        if (mProgressBarCoordinator != null) {
+            mProgressBarCoordinator.destroy();
+        }
+    }
 }
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java
new file mode 100644
index 0000000..6030a80
--- /dev/null
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.touchless.ui.progressbar;
+
+import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
+
+/**
+ * A class to manage the touchless progress bar UI element.
+ */
+public class ProgressBarCoordinator {
+    private final ProgressBarMediator mMediator;
+
+    /**
+     * @param activityTabProvider Progress will be displayed for {@link Tab}s that are added to
+     * this {@link ActivityTabProvider}.
+     * @param progressBarView {@link ProgressBarView} used for displaying current progress and
+     * eTLD+1.
+     */
+    public ProgressBarCoordinator(
+            ActivityTabProvider activityTabProvider, ProgressBarView progressBarView) {
+        PropertyModel model = new PropertyModel.Builder(ProgressBarProperties.ALL_KEYS).build();
+        PropertyModelChangeProcessor.create(model, progressBarView, ProgressBarViewBinder::bind);
+        mMediator = new ProgressBarMediator(model, activityTabProvider);
+    }
+
+    public void onKeyEvent() {
+        mMediator.onKeyEvent();
+    }
+
+    public void destroy() {
+        mMediator.destroy();
+    }
+}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java
new file mode 100644
index 0000000..d23520e
--- /dev/null
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java
@@ -0,0 +1,110 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.touchless.ui.progressbar;
+
+import org.chromium.base.task.PostTask;
+import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.native_page.NativePageFactory;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlUtilities;
+import org.chromium.content_public.browser.UiThreadTaskTraits;
+import org.chromium.ui.modelutil.PropertyModel;
+
+import java.util.concurrent.FutureTask;
+
+/**
+ * This part of the touchless progress bar component controls the UI model based on the status of
+ * the current tab and key events.
+ */
+public class ProgressBarMediator {
+    private final PropertyModel mModel;
+    private final ProgressBarTabObserver mProgressBarTabObserver;
+    private FutureTask mHideTask;
+    private boolean mCanHideProgressBar;
+    private boolean mWasDisplayedForMinimumDuration;
+
+    private static final int MINIMUM_DISPLAY_DURATION_MS = 3 * 1000;
+
+    ProgressBarMediator(PropertyModel model, ActivityTabProvider activityTabProvider) {
+        mProgressBarTabObserver = new ProgressBarTabObserver(activityTabProvider);
+        mModel = model;
+    }
+
+    void onKeyEvent() {
+        mCanHideProgressBar = true;
+        hide();
+    }
+
+    private void show() {
+        if (mHideTask != null) mHideTask.cancel(false);
+        mHideTask = new FutureTask<Void>(() -> {
+            mWasDisplayedForMinimumDuration = true;
+            hide();
+            return null;
+        });
+        PostTask.postDelayedTask(
+                UiThreadTaskTraits.DEFAULT, mHideTask, MINIMUM_DISPLAY_DURATION_MS);
+        mModel.set(ProgressBarProperties.IS_VISIBLE, true);
+    }
+
+    private void hide() {
+        if (!mCanHideProgressBar || !mWasDisplayedForMinimumDuration) return;
+
+        mModel.set(ProgressBarProperties.IS_VISIBLE, false);
+    }
+
+    private void onLoadingStopped() {
+        mCanHideProgressBar = true;
+        hide();
+    }
+
+    void destroy() {
+        if (mHideTask != null) mHideTask.cancel(false);
+        mProgressBarTabObserver.destroy();
+    }
+
+    private class ProgressBarTabObserver extends ActivityTabProvider.ActivityTabTabObserver {
+        ProgressBarTabObserver(ActivityTabProvider tabProvider) {
+            super(tabProvider);
+        }
+
+        @Override
+        public void onPageLoadStarted(Tab tab, String url) {
+            if (NativePageFactory.isNativePageUrl(url, tab.isIncognito())) {
+                mModel.set(ProgressBarProperties.IS_ENABLED, false);
+            } else {
+                mModel.set(ProgressBarProperties.IS_ENABLED, true);
+                mWasDisplayedForMinimumDuration = false;
+                mCanHideProgressBar = false;
+                show();
+                mModel.set(ProgressBarProperties.PROGRESS_FRACTION, 0f);
+            }
+        }
+
+        @Override
+        public void onLoadProgressChanged(Tab tab, int progress) {
+            if (NativePageFactory.isNativePageUrl(tab.getUrl(), tab.isIncognito())) return;
+
+            mModel.set(ProgressBarProperties.PROGRESS_FRACTION, progress / 100f);
+            mModel.set(ProgressBarProperties.URL,
+                    UrlUtilities.getDomainAndRegistry(tab.getUrl(), false));
+        }
+
+        @Override
+        public void onCrash(Tab tab) {
+            onLoadingStopped();
+        }
+
+        @Override
+        public void onPageLoadFailed(Tab tab, int errorCode) {
+            onLoadingStopped();
+        }
+
+        @Override
+        public void onPageLoadFinished(Tab tab, String url) {
+            onLoadingStopped();
+        }
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarProperties.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarProperties.java
new file mode 100644
index 0000000..2bc0035
--- /dev/null
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarProperties.java
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.touchless.ui.progressbar;
+
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/**
+ * This class holds property keys used in the Loading Bar {@link PropertyModel}.
+ */
+public class ProgressBarProperties {
+    public static final PropertyModel.WritableFloatPropertyKey PROGRESS_FRACTION =
+            new PropertyModel.WritableFloatPropertyKey();
+
+    public static final PropertyModel.WritableBooleanPropertyKey IS_ENABLED =
+            new PropertyModel.WritableBooleanPropertyKey();
+
+    public static final PropertyModel.WritableBooleanPropertyKey IS_VISIBLE =
+            new PropertyModel.WritableBooleanPropertyKey();
+
+    public static final PropertyModel.WritableObjectPropertyKey<String> URL =
+            new PropertyModel.WritableObjectPropertyKey<>();
+
+    public static final PropertyKey[] ALL_KEYS = {PROGRESS_FRACTION, IS_ENABLED, IS_VISIBLE, URL};
+}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarView.java
new file mode 100644
index 0000000..6d50d319
--- /dev/null
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarView.java
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.touchless.ui.progressbar;
+
+import android.content.Context;
+import android.support.design.widget.CoordinatorLayout;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import org.chromium.chrome.touchless.R;
+
+/**
+ * View responsible for displaying touchless progress bar UI. It displays the progress and current
+ * eTLD+1.
+ */
+public class ProgressBarView extends RelativeLayout {
+    private static final int MAX_PROGRESS = 100;
+
+    private TextView mUrlTextView;
+    private ProgressBar mProgressBar;
+
+    public ProgressBarView(Context context) {
+        super(context);
+        init();
+    }
+
+    public ProgressBarView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public ProgressBarView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    private void init() {
+        CoordinatorLayout.LayoutParams layoutParams =
+                new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.WRAP_CONTENT,
+                        CoordinatorLayout.LayoutParams.WRAP_CONTENT);
+        layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
+        setLayoutParams(layoutParams);
+
+        inflate(getContext(), R.layout.notouch_progress_bar_view, this);
+        mProgressBar = findViewById(R.id.notouch_progress_bar_view);
+        mUrlTextView = findViewById(R.id.notouch_url_text_view);
+
+        mProgressBar.setMax(MAX_PROGRESS);
+    }
+
+    void setProgress(float progressFraction) {
+        assert progressFraction >= 0f && progressFraction <= 1f;
+        mProgressBar.setProgress((int) (progressFraction * MAX_PROGRESS));
+    }
+
+    void setUrlText(String text) {
+        mUrlTextView.setText(text);
+    }
+
+    void setVisibility(boolean isVisible) {
+        setVisibility(isVisible ? VISIBLE : GONE);
+    }
+}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarViewBinder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarViewBinder.java
new file mode 100644
index 0000000..9e0acb2c
--- /dev/null
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarViewBinder.java
@@ -0,0 +1,34 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.touchless.ui.progressbar;
+
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/**
+ * This class binds the touchless progress bar {@link PropertyModel} to {@link ProgressBarView}.
+ */
+public class ProgressBarViewBinder {
+    public static void bind(
+            PropertyModel model, ProgressBarView progressBarView, PropertyKey propertyKey) {
+        if (ProgressBarProperties.PROGRESS_FRACTION == propertyKey) {
+            progressBarView.setProgress(model.get(ProgressBarProperties.PROGRESS_FRACTION));
+        } else if (ProgressBarProperties.IS_ENABLED == propertyKey) {
+            if (!model.get(ProgressBarProperties.IS_ENABLED)) {
+                progressBarView.setVisibility(false);
+            } else if (model.getAllProperties().contains(ProgressBarProperties.IS_VISIBLE)) {
+                progressBarView.setVisibility(model.get(ProgressBarProperties.IS_VISIBLE));
+            }
+            progressBarView.setVisibility(model.get(ProgressBarProperties.IS_VISIBLE));
+        } else if (ProgressBarProperties.IS_VISIBLE == propertyKey) {
+            if (!model.getAllProperties().contains(ProgressBarProperties.IS_ENABLED)
+                    || model.get(ProgressBarProperties.IS_ENABLED)) {
+                progressBarView.setVisibility(model.get(ProgressBarProperties.IS_VISIBLE));
+            }
+        } else if (ProgressBarProperties.URL == propertyKey) {
+            progressBarView.setUrlText(model.get(ProgressBarProperties.URL));
+        }
+    }
+}
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index 8670f53..69c677a 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -453,6 +453,7 @@
       "//ash/components/shortcut_viewer/public/mojom",
       "//ash/components/tap_visualizer/public/cpp:manifest",
       "//ash/components/tap_visualizer/public/mojom",
+      "//chrome/browser/chromeos/kiosk_next_home/mojom",
       "//chromeos/assistant:buildflags",
       "//chromeos/services/device_sync/public/cpp:manifest",
       "//chromeos/services/ime/public/mojom",
diff --git a/chrome/app/OWNERS b/chrome/app/OWNERS
index ea96994..6693dae 100644
--- a/chrome/app/OWNERS
+++ b/chrome/app/OWNERS
@@ -12,7 +12,6 @@
 per-file bookmarks_strings.grdp=*
 per-file chromeos_strings.grdp=*
 per-file chromium_strings.grd=*
-per-file file_manager_strings.grdp=*
 per-file generated_resources.grd=*
 per-file google_chrome_strings.grd=*
 per-file md_extensions_strings.grdp=*
diff --git a/chrome/app/chrome_content_browser_overlay_manifest.cc b/chrome/app/chrome_content_browser_overlay_manifest.cc
index 916e85c..824fe3d 100644
--- a/chrome/app/chrome_content_browser_overlay_manifest.cc
+++ b/chrome/app/chrome_content_browser_overlay_manifest.cc
@@ -53,6 +53,7 @@
 #include "ash/components/shortcut_viewer/public/mojom/shortcut_viewer.mojom.h"  // nogncheck
 #include "ash/components/tap_visualizer/public/cpp/manifest.h"  // nogncheck
 #include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h"  // nogncheck
+#include "chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom.h"  // nogncheck
 #include "chromeos/assistant/buildflags.h"  // nogncheck
 #include "chromeos/services/device_sync/public/cpp/manifest.h"
 #include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
@@ -208,6 +209,8 @@
                     chrome::mojom::PrerenderCanceler,
 #if defined(OS_CHROMEOS)
                     chromeos::ime::mojom::InputEngineManager,
+                    chromeos::kiosk_next_home::mojom::
+                        KioskNextHomeInterfaceBroker,
                     chromeos::media_perception::mojom::MediaPerception,
                     cros::mojom::CrosImageCapture,
 #endif
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 4b48a52..ebdf71b9 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -200,7 +200,6 @@
       <!-- Chrome-OS-specific strings -->
       <if expr="chromeos">
         <part file="chromeos_strings.grdp" />
-        <part file="file_manager_strings.grdp" />
       </if>
 
       <!-- Settings specific strings -->
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 8c9c515..3b6177cc 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2085,6 +2085,7 @@
     "//ui/accessibility",
     "//ui/base",
     "//ui/base:ui_data_pack",
+    "//ui/base/idle",
     "//ui/base/ime",
     "//ui/events:events_base",
     "//ui/gfx",
@@ -3433,6 +3434,8 @@
     deps += [
       "//ash/public/cpp",
       "//chrome/browser/chromeos",
+      "//chrome/browser/chromeos/kiosk_next_home",
+      "//chrome/browser/chromeos/kiosk_next_home/mojom",
       "//chromeos/services/assistant/public:feature_flags",
       "//chromeos/services/device_sync",
       "//chromeos/services/device_sync/public/mojom",
diff --git a/chrome/browser/android/compositor/tab_content_manager.cc b/chrome/browser/android/compositor/tab_content_manager.cc
index 7e6d7c54..9bc082f 100644
--- a/chrome/browser/android/compositor/tab_content_manager.cc
+++ b/chrome/browser/android/compositor/tab_content_manager.cc
@@ -340,7 +340,14 @@
     SkBitmap bitmap) {
   ScopedJavaLocalRef<jobject> j_bitmap;
   if (!bitmap.isNull() && result) {
-    SkIRect dest_subset = {0, 0, bitmap.width() / 2, bitmap.width() / 2};
+    // In portrait mode, we want to show thumbnails in squares.
+    // Therefore, the thumbnail saved in portrait mode needs to be cropped to
+    // a square, or it would be vertically center-aligned, and the top would
+    // be hidden.
+    // It's fine to horizontally center-align thumbnail saved in landscape
+    // mode.
+    SkIRect dest_subset = {0, 0, bitmap.width() / 2,
+                           std::min(bitmap.width(), bitmap.height()) / 2};
     SkBitmap result_bitmap = skia::ImageOperations::Resize(
         bitmap, skia::ImageOperations::RESIZE_BETTER, bitmap.width() / 2,
         bitmap.height() / 2, dest_subset);
diff --git a/chrome/browser/apps/platform_apps/app_browsertest.cc b/chrome/browser/apps/platform_apps/app_browsertest.cc
index 9d9d74b..fc1e7a53 100644
--- a/chrome/browser/apps/platform_apps/app_browsertest.cc
+++ b/chrome/browser/apps/platform_apps/app_browsertest.cc
@@ -67,7 +67,7 @@
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/user_manager/scoped_user_manager.h"
 #endif
 
diff --git a/chrome/browser/autofill/autofill_uitest.cc b/chrome/browser/autofill/autofill_uitest.cc
index 80680381..51f3b11 100644
--- a/chrome/browser/autofill/autofill_uitest.cc
+++ b/chrome/browser/autofill/autofill_uitest.cc
@@ -74,8 +74,10 @@
   // Don't want Keychain coming up on Mac.
   test::DisableSystemServices(browser()->profile()->GetPrefs());
 
-  // Inject the test delegate into the AutofillManager.
-  GetAutofillManager()->SetTestDelegate(test_delegate());
+  // Inject the test delegate into the AutofillManager of the main frame.
+  RenderFrameHostChanged(/* old_host = */ nullptr,
+                         /* new_host = */ GetWebContents()->GetMainFrame());
+  Observe(GetWebContents());
 
   // If the mouse happened to be over where the suggestions are shown, then
   // the preview will show up and will fail the tests. We need to give it a
@@ -218,10 +220,18 @@
 }
 
 AutofillManager* AutofillUiTest::GetAutofillManager() {
-  content::WebContents* web_contents = GetWebContents();
-  return ContentAutofillDriverFactory::FromWebContents(web_contents)
-      ->DriverForFrame(web_contents->GetMainFrame())
+  return ContentAutofillDriverFactory::FromWebContents(GetWebContents())
+      ->DriverForFrame(current_main_rfh_)
       ->autofill_manager();
 }
 
+void AutofillUiTest::RenderFrameHostChanged(
+    content::RenderFrameHost* old_frame,
+    content::RenderFrameHost* new_frame) {
+  if (current_main_rfh_ != old_frame)
+    return;
+  current_main_rfh_ = new_frame;
+  GetAutofillManager()->SetTestDelegate(test_delegate());
+}
+
 }  // namespace autofill
diff --git a/chrome/browser/autofill/autofill_uitest.h b/chrome/browser/autofill/autofill_uitest.h
index f6d770b..50d4a86 100644
--- a/chrome/browser/autofill/autofill_uitest.h
+++ b/chrome/browser/autofill/autofill_uitest.h
@@ -13,6 +13,7 @@
 #include "components/autofill/core/browser/autofill_manager_test_delegate.h"
 #include "components/autofill/core/browser/test_event_waiter.h"
 #include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/keycodes/dom/dom_key.h"
@@ -56,7 +57,8 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillManagerTestDelegateImpl);
 };
 
-class AutofillUiTest : public InProcessBrowserTest {
+class AutofillUiTest : public InProcessBrowserTest,
+                       public content::WebContentsObserver {
  protected:
   AutofillUiTest();
   ~AutofillUiTest() override;
@@ -98,6 +100,10 @@
   content::RenderWidgetHost::KeyPressEventCallback key_press_event_sink();
 
  private:
+  // WebContentsObserver override:
+  void RenderFrameHostChanged(content::RenderFrameHost* old_host,
+                              content::RenderFrameHost* new_host) override;
+  content::RenderFrameHost* current_main_rfh_ = nullptr;
   AutofillManagerTestDelegateImpl test_delegate_;
 
   // KeyPressEventCallback that serves as a sink to ensure that every key press
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 5e6ce184..5b79d7a 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -231,6 +231,7 @@
     "//ui/accessibility",
     "//ui/aura",
     "//ui/base",
+    "//ui/base/idle",
     "//ui/chromeos",
     "//ui/chromeos/events",
     "//ui/compositor",
@@ -583,6 +584,8 @@
     "attestation/platform_verification_flow.h",
     "authpolicy/auth_policy_credentials_manager.cc",
     "authpolicy/auth_policy_credentials_manager.h",
+    "authpolicy/kerberos_files_handler.cc",
+    "authpolicy/kerberos_files_handler.h",
     "base/file_flusher.cc",
     "base/file_flusher.h",
     "base/locale_util.cc",
@@ -1642,6 +1645,8 @@
     "policy/system_log_uploader.h",
     "policy/ticl_device_settings_provider.cc",
     "policy/ticl_device_settings_provider.h",
+    "policy/tpm_auto_update_mode_policy_handler.cc",
+    "policy/tpm_auto_update_mode_policy_handler.h",
     "policy/upload_job.h",
     "policy/upload_job_impl.cc",
     "policy/upload_job_impl.h",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 5bf5279..831151a 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -57,7 +57,7 @@
 #include "chrome/grit/browser_resources.h"
 #include "chromeos/audio/chromeos_sounds.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_member.h"
diff --git a/chrome/browser/chromeos/app_mode/app_session.cc b/chrome/browser/chromeos/app_mode/app_session.cc
index c615bfe..15e1adda 100644
--- a/chrome/browser/chromeos/app_mode/app_session.cc
+++ b/chrome/browser/chromeos/app_mode/app_session.cc
@@ -30,7 +30,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/chromeos/app_mode/kiosk_mode_idle_app_name_notification.h b/chrome/browser/chromeos/app_mode/kiosk_mode_idle_app_name_notification.h
index f047d24..c4f4e6dd 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_mode_idle_app_name_notification.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_mode_idle_app_name_notification.h
@@ -10,7 +10,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/base/user_activity/user_activity_observer.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc b/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc
index 4e8b4ee..94ccad3 100644
--- a/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc
+++ b/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc
@@ -19,8 +19,8 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/chromeos/devicetype_utils.h"
 #include "ui/gfx/color_palette.h"
diff --git a/chrome/browser/chromeos/arc/arc_migration_guide_notification_unittest.cc b/chrome/browser/chromeos/arc/arc_migration_guide_notification_unittest.cc
index 30e1f34..2bea0fa2 100644
--- a/chrome/browser/chromeos/arc/arc_migration_guide_notification_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_migration_guide_notification_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
index 6f44589..0c1a65a 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
@@ -42,7 +42,7 @@
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/arc_features.h"
diff --git a/chrome/browser/chromeos/authpolicy/OWNERS b/chrome/browser/chromeos/authpolicy/OWNERS
new file mode 100644
index 0000000..3ceab6d
--- /dev/null
+++ b/chrome/browser/chromeos/authpolicy/OWNERS
@@ -0,0 +1,6 @@
+# This is for the common case of adding or renaming files. If you're doing
+# structural changes, use usual OWNERS rules.
+per-file BUILD.gn=*
+
+rsorokin@chromium.org
+ljusten@chromium.org
diff --git a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc
index c916cc0..12056c7 100644
--- a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc
+++ b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc
@@ -10,14 +10,10 @@
 #include "ash/public/cpp/notification_utils.h"
 #include "ash/public/cpp/vector_icons/vector_icons.h"
 #include "base/bind.h"
-#include "base/files/important_file_writer.h"
 #include "base/location.h"
 #include "base/memory/singleton.h"
-#include "base/path_service.h"
 #include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
@@ -25,7 +21,6 @@
 #include "chrome/browser/notifications/notification_display_service.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
@@ -38,10 +33,7 @@
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "content/public/browser/network_service_instance.h"
-#include "content/public/common/network_service_util.h"
 #include "dbus/message.h"
-#include "services/network/public/mojom/network_service.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/message_center/public/cpp/notification.h"
@@ -55,47 +47,6 @@
     base::TimeDelta::FromHours(1);
 constexpr char kProfileSigninNotificationId[] = "chrome://settings/signin/";
 
-// Prefix for KRB5CCNAME environment variable. Defines credential cache type.
-constexpr char kKrb5CCFilePrefix[] = "FILE:";
-// Directory in the user home to store Kerberos files.
-constexpr char kKrb5Directory[] = "kerberos";
-// Environment variable pointing to credential cache file.
-constexpr char kKrb5CCEnvName[] = "KRB5CCNAME";
-// Credential cache file name.
-constexpr char kKrb5CCFile[] = "krb5cc";
-// Environment variable pointing to Kerberos config file.
-constexpr char kKrb5ConfEnvName[] = "KRB5_CONFIG";
-// Kerberos config file name.
-constexpr char kKrb5ConfFile[] = "krb5.conf";
-
-// Writes |blob| into file <UserPath>/kerberos/|file_name|. First writes into
-// temporary file and then replaces existing one.
-void WriteFile(const std::string& file_name, const std::string& blob) {
-  base::FilePath dir;
-  base::PathService::Get(base::DIR_HOME, &dir);
-  dir = dir.Append(kKrb5Directory);
-  base::File::Error error;
-  if (!base::CreateDirectoryAndGetError(dir, &error)) {
-    LOG(ERROR) << "Failed to create '" << dir.value()
-               << "' directory: " << base::File::ErrorToString(error);
-    return;
-  }
-  base::FilePath dest_file = dir.Append(file_name);
-  if (!base::ImportantFileWriter::WriteFileAtomically(dest_file, blob)) {
-    LOG(ERROR) << "Failed to write file " << dest_file.value();
-  }
-}
-
-// Put canonicalization settings first depending on user policy. Whatever
-// setting comes first wins, so even if krb5.conf sets rdns or
-// dns_canonicalize_hostname below, it would get overridden.
-std::string AdjustConfig(const std::string& config, bool is_dns_cname_enabled) {
-  std::string adjusted_config = base::StringPrintf(
-      kKrb5CnameSettings, is_dns_cname_enabled ? "true" : "false");
-  adjusted_config.append(config);
-  return adjusted_config;
-}
-
 // Sets up Chrome OS Account Manager.
 // |profile| is a non-owning pointer to |Profile|.
 // |account_id| is the |AccountId| for the Device Account.
@@ -120,13 +71,11 @@
 
 }  // namespace
 
-const char* kKrb5CnameSettings =
-    "[libdefaults]\n"
-    "\tdns_canonicalize_hostname = %s\n"
-    "\trdns = false\n";
-
 AuthPolicyCredentialsManager::AuthPolicyCredentialsManager(Profile* profile)
-    : profile_(profile) {
+    : profile_(profile),
+      kerberos_files_handler_(base::BindRepeating(
+          &AuthPolicyCredentialsManager::GetUserKerberosFiles,
+          base::Unretained(this))) {
   const user_manager::User* user =
       ProfileHelper::Get()->GetUserByProfile(profile);
   CHECK(user && user->IsActiveDirectoryUser());
@@ -135,34 +84,6 @@
   GetUserStatus();
   GetUserKerberosFiles();
 
-  // Setting environment variables for GSSAPI library.
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
-  base::FilePath path;
-  base::PathService::Get(base::DIR_HOME, &path);
-  path = path.Append(kKrb5Directory);
-  std::string krb5cc_env_value =
-      kKrb5CCFilePrefix + path.Append(kKrb5CCFile).value();
-  std::string krb5conf_env_value = path.Append(kKrb5ConfFile).value();
-  env->SetVar(kKrb5CCEnvName, krb5cc_env_value);
-  env->SetVar(kKrb5ConfEnvName, krb5conf_env_value);
-
-  // Send the environment variables to the network service if it's running
-  // out of process.
-  if (content::IsOutOfProcessNetworkService()) {
-    std::vector<network::mojom::EnvironmentVariablePtr> environment;
-    environment.push_back(network::mojom::EnvironmentVariable::New(
-        kKrb5CCEnvName, krb5cc_env_value));
-    environment.push_back(network::mojom::EnvironmentVariable::New(
-        kKrb5ConfEnvName, krb5conf_env_value));
-    content::GetNetworkService()->SetEnvironment(std::move(environment));
-  }
-
-  negotiate_disable_cname_lookup_.Init(
-      prefs::kDisableAuthNegotiateCnameLookup, g_browser_process->local_state(),
-      base::BindRepeating(&AuthPolicyCredentialsManager::
-                              OnDisabledAuthNegotiateCnameLookupChanged,
-                          weak_factory_.GetWeakPtr()));
-
   // Connecting to the signal sent by authpolicyd notifying that Kerberos files
   // have changed.
   DBusThreadManager::Get()->GetAuthPolicyClient()->ConnectToSignal(
@@ -277,23 +198,10 @@
 void AuthPolicyCredentialsManager::OnGetUserKerberosFilesCallback(
     authpolicy::ErrorType error,
     const authpolicy::KerberosFiles& kerberos_files) {
-  if (kerberos_files.has_krb5cc()) {
-    base::PostTaskWithTraits(
-        FROM_HERE,
-        {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-        base::BindOnce(&WriteFile, kKrb5CCFile, kerberos_files.krb5cc()));
-  }
-  if (kerberos_files.has_krb5conf()) {
-    base::PostTaskWithTraits(
-        FROM_HERE,
-        {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-        base::BindOnce(
-            &WriteFile, kKrb5ConfFile,
-            AdjustConfig(kerberos_files.krb5conf(),
-                         !negotiate_disable_cname_lookup_.GetValue())));
-  }
+  auto nullstr = base::Optional<std::string>();
+  kerberos_files_handler_.SetFiles(
+      kerberos_files.has_krb5cc() ? kerberos_files.krb5cc() : nullstr,
+      kerberos_files.has_krb5conf() ? kerberos_files.krb5conf() : nullstr);
 }
 
 void AuthPolicyCredentialsManager::ScheduleGetUserStatus() {
@@ -410,10 +318,6 @@
   DCHECK(success);
 }
 
-void AuthPolicyCredentialsManager::OnDisabledAuthNegotiateCnameLookupChanged() {
-  GetUserKerberosFiles();
-}
-
 // static
 AuthPolicyCredentialsManagerFactory*
 AuthPolicyCredentialsManagerFactory::GetInstance() {
@@ -423,8 +327,7 @@
 AuthPolicyCredentialsManagerFactory::AuthPolicyCredentialsManagerFactory()
     : BrowserContextKeyedServiceFactory(
           "AuthPolicyCredentialsManager",
-          BrowserContextDependencyManager::GetInstance()) {
-}
+          BrowserContextDependencyManager::GetInstance()) {}
 
 AuthPolicyCredentialsManagerFactory::~AuthPolicyCredentialsManagerFactory() {}
 
diff --git a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h
index 801638b..a4e98a49f 100644
--- a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h
+++ b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h
@@ -10,12 +10,12 @@
 
 #include "base/cancelable_callback.h"
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/authpolicy/kerberos_files_handler.h"
 #include "chromeos/dbus/authpolicy/active_directory_info.pb.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "components/account_id/account_id.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/prefs/pref_member.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 class Profile;
@@ -35,11 +35,6 @@
 
 namespace chromeos {
 
-// Kerberos defaults for canonicalization SPN. (see
-// https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html)
-// Exported for browsertests.
-extern const char* kKrb5CnameSettings;
-
 // A service responsible for tracking user credential status. Created for each
 // Active Directory user profile.
 class AuthPolicyCredentialsManager
@@ -103,9 +98,6 @@
                                  const std::string& signal_name,
                                  bool success);
 
-  // Called whenever prefs::kDisableAuthNegotiateCnameLookup is changed.
-  void OnDisabledAuthNegotiateCnameLookupChanged();
-
   Profile* const profile_;
   AccountId account_id_;
   std::string display_name_;
@@ -113,13 +105,13 @@
   bool is_get_status_in_progress_ = false;
   bool rerun_get_status_on_error_ = false;
   bool is_observing_network_ = false;
+  KerberosFilesHandler kerberos_files_handler_;
 
   // Stores message ids of shown notifications. Each notification is shown at
   // most once.
   std::set<int> shown_notifications_;
   authpolicy::ErrorType last_error_ = authpolicy::ERROR_NONE;
   base::CancelableClosure scheduled_get_user_status_call_;
-  PrefMember<bool> negotiate_disable_cname_lookup_;
 
   base::WeakPtrFactory<AuthPolicyCredentialsManager> weak_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(AuthPolicyCredentialsManager);
diff --git a/chrome/browser/chromeos/authpolicy/kerberos_files_handler.cc b/chrome/browser/chromeos/authpolicy/kerberos_files_handler.cc
new file mode 100644
index 0000000..939febf6
--- /dev/null
+++ b/chrome/browser/chromeos/authpolicy/kerberos_files_handler.cc
@@ -0,0 +1,139 @@
+// Copyright 2019 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 "chrome/browser/chromeos/authpolicy/kerberos_files_handler.h"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/environment.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/important_file_writer.h"
+#include "base/location.h"
+#include "base/path_service.h"
+#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/network_service_instance.h"
+#include "content/public/common/network_service_util.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+
+namespace chromeos {
+
+namespace {
+
+// Prefix for KRB5CCNAME environment variable. Defines credential cache type.
+constexpr char kKrb5CCFilePrefix[] = "FILE:";
+// Directory in the user home to store Kerberos files.
+constexpr char kKrb5Directory[] = "kerberos";
+// Environment variable pointing to credential cache file.
+constexpr char kKrb5CCEnvName[] = "KRB5CCNAME";
+// Credential cache file name.
+constexpr char kKrb5CCFile[] = "krb5cc";
+// Environment variable pointing to Kerberos config file.
+constexpr char kKrb5ConfEnvName[] = "KRB5_CONFIG";
+// Kerberos config file name.
+constexpr char kKrb5ConfFile[] = "krb5.conf";
+
+// Writes |blob| into file <UserPath>/kerberos/|file_name|. First writes into
+// temporary file and then replaces existing one.
+void WriteFile(const std::string& file_name, const std::string& blob) {
+  base::FilePath dir;
+  base::PathService::Get(base::DIR_HOME, &dir);
+  dir = dir.Append(kKrb5Directory);
+  base::File::Error error;
+  if (!base::CreateDirectoryAndGetError(dir, &error)) {
+    LOG(ERROR) << "Failed to create '" << dir.value()
+               << "' directory: " << base::File::ErrorToString(error);
+    return;
+  }
+  base::FilePath dest_file = dir.Append(file_name);
+  if (!base::ImportantFileWriter::WriteFileAtomically(dest_file, blob)) {
+    LOG(ERROR) << "Failed to write file " << dest_file.value();
+  }
+}
+
+// Put canonicalization settings first depending on user policy. Whatever
+// setting comes first wins, so even if krb5.conf sets rdns or
+// dns_canonicalize_hostname below, it would get overridden.
+std::string AdjustConfig(const std::string& config, bool is_dns_cname_enabled) {
+  std::string adjusted_config = base::StringPrintf(
+      kKrb5CnameSettings, is_dns_cname_enabled ? "true" : "false");
+  adjusted_config.append(config);
+  return adjusted_config;
+}
+
+}  // namespace
+
+const char* kKrb5CnameSettings =
+    "[libdefaults]\n"
+    "\tdns_canonicalize_hostname = %s\n"
+    "\trdns = false\n";
+
+KerberosFilesHandler::KerberosFilesHandler(
+    base::RepeatingClosure get_kerberos_files)
+    : get_kerberos_files_(std::move(get_kerberos_files)) {
+  // Set environment variables for GSSAPI library.
+  std::unique_ptr<base::Environment> env(base::Environment::Create());
+  base::FilePath path;
+  base::PathService::Get(base::DIR_HOME, &path);
+  path = path.Append(kKrb5Directory);
+  std::string krb5cc_env_value =
+      kKrb5CCFilePrefix + path.Append(kKrb5CCFile).value();
+  std::string krb5conf_env_value = path.Append(kKrb5ConfFile).value();
+  env->SetVar(kKrb5CCEnvName, krb5cc_env_value);
+  env->SetVar(kKrb5ConfEnvName, krb5conf_env_value);
+
+  // Send the environment variables to the network service if it's running
+  // out of process.
+  if (content::IsOutOfProcessNetworkService()) {
+    std::vector<network::mojom::EnvironmentVariablePtr> environment;
+    environment.push_back(network::mojom::EnvironmentVariable::New(
+        kKrb5CCEnvName, krb5cc_env_value));
+    environment.push_back(network::mojom::EnvironmentVariable::New(
+        kKrb5ConfEnvName, krb5conf_env_value));
+    content::GetNetworkService()->SetEnvironment(std::move(environment));
+  }
+
+  // Listen to kDisableAuthNegotiateCnameLookup pref. It might change the
+  // Kerberos config.
+  negotiate_disable_cname_lookup_.Init(
+      prefs::kDisableAuthNegotiateCnameLookup, g_browser_process->local_state(),
+      base::BindRepeating(
+          &KerberosFilesHandler::OnDisabledAuthNegotiateCnameLookupChanged,
+          weak_factory_.GetWeakPtr()));
+}
+
+KerberosFilesHandler::~KerberosFilesHandler() = default;
+
+void KerberosFilesHandler::SetFiles(base::Optional<std::string> krb5cc,
+                                    base::Optional<std::string> krb5conf) {
+  if (krb5cc.has_value()) {
+    base::PostTaskWithTraits(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+        base::BindOnce(&WriteFile, kKrb5CCFile, krb5cc.value()));
+  }
+  if (krb5conf.has_value()) {
+    base::PostTaskWithTraits(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+        base::BindOnce(
+            &WriteFile, kKrb5ConfFile,
+            AdjustConfig(krb5conf.value(),
+                         !negotiate_disable_cname_lookup_.GetValue())));
+  }
+}
+
+void KerberosFilesHandler::OnDisabledAuthNegotiateCnameLookupChanged() {
+  // Refresh kerberos files to adjust config for changed pref.
+  get_kerberos_files_.Run();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/authpolicy/kerberos_files_handler.h b/chrome/browser/chromeos/authpolicy/kerberos_files_handler.h
new file mode 100644
index 0000000..2f93805
--- /dev/null
+++ b/chrome/browser/chromeos/authpolicy/kerberos_files_handler.h
@@ -0,0 +1,48 @@
+// Copyright 2019 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 CHROME_BROWSER_CHROMEOS_AUTHPOLICY_KERBEROS_FILES_HANDLER_H_
+#define CHROME_BROWSER_CHROMEOS_AUTHPOLICY_KERBEROS_FILES_HANDLER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "components/prefs/pref_member.h"
+
+namespace chromeos {
+
+// Kerberos defaults for canonicalization SPN. (see
+// https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html)
+// Exported for browsertests.
+extern const char* kKrb5CnameSettings;
+
+// Helper class to update Kerberos credential cache and config files used by
+// Chrome for Kerberos authentication.
+class KerberosFilesHandler {
+ public:
+  explicit KerberosFilesHandler(base::RepeatingClosure get_kerberos_files);
+  ~KerberosFilesHandler();
+
+  void SetFiles(base::Optional<std::string> krb5cc,
+                base::Optional<std::string> krb5conf);
+
+ private:
+  // Called whenever prefs::kDisableAuthNegotiateCnameLookup is changed.
+  void OnDisabledAuthNegotiateCnameLookupChanged();
+
+  PrefMember<bool> negotiate_disable_cname_lookup_;
+
+  // Triggers a fetch of Kerberos files. Called when the watched pref changes.
+  base::RepeatingClosure get_kerberos_files_;
+
+  base::WeakPtrFactory<KerberosFilesHandler> weak_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(KerberosFilesHandler);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_AUTHPOLICY_KERBEROS_FILES_HANDLER_H_
diff --git a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h b/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h
index 80fc39b..3a8df742 100644
--- a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h
+++ b/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service.h
@@ -11,7 +11,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/session_manager/core/session_manager_observer.h"
 #include "services/network/public/cpp/network_connection_tracker.h"
diff --git a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc b/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc
index 0f4af8fd..da3c138 100644
--- a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc
+++ b/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc
@@ -18,7 +18,7 @@
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/system_clock/system_clock_client.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/common/app.mojom.h"
@@ -88,7 +88,7 @@
 
   void SetUp() override {
     PowerManagerClient::Initialize();
-    SystemClockClient::Initialize(nullptr /* bus */);
+    SystemClockClient::InitializeFake();
     profile_ = std::make_unique<TestingProfile>();
     profile_.get()->SetSupervisedUserId(supervised_users::kChildAccountSUID);
     arc_test_.SetUp(profile());
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
index a2ad4a4..86a20dc7 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
+++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
@@ -8,7 +8,6 @@
 #include <string>
 #include <utility>
 
-#include "ash/public/interfaces/login_screen.mojom.h"
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/optional.h"
@@ -174,12 +173,10 @@
       now, now, &time_zone, last_state);
   SaveCurrentStateToPref(state);
 
-  // Show/hide time limits message based on the policy enforcement.
-  UpdateLockScreenState(
-      state.is_locked, state.is_locked ? state.next_unlock_time : base::Time());
   VLOG(1) << "Screen should be locked is set to " << state.is_locked;
 
   if (state.is_locked) {
+    EnableTimeLimitsMessage(state.active_policy, state.next_unlock_time);
     DCHECK(!state.next_unlock_time.is_null());
     if (!session_manager::SessionManager::Get()->IsScreenLocked()) {
       // This status report are going to be done in EventBasedStatusReporting if
@@ -189,9 +186,10 @@
         ConsumerStatusReportingServiceFactory::GetForBrowserContext(context_)
             ->RequestImmediateStatusReport();
       }
-      ForceScreenLockByPolicy(state.next_unlock_time);
+      ForceScreenLockByPolicy();
     }
   } else {
+    DisableTimeLimitsMessage();
     base::Optional<TimeLimitNotifier::LimitType> notification_type;
     switch (state.next_state_active_policy) {
       case usage_time_limit::ActivePolicies::kFixedLimit:
@@ -235,8 +233,7 @@
   }
 }
 
-void ScreenTimeController::ForceScreenLockByPolicy(
-    base::Time next_unlock_time) {
+void ScreenTimeController::ForceScreenLockByPolicy() {
   DCHECK(!session_manager::SessionManager::Get()->IsScreenLocked());
 
   // Avoid abrupt session restart that looks like a crash and happens when lock
@@ -252,14 +249,11 @@
   chromeos::DBusThreadManager::Get()
       ->GetSessionManagerClient()
       ->RequestLockScreen();
-
-  // Update the time limits message when the lock screen UI is ready.
-  next_unlock_time_ = next_unlock_time;
 }
 
-void ScreenTimeController::UpdateLockScreenState(bool blocked,
-                                                 base::Time next_unlock_time) {
-  DCHECK(blocked || next_unlock_time.is_null());
+void ScreenTimeController::EnableTimeLimitsMessage(
+    usage_time_limit::ActivePolicies active_policy,
+    base::Time next_unlock_time) {
   if (!session_manager::SessionManager::Get()->IsScreenLocked())
     return;
 
@@ -267,13 +261,48 @@
       chromeos::ProfileHelper::Get()
           ->GetUserByProfile(Profile::FromBrowserContext(context_))
           ->GetAccountId();
-  ScreenLocker::default_screen_locker()->SetAuthEnabledForUser(
-      account_id, !blocked,
-      blocked ? next_unlock_time : base::Optional<base::Time>());
-  if (base::FeatureList::IsEnabled(features::kParentAccessCode)) {
-    LoginScreenClient::Get()->login_screen()->SetShowParentAccessButton(
-        blocked);
+  base::Optional<ash::mojom::AuthDisabledReason> disabled_reason =
+      ConvertLockReason(active_policy);
+  DCHECK(disabled_reason.has_value());
+  ScreenLocker::default_screen_locker()->DisableAuthForUser(
+      account_id,
+      ash::mojom::AuthDisabledData::New(
+          disabled_reason.value(), next_unlock_time, GetScreenTimeDuration()));
+  if (base::FeatureList::IsEnabled(features::kParentAccessCode))
+    LoginScreenClient::Get()->login_screen()->SetShowParentAccessButton(true);
+}
+
+void ScreenTimeController::DisableTimeLimitsMessage() {
+  if (!session_manager::SessionManager::Get()->IsScreenLocked())
+    return;
+
+  AccountId account_id =
+      chromeos::ProfileHelper::Get()
+          ->GetUserByProfile(Profile::FromBrowserContext(context_))
+          ->GetAccountId();
+  ScreenLocker::default_screen_locker()->EnableAuthForUser(account_id);
+  if (base::FeatureList::IsEnabled(features::kParentAccessCode))
+    LoginScreenClient::Get()->login_screen()->SetShowParentAccessButton(false);
+}
+
+base::Optional<ash::mojom::AuthDisabledReason>
+ScreenTimeController::ConvertLockReason(
+    usage_time_limit::ActivePolicies active_policy) {
+  base::Optional<ash::mojom::AuthDisabledReason> disabled_reason;
+  switch (active_policy) {
+    case usage_time_limit::ActivePolicies::kFixedLimit:
+      disabled_reason = ash::mojom::AuthDisabledReason::TIME_WINDOW_LIMIT;
+      break;
+    case usage_time_limit::ActivePolicies::kUsageLimit:
+      disabled_reason = ash::mojom::AuthDisabledReason::TIME_USAGE_LIMIT;
+      break;
+    case usage_time_limit::ActivePolicies::kOverride:
+      disabled_reason = ash::mojom::AuthDisabledReason::TIME_LIMIT_OVERRIDE;
+      break;
+    default:
+      disabled_reason = base::nullopt;
   }
+  return disabled_reason;
 }
 
 void ScreenTimeController::OnPolicyChanged() {
@@ -456,18 +485,20 @@
   session_manager::SessionState session_state =
       session_manager::SessionManager::Get()->session_state();
   if (base::FeatureList::IsEnabled(features::kUsageTimeStateNotifier)) {
-    if (session_state == session_manager::SessionState::LOCKED &&
-        next_unlock_time_) {
-      UpdateLockScreenState(true /*blocked*/, next_unlock_time_.value());
-      next_unlock_time_.reset();
+    base::Optional<usage_time_limit::State> last_state = GetLastStateFromPref();
+    if (session_state == session_manager::SessionState::LOCKED && last_state &&
+        last_state->is_locked) {
+      EnableTimeLimitsMessage(last_state->active_policy,
+                              last_state->next_unlock_time);
     }
     return;
   }
 
   if (session_state == session_manager::SessionState::LOCKED) {
-    if (next_unlock_time_) {
-      UpdateLockScreenState(true /*blocked*/, next_unlock_time_.value());
-      next_unlock_time_.reset();
+    base::Optional<usage_time_limit::State> last_state = GetLastStateFromPref();
+    if (last_state && last_state->is_locked) {
+      EnableTimeLimitsMessage(last_state->active_policy,
+                              last_state->next_unlock_time);
     }
     ResetInSessionTimers();
   } else if (session_state == session_manager::SessionState::ACTIVE) {
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.h b/chrome/browser/chromeos/child_accounts/screen_time_controller.h
index 64cf02c7..dd5a08d6 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller.h
+++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include "ash/public/interfaces/login_screen.mojom.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
@@ -88,16 +89,23 @@
 
   // Request to lock the screen and show the time limits message when the screen
   // is locked.
-  void ForceScreenLockByPolicy(base::Time next_unlock_time);
+  void ForceScreenLockByPolicy();
 
-  // Updates the state of lock screen.
-  // |blocked|: If true, user authentication is disabled and a message is shown
-  //            to indicate when user will be able to unlock the screen.
-  //            If false, authentication is re-enabled, message is dismissed and
-  //            user is able to unlock immediately.
+  // Enables and updates the content of the time limits message in the lock
+  // screen.
+  // |active_policy|: Which policy is locking the device, only valid when
+  //                  |visible| is true.
   // |next_unlock_time|: When user will be able to unlock the screen, only valid
   //                     when |visible| is true.
-  void UpdateLockScreenState(bool blocked, base::Time next_unlock_time);
+  void EnableTimeLimitsMessage(usage_time_limit::ActivePolicies active_policy,
+                               base::Time next_unlock_time);
+
+  // Disables the time limits message in the lock screen.
+  void DisableTimeLimitsMessage();
+
+  // Converts the active policy to its equivalent on the ash enum.
+  base::Optional<ash::mojom::AuthDisabledReason> ConvertLockReason(
+      usage_time_limit::ActivePolicies active_policy);
 
   // Called when the policy of time limits changes.
   void OnPolicyChanged();
@@ -161,9 +169,6 @@
 
   PrefChangeRegistrar pref_change_registrar_;
 
-  // Used to update the time limits message, if any, when screen is locked.
-  base::Optional<base::Time> next_unlock_time_;
-
   DISALLOW_COPY_AND_ASSIGN(ScreenTimeController);
 };
 
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc
index 802d286..9c55f360 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc
@@ -15,6 +15,9 @@
 namespace time_limit_consistency {
 namespace {
 
+// The default resets_at value is 6AM.
+constexpr base::TimeDelta kDefaultResetsAt = base::TimeDelta::FromHours(6);
+
 // Converts a ActivePolicies object from the time limit processor to a
 // ConsistencyGoldenPolicy used by the goldens.
 ConsistencyGoldenPolicy ConvertProcessorPolicyToGoldenPolicy(
@@ -61,42 +64,89 @@
 }  // namespace
 
 std::unique_ptr<base::DictionaryValue> ConvertGoldenInputToProcessorInput(
-    ConsistencyGoldenInput input) {
+    const ConsistencyGoldenInput& input) {
   // Random date representing the last time the policies were updated,
-  // since the tests won't take this into account for now.
-  base::Time last_updated = utils::TimeFromString("1 Jan 2018 10:00 GMT+0300");
+  // used whenever the last_updated field is not specified in the input proto.
+  base::Time default_last_updated =
+      utils::TimeFromString("1 Jan 2018 10:00 GMT+0300");
+  base::TimeDelta resets_at =
+      input.has_usage_limit_resets_at()
+          ? utils::CreateTime(input.usage_limit_resets_at().hour(),
+                              input.usage_limit_resets_at().minute())
+          : kDefaultResetsAt;
 
   std::unique_ptr<base::DictionaryValue> policy =
-      utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6));
+      utils::CreateTimeLimitPolicy(resets_at);
 
   /* Begin Window Limits data */
 
-  if (input.window_limits_size() > 0) {
-    for (ConsistencyGoldenWindowLimitEntry window_limit :
-         input.window_limits()) {
-      utils::AddTimeWindowLimit(
-          policy.get(),
-          ConvertGoldenDayToProcessorDay(window_limit.effective_day()),
-          utils::CreateTime(window_limit.starts_at().hour(),
-                            window_limit.starts_at().minute()),
-          utils::CreateTime(window_limit.ends_at().hour(),
-                            window_limit.ends_at().minute()),
-          last_updated);
-    }
+  for (const ConsistencyGoldenWindowLimitEntry& window_limit :
+       input.window_limits()) {
+    utils::AddTimeWindowLimit(
+        policy.get(),
+        ConvertGoldenDayToProcessorDay(window_limit.effective_day()),
+        utils::CreateTime(window_limit.starts_at().hour(),
+                          window_limit.starts_at().minute()),
+        utils::CreateTime(window_limit.ends_at().hour(),
+                          window_limit.ends_at().minute()),
+        window_limit.has_last_updated_millis()
+            ? base::Time::FromJavaTime(window_limit.last_updated_millis())
+            : default_last_updated);
   }
 
   /* End Window Limits data */
+  /* Begin Usage Limits data */
+
+  for (const ConsistencyGoldenUsageLimitEntry& usage_limit :
+       input.usage_limits()) {
+    utils::AddTimeUsageLimit(
+        policy.get(),
+        ConvertGoldenDayToProcessorDay(usage_limit.effective_day()),
+        base::TimeDelta::FromMinutes(usage_limit.usage_quota_mins()),
+        usage_limit.has_last_updated_millis()
+            ? base::Time::FromJavaTime(usage_limit.last_updated_millis())
+            : default_last_updated);
+  }
+
+  /* End Usage Limits data */
+  /* Begin Overrides data */
+
+  for (const ConsistencyGoldenOverride& override_entry : input.overrides()) {
+    if (override_entry.action() == UNLOCK_UNTIL_LOCK_DEADLINE) {
+      utils::AddOverrideWithDuration(
+          policy.get(), usage_time_limit::TimeLimitOverride::Action::kUnlock,
+          base::Time::FromJavaTime(override_entry.created_at_millis()),
+          base::TimeDelta::FromMilliseconds(override_entry.duration_millis()));
+    } else {
+      utils::AddOverride(
+          policy.get(),
+          override_entry.action() == LOCK
+              ? usage_time_limit::TimeLimitOverride::Action::kLock
+              : usage_time_limit::TimeLimitOverride::Action::kUnlock,
+          base::Time::FromJavaTime(override_entry.created_at_millis()));
+    }
+  }
+
+  /* End Overrides data */
 
   return policy;
 }
 
 ConsistencyGoldenOutput ConvertProcessorOutputToGoldenOutput(
-    usage_time_limit::State state) {
+    const usage_time_limit::State& state) {
   ConsistencyGoldenOutput golden_output;
 
   golden_output.set_is_locked(state.is_locked);
   golden_output.set_active_policy(
       ConvertProcessorPolicyToGoldenPolicy(state.active_policy));
+  golden_output.set_next_active_policy(
+      ConvertProcessorPolicyToGoldenPolicy(state.next_state_active_policy));
+
+  if (state.is_time_usage_limit_enabled &&
+      golden_output.active_policy() != OVERRIDE) {
+    golden_output.set_remaining_quota_millis(
+        state.remaining_usage.InMilliseconds());
+  }
 
   if (state.is_locked) {
     golden_output.set_next_unlocking_time_millis(
@@ -106,5 +156,35 @@
   return golden_output;
 }
 
+base::Optional<usage_time_limit::State>
+GenerateUnlockUsageLimitOverrideStateFromInput(
+    const ConsistencyGoldenInput& input) {
+  ConsistencyGoldenOverride* usage_limit_override = nullptr;
+  for (ConsistencyGoldenOverride override_entry : input.overrides()) {
+    if (override_entry.action() == UNLOCK_USAGE_LIMIT &&
+        (!usage_limit_override ||
+         override_entry.created_at_millis() >
+             usage_limit_override->created_at_millis())) {
+      usage_limit_override = &override_entry;
+    }
+  }
+
+  if (!usage_limit_override)
+    return base::nullopt;
+
+  usage_time_limit::State previous_state;
+  previous_state.is_locked = true;
+  previous_state.active_policy = usage_time_limit::ActivePolicies::kUsageLimit;
+  previous_state.is_time_usage_limit_enabled = true;
+  previous_state.remaining_usage = base::TimeDelta::FromMinutes(0);
+
+  // Usage limit started one minute before the override was created.
+  previous_state.time_usage_limit_started =
+      base::Time::FromJavaTime(usage_limit_override->created_at_millis()) -
+      base::TimeDelta::FromMinutes(1);
+
+  return previous_state;
+}
+
 }  // namespace time_limit_consistency
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h
index 5d55e1a..1357471f 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h
@@ -10,6 +10,7 @@
 
 #include <memory>
 
+#include "base/optional.h"
 #include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.pb.h"
 #include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
 
@@ -23,12 +24,21 @@
 // Converts the input part of a consistency golden case to the structure used by
 // the time limit processor.
 std::unique_ptr<base::DictionaryValue> ConvertGoldenInputToProcessorInput(
-    ConsistencyGoldenInput input);
+    const ConsistencyGoldenInput& input);
 
 // Converts the output struct generated by the time limit processor to the
 // consistency golden output proto.
 ConsistencyGoldenOutput ConvertProcessorOutputToGoldenOutput(
-    usage_time_limit::State state);
+    const usage_time_limit::State& state);
+
+// Generates a State struct representing the previous state required by the
+// processor if there is a UNLOCK_USAGE_LIMIT override present. The generated
+// state simulates being locked by usage limit since one minute before the
+// override was created.
+// If the override is of another type, base::nullopt will be returned.
+base::Optional<usage_time_limit::State>
+GenerateUnlockUsageLimitOverrideStateFromInput(
+    const ConsistencyGoldenInput& input);
 
 }  // namespace time_limit_consistency
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc
index ea9ce85..0c035e0 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h"
 
 #include "base/time/time.h"
+#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h"
 #include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/proto_matcher.h"
 #include "chrome/browser/chromeos/child_accounts/time_limit_test_utils.h"
 #include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
@@ -13,6 +14,7 @@
 namespace chromeos {
 
 namespace utils = time_limit_test_utils;
+namespace consistency_utils = time_limit_consistency_utils;
 
 namespace time_limit_consistency {
 
@@ -22,6 +24,11 @@
 // points to.
 constexpr int64_t kTestTimestamp = 1548709200000L;
 
+// An arbitrary date representing the last time the policy was updated. Used on
+// tests where such information is required but irrelevant to the test.
+const base::Time kTestLastUpdated =
+    utils::TimeFromString("1 Jan 2018 10:00 GMT+0300");
+
 TEST_F(ConsistencyGoldenConverterTest, ConvertInputWhenEmpty) {
   ConsistencyGoldenInput input;
 
@@ -35,33 +42,150 @@
 }
 
 TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithBedtimes) {
-  base::Time last_updated = utils::TimeFromString("1 Jan 2018 10:00 GMT+0300");
-
   ConsistencyGoldenInput input;
   std::unique_ptr<base::DictionaryValue> expected_output =
       utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6));
 
   // First window: Wednesday, 22:30 to 8:00
-  ConsistencyGoldenWindowLimitEntry* window_one = input.add_window_limits();
-  window_one->mutable_starts_at()->set_hour(22);
-  window_one->mutable_starts_at()->set_minute(30);
-  window_one->mutable_ends_at()->set_hour(8);
-  window_one->mutable_ends_at()->set_minute(0);
-  window_one->set_effective_day(WEDNESDAY);
+  consistency_utils::AddWindowLimitEntryToGoldenInput(
+      &input, WEDNESDAY, consistency_utils::TimeOfDay({22, 30}),
+      consistency_utils::TimeOfDay({8, 0}), base::nullopt);
   utils::AddTimeWindowLimit(expected_output.get(), utils::kWednesday,
                             utils::CreateTime(22, 30), utils::CreateTime(8, 0),
-                            last_updated);
+                            kTestLastUpdated);
 
   // Second window: Saturday, 18:45 to 22:30
-  ConsistencyGoldenWindowLimitEntry* window_two = input.add_window_limits();
-  window_two->mutable_starts_at()->set_hour(18);
-  window_two->mutable_starts_at()->set_minute(45);
-  window_two->mutable_ends_at()->set_hour(22);
-  window_two->mutable_ends_at()->set_minute(30);
-  window_two->set_effective_day(SATURDAY);
+  consistency_utils::AddWindowLimitEntryToGoldenInput(
+      &input, SATURDAY, consistency_utils::TimeOfDay({18, 45}),
+      consistency_utils::TimeOfDay({22, 30}), base::nullopt);
   utils::AddTimeWindowLimit(expected_output.get(), utils::kSaturday,
                             utils::CreateTime(18, 45),
-                            utils::CreateTime(22, 30), last_updated);
+                            utils::CreateTime(22, 30), kTestLastUpdated);
+
+  std::unique_ptr<base::DictionaryValue> actual_output =
+      ConvertGoldenInputToProcessorInput(input);
+
+  EXPECT_TRUE(*actual_output == *expected_output);
+}
+
+TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithBedtimesLastUpdated) {
+  ConsistencyGoldenInput input;
+  std::unique_ptr<base::DictionaryValue> expected_output =
+      utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6));
+
+  // First window: Wednesday, 22:30 to 8:00
+  consistency_utils::AddWindowLimitEntryToGoldenInput(
+      &input, WEDNESDAY, consistency_utils::TimeOfDay({22, 30}),
+      consistency_utils::TimeOfDay({8, 0}), kTestTimestamp);
+  utils::AddTimeWindowLimit(expected_output.get(), utils::kWednesday,
+                            utils::CreateTime(22, 30), utils::CreateTime(8, 0),
+                            base::Time::FromJavaTime(kTestTimestamp));
+
+  std::unique_ptr<base::DictionaryValue> actual_output =
+      ConvertGoldenInputToProcessorInput(input);
+
+  EXPECT_TRUE(*actual_output == *expected_output);
+}
+
+TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithUsageLimit) {
+  ConsistencyGoldenInput input;
+  std::unique_ptr<base::DictionaryValue> expected_output =
+      utils::CreateTimeLimitPolicy(utils::CreateTime(17, 30));
+
+  input.mutable_usage_limit_resets_at()->set_hour(17);
+  input.mutable_usage_limit_resets_at()->set_minute(30);
+
+  // First quota: Tuesday, 60 minutes
+  consistency_utils::AddUsageLimitEntryToGoldenInput(&input, TUESDAY, 60,
+                                                     base::nullopt);
+  utils::AddTimeUsageLimit(expected_output.get(), utils::kTuesday,
+                           base::TimeDelta::FromMinutes(60), kTestLastUpdated);
+
+  // Second quota: Friday, 30 minutes
+  consistency_utils::AddUsageLimitEntryToGoldenInput(&input, FRIDAY, 30,
+                                                     base::nullopt);
+  utils::AddTimeUsageLimit(expected_output.get(), utils::kFriday,
+                           base::TimeDelta::FromMinutes(30), kTestLastUpdated);
+
+  std::unique_ptr<base::DictionaryValue> actual_output =
+      ConvertGoldenInputToProcessorInput(input);
+
+  EXPECT_TRUE(*actual_output == *expected_output);
+}
+
+TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithUsageLimitDefaultReset) {
+  ConsistencyGoldenInput input;
+  std::unique_ptr<base::DictionaryValue> expected_output =
+      utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6));
+
+  // First quota: Tuesday, 60 minutes
+  consistency_utils::AddUsageLimitEntryToGoldenInput(&input, TUESDAY, 60,
+                                                     base::nullopt);
+  utils::AddTimeUsageLimit(expected_output.get(), utils::kTuesday,
+                           base::TimeDelta::FromMinutes(60), kTestLastUpdated);
+
+  // Second quota: Friday, 30 minutes
+  consistency_utils::AddUsageLimitEntryToGoldenInput(&input, FRIDAY, 30,
+                                                     base::nullopt);
+  utils::AddTimeUsageLimit(expected_output.get(), utils::kFriday,
+                           base::TimeDelta::FromMinutes(30), kTestLastUpdated);
+
+  std::unique_ptr<base::DictionaryValue> actual_output =
+      ConvertGoldenInputToProcessorInput(input);
+
+  EXPECT_TRUE(*actual_output == *expected_output);
+}
+
+TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithUsageLimitLastUpdated) {
+  ConsistencyGoldenInput input;
+  std::unique_ptr<base::DictionaryValue> expected_output =
+      utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6));
+
+  // First quota: Tuesday, 60 minutes
+  consistency_utils::AddUsageLimitEntryToGoldenInput(&input, TUESDAY, 60,
+                                                     kTestTimestamp);
+  utils::AddTimeUsageLimit(expected_output.get(), utils::kTuesday,
+                           base::TimeDelta::FromMinutes(60),
+                           base::Time::FromJavaTime(kTestTimestamp));
+
+  std::unique_ptr<base::DictionaryValue> actual_output =
+      ConvertGoldenInputToProcessorInput(input);
+
+  EXPECT_TRUE(*actual_output == *expected_output);
+}
+
+TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithOverride) {
+  ConsistencyGoldenInput input;
+  std::unique_ptr<base::DictionaryValue> expected_output =
+      utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6));
+
+  // Override: Unlock bedtime
+  consistency_utils::AddOverrideToGoldenInput(&input, UNLOCK_WINDOW_LIMIT,
+                                              kTestTimestamp);
+  utils::AddOverride(expected_output.get(),
+                     usage_time_limit::TimeLimitOverride::Action::kUnlock,
+                     base::Time::FromJavaTime(kTestTimestamp));
+
+  std::unique_ptr<base::DictionaryValue> actual_output =
+      ConvertGoldenInputToProcessorInput(input);
+
+  EXPECT_TRUE(*actual_output == *expected_output);
+}
+
+TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithTimedOverride) {
+  ConsistencyGoldenInput input;
+  std::unique_ptr<base::DictionaryValue> expected_output =
+      utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6));
+  const int64_t override_duration_millis = 10000;
+
+  // Override: Grant more time
+  consistency_utils::AddTimedOverrideToGoldenInput(
+      &input, override_duration_millis, kTestTimestamp);
+  utils::AddOverrideWithDuration(
+      expected_output.get(),
+      usage_time_limit::TimeLimitOverride::Action::kUnlock,
+      base::Time::FromJavaTime(kTestTimestamp),
+      base::TimeDelta::FromMilliseconds(override_duration_millis));
 
   std::unique_ptr<base::DictionaryValue> actual_output =
       ConvertGoldenInputToProcessorInput(input);
@@ -73,6 +197,8 @@
   usage_time_limit::State state;
   state.is_locked = false;
   state.active_policy = usage_time_limit::ActivePolicies::kNoActivePolicy;
+  state.next_state_active_policy =
+      usage_time_limit::ActivePolicies::kNoActivePolicy;
   state.next_unlock_time = base::Time::FromJavaTime(kTestTimestamp);
 
   ConsistencyGoldenOutput actual_output =
@@ -81,14 +207,17 @@
   ConsistencyGoldenOutput expected_output;
   expected_output.set_is_locked(false);
   expected_output.set_active_policy(NO_ACTIVE_POLICY);
+  expected_output.set_next_active_policy(NO_ACTIVE_POLICY);
 
   EXPECT_THAT(actual_output, EqualsProto(expected_output));
 }
 
-TEST_F(ConsistencyGoldenConverterTest, ConvertOutputWhenLocked) {
+TEST_F(ConsistencyGoldenConverterTest, ConvertOutputWhenLockedByBedtime) {
   usage_time_limit::State state;
   state.is_locked = true;
   state.active_policy = usage_time_limit::ActivePolicies::kFixedLimit;
+  state.next_state_active_policy =
+      usage_time_limit::ActivePolicies::kNoActivePolicy;
   state.next_unlock_time = base::Time::FromJavaTime(kTestTimestamp);
 
   ConsistencyGoldenOutput actual_output =
@@ -97,10 +226,65 @@
   ConsistencyGoldenOutput expected_output;
   expected_output.set_is_locked(true);
   expected_output.set_active_policy(FIXED_LIMIT);
+  expected_output.set_next_active_policy(NO_ACTIVE_POLICY);
   expected_output.set_next_unlocking_time_millis(kTestTimestamp);
 
   EXPECT_THAT(actual_output, EqualsProto(expected_output));
 }
 
+TEST_F(ConsistencyGoldenConverterTest, ConvertOutputWhenLockedByUsageLimit) {
+  int remaining_millis = 10000;
+
+  usage_time_limit::State state;
+  state.is_locked = true;
+  state.active_policy = usage_time_limit::ActivePolicies::kUsageLimit;
+  state.next_state_active_policy =
+      usage_time_limit::ActivePolicies::kNoActivePolicy;
+  state.is_time_usage_limit_enabled = true;
+  state.remaining_usage = base::TimeDelta::FromMilliseconds(remaining_millis);
+  state.next_unlock_time = base::Time::FromJavaTime(kTestTimestamp);
+
+  ConsistencyGoldenOutput actual_output =
+      ConvertProcessorOutputToGoldenOutput(state);
+
+  ConsistencyGoldenOutput expected_output;
+  expected_output.set_is_locked(true);
+  expected_output.set_active_policy(USAGE_LIMIT);
+  expected_output.set_next_active_policy(NO_ACTIVE_POLICY);
+  expected_output.set_remaining_quota_millis(remaining_millis);
+  expected_output.set_next_unlocking_time_millis(kTestTimestamp);
+
+  EXPECT_THAT(actual_output, EqualsProto(expected_output));
+}
+
+TEST_F(ConsistencyGoldenConverterTest, GeneratePreviousStateUnlockUsageLimit) {
+  ConsistencyGoldenInput input;
+  consistency_utils::AddOverrideToGoldenInput(&input, UNLOCK_USAGE_LIMIT,
+                                              kTestTimestamp);
+
+  base::Optional<usage_time_limit::State> generated_state =
+      GenerateUnlockUsageLimitOverrideStateFromInput(input);
+
+  EXPECT_TRUE(generated_state->is_locked);
+  EXPECT_TRUE(generated_state->is_time_usage_limit_enabled);
+  EXPECT_EQ(generated_state->active_policy,
+            usage_time_limit::ActivePolicies::kUsageLimit);
+  EXPECT_EQ(generated_state->remaining_usage, base::TimeDelta::FromMinutes(0));
+  EXPECT_EQ(generated_state->time_usage_limit_started,
+            base::Time::FromJavaTime(kTestTimestamp) -
+                base::TimeDelta::FromMinutes(1));
+}
+
+TEST_F(ConsistencyGoldenConverterTest, GeneratePreviousStateOtherOverrides) {
+  ConsistencyGoldenInput input;
+  consistency_utils::AddOverrideToGoldenInput(&input, UNLOCK_WINDOW_LIMIT,
+                                              kTestTimestamp);
+
+  base::Optional<usage_time_limit::State> generated_state =
+      GenerateUnlockUsageLimitOverrideStateFromInput(input);
+
+  EXPECT_EQ(generated_state, base::nullopt);
+}
+
 }  // namespace time_limit_consistency
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test.cc b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test.cc
new file mode 100644
index 0000000..ecb2d8a
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test.cc
@@ -0,0 +1,67 @@
+// Copyright 2019 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.
+//
+// Test for the time limit processor which checks its behavior against golden
+// files. This is a parameterized test, so the single test method will actually
+// produce one test case for each case listed inside each golden file.
+
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h"
+#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_loader.h"
+#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.pb.h"
+#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/proto_matcher.h"
+#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
+#include "chromeos/settings/timezone_settings.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace time_limit_consistency {
+
+using TimeLimitConsistencyTest = testing::TestWithParam<GoldenParam>;
+
+// The main test case for the consistency tests, which will be run once for each
+// golden case.
+TEST_P(TimeLimitConsistencyTest, OutputMatchesGolden) {
+  const ConsistencyGoldenCase golden_case = GetParam().golden_case;
+  const ConsistencyGoldenCurrentState current_state =
+      golden_case.current_state();
+
+  icu::TimeZone* timezone(
+      icu::TimeZone::createTimeZone(current_state.timezone().c_str()));
+  base::Time current_time =
+      base::Time::FromJavaTime(current_state.time_millis());
+  base::Time usage_timestamp =
+      base::Time::FromJavaTime(current_state.usage_timestamp());
+  base::Optional<usage_time_limit::State> previous_state =
+      GenerateUnlockUsageLimitOverrideStateFromInput(golden_case.input());
+
+  std::unique_ptr<base::DictionaryValue> policy =
+      ConvertGoldenInputToProcessorInput(golden_case.input());
+  usage_time_limit::State state = usage_time_limit::GetState(
+      policy, /* local_override */ nullptr,
+      base::TimeDelta::FromMilliseconds(current_state.usage_millis()),
+      usage_timestamp, current_time, timezone, previous_state);
+  ConsistencyGoldenOutput actual_output =
+      ConvertProcessorOutputToGoldenOutput(state);
+
+  EXPECT_THAT(actual_output, EqualsProto(golden_case.output()));
+}
+
+// Generate the test case name from the metadata included in GoldenParam.
+static std::string GetTestCaseName(
+    testing::TestParamInfo<GoldenParam> param_info) {
+  return param_info.param.suite_name + "_" +
+         std::to_string(param_info.param.index);
+}
+
+// Instantiate the test suite, creating one test case for each golden case
+// loaded and providing it as a parameter.
+INSTANTIATE_TEST_SUITE_P(Parameterized,
+                         TimeLimitConsistencyTest,
+                         testing::ValuesIn(LoadGoldenCases()),
+                         GetTestCaseName);
+
+}  // namespace time_limit_consistency
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.cc b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.cc
new file mode 100644
index 0000000..ba83796
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.cc
@@ -0,0 +1,68 @@
+// Copyright 2019 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 "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h"
+#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.pb.h"
+
+namespace chromeos {
+namespace time_limit_consistency_utils {
+
+void AddWindowLimitEntryToGoldenInput(
+    time_limit_consistency::ConsistencyGoldenInput* golden_input,
+    time_limit_consistency::ConsistencyGoldenEffectiveDay effective_day,
+    const TimeOfDay& starts_at,
+    const TimeOfDay& ends_at,
+    base::Optional<int64_t> last_updated) {
+  time_limit_consistency::ConsistencyGoldenWindowLimitEntry* window =
+      golden_input->add_window_limits();
+  window->mutable_starts_at()->set_hour(starts_at.hour);
+  window->mutable_starts_at()->set_minute(starts_at.minute);
+  window->mutable_ends_at()->set_hour(ends_at.hour);
+  window->mutable_ends_at()->set_minute(ends_at.minute);
+  window->set_effective_day(effective_day);
+
+  if (last_updated)
+    window->set_last_updated_millis(last_updated.value());
+}
+
+void AddUsageLimitEntryToGoldenInput(
+    time_limit_consistency::ConsistencyGoldenInput* golden_input,
+    time_limit_consistency::ConsistencyGoldenEffectiveDay effective_day,
+    int usage_quota_mins,
+    base::Optional<int64_t> last_updated) {
+  time_limit_consistency::ConsistencyGoldenUsageLimitEntry* usage_limit =
+      golden_input->add_usage_limits();
+  usage_limit->set_usage_quota_mins(usage_quota_mins);
+  usage_limit->set_effective_day(effective_day);
+
+  if (last_updated)
+    usage_limit->set_last_updated_millis(last_updated.value());
+}
+
+void AddOverrideToGoldenInput(
+    time_limit_consistency::ConsistencyGoldenInput* golden_input,
+    time_limit_consistency::ConsistencyGoldenOverrideAction action,
+    int64_t created_at) {
+  DCHECK(action != time_limit_consistency::UNLOCK_UNTIL_LOCK_DEADLINE);
+
+  time_limit_consistency::ConsistencyGoldenOverride* override_entry =
+      golden_input->add_overrides();
+  override_entry->set_action(action);
+  override_entry->set_created_at_millis(created_at);
+}
+
+void AddTimedOverrideToGoldenInput(
+    time_limit_consistency::ConsistencyGoldenInput* golden_input,
+    int64_t duration_millis,
+    int64_t created_at) {
+  time_limit_consistency::ConsistencyGoldenOverride* override_entry =
+      golden_input->add_overrides();
+  override_entry->set_action(
+      time_limit_consistency::UNLOCK_UNTIL_LOCK_DEADLINE);
+  override_entry->set_duration_millis(duration_millis);
+  override_entry->set_created_at_millis(created_at);
+}
+
+}  // namespace time_limit_consistency_utils
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h
new file mode 100644
index 0000000..cb16c00
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h
@@ -0,0 +1,56 @@
+// Copyright 2019 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.
+//
+// Utilities to be used by the consistency golden converter unit tests.
+
+#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_CONSISTENCY_TEST_CONSISTENCY_TEST_UTILS_H_
+#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_CONSISTENCY_TEST_CONSISTENCY_TEST_UTILS_H_
+
+#include "base/optional.h"
+#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.pb.h"
+
+namespace chromeos {
+namespace time_limit_consistency_utils {
+
+// A time of day composed of hours and minutes, used when generating bedtime
+// entries.
+struct TimeOfDay {
+  int hour;
+  int minute;
+};
+
+// Adds a time window limit entry to the provided ConsistencyGoldenInput.
+void AddWindowLimitEntryToGoldenInput(
+    time_limit_consistency::ConsistencyGoldenInput* golden_input,
+    time_limit_consistency::ConsistencyGoldenEffectiveDay effective_day,
+    const TimeOfDay& starts_at,
+    const TimeOfDay& ends_at,
+    base::Optional<int64_t> last_updated);
+
+// Adds a usage limit entry to the provided ConsistencyGoldenInput.
+void AddUsageLimitEntryToGoldenInput(
+    time_limit_consistency::ConsistencyGoldenInput* golden_input,
+    time_limit_consistency::ConsistencyGoldenEffectiveDay effective_day,
+    int usage_quota_mins,
+    base::Optional<int64_t> last_updated);
+
+// Adds an override to the provided ConsistencyGoldenInput. Must not be used
+// for UNLOCK_UNTIL_LOCK_DEADLINE actions (will DCHECK()), use
+// AddTimedOverrideToGoldenInput() instead.
+void AddOverrideToGoldenInput(
+    time_limit_consistency::ConsistencyGoldenInput* golden_input,
+    time_limit_consistency::ConsistencyGoldenOverrideAction action,
+    int64_t created_at);
+
+// Adds a timed override (UNLOCK_UNTIL_LOCK_DEADLINE action) with duration set
+// to |duration_millis| to the provided ConsistencyGoldenInput.
+void AddTimedOverrideToGoldenInput(
+    time_limit_consistency::ConsistencyGoldenInput* golden_input,
+    int64_t duration_millis,
+    int64_t created_at);
+
+}  // namespace time_limit_consistency_utils
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_CONSISTENCY_TEST_CONSISTENCY_TEST_UTILS_H_
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto
index c3cec2e..f187160 100644
--- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto
@@ -23,6 +23,18 @@
   USAGE_LIMIT = 4;
 }
 
+// Actions that an override can take.
+enum ConsistencyGoldenOverrideAction {
+  UNSPECIFIED_ACTION = 0;
+  LOCK = 1;
+  UNLOCK_USAGE_LIMIT = 2;
+  UNLOCK_WINDOW_LIMIT = 3;
+  // Deprecated but kept here for easier conversion to/from the original enum.
+  UNLOCK_LOCK_OVERRIDE = 4 [deprecated = true];
+  UNLOCK_WITH_DEADLINE = 5;
+  UNLOCK_UNTIL_LOCK_DEADLINE = 6;
+}
+
 // Days of the week.
 enum ConsistencyGoldenEffectiveDay {
   UNSPECIFIED_EFFECTIVE_DAY = 0;
@@ -61,6 +73,16 @@
 message ConsistencyGoldenInput {
   // List of bedtime configurations for different days of the week.
   repeated ConsistencyGoldenWindowLimitEntry window_limits = 1;
+
+  // Time of day when the usage time counter is reset. Optional, will default
+  // to 6am if unset.
+  optional ConsistencyGoldenTimeOfDay usage_limit_resets_at = 2;
+
+  // List of usage time configurations for different days of the week.
+  repeated ConsistencyGoldenUsageLimitEntry usage_limits = 3;
+
+  // List of overrides currently active.
+  repeated ConsistencyGoldenOverride overrides = 4;
 }
 
 // Bedtime configuration for a given day.
@@ -73,6 +95,35 @@
 
   // At which hour and minute this bedtime should end. Required
   optional ConsistencyGoldenTimeOfDay ends_at = 3;
+
+  // The moment when this configuration was last updated. Optional but some more
+  // complex scenarios may require it.
+  optional int64 last_updated_millis = 4;
+}
+
+// Usage limit configuration for a given day.
+message ConsistencyGoldenUsageLimitEntry {
+  // Which day of the week this configuration relates to. Required
+  optional ConsistencyGoldenEffectiveDay effective_day = 1;
+
+  // Available usage quota for this day in minutes. Required (0 means no quota).
+  optional int32 usage_quota_mins = 2;
+
+  // The moment when this configuration was last updated. Optional but some more
+  // complex scenarios may require it.
+  optional int64 last_updated_millis = 3;
+}
+
+// Represents an override that is currently active.
+message ConsistencyGoldenOverride {
+  // What this override does. Required
+  optional ConsistencyGoldenOverrideAction action = 1;
+
+  // Moment when this override was created, in millis. Required.
+  optional int64 created_at_millis = 2;
+
+  // The duration of the unlock, if it is of type "UNLOCK_UNTIL_LOCK_DEADLINE".
+  optional int64 duration_millis = 3;
 }
 
 // Represents a moment of a day.
@@ -92,6 +143,14 @@
   // String representing the desired timezone, formatted like "GMT+2"/"GMT-3"
   // or "America/Sao_Paulo". Required
   optional string timezone = 2;
+
+  // How much usage time was already spent, in milliseconds.
+  // Optional, will be treated as zero if unset.
+  optional int64 usage_millis = 3;
+
+  // Timestamp representing the moment when usage data was last collected.
+  // Optional, will default to |time_millis| if unset.
+  optional int64 usage_timestamp = 4;
 }
 
 // Information on the output.
@@ -105,4 +164,11 @@
   // Timestamp of when is the device supposed to unlock.
   // This field must be present if and only if the device is locked.
   optional int64 next_unlocking_time_millis = 3;
+
+  // Policy that is expected to be active when next state begins. Required
+  optional ConsistencyGoldenPolicy next_active_policy = 4;
+
+  // How much time in millis is still available in the current day's quota.
+  // Required only if dealing with usage limits.
+  optional int64 remaining_quota_millis = 5;
 }
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_bedtimes.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_bedtimes.textproto
new file mode 100644
index 0000000..d929032
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_bedtimes.textproto
@@ -0,0 +1,110 @@
+supported_platforms: [ANDROID, CHROME_OS]
+
+# Override created while bedtime is active
+cases {
+  input {
+    window_limits {
+      effective_day: MONDAY
+      starts_at {
+        hour: 23
+        minute: 0
+      }
+      ends_at {
+        hour: 8
+        minute: 0
+      }
+    }
+    overrides {
+      action: UNLOCK_WINDOW_LIMIT
+      # Monday, Jan 28th 2019 at 11:29pm
+      created_at_millis: 1548718140000
+    }
+  }
+  current_state {
+    # Monday, Jan 28th 2019 at 11:30pm
+    time_millis: 1548718200000
+    timezone: "GMT"
+  }
+  output {
+    is_locked: false
+    active_policy: OVERRIDE
+    next_active_policy: FIXED_LIMIT
+  }
+}
+
+# Override created before bedtime started
+cases {
+  input {
+    window_limits {
+      effective_day: MONDAY
+      starts_at {
+        hour: 23
+        minute: 0
+      }
+      ends_at {
+        hour: 8
+        minute: 0
+      }
+    }
+    overrides {
+      action: UNLOCK_WINDOW_LIMIT
+      # Monday, Jan 28th 2019 at 10:30pm
+      created_at_millis: 1548714600000
+    }
+  }
+  current_state {
+    # Monday, Jan 28th 2019 at 11:30pm
+    time_millis: 1548718200000
+    timezone: "GMT"
+  }
+  output {
+    is_locked: true
+    active_policy: FIXED_LIMIT
+    # Tuesday, Jan 29th 2019 at 8:00am
+    next_unlocking_time_millis: 1548748800000
+    next_active_policy: NO_ACTIVE_POLICY
+  }
+}
+
+# Override created during intersection of bedtimes
+cases {
+  input {
+    window_limits {
+      effective_day: MONDAY
+      starts_at {
+        hour: 23
+        minute: 0
+      }
+      ends_at {
+        hour: 8
+        minute: 0
+      }
+    }
+    window_limits {
+      effective_day: TUESDAY
+      starts_at {
+        hour: 2
+        minute: 0
+      }
+      ends_at {
+        hour: 11
+        minute: 0
+      }
+    }
+    overrides {
+      action: UNLOCK_WINDOW_LIMIT
+      # Tuesday, Jan 29th 2019 at 2:20am
+      created_at_millis: 1548728400000
+    }
+  }
+  current_state {
+    # Tuesday, Jan 29th 2019 at 2:30am
+    time_millis: 1548729000000
+    timezone: "GMT"
+  }
+  output {
+    is_locked: false
+    active_policy: OVERRIDE
+    next_active_policy: FIXED_LIMIT
+  }
+}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_then_modify.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_then_modify.textproto
new file mode 100644
index 0000000..515e1db5
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_then_modify.textproto
@@ -0,0 +1,102 @@
+supported_platforms: [ANDROID, CHROME_OS]
+
+# Override created for bedtime, then bedtime is altered.
+cases {
+  input {
+    window_limits {
+      effective_day: MONDAY
+      starts_at {
+        hour: 23
+        minute: 0
+      }
+      ends_at {
+        hour: 8
+        minute: 0
+      }
+      # Monday, Jan 28th 2019 at 11:25pm
+      last_updated_millis: 1548717900000
+    }
+    overrides {
+      action: UNLOCK_WINDOW_LIMIT
+      # Monday, Jan 28th 2019 at 11:20pm
+      created_at_millis: 1548717600000
+    }
+  }
+  current_state {
+    # Monday, Jan 28th 2019 at 11:30pm
+    time_millis: 1548718200000
+    timezone: "GMT"
+  }
+  output {
+    is_locked: true
+    active_policy: FIXED_LIMIT
+    next_active_policy: NO_ACTIVE_POLICY
+    # Tuesday, Jan 29th 2019 at 8:00am
+    next_unlocking_time_millis: 1548748800000
+  }
+}
+
+# Override created after hitting usage limit, then usage limit quota is updated
+# to a value bigger than the current usage.
+cases {
+  input {
+    usage_limits {
+      effective_day: THURSDAY
+      usage_quota_mins: 120
+      # Thursday, Feb 21st 2019 at 2:50pm
+      last_updated_millis: 1550760600000
+    }
+    overrides {
+      action: UNLOCK_USAGE_LIMIT
+      # Thursday, Feb 21st 2019 at 2:40pm
+      created_at_millis: 1550760000000
+    }
+  }
+  current_state {
+    # Thursday, Feb 21st 2019 at 3:00pm
+    time_millis: 1550761200000
+    timezone: "GMT"
+    # 1 hour
+    usage_millis: 3600000
+  }
+  output {
+    is_locked: false
+    active_policy: NO_ACTIVE_POLICY
+    next_active_policy: USAGE_LIMIT
+    # 1 hour
+    remaining_quota_millis: 3600000
+  }
+}
+
+# Override created after hitting usage limit, then usage limit quota is updated
+# to a value smaller than the current usage.
+cases {
+  input {
+    usage_limits {
+      effective_day: THURSDAY
+      usage_quota_mins: 45
+      # Thursday, Feb 21st 2019 at 2:50pm
+      last_updated_millis: 1550760600000
+    }
+    overrides {
+      action: UNLOCK_USAGE_LIMIT
+      # Thursday, Feb 21st 2019 at 2:40pm
+      created_at_millis: 1550760000000
+    }
+  }
+  current_state {
+    # Thursday, Feb 21st 2019 at 3:00pm
+    time_millis: 1550761200000
+    timezone: "GMT"
+    # 1 hour
+    usage_millis: 3600000
+  }
+  output {
+    is_locked: true
+    active_policy: USAGE_LIMIT
+    # Friday, Feb 22nd 2019 at 6:00am
+    next_unlocking_time_millis: 1550815200000
+    next_active_policy: NO_ACTIVE_POLICY
+    remaining_quota_millis: 0
+  }
+}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_android.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_android.textproto
new file mode 100644
index 0000000..77ce4298
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_android.textproto
@@ -0,0 +1,61 @@
+# There is a different behavior on Android and ChromeOS for the first test case
+# so they are split in two different suites temporarily.
+
+supported_platforms: [ANDROID]
+
+# Override created while usage limit is active
+cases {
+  input {
+    usage_limits {
+      effective_day: THURSDAY
+      usage_quota_mins: 120
+    }
+    overrides {
+      action: UNLOCK_USAGE_LIMIT
+      # Thursday, Feb 21th 2019 at 14:50pm
+      created_at_millis: 1550760600000
+    }
+  }
+  current_state {
+    # Thursday, Feb 21th 2019 at 15:00pm
+    time_millis: 1550761200000
+    timezone: "GMT"
+    # 2 hours
+    usage_millis: 7200000
+  }
+  output {
+    is_locked: false
+    active_policy: OVERRIDE
+    next_active_policy: USAGE_LIMIT
+  }
+}
+
+# Usage limit reached while other override is in place
+cases {
+  input {
+    usage_limits {
+      effective_day: THURSDAY
+      usage_quota_mins: 120
+    }
+    overrides {
+      action: UNLOCK_WINDOW_LIMIT
+      # Thursday, Feb 21th 2019 at 14:50pm
+      created_at_millis: 1550760600000
+    }
+  }
+  current_state {
+    # Thursday, Feb 21th 2019 at 15:00pm
+    time_millis: 1550761200000
+    timezone: "GMT"
+    # 2 hours
+    usage_millis: 7200000
+  }
+  output {
+    is_locked: true
+    active_policy: USAGE_LIMIT
+    next_active_policy: NO_ACTIVE_POLICY
+    remaining_quota_millis: 0
+    # Friday, Feb 22nd 2019 at 6:00am
+    next_unlocking_time_millis: 1550815200000
+  }
+}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_cros.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_cros.textproto
new file mode 100644
index 0000000..e123418
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_cros.textproto
@@ -0,0 +1,61 @@
+# There is a different behavior on Android and ChromeOS for the first test case
+# so they are split in two different suites temporarily.
+
+supported_platforms: [CHROME_OS]
+
+# Override created while usage limit is active
+cases {
+  input {
+    usage_limits {
+      effective_day: THURSDAY
+      usage_quota_mins: 120
+    }
+    overrides {
+      action: UNLOCK_USAGE_LIMIT
+      # Thursday, Feb 21th 2019 at 14:50pm
+      created_at_millis: 1550760600000
+    }
+  }
+  current_state {
+    # Thursday, Feb 21th 2019 at 15:00pm
+    time_millis: 1550761200000
+    timezone: "GMT"
+    # 2 hours
+    usage_millis: 7200000
+  }
+  output {
+    is_locked: false
+    active_policy: OVERRIDE
+    next_active_policy: NO_ACTIVE_POLICY
+  }
+}
+
+# Usage limit reached while other override is in place
+cases {
+  input {
+    usage_limits {
+      effective_day: THURSDAY
+      usage_quota_mins: 120
+    }
+    overrides {
+      action: UNLOCK_WINDOW_LIMIT
+      # Thursday, Feb 21th 2019 at 14:50pm
+      created_at_millis: 1550760600000
+    }
+  }
+  current_state {
+    # Thursday, Feb 21th 2019 at 15:00pm
+    time_millis: 1550761200000
+    timezone: "GMT"
+    # 2 hours
+    usage_millis: 7200000
+  }
+  output {
+    is_locked: true
+    active_policy: USAGE_LIMIT
+    next_active_policy: NO_ACTIVE_POLICY
+    remaining_quota_millis: 0
+    # Friday, Feb 22nd 2019 at 6:00am
+    next_unlocking_time_millis: 1550815200000
+  }
+}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_bedtimes.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_bedtimes.textproto
new file mode 100644
index 0000000..f0a4946
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_bedtimes.textproto
@@ -0,0 +1,68 @@
+supported_platforms: [ANDROID, CHROME_OS]
+
+# Bedtime set for 11pm to 8am, current time is 11:30pm, device should be locked.
+cases {
+  input {
+    window_limits {
+      effective_day: MONDAY
+      starts_at {
+        hour: 23
+        minute: 0
+      }
+      ends_at {
+        hour: 8
+        minute: 0
+      }
+    }
+  }
+  current_state {
+    # Monday, Jan 28th 2019 at 11:30pm
+    time_millis: 1548718200000
+    timezone: "GMT"
+  }
+  output {
+    is_locked: true
+    active_policy: FIXED_LIMIT
+    # Tuesday, Jan 29th 2019 at 8:00am
+    next_unlocking_time_millis: 1548748800000
+    next_active_policy: NO_ACTIVE_POLICY
+  }
+}
+
+# Bedtime set for 12pm to 9:30pm, current time is 9:40pm, should be unlocked.
+cases {
+  input {
+    window_limits {
+      effective_day: WEDNESDAY
+      starts_at {
+        hour: 12
+        minute: 0
+      }
+      ends_at {
+        hour: 21
+        minute: 30
+      }
+    }
+    window_limits {
+      effective_day: FRIDAY
+      starts_at {
+        hour: 15
+        minute: 0
+      }
+      ends_at {
+        hour: 5
+        minute: 30
+      }
+    }
+  }
+  current_state {
+    # Wednesday, Jan 30th 2019 at 9:40pm
+    time_millis: 1548884400000
+    timezone: "GMT"
+  }
+  output {
+    is_locked: false
+    active_policy: NO_ACTIVE_POLICY
+    next_active_policy: FIXED_LIMIT
+  }
+}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_override.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_override.textproto
new file mode 100644
index 0000000..db0ceed
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_override.textproto
@@ -0,0 +1,24 @@
+supported_platforms: [ANDROID, CHROME_OS]
+
+# Create a simple lock override.
+cases {
+  input {
+    overrides {
+      action: LOCK
+      # Thursday, Feb 21st 2019 at 14:50pm
+      created_at_millis: 1550760600000
+    }
+  }
+  current_state {
+    # Thursday, Feb 21st 2019 at 15:00pm
+    time_millis: 1550761200000
+    timezone: "GMT"
+  }
+  output {
+    is_locked: true
+    active_policy: OVERRIDE
+    # Friday, Feb 22nd 2019 at 6:00am
+    next_unlocking_time_millis: 1550815200000
+    next_active_policy: NO_ACTIVE_POLICY
+  }
+}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_usage_limits.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_usage_limits.textproto
new file mode 100644
index 0000000..e93e2511
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_usage_limits.textproto
@@ -0,0 +1,50 @@
+supported_platforms: [ANDROID, CHROME_OS]
+
+# Usage quota fully used, should lock the device by usage limit.
+cases {
+  input {
+    usage_limits {
+      effective_day: SUNDAY
+      usage_quota_mins: 120
+    }
+  }
+  current_state {
+    # Sunday, Feb 24th 2019 at 15:00pm
+    time_millis: 1551020400000
+    timezone: "GMT"
+    # 2 hours
+    usage_millis: 7200000
+  }
+  output {
+    is_locked: true
+    active_policy: USAGE_LIMIT
+    # Monday, Feb 25th 2019 at 6:00am
+    next_unlocking_time_millis: 1551074400000
+    next_active_policy: NO_ACTIVE_POLICY
+    remaining_quota_millis: 0
+  }
+}
+
+# Only a fraction of quota used, device should be unlocked.
+cases {
+  input {
+    usage_limits {
+      effective_day: FRIDAY
+      usage_quota_mins: 60
+    }
+  }
+  current_state {
+    # Friday, Feb 22th 2019 at 15:00pm
+    time_millis: 1550847600000
+    timezone: "GMT"
+    # 15 minutes
+    usage_millis: 900000
+  }
+  output {
+    is_locked: false
+    active_policy: NO_ACTIVE_POLICY
+    next_active_policy: USAGE_LIMIT
+    # 45 minutes
+    remaining_quota_millis: 2700000
+  }
+}
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h b/chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h
index 80ee9a9..652f05a 100644
--- a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h
+++ b/chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h
@@ -9,8 +9,8 @@
 #include "base/no_destructor.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "components/session_manager/core/session_manager_observer.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier_unittest.cc b/chrome/browser/chromeos/child_accounts/usage_time_state_notifier_unittest.cc
index b45f894..1aaf4ac1 100644
--- a/chrome/browser/chromeos/child_accounts/usage_time_state_notifier_unittest.cc
+++ b/chrome/browser/chromeos/child_accounts/usage_time_state_notifier_unittest.cc
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/session_manager/core/session_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 69a09f9c6..d0ddfbc 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -133,7 +133,7 @@
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/services/cros_dbus_service.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/dbus/util/version_loader.h"
diff --git a/chrome/browser/chromeos/dbus/dbus_helper.cc b/chrome/browser/chromeos/dbus/dbus_helper.cc
index 8e2d94a..488b8ba1 100644
--- a/chrome/browser/chromeos/dbus/dbus_helper.cc
+++ b/chrome/browser/chromeos/dbus/dbus_helper.cc
@@ -9,7 +9,7 @@
 #include "chromeos/dbus/biod/biod_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/hammerd/hammerd_client.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/system_clock/system_clock_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/tpm/install_attributes.h"
@@ -29,19 +29,24 @@
   // Features only needed in Ash. Initialize them here for non MultiProcessMash
   // to limit the number of places where dbus handlers are initialized. For
   // MultiProcessMash they are initialized in AshService::InitializeDBusClients.
-  if (!::features::IsMultiProcessMash())
-    chromeos::HammerdClient::Initialize(bus);
+  if (!::features::IsMultiProcessMash()) {
+    if (bus) {
+      chromeos::HammerdClient::Initialize(bus);
+    } else {
+      chromeos::HammerdClient::InitializeFake();
+    }
+  }
 
+  // TODO(estade/stevenjb): Modify PowerManagerClient to use InitializeFake.
   PowerManagerClient::Initialize(bus);
-  SystemClockClient::Initialize(bus);
 
-  // TODO(stevenjb): Modify PowerManagerClient and SystemClockClient to use
-  // the same pattern as UpstartClient.
   if (bus) {
     BiodClient::Initialize(bus);  // For device::Fingerprint.
+    SystemClockClient::Initialize(bus);
     UpstartClient::Initialize(bus);
   } else {
     BiodClient::InitializeFake();  // For device::Fingerprint.
+    SystemClockClient::InitializeFake();
     UpstartClient::InitializeFake();
   }
 
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index a5678478..bc95073d 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -39,7 +39,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/generated_resources.h"
 #include "chromeos/components/drivefs/drivefs_bootstrap.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/network/portal_detector/network_portal_detector.h"
@@ -75,6 +74,7 @@
 #include "services/service_manager/public/cpp/connector.h"
 #include "storage/browser/fileapi/external_mount_points.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 
 using content::BrowserContext;
 using content::BrowserThread;
diff --git a/chrome/browser/chromeos/extensions/file_manager/device_event_router.h b/chrome/browser/chromeos/extensions/file_manager/device_event_router.h
index 2aee5cb..62ee756e 100644
--- a/chrome/browser/chromeos/extensions/file_manager/device_event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/device_event_router.h
@@ -13,7 +13,7 @@
 #include "base/threading/thread_checker.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager_observer.h"
 #include "chrome/common/extensions/api/file_manager_private.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace file_manager {
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index cc6d6c26..c03e638a 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -37,7 +37,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/components/drivefs/drivefs_host.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/disks/disk.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
diff --git a/chrome/browser/chromeos/file_manager/path_util.cc b/chrome/browser/chromeos/file_manager/path_util.cc
index 713c1b2..46fb66c0 100644
--- a/chrome/browser/chromeos/file_manager/path_util.cc
+++ b/chrome/browser/chromeos/file_manager/path_util.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/grit/generated_resources.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "components/drive/file_system_core_util.h"
 #include "components/user_manager/user.h"
@@ -37,6 +36,7 @@
 #include "net/base/filename_util.h"
 #include "storage/browser/fileapi/external_mount_points.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 #include "url/gurl.h"
 
 namespace file_manager {
diff --git a/chrome/browser/chromeos/file_manager/select_file_dialog_util.cc b/chrome/browser/chromeos/file_manager/select_file_dialog_util.cc
index 2c2a48c..96990046 100644
--- a/chrome/browser/chromeos/file_manager/select_file_dialog_util.cc
+++ b/chrome/browser/chromeos/file_manager/select_file_dialog_util.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/chromeos/file_manager/select_file_dialog_util.h"
 
-#include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 
 namespace file_manager {
 namespace util {
diff --git a/chrome/browser/chromeos/file_manager/volume_manager_factory.cc b/chrome/browser/chromeos/file_manager/volume_manager_factory.cc
index 37543d4..10b93e5 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager_factory.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager_factory.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/storage_monitor/storage_monitor.h"
diff --git a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
index 67b5f5d3..dfbaaac2 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
@@ -26,7 +26,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/constants/chromeos_features.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "chromeos/disks/disk.h"
 #include "chromeos/disks/disk_mount_manager.h"
diff --git a/chrome/browser/chromeos/file_system_provider/notification_manager.cc b/chrome/browser/chromeos/file_system_provider/notification_manager.cc
index 9353bba..d5e5f72 100644
--- a/chrome/browser/chromeos/file_system_provider/notification_manager.cc
+++ b/chrome/browser/chromeos/file_system_provider/notification_manager.cc
@@ -9,9 +9,9 @@
 #include "chrome/browser/extensions/chrome_app_icon_loader.h"
 #include "chrome/browser/notifications/notification_display_service.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/account_id/account_id.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 #include "ui/message_center/public/cpp/notification.h"
 #include "ui/message_center/public/cpp/notification_types.h"
 #include "ui/message_center/public/cpp/notifier_id.h"
diff --git a/chrome/browser/chromeos/kiosk_next_home/BUILD.gn b/chrome/browser/chromeos/kiosk_next_home/BUILD.gn
new file mode 100644
index 0000000..cdf787e
--- /dev/null
+++ b/chrome/browser/chromeos/kiosk_next_home/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright 2019 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.
+
+source_set("kiosk_next_home") {
+  sources = [
+    "kiosk_next_home_interface_broker_impl.cc",
+    "kiosk_next_home_interface_broker_impl.h",
+  ]
+
+  deps = [
+    "//base",
+    "//chrome/browser/chromeos/kiosk_next_home/mojom",
+    "//services/identity/public/mojom",
+    "//services/service_manager/public/cpp",
+  ]
+}
diff --git a/chrome/browser/chromeos/kiosk_next_home/OWNERS b/chrome/browser/chromeos/kiosk_next_home/OWNERS
new file mode 100644
index 0000000..c28af4a
--- /dev/null
+++ b/chrome/browser/chromeos/kiosk_next_home/OWNERS
@@ -0,0 +1,2 @@
+agawronska@chromium.org
+michaelpg@chromium.org
diff --git a/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.cc b/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.cc
new file mode 100644
index 0000000..9a0e759
--- /dev/null
+++ b/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.cc
@@ -0,0 +1,34 @@
+// Copyright 2019 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 "chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.h"
+
+#include <utility>
+
+#include "services/identity/public/mojom/constants.mojom.h"
+#include "services/identity/public/mojom/identity_accessor.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace chromeos {
+namespace kiosk_next_home {
+
+KioskNextHomeInterfaceBrokerImpl::KioskNextHomeInterfaceBrokerImpl(
+    service_manager::Connector* connector)
+    : connector_(connector->Clone()) {}
+
+KioskNextHomeInterfaceBrokerImpl::~KioskNextHomeInterfaceBrokerImpl() = default;
+
+void KioskNextHomeInterfaceBrokerImpl::GetIdentityAccessor(
+    ::identity::mojom::IdentityAccessorRequest request) {
+  connector_->BindInterface(::identity::mojom::kServiceName,
+                            std::move(request));
+}
+
+void KioskNextHomeInterfaceBrokerImpl::BindRequest(
+    mojom::KioskNextHomeInterfaceBrokerRequest request) {
+  bindings_.AddBinding(this, std::move(request));
+}
+
+}  // namespace kiosk_next_home
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.h b/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.h
new file mode 100644
index 0000000..c241c4b
--- /dev/null
+++ b/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.h
@@ -0,0 +1,52 @@
+// Copyright 2019 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 CHROME_BROWSER_CHROMEOS_KIOSK_NEXT_HOME_KIOSK_NEXT_HOME_INTERFACE_BROKER_IMPL_H_
+#define CHROME_BROWSER_CHROMEOS_KIOSK_NEXT_HOME_KIOSK_NEXT_HOME_INTERFACE_BROKER_IMPL_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/supports_user_data.h"
+#include "chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/identity/public/mojom/identity_accessor.mojom.h"
+
+namespace service_manager {
+class Connector;
+}
+
+namespace chromeos {
+namespace kiosk_next_home {
+
+// Implementation of interface responsible for brokering other interfaces needed
+// to support Kiosk Next Home functionality.
+class KioskNextHomeInterfaceBrokerImpl
+    : public mojom::KioskNextHomeInterfaceBroker,
+      public base::SupportsUserData::Data {
+ public:
+  explicit KioskNextHomeInterfaceBrokerImpl(
+      service_manager::Connector* connector);
+  ~KioskNextHomeInterfaceBrokerImpl() override;
+
+  // Binds client requests to this implementation.
+  void BindRequest(mojom::KioskNextHomeInterfaceBrokerRequest request);
+
+  // mojom::KioskNextHomeInterfaceBroker:
+  void GetIdentityAccessor(
+      ::identity::mojom::IdentityAccessorRequest request) override;
+
+ private:
+  mojo::BindingSet<mojom::KioskNextHomeInterfaceBroker> bindings_;
+  // Clone of BrowserContext's Connector, which allows binding to other
+  // services.
+  std::unique_ptr<service_manager::Connector> connector_;
+
+  DISALLOW_COPY_AND_ASSIGN(KioskNextHomeInterfaceBrokerImpl);
+};
+
+}  // namespace kiosk_next_home
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_KIOSK_NEXT_HOME_KIOSK_NEXT_HOME_INTERFACE_BROKER_IMPL_H_
diff --git a/chrome/browser/chromeos/kiosk_next_home/mojom/BUILD.gn b/chrome/browser/chromeos/kiosk_next_home/mojom/BUILD.gn
new file mode 100644
index 0000000..9ed56ed
--- /dev/null
+++ b/chrome/browser/chromeos/kiosk_next_home/mojom/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2019 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+  sources = [
+    "kiosk_next_home_interface_broker.mojom",
+  ]
+
+  public_deps = [
+    "//services/identity/public/mojom",
+  ]
+}
diff --git a/chrome/browser/chromeos/kiosk_next_home/mojom/OWNERS b/chrome/browser/chromeos/kiosk_next_home/mojom/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/chrome/browser/chromeos/kiosk_next_home/mojom/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom b/chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom
new file mode 100644
index 0000000..2d613b2
--- /dev/null
+++ b/chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom
@@ -0,0 +1,15 @@
+// Copyright 2019 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.
+
+module chromeos.kiosk_next_home.mojom;
+
+import "services/identity/public/mojom/identity_accessor.mojom";
+
+// Single entry point for any interface requests issued by the Kiosk Next
+// Home app and brokered by the browser for services needed to support
+// its functionality.
+interface KioskNextHomeInterfaceBroker {
+  // Binds IdentityAccessor service request.
+  GetIdentityAccessor(identity.mojom.IdentityAccessor& request);
+};
diff --git a/chrome/browser/chromeos/lock_screen_apps/state_controller.h b/chrome/browser/chromeos/lock_screen_apps/state_controller.h
index 2ac0a29..192edc3 100644
--- a/chrome/browser/chromeos/lock_screen_apps/state_controller.h
+++ b/chrome/browser/chromeos/lock_screen_apps/state_controller.h
@@ -16,7 +16,7 @@
 #include "base/scoped_observer.h"
 #include "chrome/browser/chromeos/lock_screen_apps/app_manager.h"
 #include "chrome/browser/chromeos/lock_screen_apps/state_observer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/session_manager/core/session_manager_observer.h"
 #include "extensions/browser/app_window/app_window_registry.h"
 #include "extensions/common/api/app_runtime.h"
diff --git a/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc b/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc
index 36f7d31..2aa1499 100644
--- a/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc
+++ b/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc
@@ -37,7 +37,7 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/arc_session.h"
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
index 39feb815..0b672d6 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
@@ -38,7 +38,7 @@
 #include "chromeos/components/proximity_auth/screenlock_bridge.h"
 #include "chromeos/components/proximity_auth/switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/auth/user_context.h"
 #include "components/account_id/account_id.h"
 #include "components/pref_registry/pref_registry_syncable.h"
diff --git a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc
index a11a76c..cef486ab 100644
--- a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc
+++ b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc
@@ -27,8 +27,8 @@
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_debug_daemon_client.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
 #include "chromeos/dbus/fake_update_engine_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 5c53b35..7c10fb71 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -73,7 +73,7 @@
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/cryptohome/cryptohome_util.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/login/auth/authpolicy_login_helper.h"
 #include "chromeos/login/auth/key.h"
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index da66286..bb2472ed 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -317,20 +317,23 @@
   SaveSyncPasswordHash(user_context);
 }
 
-void ScreenLocker::SetAuthEnabledForUser(
+void ScreenLocker::EnableAuthForUser(const AccountId& account_id) {
+  const user_manager::User* user = FindUnlockUser(account_id);
+  CHECK(user) << "Invalid user - cannot enable authentication.";
+
+  users_with_disabled_auth_.erase(account_id);
+  LoginScreenClient::Get()->login_screen()->EnableAuthForUser(account_id);
+}
+
+void ScreenLocker::DisableAuthForUser(
     const AccountId& account_id,
-    bool is_enabled,
-    base::Optional<base::Time> auth_reenabled_time) {
+    ash::mojom::AuthDisabledDataPtr auth_disabled_data) {
   const user_manager::User* user = FindUnlockUser(account_id);
   CHECK(user) << "Invalid user - cannot disable authentication.";
 
-  if (is_enabled) {
-    users_with_disabled_auth_.erase(account_id);
-  } else {
-    users_with_disabled_auth_.insert(account_id);
-  }
-  LoginScreenClient::Get()->login_screen()->SetAuthEnabledForUser(
-      account_id, is_enabled, auth_reenabled_time);
+  users_with_disabled_auth_.insert(account_id);
+  LoginScreenClient::Get()->login_screen()->DisableAuthForUser(
+      account_id, std::move(auth_disabled_data));
 }
 
 void ScreenLocker::Authenticate(const UserContext& user_context,
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.h b/chrome/browser/chromeos/login/lock/screen_locker.h
index ae8df8f..38a5874 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/screen_locker.h
@@ -9,6 +9,7 @@
 #include <set>
 #include <string>
 
+#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/public/interfaces/login_user_info.mojom.h"
 #include "base/callback_forward.h"
 #include "base/macros.h"
@@ -89,12 +90,14 @@
   // unlock the device.
   void OnPasswordAuthSuccess(const UserContext& user_context);
 
-  // Enables or disables authentication for the user with |account_id|. Notifies
-  // lock screen UI. |auth_reenabled_time| is used to display informaton in the
-  // UI.
-  void SetAuthEnabledForUser(const AccountId& account_id,
-                             bool is_enabled,
-                             base::Optional<base::Time> auth_reenabled_time);
+  // Disables authentication for the user with |account_id|. Notifies lock
+  // screen UI.
+  void EnableAuthForUser(const AccountId& account_id);
+
+  // Enables authentication for the user with |account_id|. Notifies lock screen
+  // UI. |auth_disabled_data| is used to display information in the UI.
+  void DisableAuthForUser(const AccountId& account_id,
+                          ash::mojom::AuthDisabledDataPtr auth_disabled_data);
 
   // Authenticates the user with given |user_context|.
   void Authenticate(const UserContext& user_context,
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
index f1986bc..1862985 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/wm/window_state.h"
 #include "base/bind.h"
 #include "base/macros.h"
@@ -251,9 +252,12 @@
   EXPECT_TRUE(tester.IsLocked());
 
   // Disable authentication for user.
-  ScreenLocker::default_screen_locker()->SetAuthEnabledForUser(
-      user_manager::StubAccountId(), false /*is_enabled*/,
-      base::Time::Now() + base::TimeDelta::FromHours(1));
+  ScreenLocker::default_screen_locker()->DisableAuthForUser(
+      user_manager::StubAccountId(),
+      ash::mojom::AuthDisabledData::New(
+          ash::mojom::AuthDisabledReason::TIME_WINDOW_LIMIT,
+          base::Time::Now() + base::TimeDelta::FromHours(1),
+          base::TimeDelta::FromHours(1)));
 
   // Try to authenticate with password.
   tester.UnlockWithPassword(user_manager::StubAccountId(), kPassword);
@@ -261,8 +265,8 @@
   EXPECT_TRUE(tester.IsLocked());
 
   // Re-enable authentication for user.
-  ScreenLocker::default_screen_locker()->SetAuthEnabledForUser(
-      user_manager::StubAccountId(), true /*is_enabled*/, base::nullopt);
+  ScreenLocker::default_screen_locker()->EnableAuthForUser(
+      user_manager::StubAccountId());
 
   // Try to authenticate with password.
   tester.UnlockWithPassword(user_manager::StubAccountId(), kPassword);
@@ -287,17 +291,20 @@
   EXPECT_TRUE(tester.IsLocked());
 
   // Disable authentication for user.
-  ScreenLocker::default_screen_locker()->SetAuthEnabledForUser(
-      user_manager::StubAccountId(), false /*is_enabled*/,
-      base::Time::Now() + base::TimeDelta::FromHours(1));
+  ScreenLocker::default_screen_locker()->DisableAuthForUser(
+      user_manager::StubAccountId(),
+      ash::mojom::AuthDisabledData::New(
+          ash::mojom::AuthDisabledReason::TIME_USAGE_LIMIT,
+          base::Time::Now() + base::TimeDelta::FromHours(1),
+          base::TimeDelta::FromHours(3)));
 
   // Try to authenticate with fingerprint.
   AuthenticateWithFingerprint();
   EXPECT_TRUE(tester.IsLocked());
 
   // Re-enable authentication for user.
-  ScreenLocker::default_screen_locker()->SetAuthEnabledForUser(
-      user_manager::StubAccountId(), true /*is_enabled*/, base::nullopt);
+  ScreenLocker::default_screen_locker()->EnableAuthForUser(
+      user_manager::StubAccountId());
 
   // Try to authenticate with fingerprint.
   AuthenticateWithFingerprint();
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.h b/chrome/browser/chromeos/login/lock/views_screen_locker.h
index 19c04ab..2e2f1d00 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.h
@@ -14,7 +14,7 @@
 #include "chrome/browser/ui/ash/login_screen_client.h"
 #include "chromeos/dbus/media_analytics_client.h"
 #include "chromeos/dbus/media_perception/media_perception.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/login/reset_browsertest.cc b/chrome/browser/chromeos/login/reset_browsertest.cc
index 01676f4..6039bd9 100644
--- a/chrome/browser/chromeos/login/reset_browsertest.cc
+++ b/chrome/browser/chromeos/login/reset_browsertest.cc
@@ -16,9 +16,9 @@
 #include "chrome/common/pref_names.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
 #include "chromeos/dbus/fake_update_engine_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test_utils.h"
 
diff --git a/chrome/browser/chromeos/login/screens/error_screen.cc b/chrome/browser/chromeos/login/screens/error_screen.cc
index eed00ba..0156f14 100644
--- a/chrome/browser/chromeos/login/screens/error_screen.cc
+++ b/chrome/browser/chromeos/login/screens/error_screen.cc
@@ -33,7 +33,7 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/browser_resources.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_handler.h"
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.cc b/chrome/browser/chromeos/login/screens/reset_screen.cc
index 0d2410ff..2121f076 100644
--- a/chrome/browser/chromeos/login/screens/reset_screen.cc
+++ b/chrome/browser/chromeos/login/screens/reset_screen.cc
@@ -20,7 +20,7 @@
 #include "chrome/common/pref_names.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/chromeos/login/test/https_forwarder.cc b/chrome/browser/chromeos/login/test/https_forwarder.cc
index 90c75e4..b81ba188 100644
--- a/chrome/browser/chromeos/login/test/https_forwarder.cc
+++ b/chrome/browser/chromeos/login/test/https_forwarder.cc
@@ -15,7 +15,6 @@
 #include "net/cert/test_root_certs.h"
 #include "net/cert/x509_certificate.h"
 #include "net/test/cert_test_util.h"
-#include "net/test/python_utils.h"
 #include "net/test/spawned_test_server/base_test_server.h"
 #include "net/test/spawned_test_server/local_test_server.h"
 #include "net/test/test_data_directory.h"
@@ -32,7 +31,7 @@
   ForwardingServer(const std::string& ssl_host, const GURL& forward_target);
 
   // net::LocalTestServer:
-  bool SetPythonPath() const override;
+  base::Optional<std::vector<base::FilePath>> GetPythonPath() const override;
   bool GetTestServerPath(base::FilePath* testserver_path) const override;
   bool GenerateAdditionalArguments(
       base::DictionaryValue* arguments) const override;
@@ -52,16 +51,18 @@
       ssl_host_(ssl_host),
       forward_target_(forward_target) {}
 
-bool ForwardingServer::SetPythonPath() const {
-  if (!net::LocalTestServer::SetPythonPath())
-    return false;
+base::Optional<std::vector<base::FilePath>> ForwardingServer::GetPythonPath()
+    const {
+  base::Optional<std::vector<base::FilePath>> ret =
+      net::LocalTestServer::GetPythonPath();
+  if (!ret)
+    return base::nullopt;
 
   base::FilePath net_testserver_path;
   if (!LocalTestServer::GetTestServerPath(&net_testserver_path))
-    return false;
-  AppendToPythonPath(net_testserver_path.DirName());
-
-  return true;
+    return base::nullopt;
+  ret->push_back(net_testserver_path.DirName());
+  return ret;
 }
 
 bool ForwardingServer::GetTestServerPath(
diff --git a/chrome/browser/chromeos/network_change_manager_client.h b/chrome/browser/chromeos/network_change_manager_client.h
index 7fd7302..9731798 100644
--- a/chrome/browser/chromeos/network_change_manager_client.h
+++ b/chrome/browser/chromeos/network_change_manager_client.h
@@ -9,7 +9,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "net/base/network_change_notifier.h"
 #include "services/network/public/mojom/network_change_manager.mojom.h"
diff --git a/chrome/browser/chromeos/network_change_manager_client_unittest.cc b/chrome/browser/chromeos/network_change_manager_client_unittest.cc
index e0e1df6..68c6bca 100644
--- a/chrome/browser/chromeos/network_change_manager_client_unittest.cc
+++ b/chrome/browser/chromeos/network_change_manager_client_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "content/public/test/test_browser_thread_bundle.h"
diff --git a/chrome/browser/chromeos/policy/app_install_event_log_collector.h b/chrome/browser/chromeos/policy/app_install_event_log_collector.h
index b8d17f3b..0b555ff 100644
--- a/chrome/browser/chromeos/policy/app_install_event_log_collector.h
+++ b/chrome/browser/chromeos/policy/app_install_event_log_collector.h
@@ -16,7 +16,7 @@
 #include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/common/policy.mojom.h"
 #include "services/network/public/cpp/network_connection_tracker.h"
 
diff --git a/chrome/browser/chromeos/policy/app_install_event_log_collector_unittest.cc b/chrome/browser/chromeos/policy/app_install_event_log_collector_unittest.cc
index c0f749c5..ac347bf 100644
--- a/chrome/browser/chromeos/policy/app_install_event_log_collector_unittest.cc
+++ b/chrome/browser/chromeos/policy/app_install_event_log_collector_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
 #include "components/arc/common/app.mojom.h"
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
index e6d307b3..54b4f066 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/chromeos/policy/minimum_version_policy_handler.h"
 #include "chrome/browser/chromeos/policy/remote_commands/affiliated_remote_commands_invalidator.h"
 #include "chrome/browser/chromeos/policy/server_backed_state_keys_broker.h"
+#include "chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
 #include "chrome/browser/chromeos/system/timezone_util.h"
@@ -238,6 +239,10 @@
       std::make_unique<DeviceWilcoDtcConfigurationHandler>(GetPolicyService());
   device_wifi_allowed_handler_ =
       std::make_unique<DeviceWiFiAllowedHandler>(chromeos::CrosSettings::Get());
+
+  tpm_auto_update_mode_policy_handler_ =
+      std::make_unique<TPMAutoUpdateModePolicyHandler>(
+          chromeos::CrosSettings::Get());
 }
 
 void BrowserPolicyConnectorChromeOS::PreShutdown() {
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
index 665cabd..1fc68a4e 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
@@ -53,6 +53,7 @@
 class ProxyPolicyProvider;
 class ServerBackedStateKeysBroker;
 class DeviceWilcoDtcConfigurationHandler;
+class TPMAutoUpdateModePolicyHandler;
 
 // Extends ChromeBrowserPolicyConnector with the setup specific to Chrome OS.
 class BrowserPolicyConnectorChromeOS
@@ -160,6 +161,10 @@
     return device_network_configuration_updater_.get();
   }
 
+  TPMAutoUpdateModePolicyHandler* GetTPMAutoUpdateModePolicyHandler() const {
+    return tpm_auto_update_mode_policy_handler_.get();
+  }
+
   // Returns device's market segment.
   MarketSegment GetEnterpriseMarketSegment() const;
 
@@ -233,6 +238,8 @@
   std::unique_ptr<DeviceWilcoDtcConfigurationHandler>
       device_wilco_dtc_configuration_handler_;
   std::unique_ptr<DeviceWiFiAllowedHandler> device_wifi_allowed_handler_;
+  std::unique_ptr<TPMAutoUpdateModePolicyHandler>
+      tpm_auto_update_mode_policy_handler_;
 
   // This policy provider is used on Chrome OS to feed user policy into the
   // global PolicyService instance. This works by installing the cloud policy
diff --git a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
index 2b80fd5..497a8bb 100644
--- a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
+++ b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
@@ -23,7 +23,7 @@
 #include "chrome/browser/chromeos/accessibility/magnifier_type.h"
 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
 #include "chrome/common/pref_names.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/network/onc/onc_signature.h"
 #include "chromeos/network/onc/onc_utils.h"
 #include "chromeos/network/onc/onc_validator.h"
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc b/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc
index a4bb97d..7a779bf 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc
@@ -10,7 +10,7 @@
 #include "base/values.h"
 #include "chrome/browser/chromeos/policy/device_local_account.h"
 #include "chrome/browser/chromeos/policy/device_local_account_external_data_manager.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
 #include "components/policy/core/common/cloud/cloud_policy_service.h"
 #include "components/policy/core/common/cloud/component_cloud_policy_service.h"
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
index d37435d..bb910f36 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
@@ -30,7 +30,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/constants/chromeos_paths.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_service.h"
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index 7653065d..2a2518c 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -1212,6 +1212,28 @@
           nullptr);
     }
   }
+
+  if (policy.has_device_power_peak_shift()) {
+    const em::DevicePowerPeakShiftProto& container(
+        policy.device_power_peak_shift());
+    if (container.has_enabled()) {
+      policies->Set(key::kDevicePowerPeakShiftEnabled, POLICY_LEVEL_MANDATORY,
+                    POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
+                    std::make_unique<base::Value>(container.enabled()),
+                    nullptr);
+    }
+    if (container.has_battery_threshold()) {
+      policies->Set(
+          key::kDevicePowerPeakShiftBatteryThreshold, POLICY_LEVEL_MANDATORY,
+          POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
+          std::make_unique<base::Value>(container.battery_threshold()),
+          nullptr);
+    }
+    if (container.has_day_configs()) {
+      SetJsonDevicePolicy(key::kDevicePowerPeakShiftDayConfig,
+                          container.day_configs(), policies);
+    }
+  }
 }
 
 }  // namespace
diff --git a/chrome/browser/chromeos/policy/device_status_collector.h b/chrome/browser/chromeos/policy/device_status_collector.h
index 895d623..83e71c4 100644
--- a/chrome/browser/chromeos/policy/device_status_collector.h
+++ b/chrome/browser/chromeos/policy/device_status_collector.h
@@ -27,7 +27,7 @@
 #include "chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chromeos/dbus/cryptohome_client.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/runtime_probe/runtime_probe.pb.h"
 #include "chromeos/dbus/runtime_probe_client.h"
 #include "components/policy/proto/device_management_backend.pb.h"
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
index 778935e..b5c615a 100644
--- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -48,8 +48,8 @@
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
 #include "chromeos/dbus/fake_update_engine_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/shill_device_client.h"
 #include "chromeos/dbus/shill_ipconfig_client.h"
diff --git a/chrome/browser/chromeos/policy/login_profile_policy_provider.cc b/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
index ee4338b..9d20616 100644
--- a/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
+++ b/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
@@ -11,7 +11,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/values.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "components/policy/core/browser/policy_error_map.h"
 #include "components/policy/core/common/external_data_fetcher.h"
 #include "components/policy/core/common/policy_bundle.h"
diff --git a/chrome/browser/chromeos/policy/off_hours/device_off_hours_controller.h b/chrome/browser/chromeos/policy/off_hours/device_off_hours_controller.h
index 7b6def2..abc65d2 100644
--- a/chrome/browser/chromeos/policy/off_hours/device_off_hours_controller.h
+++ b/chrome/browser/chromeos/policy/off_hours/device_off_hours_controller.h
@@ -14,7 +14,7 @@
 #include "base/time/clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/system_clock/system_clock_client.h"
 #include "chromeos/policy/weekly_time/weekly_time_interval.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
diff --git a/chrome/browser/chromeos/policy/off_hours/device_off_hours_controller_unittest.cc b/chrome/browser/chromeos/policy/off_hours/device_off_hours_controller_unittest.cc
index d764a2f..030a0077 100644
--- a/chrome/browser/chromeos/policy/off_hours/device_off_hours_controller_unittest.cc
+++ b/chrome/browser/chromeos/policy/off_hours/device_off_hours_controller_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/system_clock/system_clock_client.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 
@@ -107,7 +107,7 @@
 
   void SetUp() override {
     chromeos::DeviceSettingsTestBase::SetUp();
-    chromeos::SystemClockClient::Initialize(nullptr /* bus */);
+    chromeos::SystemClockClient::InitializeFake();
 
     device_settings_service_->SetDeviceOffHoursControllerForTesting(
         std::make_unique<policy::off_hours::DeviceOffHoursController>());
diff --git a/chrome/browser/chromeos/policy/power_policy_browsertest.cc b/chrome/browser/chromeos/policy/power_policy_browsertest.cc
index 47f6c5c..cf39866b 100644
--- a/chrome/browser/chromeos/policy/power_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/power_policy_browsertest.cc
@@ -38,10 +38,10 @@
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/power_manager/policy.pb.h"
-#include "chromeos/dbus/power_policy_controller.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_reboot_job.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_reboot_job.cc
index b7c830d..03c98ce 100644
--- a/chrome/browser/chromeos/policy/remote_commands/device_command_reboot_job.cc
+++ b/chrome/browser/chromeos/policy/remote_commands/device_command_reboot_job.cc
@@ -14,7 +14,7 @@
 #include "base/system/sys_info.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc b/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc
index df176c7..caf9382 100644
--- a/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc
+++ b/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.h"
 #include "chrome/browser/chromeos/policy/remote_commands/device_command_wipe_users_job.h"
 #include "chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/policy/core/common/remote_commands/remote_command_job.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 
diff --git a/chrome/browser/chromeos/policy/status_uploader_unittest.cc b/chrome/browser/chromeos/policy/status_uploader_unittest.cc
index e821eeea..dbc805c 100644
--- a/chrome/browser/chromeos/policy/status_uploader_unittest.cc
+++ b/chrome/browser/chromeos/policy/status_uploader_unittest.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h"
 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
diff --git a/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.cc b/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.cc
new file mode 100644
index 0000000..73bf43d
--- /dev/null
+++ b/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.cc
@@ -0,0 +1,102 @@
+// Copyright 2019 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 "chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.h"
+
+#include "base/bind.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/tpm_firmware_update.h"
+#include "chromeos/settings/cros_settings_names.h"
+#include "chromeos/settings/cros_settings_provider.h"
+
+namespace {
+// Enum that corresponds to the possible values of the device policy key
+// TPMFirmwareUpdateSettings.AutoUpdateMode.
+enum class AutoUpdateMode {
+  // Never force update TPM firmware.
+  kNever = 1,
+  // Update the TPM firmware at the next reboot after user acknowledgment.
+  kUserAcknowledgment = 2,
+  // Foce update the TPM firmware at the next reboot.
+  kWithoutAcknowledgment = 3,
+  // Update the TPM firmware after enrollment.
+  kEnrollment = 4
+};
+
+// Reads the value of the the device setting key
+// TPMFirmwareUpdateSettings.AutoUpdateMode from a trusted store. If the value
+// is temporarily untrusted |callback| will be invoked later when trusted values
+// are available and AutoUpdateMode::kNever will be returned. This value is set
+// via the device policy TPMFirmwareUpdateSettings.
+AutoUpdateMode GetTPMAutoUpdateModeSetting(
+    const chromeos::CrosSettings* cros_settings,
+    const base::RepeatingCallback<void()> callback) {
+  if (!g_browser_process->platform_part()
+           ->browser_policy_connector_chromeos()
+           ->IsEnterpriseManaged()) {
+    return AutoUpdateMode::kNever;
+  }
+  chromeos::CrosSettingsProvider::TrustedStatus status =
+      cros_settings->PrepareTrustedValues(base::BindRepeating(callback));
+  if (status != chromeos::CrosSettingsProvider::TRUSTED)
+    return AutoUpdateMode::kNever;
+
+  const base::Value* tpm_settings =
+      cros_settings->GetPref(chromeos::kTPMFirmwareUpdateSettings);
+
+  if (!tpm_settings)
+    return AutoUpdateMode::kNever;
+
+  const base::Value* const auto_update_mode = tpm_settings->FindKeyOfType(
+      chromeos::tpm_firmware_update::kSettingsKeyAutoUpdateMode,
+      base::Value::Type::INTEGER);
+
+  // Policy not set.
+  if (!auto_update_mode || auto_update_mode->GetInt() == 0)
+    return AutoUpdateMode::kNever;
+
+  // Verify that the value is within range.
+  if (auto_update_mode->GetInt() < static_cast<int>(AutoUpdateMode::kNever) ||
+      auto_update_mode->GetInt() >
+          static_cast<int>(AutoUpdateMode::kEnrollment)) {
+    NOTREACHED() << "Invalid value for device policy key "
+                    "TPMFirmwareUpdateSettings.AutoUpdateMode";
+    return AutoUpdateMode::kNever;
+  }
+
+  return static_cast<AutoUpdateMode>(auto_update_mode->GetInt());
+}
+
+}  // namespace
+
+namespace policy {
+
+TPMAutoUpdateModePolicyHandler::TPMAutoUpdateModePolicyHandler(
+    chromeos::CrosSettings* cros_settings)
+    : cros_settings_(cros_settings), weak_factory_(this) {
+  policy_subscription_ = cros_settings_->AddSettingsObserver(
+      chromeos::kTPMFirmwareUpdateSettings,
+      base::BindRepeating(&TPMAutoUpdateModePolicyHandler::OnPolicyChanged,
+                          weak_factory_.GetWeakPtr()));
+  // Fire it once so we're sure we get an invocation on startup.
+  OnPolicyChanged();
+}
+
+TPMAutoUpdateModePolicyHandler::~TPMAutoUpdateModePolicyHandler() = default;
+
+void TPMAutoUpdateModePolicyHandler::OnPolicyChanged() {
+  AutoUpdateMode auto_update_mode = GetTPMAutoUpdateModeSetting(
+      cros_settings_,
+      base::BindRepeating(&TPMAutoUpdateModePolicyHandler::OnPolicyChanged,
+                          weak_factory_.GetWeakPtr()));
+
+  if (auto_update_mode == AutoUpdateMode::kNever ||
+      auto_update_mode == AutoUpdateMode::kEnrollment) {
+    return;
+  }
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.h b/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.h
new file mode 100644
index 0000000..c050b4d2
--- /dev/null
+++ b/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.h
@@ -0,0 +1,40 @@
+// Copyright 2019 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 CHROME_BROWSER_CHROMEOS_POLICY_TPM_AUTO_UPDATE_MODE_POLICY_HANDLER_H_
+#define CHROME_BROWSER_CHROMEOS_POLICY_TPM_AUTO_UPDATE_MODE_POLICY_HANDLER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+
+namespace policy {
+
+// This class observes the device setting |kTPMFirmwareUpdateSettings| and
+// starts the TPM firmware auto-update flow according to its value.
+class TPMAutoUpdateModePolicyHandler {
+ public:
+  explicit TPMAutoUpdateModePolicyHandler(
+      chromeos::CrosSettings* cros_settings);
+  ~TPMAutoUpdateModePolicyHandler();
+
+ private:
+  void OnPolicyChanged();
+
+  chromeos::CrosSettings* cros_settings_;
+
+  std::unique_ptr<chromeos::CrosSettings::ObserverSubscription>
+      policy_subscription_;
+
+  base::WeakPtrFactory<TPMAutoUpdateModePolicyHandler> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(TPMAutoUpdateModePolicyHandler);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_CHROMEOS_POLICY_TPM_AUTO_UPDATE_MODE_POLICY_HANDLER_H_
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h
index a4086db..40b128a 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h
@@ -24,7 +24,7 @@
 #include "chrome/browser/chromeos/power/auto_screen_brightness/modeller.h"
 #include "chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline.h"
 #include "chrome/browser/chromeos/power/auto_screen_brightness/utils.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 class Profile;
 
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc
index ba15a00..bb61efa 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc
@@ -24,7 +24,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/constants/chromeos_features.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/testing_pref_store.h"
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl.h b/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl.h
index bba67de..163181b 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl.h
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl.h
@@ -17,7 +17,7 @@
 #include "base/task_runner_util.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace chromeos {
 namespace power {
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl_unittest.cc
index 5df09739..d389acbf 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/metrics_reporter.h b/chrome/browser/chromeos/power/auto_screen_brightness/metrics_reporter.h
index 3da65780..1385674 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/metrics_reporter.h
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/metrics_reporter.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/scoped_observer.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/metrics/daily_event.h"
 
 class PrefRegistrySimple;
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/metrics_reporter_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/metrics_reporter_unittest.cc
index 6d59392..d666a9a 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/metrics_reporter_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/metrics_reporter_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_task_environment.h"
 #include "chrome/common/pref_names.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/metrics/daily_event.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/chromeos/power/extension_event_observer.h b/chrome/browser/chromeos/power/extension_event_observer.h
index 7d4510e..960170c8 100644
--- a/chrome/browser/chromeos/power/extension_event_observer.h
+++ b/chrome/browser/chromeos/power/extension_event_observer.h
@@ -17,7 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/chromeos/power/extension_event_observer_unittest.cc b/chrome/browser/chromeos/power/extension_event_observer_unittest.cc
index a938dfd..bf39ef7 100644
--- a/chrome/browser/chromeos/power/extension_event_observer_unittest.cc
+++ b/chrome/browser/chromeos/power/extension_event_observer_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
diff --git a/chrome/browser/chromeos/power/idle_action_warning_observer.h b/chrome/browser/chromeos/power/idle_action_warning_observer.h
index f98ea71..3ee69931 100644
--- a/chrome/browser/chromeos/power/idle_action_warning_observer.h
+++ b/chrome/browser/chromeos/power/idle_action_warning_observer.h
@@ -7,7 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager.h b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager.h
index ff0b08f..f6d8230 100644
--- a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager.h
+++ b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager.h
@@ -13,8 +13,8 @@
 #include "base/scoped_observer.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/power/ml/screen_brightness_event.pb.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/viz/public/interfaces/compositing/video_detector_observer.mojom.h"
 #include "ui/base/user_activity/user_activity_observer.h"
diff --git a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc
index cf08c923b..13bb5950 100644
--- a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc
@@ -22,10 +22,10 @@
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/test_browser_window_aura.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "components/ukm/content/source_url_recorder.h"
 #include "content/public/test/web_contents_tester.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
diff --git a/chrome/browser/chromeos/power/ml/idle_event_notifier.h b/chrome/browser/chromeos/power/ml/idle_event_notifier.h
index f61122e..cbd0adb 100644
--- a/chrome/browser/chromeos/power/ml/idle_event_notifier.h
+++ b/chrome/browser/chromeos/power/ml/idle_event_notifier.h
@@ -15,8 +15,8 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_event.pb.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/viz/public/interfaces/compositing/video_detector_observer.mojom.h"
 #include "ui/base/user_activity/user_activity_detector.h"
diff --git a/chrome/browser/chromeos/power/ml/idle_event_notifier_unittest.cc b/chrome/browser/chromeos/power/ml/idle_event_notifier_unittest.cc
index fea70ec..b733b019 100644
--- a/chrome/browser/chromeos/power/ml/idle_event_notifier_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/idle_event_notifier_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/time/clock.h"
 #include "chrome/browser/chromeos/power/ml/fake_boot_clock.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager.h b/chrome/browser/chromeos/power/ml/user_activity_manager.h
index 43a1e2e..7d72f605 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_manager.h
+++ b/chrome/browser/chromeos/power/ml/user_activity_manager.h
@@ -16,10 +16,10 @@
 #include "chrome/browser/chromeos/power/ml/user_activity_event.pb.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_ukm_logger.h"
 #include "chrome/browser/resource_coordinator/tab_metrics_event.pb.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/power_manager/policy.pb.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/session_manager/core/session_manager_observer.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
index ec1d523..b24a552 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
@@ -32,7 +32,7 @@
 #include "chrome/test/base/test_browser_window_aura.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/constants/chromeos_features.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
 #include "components/session_manager/session_manager_types.h"
diff --git a/chrome/browser/chromeos/power/power_data_collector.cc b/chrome/browser/chromeos/power/power_data_collector.cc
index fe7668b..98daa2c8 100644
--- a/chrome/browser/chromeos/power/power_data_collector.cc
+++ b/chrome/browser/chromeos/power/power_data_collector.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/chromeos/power/power_data_collector.h"
 
 #include "base/logging.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/power/power_data_collector.h b/chrome/browser/chromeos/power/power_data_collector.h
index 7d299b5..47b1bf0 100644
--- a/chrome/browser/chromeos/power/power_data_collector.h
+++ b/chrome/browser/chromeos/power/power_data_collector.h
@@ -10,7 +10,7 @@
 #include "base/macros.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/power/cpu_data_collector.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace power_manager {
 class PowerSupplyProperties;
diff --git a/chrome/browser/chromeos/power/power_data_collector_unittest.cc b/chrome/browser/chromeos/power/power_data_collector_unittest.cc
index 1af928f..affbd62 100644
--- a/chrome/browser/chromeos/power/power_data_collector_unittest.cc
+++ b/chrome/browser/chromeos/power/power_data_collector_unittest.cc
@@ -6,8 +6,8 @@
 #include <stdint.h>
 
 #include "chrome/browser/chromeos/power/power_data_collector.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/power/power_metrics_reporter.h b/chrome/browser/chromeos/power/power_metrics_reporter.h
index d55d5e96..eb0bf391 100644
--- a/chrome/browser/chromeos/power/power_metrics_reporter.h
+++ b/chrome/browser/chromeos/power/power_metrics_reporter.h
@@ -11,8 +11,8 @@
 
 #include "base/macros.h"
 #include "base/timer/timer.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "components/metrics/daily_event.h"
 
 class PrefRegistrySimple;
diff --git a/chrome/browser/chromeos/power/power_metrics_reporter_unittest.cc b/chrome/browser/chromeos/power/power_metrics_reporter_unittest.cc
index 6df185b..8ae609b4 100644
--- a/chrome/browser/chromeos/power/power_metrics_reporter_unittest.cc
+++ b/chrome/browser/chromeos/power/power_metrics_reporter_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_task_environment.h"
 #include "chrome/common/pref_names.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/metrics/daily_event.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/chromeos/power/process_data_collector.cc b/chrome/browser/chromeos/power/process_data_collector.cc
index ac63c00..0366d06 100644
--- a/chrome/browser/chromeos/power/process_data_collector.cc
+++ b/chrome/browser/chromeos/power/process_data_collector.cc
@@ -36,7 +36,7 @@
 #include "base/values.h"
 #include "chrome/browser/chromeos/system/procfs_util.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/power/process_data_collector.h b/chrome/browser/chromeos/power/process_data_collector.h
index a56b1d0..9517a6e 100644
--- a/chrome/browser/chromeos/power/process_data_collector.h
+++ b/chrome/browser/chromeos/power/process_data_collector.h
@@ -27,7 +27,7 @@
 #include "base/synchronization/lock.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/power/process_data_collector.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/power/renderer_freezer.h b/chrome/browser/chromeos/power/renderer_freezer.h
index 0d1cf16..14f8d38 100644
--- a/chrome/browser/chromeos/power/renderer_freezer.h
+++ b/chrome/browser/chromeos/power/renderer_freezer.h
@@ -14,7 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/process/kill.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/render_process_host_observer.h"
diff --git a/chrome/browser/chromeos/power/renderer_freezer_unittest.cc b/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
index 0e4c6ce9..453879d 100644
--- a/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
+++ b/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
diff --git a/chrome/browser/chromeos/settings/device_settings_test_helper.cc b/chrome/browser/chromeos/settings/device_settings_test_helper.cc
index 7e731020..883cdb1 100644
--- a/chrome/browser/chromeos/settings/device_settings_test_helper.cc
+++ b/chrome/browser/chromeos/settings/device_settings_test_helper.cc
@@ -13,7 +13,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/ownership/mock_owner_key_util.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.h b/chrome/browser/chromeos/system/automatic_reboot_manager.h
index 88f2b6f5..2a083c6 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager.h
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager.h
@@ -15,7 +15,7 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/system/automatic_reboot_manager_observer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/update_engine_client.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager_unittest.cc b/chrome/browser/chromeos/system/automatic_reboot_manager_unittest.cc
index 3d13760..5b12845 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager_unittest.cc
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager_unittest.cc
@@ -28,8 +28,8 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/constants/chromeos_paths.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
 #include "chromeos/dbus/fake_update_engine_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/user_manager/scoped_user_manager.h"
diff --git a/chrome/browser/chromeos/tether/tether_service.h b/chrome/browser/chromeos/tether/tether_service.h
index e6c9057..7a32eb62 100644
--- a/chrome/browser/chromeos/tether/tether_service.h
+++ b/chrome/browser/chromeos/tether/tether_service.h
@@ -13,7 +13,7 @@
 #include "base/timer/timer.h"
 #include "chromeos/components/tether/tether_component.h"
 #include "chromeos/components/tether/tether_host_fetcher.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
diff --git a/chrome/browser/chromeos/tether/tether_service_unittest.cc b/chrome/browser/chromeos/tether/tether_service_unittest.cc
index 1e0ce9b..fcbbfde 100644
--- a/chrome/browser/chromeos/tether/tether_service_unittest.cc
+++ b/chrome/browser/chromeos/tether/tether_service_unittest.cc
@@ -30,9 +30,9 @@
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "chromeos/dbus/shill_device_client.h"
 #include "chromeos/dbus/shill_manager_client.h"
 #include "chromeos/dbus/shill_service_client.h"
diff --git a/chrome/browser/chromeos/tpm_firmware_update.cc b/chrome/browser/chromeos/tpm_firmware_update.cc
index 3038238..37852f4f 100644
--- a/chrome/browser/chromeos/tpm_firmware_update.cc
+++ b/chrome/browser/chromeos/tpm_firmware_update.cc
@@ -57,6 +57,7 @@
 const char kSettingsKeyAllowPowerwash[] = "allow-user-initiated-powerwash";
 const char kSettingsKeyAllowPreserveDeviceState[] =
     "allow-user-initiated-preserve-device-state";
+const char kSettingsKeyAutoUpdateMode[] = "auto-update-mode";
 
 std::unique_ptr<base::DictionaryValue> DecodeSettingsProto(
     const enterprise_management::TPMFirmwareUpdateSettingsProto& settings) {
@@ -73,6 +74,11 @@
         base::Value(settings.allow_user_initiated_preserve_device_state()));
   }
 
+  if (settings.has_auto_update_mode()) {
+    result->SetKey(kSettingsKeyAutoUpdateMode,
+                   base::Value(settings.auto_update_mode()));
+  }
+
   return result;
 }
 
diff --git a/chrome/browser/chromeos/tpm_firmware_update.h b/chrome/browser/chromeos/tpm_firmware_update.h
index e6f5161..e1eb673 100644
--- a/chrome/browser/chromeos/tpm_firmware_update.h
+++ b/chrome/browser/chromeos/tpm_firmware_update.h
@@ -40,6 +40,7 @@
 // Settings dictionary key constants.
 extern const char kSettingsKeyAllowPowerwash[];
 extern const char kSettingsKeyAllowPreserveDeviceState[];
+extern const char kSettingsKeyAutoUpdateMode[];
 
 // Decodes the TPM firmware update settings into base::Value representation.
 std::unique_ptr<base::DictionaryValue> DecodeSettingsProto(
diff --git a/chrome/browser/content_settings/OWNERS b/chrome/browser/content_settings/OWNERS
index 4882b38..83eb633 100644
--- a/chrome/browser/content_settings/OWNERS
+++ b/chrome/browser/content_settings/OWNERS
@@ -1,3 +1,4 @@
+engedy@chromium.org
 msramek@chromium.org
 raymes@chromium.org
 
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 548dbe0..5cb018b74 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -967,6 +967,8 @@
     }
     deps += [
       "//ash/public/cpp",
+      "//chrome/browser/chromeos/kiosk_next_home",
+      "//chrome/browser/chromeos/kiosk_next_home/mojom",
       "//chrome/browser/resources/chromeos/camera:chrome_camera_app",
       "//chromeos/attestation",
       "//chromeos/components/proximity_auth",
diff --git a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
index d755321a..06c5812 100644
--- a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
+++ b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
@@ -40,7 +40,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/user_manager/user_manager.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #endif
diff --git a/chrome/browser/extensions/api/socket/udp_socket_unittest.cc b/chrome/browser/extensions/api/socket/udp_socket_unittest.cc
index 1cc6649..5baa299e 100644
--- a/chrome/browser/extensions/api/socket/udp_socket_unittest.cc
+++ b/chrome/browser/extensions/api/socket/udp_socket_unittest.cc
@@ -143,7 +143,7 @@
   if (result == 0) {
     scoped_refptr<net::IOBuffer> data =
         base::MakeRefCounted<net::WrappedIOBuffer>(kTestMessage);
-    src->Write(data, kTestMessageLength, base::BindRepeating(&OnSendCompleted));
+    src->Write(data, kTestMessageLength, base::BindOnce(&OnSendCompleted));
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
         FROM_HERE,
         base::BindOnce(&SendMulticastPacket, quit_run_loop, src, result),
diff --git a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
index e9a5ef1..ff898c2 100644
--- a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
+++ b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
@@ -17,6 +17,7 @@
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/file_manager/file_manager_string_util.h"
+#include "chrome/grit/component_extension_resources.h"
 #include "extensions/common/constants.h"
 #include "third_party/ink/grit/ink_resources.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -38,6 +39,11 @@
     {"web_store/webstore_icon_16.png", IDR_WEBSTORE_ICON_16},
 #endif
 
+#if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
+    {"chromeos/kiosk_next_home/kiosk_next_home.mojom.js",
+     IDR_KIOSK_NEXT_HOME_MOJOM_JS},
+#endif
+
 #if defined(OS_CHROMEOS)
     {"chrome_app/chrome_app_icon_32.png", IDR_CHROME_APP_ICON_32},
     {"chrome_app/chrome_app_icon_192.png", IDR_CHROME_APP_ICON_192},
diff --git a/chrome/browser/extensions/chrome_extensions_interface_registration.cc b/chrome/browser/extensions/chrome_extensions_interface_registration.cc
index 3cae620..401c43b 100644
--- a/chrome/browser/extensions/chrome_extensions_interface_registration.cc
+++ b/chrome/browser/extensions/chrome_extensions_interface_registration.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/extensions/chrome_extensions_interface_registration.h"
 
+#include <memory>
+#include <utility>
+
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
@@ -18,6 +21,9 @@
 #include "services/service_manager/public/cpp/binder_registry.h"
 
 #if defined(OS_CHROMEOS)
+#include "ash/public/cpp/ash_features.h"
+#include "chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.h"
+#include "chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom.h"  // nogncheck
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/services/ime/public/mojom/constants.mojom.h"
 #include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
@@ -33,6 +39,8 @@
 namespace extensions {
 namespace {
 #if defined(OS_CHROMEOS)
+const char kKioskNextHomeInterfaceBrokerImplKey[] = "cros_kiosk_next_home_impl";
+
 // Forwards service requests to Service Manager since the renderer cannot launch
 // out-of-process services on its own.
 template <typename Interface>
@@ -43,6 +51,27 @@
       ->GetConnector()
       ->BindInterface(service_name, std::move(request));
 }
+
+void BindKioskNextHomeInterfaceBrokerRequest(
+    content::BrowserContext* context,
+    chromeos::kiosk_next_home::mojom::KioskNextHomeInterfaceBrokerRequest
+        request,
+    content::RenderFrameHost* source) {
+  auto* impl =
+      static_cast<chromeos::kiosk_next_home::KioskNextHomeInterfaceBrokerImpl*>(
+          context->GetUserData(kKioskNextHomeInterfaceBrokerImplKey));
+  if (!impl) {
+    auto* connector = content::BrowserContext::GetConnectorFor(context);
+    if (!connector)
+      return;
+    auto new_impl = std::make_unique<
+        chromeos::kiosk_next_home::KioskNextHomeInterfaceBrokerImpl>(connector);
+    impl = new_impl.get();
+    context->SetUserData(kKioskNextHomeInterfaceBrokerImplKey,
+                         std::move(new_impl));
+  }
+  impl->BindRequest(std::move(request));
+}
 #endif
 }  // namespace
 
@@ -72,6 +101,12 @@
         chromeos::ime::mojom::kServiceName));
   }
 
+  if (base::FeatureList::IsEnabled(ash::features::kKioskNextShell) &&
+      extension->id() == extension_misc::kKioskNextHomeAppId) {
+    registry->AddInterface(
+        base::BindRepeating(&BindKioskNextHomeInterfaceBrokerRequest, context));
+  }
+
   if (extension->permissions_data()->HasAPIPermission(
           APIPermission::kMediaPerceptionPrivate)) {
     extensions::ExtensionsAPIClient* client =
diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc
index 4f0c6166..07534da 100644
--- a/chrome/browser/extensions/extension_context_menu_browsertest.cc
+++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc
@@ -4,7 +4,10 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "base/bind.h"
+#include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -15,7 +18,9 @@
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/channel_info.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/version_info/channel.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/common/context_menu_params.h"
 #include "content/public/test/browser_test_utils.h"
@@ -24,6 +29,7 @@
 #include "extensions/browser/process_manager.h"
 #include "extensions/browser/test_management_policy.h"
 #include "extensions/common/extension_set.h"
+#include "extensions/common/features/feature_channel.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "net/dns/mock_host_resolver.h"
 #include "ui/base/models/menu_model.h"
@@ -33,32 +39,62 @@
 using extensions::MenuItem;
 using ui::MenuModel;
 
+namespace {
+
+enum class ContextType {
+  kBackgroundPage,
+  kServiceWorker,
+};
+
+}  // namespace
+
 class ExtensionContextMenuBrowserTest
-    : public extensions::ExtensionBrowserTest {
+    : public extensions::ExtensionBrowserTest,
+      public testing::WithParamInterface<ContextType> {
  public:
+  void SetUp() override {
+    extensions::ExtensionBrowserTest::SetUp();
+    // Service Workers are currently only available on the trunk, so set
+    // the channel for those tests.
+    if (GetParam() == ContextType::kServiceWorker) {
+      current_channel_ = std::make_unique<extensions::ScopedCurrentChannel>(
+          version_info::Channel::UNKNOWN);
+    }
+  }
+
+  std::string GetExtensionDirectory(base::StringPiece root) {
+    if (GetParam() == ContextType::kBackgroundPage)
+      return std::string(root);
+    DCHECK_EQ(ContextType::kServiceWorker, GetParam());
+    return base::StrCat({root, "/service_worker"});
+  }
+
   // Helper to load an extension from context_menus/|subdirectory| in the
   // extensions test data dir.
   const extensions::Extension* LoadContextMenuExtension(
-      std::string subdirectory) {
+      base::StringPiece subdirectory) {
     base::FilePath extension_dir =
-        test_data_dir_.AppendASCII("context_menus").AppendASCII(subdirectory);
+        test_data_dir_.AppendASCII("context_menus")
+            .AppendASCII(GetExtensionDirectory(subdirectory));
     return LoadExtension(extension_dir);
   }
 
   // Helper to load an extension from context_menus/top_level/|subdirectory| in
   // the extensions test data dir.
   const extensions::Extension* LoadTopLevelContextMenuExtension(
-      std::string subdirectory) {
+      base::StringPiece subdirectory) {
     base::FilePath extension_dir =
         test_data_dir_.AppendASCII("context_menus").AppendASCII("top_level");
-    extension_dir = extension_dir.AppendASCII(subdirectory);
+    extension_dir =
+        extension_dir.AppendASCII(GetExtensionDirectory(subdirectory));
     return LoadExtension(extension_dir);
   }
 
   const extensions::Extension* LoadContextMenuExtensionIncognito(
-      std::string subdirectory) {
+      base::StringPiece subdirectory) {
     base::FilePath extension_dir =
-        test_data_dir_.AppendASCII("context_menus").AppendASCII(subdirectory);
+        test_data_dir_.AppendASCII("context_menus")
+            .AppendASCII(GetExtensionDirectory(subdirectory));
     return LoadExtensionIncognito(extension_dir);
   }
 
@@ -244,10 +280,12 @@
     ASSERT_TRUE(FindCommandId(menu, id, &command_id));
     EXPECT_EQ(should_be_checked, menu->IsCommandIdChecked(command_id));
   }
+
+  std::unique_ptr<extensions::ScopedCurrentChannel> current_channel_;
 };
 
 // Tests adding a simple context menu item.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Simple) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, Simple) {
   ExtensionTestMessageListener listener1("created item", false);
   ExtensionTestMessageListener listener2("onclick fired", false);
   ASSERT_TRUE(LoadContextMenuExtension("simple"));
@@ -273,7 +311,7 @@
 
 // Tests that previous onclick is not fired after updating the menu's onclick,
 // and whether setting onclick to null removes the handler.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, UpdateOnclick) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, UpdateOnclick) {
   ExtensionTestMessageListener listener_error1("onclick1-unexpected", false);
   ExtensionTestMessageListener listener_error2("onclick2-unexpected", false);
   ExtensionTestMessageListener listener_update1("update1", true);
@@ -323,7 +361,7 @@
 // Tests that updating the first radio item in a radio list from checked to
 // unchecked should not work. The radio button should remain checked because
 // context menu radio lists should always have one item selected.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest,
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest,
                        UpdateCheckedStateOfFirstRadioItem) {
   ExtensionTestMessageListener listener_created_radio1("created radio1 item",
                                                        false);
@@ -374,7 +412,7 @@
 // Tests that updating a checked radio button (that is not the first item) to be
 // unchecked should not work. The radio button should remain checked because
 // context menu radio lists should always have one item selected.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest,
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest,
                        UpdateCheckedStateOfNonfirstRadioItem) {
   ExtensionTestMessageListener listener_created_radio1("created radio1 item",
                                                        false);
@@ -432,7 +470,7 @@
 
 // Tests that setting "documentUrlPatterns" for an item properly restricts
 // those items to matching pages.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Patterns) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, Patterns) {
   ExtensionTestMessageListener listener("created items", false);
 
   ASSERT_TRUE(LoadContextMenuExtension("patterns"));
@@ -442,30 +480,22 @@
 
   // Check that a document url that should match the items' patterns appears.
   GURL google_url("http://www.google.com");
-  ASSERT_TRUE(MenuHasItemWithLabel(google_url,
-                                   GURL(),
-                                   GURL(),
+  ASSERT_TRUE(MenuHasItemWithLabel(google_url, GURL(), GURL(),
                                    std::string("test_item1")));
-  ASSERT_TRUE(MenuHasItemWithLabel(google_url,
-                                   GURL(),
-                                   GURL(),
+  ASSERT_TRUE(MenuHasItemWithLabel(google_url, GURL(), GURL(),
                                    std::string("test_item2")));
 
   // Now check with a non-matching url.
   GURL test_url("http://www.test.com");
-  ASSERT_FALSE(MenuHasItemWithLabel(test_url,
-                                    GURL(),
-                                   GURL(),
+  ASSERT_FALSE(MenuHasItemWithLabel(test_url, GURL(), GURL(),
                                     std::string("test_item1")));
-  ASSERT_FALSE(MenuHasItemWithLabel(test_url,
-                                    GURL(),
-                                    GURL(),
+  ASSERT_FALSE(MenuHasItemWithLabel(test_url, GURL(), GURL(),
                                     std::string("test_item2")));
 }
 
 // Tests registering an item with a very long title that should get truncated in
 // the actual menu displayed.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, LongTitle) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, LongTitle) {
   ExtensionTestMessageListener listener("created", false);
 
   // Load the extension and wait until it's created a menu item.
@@ -499,7 +529,7 @@
 // Checks that Context Menus are ordered alphabetically by their name when
 // extensions have only one single Context Menu item and by the extension name
 // when multiples Context Menu items are created.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, MAYBE_TopLevel) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, MAYBE_TopLevel) {
   // We expect to see the following items in the menu:
   //   An Extension with multiple Context Menus
   //     Context Menu #1
@@ -541,19 +571,18 @@
   MenuModel* model = nullptr;
 
   ASSERT_TRUE(menu->GetMenuModelAndItemIndex(
-      ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0),
-      &model,
+      ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0), &model,
       &index));
   EXPECT_EQ(base::UTF8ToUTF16("An Extension with multiple Context Menus"),
-                              model->GetLabelAt(index++));
+            model->GetLabelAt(index++));
   EXPECT_EQ(base::UTF8ToUTF16("Context Menu #1 - Extension #2"),
-                              model->GetLabelAt(index++));
+            model->GetLabelAt(index++));
   EXPECT_EQ(base::UTF8ToUTF16("Context Menu #2 - Extension #3"),
-                              model->GetLabelAt(index++));
+            model->GetLabelAt(index++));
   EXPECT_EQ(base::UTF8ToUTF16("Context Menu #3 - Extension #1"),
-                              model->GetLabelAt(index++));
+            model->GetLabelAt(index++));
   EXPECT_EQ(base::UTF8ToUTF16("Ze Extension with multiple Context Menus"),
-                              model->GetLabelAt(index++));
+            model->GetLabelAt(index++));
 }
 
 // Checks that in |menu|, the item at |index| has type |expected_type| and a
@@ -617,7 +646,10 @@
 #endif
 
 // Tests a number of cases for auto-generated and explicitly added separators.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Separators) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, Separators) {
+  // TODO(crbug.com/939664): Not yet implemented.
+  if (GetParam() == ContextType::kServiceWorker)
+    return;
   // Load the extension.
   ASSERT_TRUE(LoadContextMenuExtension("separators"));
   const extensions::Extension* extension = GetExtensionNamed("Separators Test");
@@ -672,7 +704,7 @@
 
 // Tests that targetUrlPattern keeps items from appearing when there is no
 // target url.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, TargetURLs) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, TargetURLs) {
   ExtensionTestMessageListener listener("created items", false);
   ASSERT_TRUE(LoadContextMenuExtension("target_urls"));
   ASSERT_TRUE(listener.WaitUntilSatisfied());
@@ -681,19 +713,15 @@
   GURL non_google_url("http://www.foo.com");
 
   // No target url - the item should not appear.
-  ASSERT_FALSE(MenuHasItemWithLabel(
-      google_url, GURL(), GURL(), std::string("item1")));
+  ASSERT_FALSE(
+      MenuHasItemWithLabel(google_url, GURL(), GURL(), std::string("item1")));
 
   // A matching target url - the item should appear.
-  ASSERT_TRUE(MenuHasItemWithLabel(google_url,
-                                   google_url,
-                                   GURL(),
+  ASSERT_TRUE(MenuHasItemWithLabel(google_url, google_url, GURL(),
                                    std::string("item1")));
 
   // A non-matching target url - the item should not appear.
-  ASSERT_FALSE(MenuHasItemWithLabel(google_url,
-                                    non_google_url,
-                                    GURL(),
+  ASSERT_FALSE(MenuHasItemWithLabel(google_url, non_google_url, GURL(),
                                     std::string("item1")));
 }
 
@@ -704,7 +732,11 @@
 #else
 #define MAYBE_IncognitoSplit IncognitoSplit
 #endif
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, MAYBE_IncognitoSplit) {
+
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, MAYBE_IncognitoSplit) {
+  // TODO(crbug.com/939664): Not yet implemented.
+  if (GetParam() == ContextType::kServiceWorker)
+    return;
   ExtensionTestMessageListener created("created item regular", false);
   ExtensionTestMessageListener created_incognito("created item incognito",
                                                  false);
@@ -753,7 +785,7 @@
 
 // Tests that items with a context of frames only appear when the menu is
 // invoked in a frame.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Frames) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, Frames) {
   ExtensionTestMessageListener listener("created items", false);
   ASSERT_TRUE(LoadContextMenuExtension("frames"));
   ASSERT_TRUE(listener.WaitUntilSatisfied());
@@ -762,19 +794,19 @@
   GURL no_frame_url;
   GURL frame_url("http://www.google.com");
 
-  ASSERT_TRUE(MenuHasItemWithLabel(
-      page_url, GURL(), no_frame_url, std::string("Page item")));
-  ASSERT_FALSE(MenuHasItemWithLabel(
-      page_url, GURL(), no_frame_url, std::string("Frame item")));
+  ASSERT_TRUE(MenuHasItemWithLabel(page_url, GURL(), no_frame_url,
+                                   std::string("Page item")));
+  ASSERT_FALSE(MenuHasItemWithLabel(page_url, GURL(), no_frame_url,
+                                    std::string("Frame item")));
 
-  ASSERT_TRUE(MenuHasItemWithLabel(
-      page_url, GURL(), frame_url, std::string("Page item")));
-  ASSERT_TRUE(MenuHasItemWithLabel(
-      page_url, GURL(), frame_url, std::string("Frame item")));
+  ASSERT_TRUE(MenuHasItemWithLabel(page_url, GURL(), frame_url,
+                                   std::string("Page item")));
+  ASSERT_TRUE(MenuHasItemWithLabel(page_url, GURL(), frame_url,
+                                   std::string("Frame item")));
 }
 
 // Tests that info.frameId is correctly set when the context menu is invoked.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, ClickInFrame) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, ClickInFrame) {
   ExtensionTestMessageListener listener("created items", false);
   ASSERT_TRUE(LoadContextMenuExtension("frames"));
   GURL url_with_frame("data:text/html,<iframe name='child'>");
@@ -788,7 +820,8 @@
 
   // Click on a menu item in the child frame.
   content::RenderFrameHost* child_frame = content::FrameMatchingPredicate(
-      GetWebContents(), base::Bind(&content::FrameMatchesName, "child"));
+      GetWebContents(),
+      base::BindRepeating(&content::FrameMatchesName, "child"));
   ASSERT_TRUE(child_frame);
   int extension_api_frame_id =
       extensions::ExtensionApiFrameIdMap::GetFrameId(child_frame);
@@ -799,7 +832,7 @@
 }
 
 // Tests enabling and disabling a context menu item.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Enabled) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, Enabled) {
   TestEnabledContextMenu(true);
   TestEnabledContextMenu(false);
 }
@@ -814,7 +847,7 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserLazyTest, EventPage) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserLazyTest, EventPage) {
   GURL about_blank("about:blank");
   LazyBackgroundObserver page_complete;
   const extensions::Extension* extension = LoadContextMenuExtension(
@@ -849,8 +882,11 @@
   ASSERT_TRUE(listener.WaitUntilSatisfied());
 }
 
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest,
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest,
                        IncognitoSplitContextMenuCount) {
+  // TODO(crbug.com/939664): Not yet implemented.
+  if (GetParam() == ContextType::kServiceWorker)
+    return;
   ExtensionTestMessageListener created("created item regular", false);
   ExtensionTestMessageListener created_incognito("created item incognito",
                                                  false);
@@ -869,10 +905,9 @@
 }
 
 // Tests updating checkboxes' checked state to true and false.
-IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, UpdateCheckboxes) {
+IN_PROC_BROWSER_TEST_P(ExtensionContextMenuBrowserTest, UpdateCheckboxes) {
   ExtensionTestMessageListener listener_context_menu_created("Menu created",
                                                              false);
-
   const extensions::Extension* extension =
       LoadContextMenuExtension("checkboxes");
   ASSERT_TRUE(extension);
@@ -905,3 +940,14 @@
   VerifyRadioItemSelectionState(menu.get(), extension->id(), "checkbox2",
                                 false);
 }
+
+INSTANTIATE_TEST_SUITE_P(BackgroundPage,
+                         ExtensionContextMenuBrowserTest,
+                         ::testing::Values(ContextType::kBackgroundPage));
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+                         ExtensionContextMenuBrowserTest,
+                         ::testing::Values(ContextType::kServiceWorker));
+// TODO(crbug.com/939664): Enable this test for service workers?
+INSTANTIATE_TEST_SUITE_P(BackgroundPage,
+                         ExtensionContextMenuBrowserLazyTest,
+                         ::testing::Values(ContextType::kBackgroundPage));
diff --git a/chrome/browser/extensions/external_pref_loader_unittest.cc b/chrome/browser/extensions/external_pref_loader_unittest.cc
index af1dc05..c3ba3c03 100644
--- a/chrome/browser/extensions/external_pref_loader_unittest.cc
+++ b/chrome/browser/extensions/external_pref_loader_unittest.cc
@@ -11,40 +11,23 @@
 #include "chrome/browser/extensions/external_provider_impl.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
-#include "chrome/browser/sync/profile_sync_test_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/sync/driver/test_sync_service.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/common/extension.h"
-#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace extensions {
 
 namespace {
 
-class TestSyncService : public browser_sync::ProfileSyncServiceMock {
+class TestSyncService : public syncer::TestSyncService {
  public:
-  enum class SyncedTypes { ALL, NONE };
-
-  explicit TestSyncService(Profile* profile)
-      : browser_sync::ProfileSyncServiceMock(
-            CreateProfileSyncServiceParamsForTest(profile)),
-        synced_types_(SyncedTypes::NONE) {}
+  TestSyncService() {}
   ~TestSyncService() override {}
 
-  // FakeSyncService:
-  int GetDisableReasons() const override { return disable_reasons_; }
-  syncer::ModelTypeSet GetActiveDataTypes() const override {
-    switch (synced_types_) {
-      case SyncedTypes::ALL:
-        return syncer::ModelTypeSet::All();
-      case SyncedTypes::NONE:
-        return syncer::ModelTypeSet();
-    }
-    NOTREACHED();
-    return syncer::ModelTypeSet();
-  }
+  // syncer::SyncService:
   void AddObserver(syncer::SyncServiceObserver* observer) override {
     ASSERT_FALSE(observer_);
     observer_ = observer;
@@ -53,26 +36,20 @@
     EXPECT_EQ(observer_, observer);
   }
 
-  void SetDisableReasons(int disable_reasons) {
-    disable_reasons_ = disable_reasons;
-  }
-
-  void FireOnStateChanged(browser_sync::ProfileSyncService* service) {
+  void FireOnStateChanged() {
     ASSERT_TRUE(observer_);
-    observer_->OnStateChanged(service);
+    observer_->OnStateChanged(this);
   }
 
  private:
   syncer::SyncServiceObserver* observer_ = nullptr;
-  int disable_reasons_ = DISABLE_REASON_NONE;
 
-  SyncedTypes synced_types_;
   DISALLOW_COPY_AND_ASSIGN(TestSyncService);
 };
 
 std::unique_ptr<KeyedService> TestingSyncFactoryFunction(
     content::BrowserContext* context) {
-  return std::make_unique<TestSyncService>(static_cast<Profile*>(context));
+  return std::make_unique<TestSyncService>();
 }
 
 }  // namespace
@@ -128,8 +105,7 @@
   TestSyncService* test_service = static_cast<TestSyncService*>(
       ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
           profile(), base::BindRepeating(&TestingSyncFactoryFunction)));
-  ON_CALL(*test_service->GetUserSettingsMock(), IsFirstSetupComplete())
-      .WillByDefault(testing::Return(true));
+  test_service->SetFirstSetupComplete(true);
 
   base::RunLoop run_loop;
   scoped_refptr<ExternalPrefLoader> loader(
@@ -144,7 +120,7 @@
   test_service->SetDisableReasons(
       syncer::SyncService::DISABLE_REASON_USER_CHOICE);
   ASSERT_FALSE(test_service->CanSyncFeatureStart());
-  test_service->FireOnStateChanged(test_service);
+  test_service->FireOnStateChanged();
   run_loop.Run();
 }
 
diff --git a/chrome/browser/extensions/theme_installed_infobar_delegate.cc b/chrome/browser/extensions/theme_installed_infobar_delegate.cc
index c6206623..5f6a70f 100644
--- a/chrome/browser/extensions/theme_installed_infobar_delegate.cc
+++ b/chrome/browser/extensions/theme_installed_infobar_delegate.cc
@@ -12,7 +12,6 @@
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/theme_service.h"
@@ -27,19 +26,17 @@
 // static
 void ThemeInstalledInfoBarDelegate::Create(
     InfoBarService* infobar_service,
-    extensions::ExtensionService* extension_service,
     ThemeService* theme_service,
     const std::string& theme_name,
     const std::string& theme_id,
-    const std::string& previous_theme_id,
-    bool previous_using_system_theme) {
+    base::OnceClosure revert_theme_callback) {
   // Create the new infobar.
   std::unique_ptr<infobars::InfoBar> new_infobar(
       infobar_service->CreateConfirmInfoBar(
           std::unique_ptr<ConfirmInfoBarDelegate>(
               new ThemeInstalledInfoBarDelegate(
-                  extension_service, theme_service, theme_name, theme_id,
-                  previous_theme_id, previous_using_system_theme))));
+                  theme_service, theme_name, theme_id,
+                  std::move(revert_theme_callback)))));
 
   // If there's a previous theme infobar, just replace that instead of adding a
   // new one.
@@ -51,6 +48,8 @@
       // If the user installed the same theme twice, ignore the second install
       // and keep the first install info bar, so that they can easily undo to
       // get back the previous theme.
+      // |theme_id| is not defined for autogenerated themes, but since those
+      // don't show an infobar, it's valid in this case.
       if (theme_infobar->theme_id_ != theme_id) {
         infobar_service->ReplaceInfoBar(old_infobar, std::move(new_infobar));
         theme_service->OnInfobarDisplayed();
@@ -65,19 +64,15 @@
 }
 
 ThemeInstalledInfoBarDelegate::ThemeInstalledInfoBarDelegate(
-    extensions::ExtensionService* extension_service,
     ThemeService* theme_service,
     const std::string& theme_name,
     const std::string& theme_id,
-    const std::string& previous_theme_id,
-    bool previous_using_system_theme)
+    base::OnceClosure revert_theme_callback)
     : ConfirmInfoBarDelegate(),
-      extension_service_(extension_service),
       theme_service_(theme_service),
       theme_name_(theme_name),
       theme_id_(theme_id),
-      previous_theme_id_(previous_theme_id),
-      previous_using_system_theme_(previous_using_system_theme) {
+      revert_theme_callback_(std::move(revert_theme_callback)) {
   registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
                  content::Source<ThemeService>(theme_service_));
 }
@@ -119,21 +114,8 @@
 }
 
 bool ThemeInstalledInfoBarDelegate::Cancel() {
-  if (!previous_theme_id_.empty()) {
-    const extensions::Extension* previous_theme =
-        extension_service_->GetExtensionById(previous_theme_id_, true);
-    if (previous_theme) {
-      theme_service_->RevertToTheme(previous_theme);
-      // TODO(estade): while we're waiting to close, it would be nice to
-      // indicate that the theme is busy reverting.
-      return false;  // The theme change will close us.
-    }
-  }
-
-  if (previous_using_system_theme_)
-    theme_service_->UseSystemTheme();
-  else
-    theme_service_->UseDefaultTheme();
+  if (!revert_theme_callback_.is_null())
+    std::move(revert_theme_callback_).Run();
   return false;  // The theme change will close us.
 }
 
diff --git a/chrome/browser/extensions/theme_installed_infobar_delegate.h b/chrome/browser/extensions/theme_installed_infobar_delegate.h
index 3e1a134..b2d211c9 100644
--- a/chrome/browser/extensions/theme_installed_infobar_delegate.h
+++ b/chrome/browser/extensions/theme_installed_infobar_delegate.h
@@ -7,19 +7,17 @@
 
 #include <string>
 
+#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "extensions/common/extension_id.h"
+#include "third_party/skia/include/core/SkColor.h"
 
 class InfoBarService;
 class ThemeService;
 
-namespace extensions {
-class ExtensionService;
-}
-
 // When a user installs a theme, we display it immediately, but provide an
 // infobar allowing them to cancel.
 class ThemeInstalledInfoBarDelegate : public ConfirmInfoBarDelegate,
@@ -28,20 +26,16 @@
   // Creates a theme installed infobar and delegate and adds the infobar to
   // |infobar_service|, replacing any previous theme infobar.
   static void Create(InfoBarService* infobar_service,
-                     extensions::ExtensionService* extension_service,
                      ThemeService* theme_service,
                      const std::string& theme_name,
                      const std::string& theme_id,
-                     const std::string& previous_theme_id,
-                     bool previous_using_system_theme);
+                     base::OnceClosure revert_theme_callback);
 
  private:
-  ThemeInstalledInfoBarDelegate(extensions::ExtensionService* extension_service,
-                                ThemeService* theme_service,
+  ThemeInstalledInfoBarDelegate(ThemeService* theme_service,
                                 const std::string& theme_name,
                                 const std::string& theme_id,
-                                const std::string& previous_theme_id,
-                                bool previous_using_system_theme);
+                                base::OnceClosure revert_theme_callback);
   ~ThemeInstalledInfoBarDelegate() override;
 
   // ConfirmInfoBarDelegate:
@@ -58,7 +52,6 @@
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
-  extensions::ExtensionService* extension_service_;
   ThemeService* theme_service_;
 
   // Name of theme that's just been installed.
@@ -68,8 +61,7 @@
   std::string theme_id_;
 
   // Used to undo theme install.
-  std::string previous_theme_id_;
-  bool previous_using_system_theme_;
+  base::OnceClosure revert_theme_callback_;
 
   // Registers and unregisters us for notifications.
   content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/feature_engagement/session_duration_updater.cc b/chrome/browser/feature_engagement/session_duration_updater.cc
index ccead333..d023ad3 100644
--- a/chrome/browser/feature_engagement/session_duration_updater.cc
+++ b/chrome/browser/feature_engagement/session_duration_updater.cc
@@ -4,13 +4,10 @@
 
 #include "chrome/browser/feature_engagement/session_duration_updater.h"
 
-#include "base/observer_list.h"
-#include "base/time/time.h"
 #include "base/timer/elapsed_timer.h"
 #include "base/values.h"
 #include "chrome/common/pref_names.h"
 #include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 
 namespace feature_engagement {
@@ -32,14 +29,15 @@
   registry->RegisterDictionaryPref(prefs::kObservedSessionTime);
 }
 
-base::TimeDelta SessionDurationUpdater::GetCumulativeElapsedSessionTime() {
+base::TimeDelta SessionDurationUpdater::GetCumulativeElapsedSessionTime()
+    const {
   base::TimeDelta elapsed_time = GetRecordedObservedSessionTime();
   return current_session_timer_
              ? elapsed_time + current_session_timer_.get()->Elapsed()
              : elapsed_time;
 }
 
-base::TimeDelta SessionDurationUpdater::GetRecordedObservedSessionTime() {
+base::TimeDelta SessionDurationUpdater::GetRecordedObservedSessionTime() const {
   const base::DictionaryValue* dict =
       pref_service_->GetDictionary(prefs::kObservedSessionTime);
   const base::Value* dict_value =
@@ -85,15 +83,14 @@
     return;
   }
 
-  base::TimeDelta elapsed_session_time;
-
   const base::DictionaryValue* dict =
       pref_service_->GetDictionary(prefs::kObservedSessionTime);
   const base::Value* dict_value =
       dict->FindKey(observed_session_time_dict_key_);
   const double stored_value = dict_value ? dict_value->GetDouble() : 0L;
 
-  elapsed_session_time += base::TimeDelta::FromSeconds(stored_value) + elapsed;
+  base::TimeDelta elapsed_session_time =
+      base::TimeDelta::FromSeconds(stored_value) + elapsed;
 
   DictionaryPrefUpdate update(pref_service_, prefs::kObservedSessionTime);
   update->SetKey(
diff --git a/chrome/browser/feature_engagement/session_duration_updater.h b/chrome/browser/feature_engagement/session_duration_updater.h
index 880e2f0..4aaf4c5 100644
--- a/chrome/browser/feature_engagement/session_duration_updater.h
+++ b/chrome/browser/feature_engagement/session_duration_updater.h
@@ -7,12 +7,17 @@
 
 #include <memory>
 
+#include "base/observer_list.h"
 #include "base/scoped_observer.h"
-#include "base/timer/elapsed_timer.h"
+#include "base/time/time.h"
 #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_service.h"
 
+namespace base {
+class ElapsedTimer;
+}
+
 namespace user_prefs {
 class PrefRegistrySyncable;
 }  // namespace user_prefs
@@ -51,8 +56,8 @@
     virtual void OnSessionEnded(base::TimeDelta total_session_time) = 0;
   };
 
-  explicit SessionDurationUpdater(PrefService* pref_service,
-                                  const char* observed_session_time_pref_key);
+  SessionDurationUpdater(PrefService* pref_service,
+                         const char* observed_session_time_pref_key);
   ~SessionDurationUpdater() override;
 
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
@@ -60,11 +65,11 @@
   // Returns the total amount of observed active session time of the current
   // session plus the previously recorded observed session time. The resulting
   // value should be cumulative session time across all Chrome restarts.
-  base::TimeDelta GetCumulativeElapsedSessionTime();
+  base::TimeDelta GetCumulativeElapsedSessionTime() const;
 
   // Gets the recorded observed session time which is cumulative for all
   // previous sessions.
-  base::TimeDelta GetRecordedObservedSessionTime();
+  base::TimeDelta GetRecordedObservedSessionTime() const;
 
   // For observing the status of the session tracker.
   void AddObserver(Observer* observer);
@@ -75,12 +80,11 @@
   void OnSessionEnded(base::TimeDelta delta) override;
 
  private:
-  // Adds the DesktopSessionDurationTracker observer.
   void AddDurationTrackerObserver();
-  // Removes the DesktopSessionDurationTracker observer.
   void RemoveDurationTrackerObserver();
+
   // Returns the pref service associated with this SessionDurationUpdater.
-  virtual PrefService* GetPrefs();
+  PrefService* GetPrefs();
 
   // Observes the DesktopSessionDurationTracker and notifies when a desktop
   // session starts and ends.
@@ -91,9 +95,9 @@
   // Owned by Profile manager.
   PrefService* const pref_service_;
 
-  // The profile dict key of kObservedSessionTime that tracks the observed
-  // session time for an In-Product Help feature.
-  const char* observed_session_time_dict_key_;
+  // The profile dict key of |kObservedSessionTime| that tracks the observed
+  // session time for an In-Product Help feature. Needs to outlive this class.
+  const char* const observed_session_time_dict_key_;
 
   // Tracks the elapsed active session time while the browser is open.
   std::unique_ptr<base::ElapsedTimer> current_session_timer_;
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc
index bb1a6f5..3b5980b 100644
--- a/chrome/browser/infobars/infobars_browsertest.cc
+++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -275,9 +275,9 @@
 
     case IBD::THEME_INSTALLED_INFOBAR_DELEGATE:
       ThemeInstalledInfoBarDelegate::Create(
-          GetInfoBarService(), nullptr,
+          GetInfoBarService(),
           ThemeServiceFactory::GetForProfile(browser()->profile()), "New Theme",
-          "id", ThemeService::kDefaultThemeID, true);
+          "id", base::OnceClosure());
       break;
 
     case IBD::NACL_INFOBAR_DELEGATE:
diff --git a/chrome/browser/lifetime/application_lifetime.cc b/chrome/browser/lifetime/application_lifetime.cc
index 7e1926e..f9e8465e 100644
--- a/chrome/browser/lifetime/application_lifetime.cc
+++ b/chrome/browser/lifetime/application_lifetime.cc
@@ -52,7 +52,7 @@
 #include "chrome/browser/chromeos/boot_times_recorder.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #endif
 
diff --git a/chrome/browser/lifetime/termination_notification.cc b/chrome/browser/lifetime/termination_notification.cc
index 0846a992..4ffc9f1b 100644
--- a/chrome/browser/lifetime/termination_notification.cc
+++ b/chrome/browser/lifetime/termination_notification.cc
@@ -14,7 +14,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/dbus/update_engine_client.h"
 #endif
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
index 9a06c58..ea7fc5d6 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/lookalikes/lookalike_url_controller_client.h"
 #include "chrome/browser/lookalikes/lookalike_url_interstitial_page.h"
 #include "chrome/browser/lookalikes/lookalike_url_service.h"
+#include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_features.h"
 #include "components/security_interstitials/content/security_interstitial_tab_helper.h"
@@ -259,7 +260,13 @@
 std::unique_ptr<LookalikeUrlNavigationThrottle>
 LookalikeUrlNavigationThrottle::MaybeCreateNavigationThrottle(
     content::NavigationHandle* navigation_handle) {
-  // For metrics, we always insert the throttle
+  // If the tab is being prerendered, stop here before it breaks metrics
+  content::WebContents* web_contents = navigation_handle->GetWebContents();
+  if (prerender::PrerenderContents::FromWebContents(web_contents)) {
+    return nullptr;
+  }
+
+  // Otherwise, always insert the throttle for metrics recording.
   return std::make_unique<LookalikeUrlNavigationThrottle>(navigation_handle);
 }
 
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
index 5b7214b..512e8af 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
@@ -103,26 +103,91 @@
   return page->GetTypeForTesting();
 }
 
+// Sets the absolute Site Engagement |score| for the testing origin.
+void SetEngagementScore(Browser* browser, const GURL& url, double score) {
+  SiteEngagementService::Get(browser->profile())
+      ->ResetBaseScoreForURL(url, score);
+}
+
+bool IsUrlShowing(Browser* browser) {
+  return !browser->location_bar_model()->GetFormattedFullURL().empty();
+}
+
+// Simulates a link click navigation. We don't use
+// ui_test_utils::NavigateToURL(const GURL&) because it simulates the user
+// typing the URL, causing the site to have a site engagement score of at
+// least LOW.
+void NavigateToURL(Browser* browser, const GURL& url) {
+  NavigateParams params(browser, url, ui::PAGE_TRANSITION_LINK);
+  params.initiator_origin = url::Origin::Create(GURL("about:blank"));
+  params.disposition = WindowOpenDisposition::CURRENT_TAB;
+  params.is_renderer_initiated = true;
+  ui_test_utils::NavigateToURL(&params);
+}
+
+// Same as NavigateToUrl, but wait for the load to complete before returning.
+void NavigateToURLSync(Browser* browser, const GURL& url) {
+  content::TestNavigationObserver navigation_observer(
+      browser->tab_strip_model()->GetActiveWebContents(), 1);
+  NavigateToURL(browser, url);
+  navigation_observer.Wait();
+}
+
+// Load given URL and verify that it loaded an interstitial and hid the URL.
+void LoadInterstitialAt(Browser* browser, const GURL& url) {
+  content::WebContents* web_contents =
+      browser->tab_strip_model()->GetActiveWebContents();
+
+  EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
+
+  NavigateToURLSync(browser, url);
+  EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
+            GetInterstitialType(web_contents));
+  EXPECT_FALSE(IsUrlShowing(browser));
+}
+
 void SendInterstitialCommand(content::WebContents* web_contents,
                              SecurityInterstitialCommand command) {
   GetCurrentInterstitial(web_contents)
       ->CommandReceived(base::NumberToString(command));
 }
 
+void SendInterstitialCommandSync(Browser* browser,
+                                 SecurityInterstitialCommand command) {
+  content::WebContents* web_contents =
+      browser->tab_strip_model()->GetActiveWebContents();
+
+  EXPECT_TRUE(GetCurrentInterstitial(web_contents));
+
+  content::TestNavigationObserver navigation_observer(web_contents, 1);
+  SendInterstitialCommand(web_contents, command);
+  navigation_observer.Wait();
+
+  EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
+  EXPECT_TRUE(IsUrlShowing(browser));
+}
+
+// Verify that no interstitial is shown, regardless of feature state.
+void TestInterstitialNotShown(Browser* browser, const GURL& navigated_url) {
+  content::WebContents* web_contents =
+      browser->tab_strip_model()->GetActiveWebContents();
+
+  NavigateToURLSync(browser, navigated_url);
+  EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
+
+  // Navigate to an empty page. This will happen after any
+  // LookalikeUrlService tasks, so will effectively wait for those tasks to
+  // finish.
+  NavigateToURLSync(browser, GURL("about:blank"));
+  EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
+}
+
 }  // namespace
 
 class LookalikeUrlNavigationThrottleBrowserTest
     : public InProcessBrowserTest,
       public testing::WithParamInterface<UIEnabled> {
  protected:
-  // Sets the absolute Site Engagement |score| for the testing origin.
-  static void SetEngagementScore(Browser* browser,
-                                 const GURL& url,
-                                 double score) {
-    SiteEngagementService::Get(browser->profile())
-        ->ResetBaseScoreForURL(url, score);
-  }
-
   void SetUp() override {
     if (ui_enabled()) {
       feature_list_.InitAndEnableFeature(
@@ -185,50 +250,9 @@
         test_ukm_recorder()->GetEntriesByName(UkmEntry::kEntryName).empty());
   }
 
-  void TestInterstitialNotShown(Browser* browser, const GURL& navigated_url) {
-    content::WebContents* web_contents =
-        browser->tab_strip_model()->GetActiveWebContents();
-    {
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      NavigateToURL(browser, navigated_url);
-      navigation_observer.Wait();
-      EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
-      EXPECT_TRUE(IsUrlShowing(browser));
-    }
-    {
-      // Navigate to an empty page. This will happen after any
-      // LookalikeUrlService tasks, so will effectively wait for those tasks to
-      // finish.
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      NavigateToURL(browser, GURL("about:blank"));
-      navigation_observer.Wait();
-      EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
-      EXPECT_TRUE(IsUrlShowing(browser));
-    }
-  }
-
-  // Tests only that the interstitial is shown (when enabled) when the user
-  // tries to visit the provided URL.
-  void TestOnlyInterstitialShown(Browser* browser, const GURL& navigated_url) {
-    if (!ui_enabled()) {
-      return;
-    }
-
-    content::WebContents* web_contents =
-        browser->tab_strip_model()->GetActiveWebContents();
-
-    content::TestNavigationObserver navigation_observer(web_contents, 1);
-    NavigateToURL(browser, navigated_url);
-    navigation_observer.Wait();
-
-    EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
-              GetInterstitialType(web_contents));
-    EXPECT_FALSE(IsUrlShowing(browser));
-  }
-
   // Tests that the histogram event |expected_event| is recorded. If the UI is
-  // enabled, additinal events for interstitial display and link click will also
-  // be tested.
+  // enabled, additional events for interstitial display and link click will
+  // also be tested.
   void TestHistogramEventsRecordedAndInterstitialShown(
       Browser* browser,
       base::HistogramTester* histograms,
@@ -236,31 +260,46 @@
       const GURL& expected_suggested_url,
       LookalikeUrlNavigationThrottle::NavigationSuggestionEvent
           expected_event) {
-    if (ui_enabled()) {
-      // If the feature is enabled, the UI will be displayed.
-      TestInterstitialShown(browser, navigated_url, expected_suggested_url);
+    if (!ui_enabled()) {
+      TestInterstitialNotShown(browser, navigated_url);
       histograms->ExpectTotalCount(
           LookalikeUrlNavigationThrottle::kHistogramName, 1);
       histograms->ExpectBucketCount(
           LookalikeUrlNavigationThrottle::kHistogramName, expected_event, 1);
 
-      histograms->ExpectTotalCount(kInterstitialDecisionMetric, 2);
-      histograms->ExpectBucketCount(kInterstitialDecisionMetric,
-                                    MetricsHelper::SHOW, 1);
-      histograms->ExpectBucketCount(kInterstitialDecisionMetric,
-                                    MetricsHelper::DONT_PROCEED, 1);
-
-      histograms->ExpectTotalCount(kInterstitialInteractionMetric, 1);
-      histograms->ExpectBucketCount(kInterstitialInteractionMetric,
-                                    MetricsHelper::TOTAL_VISITS, 1);
       return;
     }
 
-    TestInterstitialNotShown(browser, navigated_url);
+    history::HistoryService* const history_service =
+        HistoryServiceFactory::GetForProfile(
+            browser->profile(), ServiceAccessType::EXPLICIT_ACCESS);
+    ui_test_utils::WaitForHistoryToLoad(history_service);
+
+    LoadInterstitialAt(browser, navigated_url);
+    SendInterstitialCommandSync(browser,
+                                SecurityInterstitialCommand::CMD_DONT_PROCEED);
+    EXPECT_EQ(expected_suggested_url,
+              browser->tab_strip_model()->GetActiveWebContents()->GetURL());
+
+    // Clicking the link in the interstitial should also remove the original
+    // URL from history.
+    ui_test_utils::HistoryEnumerator enumerator(browser->profile());
+    EXPECT_FALSE(base::ContainsValue(enumerator.urls(), navigated_url));
+
     histograms->ExpectTotalCount(LookalikeUrlNavigationThrottle::kHistogramName,
                                  1);
     histograms->ExpectBucketCount(
         LookalikeUrlNavigationThrottle::kHistogramName, expected_event, 1);
+
+    histograms->ExpectTotalCount(kInterstitialDecisionMetric, 2);
+    histograms->ExpectBucketCount(kInterstitialDecisionMetric,
+                                  MetricsHelper::SHOW, 1);
+    histograms->ExpectBucketCount(kInterstitialDecisionMetric,
+                                  MetricsHelper::DONT_PROCEED, 1);
+
+    histograms->ExpectTotalCount(kInterstitialInteractionMetric, 1);
+    histograms->ExpectBucketCount(kInterstitialInteractionMetric,
+                                  MetricsHelper::TOTAL_VISITS, 1);
   }
 
   // Tests that the histogram event |expected_event| is recorded. If the UI is
@@ -272,146 +311,59 @@
       const GURL& navigated_url,
       LookalikeUrlNavigationThrottle::NavigationSuggestionEvent
           expected_event) {
-    if (ui_enabled()) {
-      // If the feature is enabled, the UI will be displayed.
-      DisplayThenIgnoreInterstitial(browser, navigated_url);
+    if (!ui_enabled()) {
+      TestInterstitialNotShown(browser, navigated_url);
       histograms->ExpectTotalCount(
           LookalikeUrlNavigationThrottle::kHistogramName, 1);
       histograms->ExpectBucketCount(
           LookalikeUrlNavigationThrottle::kHistogramName, expected_event, 1);
 
-      histograms->ExpectTotalCount(kInterstitialDecisionMetric, 2);
-      histograms->ExpectBucketCount(kInterstitialDecisionMetric,
-                                    MetricsHelper::SHOW, 1);
-      histograms->ExpectBucketCount(kInterstitialDecisionMetric,
-                                    MetricsHelper::PROCEED, 1);
-
-      histograms->ExpectTotalCount(kInterstitialInteractionMetric, 1);
-      histograms->ExpectBucketCount(kInterstitialInteractionMetric,
-                                    MetricsHelper::TOTAL_VISITS, 1);
-
-      TestInterstitialNotShown(browser, navigated_url);
-
       return;
     }
 
-    TestInterstitialNotShown(browser, navigated_url);
+    history::HistoryService* const history_service =
+        HistoryServiceFactory::GetForProfile(
+            browser->profile(), ServiceAccessType::EXPLICIT_ACCESS);
+    ui_test_utils::WaitForHistoryToLoad(history_service);
+
+    LoadInterstitialAt(browser, navigated_url);
+
+    // Clicking the ignore button in the interstitial should remove the
+    // interstitial and navigate to the original URL.
+    SendInterstitialCommandSync(browser,
+                                SecurityInterstitialCommand::CMD_PROCEED);
+    EXPECT_EQ(navigated_url,
+              browser->tab_strip_model()->GetActiveWebContents()->GetURL());
+
+    // Clicking the link should cause the original URL to appear in history.
+    ui_test_utils::HistoryEnumerator enumerator(browser->profile());
+    EXPECT_TRUE(base::ContainsValue(enumerator.urls(), navigated_url));
+
     histograms->ExpectTotalCount(LookalikeUrlNavigationThrottle::kHistogramName,
                                  1);
     histograms->ExpectBucketCount(
         LookalikeUrlNavigationThrottle::kHistogramName, expected_event, 1);
+
+    histograms->ExpectTotalCount(kInterstitialDecisionMetric, 2);
+    histograms->ExpectBucketCount(kInterstitialDecisionMetric,
+                                  MetricsHelper::SHOW, 1);
+    histograms->ExpectBucketCount(kInterstitialDecisionMetric,
+                                  MetricsHelper::PROCEED, 1);
+
+    histograms->ExpectTotalCount(kInterstitialInteractionMetric, 1);
+    histograms->ExpectBucketCount(kInterstitialInteractionMetric,
+                                  MetricsHelper::TOTAL_VISITS, 1);
+
+    TestInterstitialNotShown(browser, navigated_url);
   }
 
   ukm::TestUkmRecorder* test_ukm_recorder() { return test_ukm_recorder_.get(); }
 
   base::SimpleTestClock* test_clock() { return &test_clock_; }
 
- protected:
   virtual bool ui_enabled() const { return GetParam() == UIEnabled::kEnabled; }
 
-  static bool IsUrlShowing(Browser* browser) {
-    return !browser->location_bar_model()->GetFormattedFullURL().empty();
-  }
-
-  // Simulates a link click navigation. We don't use
-  // ui_test_utils::NavigateToURL(const GURL&) because it simulates the user
-  // typing the URL, causing the site to have a site engagement score of at
-  // least LOW.
-  static void NavigateToURL(Browser* browser, const GURL& url) {
-    NavigateParams params(browser, url, ui::PAGE_TRANSITION_LINK);
-    params.initiator_origin = url::Origin::Create(GURL("about:blank"));
-    params.disposition = WindowOpenDisposition::CURRENT_TAB;
-    params.is_renderer_initiated = true;
-    ui_test_utils::NavigateToURL(&params);
-  }
-
-  // Checks that navigating to |navigated_url| results in displaying an
-  // interstitial suggesting navigation to |expected_suggestion_url|.
-  // Both |navigated_url| and |expected_suggested_url| can be ASCII or IDN.
-  static void TestInterstitialShown(Browser* browser,
-                                    const GURL& navigated_url,
-                                    const GURL& expected_suggested_url) {
-    history::HistoryService* const history_service =
-        HistoryServiceFactory::GetForProfile(
-            browser->profile(), ServiceAccessType::EXPLICIT_ACCESS);
-    ui_test_utils::WaitForHistoryToLoad(history_service);
-
-    content::WebContents* web_contents =
-        browser->tab_strip_model()->GetActiveWebContents();
-
-    EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
-    EXPECT_TRUE(IsUrlShowing(browser));
-    {
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      NavigateToURL(browser, navigated_url);
-      navigation_observer.Wait();
-    }
-
-    EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
-              GetInterstitialType(web_contents));
-    EXPECT_FALSE(IsUrlShowing(browser));
-
-    // Clicking the link in the interstitial should remove the interstitial and
-    // navigate to the suggested URL.
-    {
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      SendInterstitialCommand(web_contents,
-                              SecurityInterstitialCommand::CMD_DONT_PROCEED);
-      navigation_observer.Wait();
-    }
-
-    EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
-    EXPECT_EQ(expected_suggested_url, web_contents->GetURL());
-    EXPECT_TRUE(IsUrlShowing(browser));
-
-    // Clicking the link in the interstitial should also remove the original URL
-    // from history.
-    ui_test_utils::HistoryEnumerator enumerator(browser->profile());
-    EXPECT_FALSE(base::ContainsValue(enumerator.urls(), navigated_url));
-  }
-
-  // Checks that navigating to |navigated_url| results in displaying an
-  // interstitial, that, when ignored, proceeds to |navigated_url|.
-  // |navigated_url| can be ASCII or IDN.
-  static void DisplayThenIgnoreInterstitial(Browser* browser,
-                                            const GURL& navigated_url) {
-    history::HistoryService* const history_service =
-        HistoryServiceFactory::GetForProfile(
-            browser->profile(), ServiceAccessType::EXPLICIT_ACCESS);
-    ui_test_utils::WaitForHistoryToLoad(history_service);
-
-    content::WebContents* web_contents =
-        browser->tab_strip_model()->GetActiveWebContents();
-
-    EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
-    {
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      NavigateToURL(browser, navigated_url);
-      navigation_observer.Wait();
-    }
-
-    EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
-              GetInterstitialType(web_contents));
-    EXPECT_FALSE(IsUrlShowing(browser));
-
-    // Clicking the ignore button in the interstitial should remove the
-    // interstitial and navigate to the original URL.
-    {
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      SendInterstitialCommand(web_contents,
-                              SecurityInterstitialCommand::CMD_PROCEED);
-      navigation_observer.Wait();
-    }
-
-    EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
-    EXPECT_EQ(navigated_url, web_contents->GetURL());
-    EXPECT_TRUE(IsUrlShowing(browser));
-
-    // Clicking the link should result in the original URL appearing in history.
-    ui_test_utils::HistoryEnumerator enumerator(browser->profile());
-    EXPECT_TRUE(base::ContainsValue(enumerator.urls(), navigated_url));
-  }
-
+ private:
   base::test::ScopedFeatureList feature_list_;
   std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
   base::SimpleTestClock test_clock_;
@@ -419,64 +371,6 @@
 
 class LookalikeUrlInterstitialPageBrowserTest
     : public LookalikeUrlNavigationThrottleBrowserTest {
- public:
-  // Checks that navigating to |navigated_url| displays an interstitial with a
-  // hidden URL, and then navigating to other pages shows/hides the URLs
-  // appropriately both when a URL is expected to be hidden (by navigating to
-  // "chrome://newtab") and when expected to be shown (by navigating to
-  // |subsequent_url|).
-  static void TestInterstitialHidesUrlThenRestores(Browser* browser,
-                                                   const GURL& navigated_url,
-                                                   const GURL& subsequent_url) {
-    content::WebContents* web_contents =
-        browser->tab_strip_model()->GetActiveWebContents();
-
-    EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
-    EXPECT_TRUE(IsUrlShowing(browser));
-    {
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      NavigateToURL(browser, navigated_url);
-      navigation_observer.Wait();
-    }
-
-    EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
-              GetInterstitialType(web_contents));
-    EXPECT_FALSE(IsUrlShowing(browser));
-
-    {
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      ui_test_utils::NavigateToURL(browser, subsequent_url);
-      navigation_observer.Wait();
-    }
-
-    EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
-    EXPECT_TRUE(IsUrlShowing(browser));
-
-    {
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      ui_test_utils::NavigateToURL(browser, GURL("chrome://newtab"));
-      navigation_observer.Wait();
-    }
-
-    EXPECT_FALSE(IsUrlShowing(browser));
-  }
-
-  // Load the given URL and verify that it loaded an interstitial.
-  void LoadInterstitialAt(const GURL& navigated_url) {
-    content::WebContents* web_contents =
-        browser()->tab_strip_model()->GetActiveWebContents();
-
-    EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
-    {
-      content::TestNavigationObserver navigation_observer(web_contents, 1);
-      NavigateToURL(browser(), navigated_url);
-      navigation_observer.Wait();
-    }
-
-    EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
-              GetInterstitialType(web_contents));
-  }
-
  protected:
   bool ui_enabled() const override { return true; }
 };
@@ -788,23 +682,28 @@
   CheckUkm({kNavigatedUrl}, "MatchType", MatchType::kEditDistance);
 }
 
-// Navigate to lookalike domains that redirect to benign domains. Ensure that
-// we display an interstitial along the way if configured via a feature param.
-IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest,
+// Navigate to lookalike domains that redirect to benign domains and ensure that
+// we display an interstitial along the way.
+IN_PROC_BROWSER_TEST_F(LookalikeUrlInterstitialPageBrowserTest,
                        Interstitial_CapturesRedirects) {
   {
     // Verify it works when the lookalike domain is the first in the chain
     const GURL kNavigatedUrl =
         GetLongRedirect("goooglé.com", "example.net", "example.com");
     SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement);
-    TestOnlyInterstitialShown(browser(), kNavigatedUrl);
+    LoadInterstitialAt(browser(), kNavigatedUrl);
   }
+
+  // LoadInterstitialAt assumes there's not an interstitial already showing
+  // (since otherwise it can't be sure that the navigation caused it).
+  NavigateToURLSync(browser(), GetURL("example.com"));
+
   {
     // ...or when it's later in the chain
     const GURL kNavigatedUrl =
         GetLongRedirect("example.net", "goooglé.com", "example.com");
     SetEngagementScore(browser(), kNavigatedUrl, kLowEngagement);
-    TestOnlyInterstitialShown(browser(), kNavigatedUrl);
+    LoadInterstitialAt(browser(), kNavigatedUrl);
   }
 }
 
@@ -817,9 +716,7 @@
     return;
 
   const GURL navigated_url = GetURL("goooglé.com");
-
   TestInterstitialNotShown(browser(), navigated_url);
-
   CheckUkm({navigated_url}, "UserAction", UserAction::kInterstitialNotShown);
 }
 
@@ -830,14 +727,8 @@
   const GURL navigated_url = GetURL("goooglé.com");
   const GURL subsequent_url = GetURL("example.com");
 
-  LoadInterstitialAt(navigated_url);
-
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  content::TestNavigationObserver navigation_observer(web_contents, 1);
-  ui_test_utils::NavigateToURL(browser(), subsequent_url);
-  navigation_observer.Wait();
-
+  LoadInterstitialAt(browser(), navigated_url);
+  NavigateToURLSync(browser(), subsequent_url);
   CheckUkm({navigated_url}, "UserAction", UserAction::kCloseOrBack);
 }
 
@@ -847,15 +738,9 @@
                        UkmRecordedAfterSuggestionAccepted) {
   const GURL navigated_url = GetURL("goooglé.com");
 
-  LoadInterstitialAt(navigated_url);
-
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  content::TestNavigationObserver navigation_observer(web_contents, 1);
-  SendInterstitialCommand(web_contents,
-                          SecurityInterstitialCommand::CMD_DONT_PROCEED);
-  navigation_observer.Wait();
-
+  LoadInterstitialAt(browser(), navigated_url);
+  SendInterstitialCommandSync(browser(),
+                              SecurityInterstitialCommand::CMD_DONT_PROCEED);
   CheckUkm({navigated_url}, "UserAction", UserAction::kAcceptSuggestion);
 }
 
@@ -865,23 +750,22 @@
                        UkmRecordedAfterSuggestionIgnored) {
   const GURL navigated_url = GetURL("goooglé.com");
 
-  LoadInterstitialAt(navigated_url);
-
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  content::TestNavigationObserver navigation_observer(web_contents, 1);
-  SendInterstitialCommand(web_contents,
-                          SecurityInterstitialCommand::CMD_PROCEED);
-  navigation_observer.Wait();
-
+  LoadInterstitialAt(browser(), navigated_url);
+  SendInterstitialCommandSync(browser(),
+                              SecurityInterstitialCommand::CMD_PROCEED);
   CheckUkm({navigated_url}, "UserAction", UserAction::kClickThrough);
 }
 
 // Verify that the URL shows normally on pages after a lookalike interstitial.
 IN_PROC_BROWSER_TEST_F(LookalikeUrlInterstitialPageBrowserTest,
                        UrlShownAfterInterstitial) {
-  const GURL kNavigatedUrl = GetURL("goooglé.com");
-  const GURL kSubsequentUrl = GetURL("example.com");
-  TestInterstitialHidesUrlThenRestores(browser(), kNavigatedUrl,
-                                       kSubsequentUrl);
+  LoadInterstitialAt(browser(), GetURL("goooglé.com"));
+
+  // URL should be showing again when we navigate to a normal URL
+  NavigateToURLSync(browser(), GetURL("example.com"));
+  EXPECT_TRUE(IsUrlShowing(browser()));
+
+  // URL should still get hidden when we navigate to a page with a hidden URL.
+  NavigateToURLSync(browser(), GURL("chrome://newtab"));
+  EXPECT_FALSE(IsUrlShowing(browser()));
 }
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc
index d4377470..c1fd541 100644
--- a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc
+++ b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc
@@ -28,11 +28,13 @@
 CastSessionClient::CastSessionClient(const std::string& client_id,
                                      const url::Origin& origin,
                                      int tab_id,
+                                     AutoJoinPolicy auto_join_policy,
                                      DataDecoder* data_decoder,
                                      CastActivityRecord* activity)
     : client_id_(client_id),
       origin_(origin),
       tab_id_(tab_id),
+      auto_join_policy_(auto_join_policy),
       data_decoder_(data_decoder),
       activity_(activity),
       connection_binding_(this),
@@ -95,6 +97,17 @@
   // method once we make sure Blink calls this on navigation and on
   // PresentationConnection::close().
 }
+bool CastSessionClient::MatchesAutoJoinPolicy(url::Origin origin,
+                                              int tab_id) const {
+  switch (auto_join_policy_) {
+    case AutoJoinPolicy::kTabAndOriginScoped:
+      return origin == origin_ && tab_id == tab_id_;
+    case AutoJoinPolicy::kOriginScoped:
+      return origin == origin_;
+    default:
+      return false;
+  }
+}
 
 void CastSessionClient::HandleParsedClientMessage(
     std::unique_ptr<base::Value> message) {
@@ -103,39 +116,48 @@
   if (!cast_message) {
     ReportClientMessageParseError(activity_->route().media_route_id(),
                                   "Not a Cast message");
-    DVLOG(2) << "Received non-Cast message from client";
+    DLOG(ERROR) << "Received non-Cast message from client";
     return;
   }
 
   if (cast_message->client_id != client_id_) {
-    DVLOG(2) << "Client ID mismatch: expected: " << client_id_
-             << ", got: " << cast_message->client_id;
+    DLOG(ERROR) << "Client ID mismatch: expected: " << client_id_
+                << ", got: " << cast_message->client_id;
     return;
   }
 
-  if (cast_message->type != CastInternalMessage::Type::kAppMessage &&
-      cast_message->type != CastInternalMessage::Type::kV2Message) {
-    DVLOG(2) << "Unhandled message type: "
-             << static_cast<int>(cast_message->type);
+  if (cast_message->has_session_id() &&
+      cast_message->session_id() != activity_->session_id()) {
+    DLOG(ERROR) << "Session ID mismatch: expected: "
+                << activity_->session_id().value_or("<missing>")
+                << ", got: " << cast_message->session_id();
     return;
   }
 
-  if (cast_message->session_id() != activity_->session_id()) {
-    DVLOG(2) << "Session ID mismatch: expected: "
-             << activity_->session_id().value_or("<missing>")
-             << ", got: " << cast_message->session_id();
-    return;
-  }
-
-  if (cast_message->type == CastInternalMessage::Type::kAppMessage &&
-      activity_->SendAppMessageToReceiver(*cast_message) ==
+  switch (cast_message->type) {
+    case CastInternalMessage::Type::kAppMessage:
+      // Send an ACK message back to SDK client to indicate it is handled.
+      if (activity_->SendAppMessageToReceiver(*cast_message) ==
           cast_channel::Result::kOk) {
-    // Send an ACK message back to SDK client to indicate it is handled.
-    DCHECK(cast_message->sequence_number);
-    SendMessageToClient(CreateAppMessageAck(cast_message->client_id,
-                                            *cast_message->sequence_number));
-  } else if (cast_message->type == CastInternalMessage::Type::kV2Message) {
-    HandleV2ProtocolMessage(*cast_message);
+        DCHECK(cast_message->sequence_number);
+        SendMessageToClient(CreateAppMessageAck(
+            cast_message->client_id, *cast_message->sequence_number));
+      }
+      break;
+
+    case CastInternalMessage::Type::kV2Message:
+      HandleV2ProtocolMessage(*cast_message);
+      break;
+
+    case CastInternalMessage::Type::kLeaveSession:
+      SendMessageToClient(CreateLeaveSessionAckMessage(
+          client_id_, cast_message->sequence_number));
+      activity_->HandleLeaveSession(client_id_);
+      break;
+
+    default:
+      DLOG(ERROR) << "Unhandled message type: "
+                  << static_cast<int>(cast_message->type);
   }
 }
 
@@ -173,7 +195,7 @@
     // TODO(jrw): implement STOP_SESSION.
     DVLOG(2) << "Ignoring stop-session (" << type_str << ") message";
   } else {
-    DLOG(FATAL) << "Unknown v2 message type: " << type_str;
+    DLOG(ERROR) << "Unknown v2 message type: " << type_str;
   }
 }
 
@@ -210,10 +232,11 @@
 mojom::RoutePresentationConnectionPtr CastActivityRecord::AddClient(
     const std::string& client_id,
     const url::Origin& origin,
-    int tab_id) {
+    int tab_id,
+    AutoJoinPolicy auto_join_policy) {
   DCHECK(!base::ContainsKey(connected_clients_, client_id));
-  auto client = std::make_unique<CastSessionClient>(client_id, origin, tab_id,
-                                                    data_decoder_, this);
+  auto client = std::make_unique<CastSessionClient>(
+      client_id, origin, tab_id, auto_join_policy, data_decoder_, this);
   auto presentation_connection = client->Init();
   connected_clients_.emplace(client_id, std::move(client));
   return presentation_connection;
@@ -244,7 +267,7 @@
                                            // SDK client.
   const std::string& message_namespace = cast_message.app_message_namespace();
   if (!base::ContainsKey(session->message_namespaces(), message_namespace)) {
-    DVLOG(2) << "Disallowed message namespace: " << message_namespace;
+    DLOG(ERROR) << "Disallowed message namespace: " << message_namespace;
     // TODO(jrw): Send error code back to SDK client.
     return cast_channel::Result::kFailed;
   }
@@ -288,13 +311,31 @@
                      std::move(callback)));
 }
 
+void CastActivityRecord::HandleLeaveSession(const std::string& client_id) {
+  auto client_it = connected_clients_.find(client_id);
+  CHECK(client_it != connected_clients_.end());
+  CastSessionClient& client = *client_it->second;
+  std::vector<std::string> leaving_client_ids;
+  for (const auto& pair : connected_clients_) {
+    if (pair.second->MatchesAutoJoinPolicy(client.origin(), client.tab_id()))
+      leaving_client_ids.push_back(pair.first);
+  }
+
+  for (const auto& client_id : leaving_client_ids) {
+    auto leaving_client_it = connected_clients_.find(client_id);
+    CHECK(leaving_client_it != connected_clients_.end());
+    leaving_client_it->second->CloseConnection();
+    connected_clients_.erase(leaving_client_it);
+  }
+}
+
 void CastActivityRecord::SendMessageToClient(
     const std::string& client_id,
     blink::mojom::PresentationConnectionMessagePtr message) {
   auto it = connected_clients_.find(client_id);
   if (it == connected_clients_.end()) {
-    DVLOG(2) << "Attempting to send message to nonexistent client: "
-             << client_id;
+    DLOG(ERROR) << "Attempting to send message to nonexistent client: "
+                << client_id;
     return;
   }
   it->second->SendMessageToClient(std::move(message));
@@ -466,7 +507,8 @@
   const std::string& client_id = cast_source.client_id();
   if (!client_id.empty()) {
     presentation_connection =
-        activity_ptr->AddClient(client_id, params.origin, params.tab_id);
+        activity_ptr->AddClient(client_id, params.origin, params.tab_id,
+                                cast_source.auto_join_policy());
     activity_ptr->SendMessageToClient(
         client_id,
         CreateReceiverActionCastMessage(client_id, sink, hash_token_));
@@ -736,7 +778,7 @@
   }
 
   if (response.result != cast_channel::LaunchSessionResponse::Result::kOk) {
-    DVLOG(2) << "Failed to launch session for " << route_id;
+    DLOG(ERROR) << "Failed to launch session for " << route_id;
     RemoveActivity(activity_it);
     SendFailedToCastIssue(sink.sink().id(), route_id);
     return;
@@ -744,7 +786,7 @@
 
   auto session = CastSession::From(sink, *response.receiver_status);
   if (!session) {
-    DVLOG(2) << "Unable to get session from launch response";
+    DLOG(ERROR) << "Unable to get session from launch response";
     RemoveActivity(activity_it);
     SendFailedToCastIssue(sink.sink().id(), route_id);
     return;
@@ -820,7 +862,7 @@
       callback(std::move(callback)) {}
 
 CastActivityManager::DoLaunchSessionParams::DoLaunchSessionParams(
-    DoLaunchSessionParams&& other) = default;
+    DoLaunchSessionParams&& other) noexcept = default;
 
 CastActivityManager::DoLaunchSessionParams::~DoLaunchSessionParams() = default;
 
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager.h b/chrome/browser/media/router/providers/cast/cast_activity_manager.h
index 0844a01..46bb4b0 100644
--- a/chrome/browser/media/router/providers/cast/cast_activity_manager.h
+++ b/chrome/browser/media/router/providers/cast/cast_activity_manager.h
@@ -41,6 +41,7 @@
   CastSessionClient(const std::string& client_id,
                     const url::Origin& origin,
                     int tab_id,
+                    AutoJoinPolicy auto_join_policy,
                     DataDecoder* data_decoder,
                     CastActivityRecord* activity);
   ~CastSessionClient() override;
@@ -81,6 +82,20 @@
   void DidClose(
       blink::mojom::PresentationConnectionCloseReason reason) override;
 
+  // Tests whether the specified origin and tab ID match this session's origin
+  // and tab ID to the extent required by this sesssion's auto-join policy.
+  // Depending on the value of |auto_join_policy_|, |origin|, |tab_id|, or both
+  // may be ignored.
+  //
+  // TODO(jrw): It appears the real purpose of this method is to detect whether
+  // this session was created by an auto-join request, but auto-joining isn't
+  // implemented yet.  This comment should probably be updated once auto-join is
+  // implemented and I've verified this method does what I think it does.
+  // Alternatively, it might make more sense to record at session creation time
+  // whether a particular session was created by an auto-join request, in which
+  // case I believe this method would no longer be needed.
+  bool MatchesAutoJoinPolicy(url::Origin origin, int tab_id) const;
+
  private:
   void HandleParsedClientMessage(std::unique_ptr<base::Value> message);
   void HandleV2ProtocolMessage(const CastInternalMessage& cast_message);
@@ -97,6 +112,8 @@
   url::Origin origin_;
   int tab_id_;
 
+  const AutoJoinPolicy auto_join_policy_;
+
   DataDecoder* const data_decoder_;
   CastActivityRecord* const activity_;
 
@@ -166,12 +183,20 @@
       const base::Optional<std::string>& client_id,
       mojom::MediaRouteProvider::TerminateRouteCallback callback);
 
+  // Called when the client given by |client_id| requests to leave the session.
+  // This will also cause all clients within the session with matching origin
+  // and/or tab ID to leave (i.e., their presentation connections will be
+  // closed).
+  void HandleLeaveSession(const std::string& client_id);
+
   // Adds a new client |client_id| to this session and returns the handles of
   // the two pipes to be held by Blink It is invalid to call this method if the
   // client already exists.
-  mojom::RoutePresentationConnectionPtr AddClient(const std::string& client_id,
-                                                  const url::Origin& origin,
-                                                  int tab_id);
+  mojom::RoutePresentationConnectionPtr AddClient(
+      const std::string& client_id,
+      const url::Origin& origin,
+      int tab_id,
+      AutoJoinPolicy auto_join_policy);
 
   // On the first call, saves the ID of |session|.  On subsequent calls,
   // notifies all connected clients that the session has been updated.  In both
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
index dddd0cd..f275394 100644
--- a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
+++ b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/media/router/providers/cast/cast_activity_manager.h"
 
+#include <tuple>
 #include <utility>
 
 #include "base/bind.h"
@@ -28,6 +29,7 @@
 using base::test::IsJson;
 using base::test::ParseJsonDeprecated;
 using testing::_;
+using testing::AnyNumber;
 using testing::IsEmpty;
 using testing::Not;
 using testing::Return;
@@ -107,7 +109,11 @@
   DISALLOW_COPY_AND_ASSIGN(ClientPresentationConnection);
 };
 
-class CastActivityManagerTest : public testing::Test {
+// Test parameters are a boolean indicating whether the client connection should
+// be closed by a leave_session message, and the URL used to create the test
+// session.
+class CastActivityManagerTest
+    : public testing::TestWithParam<std::pair<bool, const char*>> {
  public:
   CastActivityManagerTest()
       : data_decoder_service_(connector_factory_.RegisterInstance(
@@ -170,10 +176,10 @@
     EXPECT_CALL(
         *client_connection_,
         DidChangeState(blink::mojom::PresentationConnectionState::CONNECTED));
-    EXPECT_CALL(*client_connection_, OnMessage(_));
+    EXPECT_CALL(*client_connection_, OnMessage).RetiresOnSaturation();
   }
 
-  void LaunchSession() {
+  void LaunchSession(const char* sourceId = kSource1) {
     // MediaRouter is notified of new route.
     ExpectSingleRouteUpdate();
 
@@ -184,7 +190,7 @@
           launch_session_callback_ = std::move(callback);
         }));
 
-    auto source = CastMediaSource::FromMediaSourceId(kSource1);
+    auto source = CastMediaSource::FromMediaSourceId(sourceId);
     ASSERT_TRUE(source);
 
     // Callback will be invoked synchronously.
@@ -219,7 +225,7 @@
         route_->media_sink_id(),
         CastSession::From(sink_, *response.receiver_status));
     std::move(launch_session_callback_).Run(std::move(response));
-    EXPECT_CALL(*client_connection_, OnMessage(_));
+    EXPECT_CALL(*client_connection_, OnMessage).RetiresOnSaturation();
     ExpectSingleRouteUpdate();
     RunUntilIdle();
   }
@@ -233,7 +239,7 @@
     response.result = cast_channel::LaunchSessionResponse::Result::kError;
     std::move(launch_session_callback_).Run(std::move(response));
 
-    EXPECT_CALL(mock_router_, OnIssue(_));
+    EXPECT_CALL(mock_router_, OnIssue);
     ExpectEmptyRouteUpdate();
     EXPECT_CALL(
         *client_connection_,
@@ -258,7 +264,7 @@
                 : &CastActivityManagerTest::ExpectTerminateResultFailure,
             base::Unretained(this)));
     // Receiver action stop message is sent to SDK client.
-    EXPECT_CALL(*client_connection_, OnMessage(_));
+    EXPECT_CALL(*client_connection_, OnMessage);
     RunUntilIdle();
 
     std::move(stop_session_callback).Run(result);
@@ -268,7 +274,7 @@
   // not called.
   void TerminateNoSession() {
     // Stop session message not sent because session has not launched yet.
-    EXPECT_CALL(message_handler_, StopSession(_, _, _, _)).Times(0);
+    EXPECT_CALL(message_handler_, StopSession).Times(0);
     manager_->TerminateSession(
         route_->media_route_id(),
         base::BindOnce(&CastActivityManagerTest::ExpectTerminateResultSuccess,
@@ -317,7 +323,7 @@
 
   // Expect that OnRoutesUpdated() will not be called.
   void ExpectNoRouteUpdate() {
-    EXPECT_CALL(mock_router_, OnRoutesUpdated(_, _, _, _)).Times(0);
+    EXPECT_CALL(mock_router_, OnRoutesUpdated).Times(0);
   }
 
  protected:
@@ -365,7 +371,7 @@
   LaunchSessionResponseSuccess();
 
   // Receiver action stop message is sent to SDK client.
-  EXPECT_CALL(*client_connection_, OnMessage(_));
+  EXPECT_CALL(*client_connection_, OnMessage);
 
   // Existing session will be terminated.
   cast_channel::ResultCallback stop_session_callback;
@@ -429,7 +435,7 @@
 
   MediaRoute route;
   ExpectSingleRouteUpdate(&route);
-  EXPECT_CALL(*client_connection_, OnMessage(_));
+  EXPECT_CALL(*client_connection_, OnMessage);
 
   manager_->OnSessionAddedOrUpdated(sink_, *session);
   RunUntilIdle();
@@ -519,7 +525,7 @@
       "urn:x-cast:com.google.foo", base::Value(base::Value::Type::DICTIONARY),
       "sourceId", "theClientId");
   message_handler_.OnMessage(socket_, message);
-  EXPECT_CALL(*client_connection_, OnMessage(_));
+  EXPECT_CALL(*client_connection_, OnMessage);
 }
 
 TEST_F(CastActivityManagerTest, AppMessageFromReceiverAllDestinations) {
@@ -531,7 +537,7 @@
       "urn:x-cast:com.google.foo", base::Value(base::Value::Type::DICTIONARY),
       "sourceId", "*");
   message_handler_.OnMessage(socket_, message);
-  EXPECT_CALL(*client_connection_, OnMessage(_));
+  EXPECT_CALL(*client_connection_, OnMessage);
 }
 
 TEST_F(CastActivityManagerTest, AppMessageFromReceiverUnknownDestination) {
@@ -543,7 +549,7 @@
       "urn:x-cast:com.google.foo", base::Value(base::Value::Type::DICTIONARY),
       "sourceId", "99999");
   message_handler_.OnMessage(socket_, message);
-  EXPECT_CALL(*client_connection_, OnMessage(_)).Times(0);
+  EXPECT_CALL(*client_connection_, OnMessage).Times(0);
 }
 
 TEST_F(CastActivityManagerTest, AppMessageFromClient) {
@@ -565,7 +571,7 @@
       })"));
 
   // An ACK message is sent back to client.
-  EXPECT_CALL(*client_connection_, OnMessage(_));
+  EXPECT_CALL(*client_connection_, OnMessage);
 }
 
 TEST_F(CastActivityManagerTest, AppMessageFromClientInvalidNamespace) {
@@ -604,8 +610,7 @@
   LaunchSession();
   LaunchSessionResponseSuccess();
 
-  EXPECT_CALL(message_handler_, SendMediaRequest(_, _, _, _))
-      .WillOnce(Return(345));
+  EXPECT_CALL(message_handler_, SendMediaRequest).WillOnce(Return(345));
   client_connection_->SendMessageToMediaRouter(
       blink::mojom::PresentationConnectionMessage::NewMessage(R"({
         "type": "v2_message",
@@ -689,4 +694,54 @@
       })"));
 }
 
+TEST_P(CastActivityManagerTest, HandleLeaveSession) {
+  bool should_close;
+  const char* url;
+  std::tie(should_close, url) = GetParam();
+
+  LaunchSession(url);
+  LaunchSessionResponseSuccess();
+
+  // Called via CastSessionClient::SendMessageToClient.
+  EXPECT_CALL(*client_connection_, OnMessage).WillOnce([](auto msg) {
+    // Verify that an acknowlegement message was sent.
+    ASSERT_TRUE(msg->is_message());
+    EXPECT_THAT(msg->get_message(), IsJson(R"({
+          "clientId": "theClientId",
+          "message": null,
+          "timeoutMillis": 0,
+          "type": "leave_session",
+        })"));
+  });
+
+  if (should_close) {
+    // Called via CastActivityRecord::HandleLeaveSession.
+    EXPECT_CALL(
+        *client_connection_,
+        DidChangeState(blink::mojom::PresentationConnectionState::CLOSED));
+  }
+
+  client_connection_->SendMessageToMediaRouter(
+      blink::mojom::PresentationConnectionMessage::NewMessage(R"({
+        "type": "leave_session",
+        "clientId": "theClientId",
+        "message": {}
+      })"));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    Urls,
+    CastActivityManagerTest,
+    testing::Values(
+        std::make_pair(true,
+                       "cast:ABCDEFGH?clientId=theClientId&autoJoinPolicy=tab_"
+                       "and_origin_scoped"),
+        std::make_pair(
+            true,
+            "cast:ABCDEFGH?clientId=theClientId&autoJoinPolicy=origin_scoped"),
+        std::make_pair(
+            false,
+            "cast:ABCDEFGH?clientId=theClientId&autoJoinPolicy=page_scoped"),
+        std::make_pair(false, "cast:ABCDEFGH?clientId=theClientId")));
+
 }  // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc b/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc
index 2fd7da5..bd83eaa7 100644
--- a/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc
+++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/media/router/providers/cast/cast_internal_message_util.h"
 
+#include <string>
+
 #include "base/base64url.h"
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
@@ -25,6 +27,7 @@
 constexpr char kClientConnect[] = "client_connect";
 constexpr char kAppMessage[] = "app_message";
 constexpr char kV2Message[] = "v2_message";
+constexpr char kLeaveSession[] = "leave_session";
 constexpr char kReceiverAction[] = "receiver_action";
 constexpr char kNewSession[] = "new_session";
 constexpr char kUpdateSession[] = "update_session";
@@ -65,6 +68,8 @@
     return CastInternalMessage::Type::kAppMessage;
   if (type == kV2Message)
     return CastInternalMessage::Type::kV2Message;
+  if (type == kLeaveSession)
+    return CastInternalMessage::Type::kLeaveSession;
   if (type == kReceiverAction)
     return CastInternalMessage::Type::kReceiverAction;
   if (type == kNewSession)
@@ -83,6 +88,8 @@
       return kAppMessage;
     case CastInternalMessage::Type::kV2Message:
       return kV2Message;
+    case CastInternalMessage::Type::kLeaveSession:
+      return kLeaveSession;
     case CastInternalMessage::Type::kReceiverAction:
       return kReceiverAction;
     case CastInternalMessage::Type::kNewSession:
@@ -490,6 +497,13 @@
                              payload.Clone(), client_id, sequence_number);
 }
 
+blink::mojom::PresentationConnectionMessagePtr CreateLeaveSessionAckMessage(
+    const std::string& client_id,
+    base::Optional<int> sequence_number) {
+  return CreateMessageCommon(CastInternalMessage::Type::kLeaveSession,
+                             base::Value(), client_id, sequence_number);
+}
+
 base::Value SupportedMediaRequestsToListValue(int media_requests) {
   base::Value value(base::Value::Type::LIST);
   auto& storage = value.GetList();
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util.h b/chrome/browser/media/router/providers/cast/cast_internal_message_util.h
index 3f94da7..23dc153b2 100644
--- a/chrome/browser/media/router/providers/cast/cast_internal_message_util.h
+++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util.h
@@ -28,6 +28,7 @@
                       // receiver.
     kV2Message,       // Cast protocol messages between SDK client and the
                       // receiver.
+    kLeaveSession,    // Message sent by SDK client to leave current session.
     kReceiverAction,  // Message sent by MRP to inform SDK client of action.
     kNewSession,      // Message sent by MRP to inform SDK client of new
                       // session.
@@ -47,8 +48,12 @@
   const std::string client_id;
   const base::Optional<int> sequence_number;
 
+  bool has_session_id() const {
+    return type == Type::kAppMessage || type == Type::kV2Message;
+  }
+
   const std::string& session_id() const {
-    DCHECK(type == Type::kAppMessage || type == Type::kV2Message);
+    DCHECK(has_session_id());
     return session_id_;
   }
 
@@ -179,6 +184,9 @@
     const std::string& client_id,
     const base::Value& payload,
     base::Optional<int> sequence_number);
+blink::mojom::PresentationConnectionMessagePtr CreateLeaveSessionAckMessage(
+    const std::string& client_id,
+    base::Optional<int> sequence_number);
 
 base::Value SupportedMediaRequestsToListValue(int media_requests);
 
diff --git a/chrome/browser/media/test_license_server.cc b/chrome/browser/media/test_license_server.cc
index de00cd0..2f251f53 100644
--- a/chrome/browser/media/test_license_server.cc
+++ b/chrome/browser/media/test_license_server.cc
@@ -7,7 +7,9 @@
 #include <utility>
 
 #include "base/command_line.h"
+#include "base/environment.h"
 #include "base/files/file_util.h"
+#include "base/optional.h"
 #include "base/process/launch.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/media/test_license_server_config.h"
@@ -35,10 +37,18 @@
     return false;
   }
 
-  DVLOG(0) << "Starting test license server " <<
-      command_line.GetCommandLineString();
-  license_server_process_ =
-      base::LaunchProcess(command_line, base::LaunchOptions());
+  base::Optional<base::EnvironmentMap> env =
+      server_config_->GetServerEnvironment();
+  if (!env) {
+    DVLOG(0) << "Could not get server environment variables.";
+    return false;
+  }
+
+  DVLOG(0) << "Starting test license server "
+           << command_line.GetCommandLineString();
+  base::LaunchOptions launch_options;
+  launch_options.environment = std::move(*env);
+  license_server_process_ = base::LaunchProcess(command_line, launch_options);
   if (!license_server_process_.IsValid()) {
     DVLOG(0) << "Failed to start test license server!";
     return false;
diff --git a/chrome/browser/media/test_license_server_config.h b/chrome/browser/media/test_license_server_config.h
index 2a2d4e7a..7a145a21 100644
--- a/chrome/browser/media/test_license_server_config.h
+++ b/chrome/browser/media/test_license_server_config.h
@@ -6,8 +6,11 @@
 #define CHROME_BROWSER_MEDIA_TEST_LICENSE_SERVER_CONFIG_H_
 
 #include <string>
+#include <vector>
 
+#include "base/environment.h"
 #include "base/macros.h"
+#include "base/optional.h"
 
 namespace base {
 class CommandLine;
@@ -28,6 +31,10 @@
   // server with needed args and switches.
   virtual bool GetServerCommandLine(base::CommandLine* command_line) = 0;
 
+  // Returns the environment map to apply to the server, or base::nullopt on
+  // error.
+  virtual base::Optional<base::EnvironmentMap> GetServerEnvironment() = 0;
+
   // Returns true if the server is supported on current platform.
   virtual bool IsPlatformSupported() = 0;
 
diff --git a/chrome/browser/media/wv_test_license_server_config.cc b/chrome/browser/media/wv_test_license_server_config.cc
index f8d3b1f..d9c64b0 100644
--- a/chrome/browser/media/wv_test_license_server_config.cc
+++ b/chrome/browser/media/wv_test_license_server_config.cc
@@ -45,14 +45,6 @@
     return false;
   }
 
-  // Add the Python protocol buffers files directory to Python path.
-  base::FilePath pyproto_dir;
-  if (!GetPyProtoPath(&pyproto_dir)) {
-    DVLOG(0) << "Cannot find pyproto directory required by license server.";
-    return false;
-  }
-  AppendToPythonPath(pyproto_dir);
-
   base::FilePath license_server_path;
   GetLicenseServerPath(&license_server_path);
   if (!base::PathExists(license_server_path)) {
@@ -101,6 +93,20 @@
   return true;
 }
 
+base::Optional<base::EnvironmentMap>
+WVTestLicenseServerConfig::GetServerEnvironment() {
+  // Add the Python protocol buffers files directory to Python path.
+  base::FilePath pyproto_dir;
+  if (!GetPyProtoPath(&pyproto_dir)) {
+    DVLOG(0) << "Cannot find pyproto directory required by license server.";
+    return base::nullopt;
+  }
+
+  base::EnvironmentMap map;
+  SetPythonPathInEnvironment({pyproto_dir}, &map);
+  return map;
+}
+
 bool WVTestLicenseServerConfig::SelectServerPort() {
   // Try all ports within the range of kMinPort to (kMinPort + kPortRangeSize)
   // Instead of starting from kMinPort, use a random port within that range.
diff --git a/chrome/browser/media/wv_test_license_server_config.h b/chrome/browser/media/wv_test_license_server_config.h
index 3bb393e..0c2e11e 100644
--- a/chrome/browser/media/wv_test_license_server_config.h
+++ b/chrome/browser/media/wv_test_license_server_config.h
@@ -24,6 +24,8 @@
 
   bool GetServerCommandLine(base::CommandLine* command_line) override;
 
+  base::Optional<base::EnvironmentMap> GetServerEnvironment() override;
+
   bool IsPlatformSupported() override;
 
  private:
diff --git a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
index 2bf433a2..d966d66 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
@@ -33,7 +33,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/assistant/buildflags.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #endif
 
diff --git a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
index 80888da7..ddee593 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "chromeos/system/statistics_provider.h"
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos.h b/chrome/browser/metrics/perf/profile_provider_chromeos.h
index 07e3c91..66183ec2 100644
--- a/chrome/browser/metrics/perf/profile_provider_chromeos.h
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos.h
@@ -9,7 +9,7 @@
 
 #include "base/time/time.h"
 #include "chrome/browser/sessions/session_restore.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
 
 namespace metrics {
diff --git a/chrome/browser/page_load_metrics/observers/data_use_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/data_use_metrics_observer.cc
index 35119153..809f109d 100644
--- a/chrome/browser/page_load_metrics/observers/data_use_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/data_use_metrics_observer.cc
@@ -24,28 +24,6 @@
 }
 
 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
-DataUseMetricsObserver::OnStart(content::NavigationHandle* navigation_handle,
-                                const GURL& currently_committed_url,
-                                bool started_in_foreground) {
-  currently_in_foreground_ = started_in_foreground;
-  return CONTINUE_OBSERVING;
-}
-
-page_load_metrics::PageLoadMetricsObserver::ObservePolicy
-DataUseMetricsObserver::OnHidden(
-    const page_load_metrics::mojom::PageLoadTiming& timing,
-    const page_load_metrics::PageLoadExtraInfo& extra_info) {
-  currently_in_foreground_ = false;
-  return CONTINUE_OBSERVING;
-}
-
-page_load_metrics::PageLoadMetricsObserver::ObservePolicy
-DataUseMetricsObserver::OnShown() {
-  currently_in_foreground_ = true;
-  return CONTINUE_OBSERVING;
-}
-
-page_load_metrics::PageLoadMetricsObserver::ObservePolicy
 DataUseMetricsObserver::ShouldObserveMimeType(
     const std::string& mime_type) const {
   // Observe all MIME types. We still only use actual data usage, so strange
@@ -69,10 +47,12 @@
     received_data_length += resource->delta_bytes;
     chrome_data_use_measurement->RecordContentTypeMetric(
         resource->mime_type, resource->is_main_frame_resource,
-        currently_in_foreground_, resource->delta_bytes);
+        GetDelegate()->GetVisibilityTracker().currently_in_foreground(),
+        resource->delta_bytes);
   }
   if (!received_data_length)
     return;
   chrome_data_use_measurement->ReportUserTrafficDataUse(
-      currently_in_foreground_, received_data_length);
+      GetDelegate()->GetVisibilityTracker().currently_in_foreground(),
+      received_data_length);
 }
diff --git a/chrome/browser/page_load_metrics/observers/data_use_metrics_observer.h b/chrome/browser/page_load_metrics/observers/data_use_metrics_observer.h
index 7ec6d4c..b4d8dff2 100644
--- a/chrome/browser/page_load_metrics/observers/data_use_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/data_use_metrics_observer.h
@@ -28,13 +28,6 @@
   // page_load_metrics::PageLoadMetricsObserver:
   ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
                          ukm::SourceId source_id) override;
-  ObservePolicy OnStart(content::NavigationHandle* navigation_handle,
-                        const GURL& currently_committed_url,
-                        bool started_in_foreground) override;
-  ObservePolicy OnHidden(
-      const page_load_metrics::mojom::PageLoadTiming& timing,
-      const page_load_metrics::PageLoadExtraInfo& extra_info) override;
-  ObservePolicy OnShown() override;
   void OnResourceDataUseObserved(
       FrameTreeNodeId frame_tree_node_id,
       const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&
@@ -42,8 +35,6 @@
   ObservePolicy ShouldObserveMimeType(
       const std::string& mime_type) const override;
 
-  bool currently_in_foreground_ = false;
-
   SEQUENCE_CHECKER(sequence_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(DataUseMetricsObserver);
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc
index be22091..19c90ae4 100644
--- a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc
@@ -27,7 +27,8 @@
   }
 
   // Don't record anything if the user never saw it.
-  base::TimeDelta foreground_time = GetDelegate()->GetForegroundDuration();
+  base::TimeDelta foreground_time =
+      GetDelegate()->GetVisibilityTracker().GetForegroundDuration();
   if (foreground_time.is_zero())
     return;
 
diff --git a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.cc
index ed9d0a2a..177d673 100644
--- a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.cc
@@ -26,7 +26,7 @@
 
 // Navigation histogram prefixes.
 const char kPageEndReasonPrefix[] = "Security.PageEndReason";
-const char kTimeOnPagePrefix[] = "Security.TimeOnPage";
+const char kTimeOnPagePrefix[] = "Security.TimeOnPage2";
 
 // Security level histograms.
 const char kSecurityLevelOnCommit[] = "Security.SecurityLevel.OnCommit";
@@ -85,8 +85,6 @@
     content::NavigationHandle* navigation_handle,
     const GURL& currently_committed_url,
     bool started_in_foreground) {
-  if (started_in_foreground)
-    OnShown();
   if (engagement_service_) {
     initial_engagement_score_ =
         engagement_service_->GetScore(navigation_handle->GetURL());
@@ -121,24 +119,6 @@
   return CONTINUE_OBSERVING;
 }
 
-page_load_metrics::PageLoadMetricsObserver::ObservePolicy
-SecurityStatePageLoadMetricsObserver::OnHidden(
-    const page_load_metrics::mojom::PageLoadTiming& timing,
-    const page_load_metrics::PageLoadExtraInfo& extra_info) {
-  if (currently_in_foreground_) {
-    foreground_time_ += base::TimeTicks::Now() - last_time_shown_;
-    currently_in_foreground_ = false;
-  }
-  return CONTINUE_OBSERVING;
-}
-
-page_load_metrics::PageLoadMetricsObserver::ObservePolicy
-SecurityStatePageLoadMetricsObserver::OnShown() {
-  last_time_shown_ = base::TimeTicks::Now();
-  currently_in_foreground_ = true;
-  return CONTINUE_OBSERVING;
-}
-
 void SecurityStatePageLoadMetricsObserver::OnComplete(
     const page_load_metrics::mojom::PageLoadTiming& timing,
     const page_load_metrics::PageLoadExtraInfo& extra_info) {
@@ -180,10 +160,10 @@
           kPageEndReasonPrefix, current_security_level_),
       extra_info.page_end_reason, page_load_metrics::PAGE_END_REASON_COUNT);
   base::UmaHistogramCustomTimes(
-      security_state::GetSecurityLevelHistogramName(
-          kTimeOnPagePrefix, current_security_level_),
-      foreground_time_, base::TimeDelta::FromMilliseconds(1),
-      base::TimeDelta::FromHours(1), 100);
+      security_state::GetSecurityLevelHistogramName(kTimeOnPagePrefix,
+                                                    current_security_level_),
+      GetDelegate()->GetVisibilityTracker().GetForegroundDuration(),
+      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100);
   base::UmaHistogramEnumeration(kSecurityLevelOnComplete,
                                 current_security_level_,
                                 security_state::SECURITY_LEVEL_COUNT);
diff --git a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.h
index d93e06a..17b460e2 100644
--- a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.h
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/time/time.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
 #include "components/security_state/core/security_state.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -54,10 +53,6 @@
                         bool started_in_foreground) override;
   ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
                          ukm::SourceId source_id) override;
-  ObservePolicy OnHidden(
-      const page_load_metrics::mojom::PageLoadTiming& timing,
-      const page_load_metrics::PageLoadExtraInfo& extra_info) override;
-  ObservePolicy OnShown() override;
   void OnComplete(
       const page_load_metrics::mojom::PageLoadTiming& timing,
       const page_load_metrics::PageLoadExtraInfo& extra_info) override;
@@ -74,9 +69,6 @@
   security_state::SecurityLevel initial_security_level_ = security_state::NONE;
   security_state::SecurityLevel current_security_level_ = security_state::NONE;
   ukm::SourceId source_id_ = ukm::kInvalidSourceId;
-  bool currently_in_foreground_ = false;
-  base::TimeDelta foreground_time_;
-  base::TimeTicks last_time_shown_;
 
   DISALLOW_COPY_AND_ASSIGN(SecurityStatePageLoadMetricsObserver);
 };
diff --git a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc
index 0c6b7d0..095b86b 100644
--- a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/run_loop.h"
+#include "base/task/post_task.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -377,3 +378,29 @@
           GetPageEndReasonHistogramNameForTesting(security_state::SECURE),
       0);
 }
+
+// Regression test for crbug.com/942326, where foreground duration was not being
+// updated unless the tab was hidden.
+IN_PROC_BROWSER_TEST_F(SecurityStatePageLoadMetricsBrowserTest,
+                       NonZeroForegroundTime) {
+  StartHttpServer();
+  StartHttpsServer(net::EmbeddedTestServer::CERT_OK);
+
+  GURL https_url = https_test_server()->GetURL("/title1.html");
+  ui_test_utils::NavigateToURL(browser(), https_url);
+
+  const base::TimeDelta kMinForegroundTime =
+      base::TimeDelta::FromMilliseconds(10);
+
+  // Ensure that the tab is open for more than 0 ms, even in the face of bots
+  // with bad clocks.
+  base::RunLoop run_loop;
+  base::PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), kMinForegroundTime);
+  run_loop.Run();
+  CloseAllTabs();
+
+  auto samples =
+      histogram_tester()->GetAllSamples("Security.TimeOnPage2.SECURE");
+  EXPECT_EQ(1u, samples.size());
+  EXPECT_LE(kMinForegroundTime.InMilliseconds(), samples.front().min);
+}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer_delegate.h b/chrome/browser/page_load_metrics/page_load_metrics_observer_delegate.h
index 18be6aa..6171fa5 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_observer_delegate.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_observer_delegate.h
@@ -7,6 +7,7 @@
 
 #include "base/optional.h"
 #include "base/time/time.h"
+#include "chrome/browser/scoped_visibility_tracker.h"
 
 namespace content {
 class WebContents;
@@ -19,9 +20,7 @@
   virtual content::WebContents* GetWebContents() const = 0;
   virtual base::TimeTicks GetNavigationStart() const = 0;
   virtual bool DidCommit() const = 0;
-
-  // Get the amount of time the page has been in the foreground.
-  virtual base::TimeDelta GetForegroundDuration() const = 0;
+  virtual const ScopedVisibilityTracker& GetVisibilityTracker() const = 0;
 
   // TODO(crbug/939403): Consider migrating PageLoadExtraInfo data to this API
   // and deprecating that struct.
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc
index 0d2a431..3b0d8ea 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.cc
+++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -728,8 +728,8 @@
   return did_commit_;
 }
 
-base::TimeDelta PageLoadTracker::GetForegroundDuration() const {
-  return visibility_tracker_.GetForegroundDuration();
+const ScopedVisibilityTracker& PageLoadTracker::GetVisibilityTracker() const {
+  return visibility_tracker_;
 }
 
 }  // namespace page_load_metrics
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.h b/chrome/browser/page_load_metrics/page_load_tracker.h
index 1d2966d..8b26e93b 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.h
+++ b/chrome/browser/page_load_metrics/page_load_tracker.h
@@ -197,7 +197,7 @@
   content::WebContents* GetWebContents() const override;
   base::TimeTicks GetNavigationStart() const override;
   bool DidCommit() const override;
-  base::TimeDelta GetForegroundDuration() const override;
+  const ScopedVisibilityTracker& GetVisibilityTracker() const override;
 
   void Redirect(content::NavigationHandle* navigation_handle);
   void WillProcessNavigationResponse(
diff --git a/chrome/browser/performance_manager/browser_child_process_watcher.cc b/chrome/browser/performance_manager/browser_child_process_watcher.cc
index cb95e85..1c8edaa 100644
--- a/chrome/browser/performance_manager/browser_child_process_watcher.cc
+++ b/chrome/browser/performance_manager/browser_child_process_watcher.cc
@@ -49,9 +49,14 @@
     const content::ChildProcessData& data) {
   if (data.process_type == content::PROCESS_TYPE_GPU) {
     auto it = gpu_process_nodes_.find(data.id);
-    DCHECK(it != gpu_process_nodes_.end());
-    PerformanceManager::GetInstance()->DeleteNode(std::move(it->second));
-    gpu_process_nodes_.erase(it);
+    // Apparently there are cases where a disconnect notification arrives here
+    // either multiple times for the same process, or else before a
+    // launch-and-connect notification arrives.
+    // See https://crbug.com/942500.
+    if (it != gpu_process_nodes_.end()) {
+      PerformanceManager::GetInstance()->DeleteNode(std::move(it->second));
+      gpu_process_nodes_.erase(it);
+    }
   }
 }
 
diff --git a/chrome/browser/platform_util_chromeos.cc b/chrome/browser/platform_util_chromeos.cc
index 700049c..2fd7423 100644
--- a/chrome/browser/platform_util_chromeos.cc
+++ b/chrome/browser/platform_util_chromeos.cc
@@ -14,9 +14,10 @@
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/simple_message_box.h"
-#include "chrome/grit/generated_resources.h"
+#include "chromeos/strings/grit/chromeos_strings.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 #include "url/gurl.h"
 
 using content::BrowserThread;
diff --git a/chrome/browser/platform_util_linux.cc b/chrome/browser/platform_util_linux.cc
index ed9d182..9fb1a7a 100644
--- a/chrome/browser/platform_util_linux.cc
+++ b/chrome/browser/platform_util_linux.cc
@@ -42,7 +42,7 @@
   // to a command that needs a terminal.  Set the environment variable telling
   // it that we definitely don't have a terminal available and that it should
   // bring up a new terminal if necessary.  See "man mailcap".
-  options.environ["MM_NOTTTY"] = "1";
+  options.environment["MM_NOTTTY"] = "1";
 
   // In Google Chrome, we do not let GNOME's bug-buddy intercept our crashes.
   // However, we do not want this environment variable to propagate to external
@@ -50,7 +50,7 @@
   char* disable_gnome_bug_buddy = getenv("GNOME_DISABLE_CRASH_DIALOG");
   if (disable_gnome_bug_buddy &&
       disable_gnome_bug_buddy == std::string("SET_BY_GOOGLE_CHROME"))
-    options.environ["GNOME_DISABLE_CRASH_DIALOG"] = std::string();
+    options.environment["GNOME_DISABLE_CRASH_DIALOG"] = std::string();
 
   base::Process process = base::LaunchProcess(argv, options);
   if (process.IsValid())
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 80be873..5fc3410 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -88,7 +88,7 @@
 #include "chrome/browser/policy/printing_restrictions_policy_handler.h"
 #include "chrome/common/chrome_features.h"
 #include "chromeos/constants/chromeos_pref_names.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/services/multidevice_setup/public/cpp/prefs.h"
 #include "components/arc/arc_prefs.h"
 #include "components/drive/drive_pref_names.h"
@@ -727,6 +727,15 @@
   { key::kVoiceInteractionHotwordEnabled,
     arc::prefs::kVoiceInteractionHotwordEnabled,
     base::Value::Type::BOOLEAN },
+  { key::kDevicePowerPeakShiftEnabled,
+    ash::prefs::kDevicePowerPeakShiftEnabled,
+    base::Value::Type::BOOLEAN },
+  { key::kDevicePowerPeakShiftBatteryThreshold,
+    ash::prefs::kDevicePowerPeakShiftBatteryThreshold,
+    base::Value::Type::INTEGER },
+  { key::kDevicePowerPeakShiftDayConfig,
+    ash::prefs::kDevicePowerPeakShiftDayConfig,
+    base::Value::Type::DICTIONARY },
 #endif  // defined(OS_CHROMEOS)
 
 // Metrics reporting is controlled by a platform specific policy for ChromeOS
diff --git a/chrome/browser/policy/test/local_policy_test_server.cc b/chrome/browser/policy/test/local_policy_test_server.cc
index bf0df74..40d6232 100644
--- a/chrome/browser/policy/test/local_policy_test_server.cc
+++ b/chrome/browser/policy/test/local_policy_test_server.cc
@@ -203,27 +203,29 @@
   return GetURL("device_management");
 }
 
-bool LocalPolicyTestServer::SetPythonPath() const {
+base::Optional<std::vector<base::FilePath>>
+LocalPolicyTestServer::GetPythonPath() const {
   base::ScopedAllowBlockingForTesting allow_blocking;
-  if (!net::LocalTestServer::SetPythonPath())
-    return false;
+  base::Optional<std::vector<base::FilePath>> ret =
+      net::LocalTestServer::GetPythonPath();
+  if (!ret)
+    return base::nullopt;
 
   // Add the net/tools/testserver directory to the path.
   base::FilePath net_testserver_path;
   if (!LocalTestServer::GetTestServerPath(&net_testserver_path)) {
     LOG(ERROR) << "Failed to get net testserver path.";
-    return false;
+    return base::nullopt;
   }
-  AppendToPythonPath(net_testserver_path.DirName());
+  ret->push_back(net_testserver_path.DirName());
 
   // We need protobuf python bindings.
   base::FilePath third_party_dir;
   if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &third_party_dir)) {
     LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT";
-    return false;
+    return base::nullopt;
   }
-  AppendToPythonPath(third_party_dir
-                     .AppendASCII("third_party")
+  ret->push_back(third_party_dir.AppendASCII("third_party")
                      .AppendASCII("protobuf")
                      .AppendASCII("python"));
 
@@ -231,23 +233,21 @@
   base::FilePath pyproto_dir;
   if (!GetPyProtoPath(&pyproto_dir)) {
     LOG(ERROR) << "Cannot find pyproto dir for generated code.";
-    return false;
+    return base::nullopt;
   }
 
-  AppendToPythonPath(pyproto_dir
-                     .AppendASCII("components")
+  ret->push_back(pyproto_dir.AppendASCII("components")
                      .AppendASCII("policy")
                      .AppendASCII("proto"));
 #if defined(OS_CHROMEOS)
-  AppendToPythonPath(pyproto_dir
-                     .AppendASCII("chrome")
+  ret->push_back(pyproto_dir.AppendASCII("chrome")
                      .AppendASCII("browser")
                      .AppendASCII("chromeos")
                      .AppendASCII("policy")
                      .AppendASCII("proto"));
 #endif
 
-  return true;
+  return ret;
 }
 
 bool LocalPolicyTestServer::GetTestServerPath(
diff --git a/chrome/browser/policy/test/local_policy_test_server.h b/chrome/browser/policy/test/local_policy_test_server.h
index 6eaff86..4c098c4 100644
--- a/chrome/browser/policy/test/local_policy_test_server.h
+++ b/chrome/browser/policy/test/local_policy_test_server.h
@@ -90,7 +90,7 @@
   GURL GetServiceURL() const;
 
   // net::LocalTestServer:
-  bool SetPythonPath() const override;
+  base::Optional<std::vector<base::FilePath>> GetPythonPath() const override;
   bool GetTestServerPath(base::FilePath* testserver_path) const override;
   bool GenerateAdditionalArguments(
       base::DictionaryValue* arguments) const override;
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 89b9888..7634601 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -115,6 +115,20 @@
       defines += [ "enable_hangout_services_extension" ]
     }
 
+    if (is_chromeos) {
+      # The .grd contains references to generated files.
+      source_is_generated = true
+
+      deps = [
+        "//chrome/browser/resources/chromeos/kiosk_next_home:mojom_bin",
+      ]
+
+      grit_flags = [
+        "-E",
+        "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+      ]
+    }
+
     outputs = [
       "grit/component_extension_resources.h",
       "grit/component_extension_resources_map.cc",
diff --git a/chrome/browser/resources/chromeos/kiosk_next_home/BUILD.gn b/chrome/browser/resources/chromeos/kiosk_next_home/BUILD.gn
index 6d2aa6f..9d5a109 100644
--- a/chrome/browser/resources/chromeos/kiosk_next_home/BUILD.gn
+++ b/chrome/browser/resources/chromeos/kiosk_next_home/BUILD.gn
@@ -15,8 +15,15 @@
     "api.js",
     "api_impl.js",
   ]
-  externs_list = [
-    "$externs_path/arc_apps_private.js",
-    "$externs_path/chrome_extensions.js",
+  externs_list = [ "$externs_path/arc_apps_private.js" ]
+  deps = [
+    "//chrome/browser/chromeos/kiosk_next_home/mojom:mojom_js_library_for_compile",
+  ]
+}
+
+js_binary("mojom_bin") {
+  sources = []
+  deps = [
+    "//chrome/browser/chromeos/kiosk_next_home/mojom:mojom_js_library_for_compile",
   ]
 }
diff --git a/chrome/browser/resources/chromeos/kiosk_next_home/api_impl.js b/chrome/browser/resources/chromeos/kiosk_next_home/api_impl.js
index 9b07289..a1b8a05 100644
--- a/chrome/browser/resources/chromeos/kiosk_next_home/api_impl.js
+++ b/chrome/browser/resources/chromeos/kiosk_next_home/api_impl.js
@@ -9,8 +9,18 @@
 /** @implements {kioskNextHome.Bridge} */
 class KioskNextHomeBridge {
   constructor() {
-    /** @type {!Array<!kioskNextHome.Listener>} */
-    this.listeners = [];
+    /**
+     * @private
+     * @const {!Array<!kioskNextHome.Listener>}
+     */
+    this.listeners_ = [];
+    /** @private */
+    this.identityAccessorProxy_ = new identity.mojom.IdentityAccessorProxy();
+
+    const kioskNextHomeInterfaceBrokerProxy =
+        chromeos.kioskNextHome.mojom.KioskNextHomeInterfaceBroker.getProxy();
+    kioskNextHomeInterfaceBrokerProxy.getIdentityAccessor(
+        this.identityAccessorProxy_.$.createRequest());
 
     chrome.arcAppsPrivate.onInstalled.addListener(installedApp => {
       const app = {
@@ -20,7 +30,7 @@
         suspended: false,
         thumbnailImage: '',
       };
-      for (const listener of this.listeners) {
+      for (const listener of this.listeners_) {
         listener.onInstalledAppChanged(
             app, kioskNextHome.AppEventType.INSTALLED);
       }
@@ -29,20 +39,23 @@
 
   /** @override */
   addListener(listener) {
-    this.listeners.push(listener);
+    this.listeners_.push(listener);
   }
 
   /** @override */
   getAccessToken(scopes) {
-    return new Promise((resolve, reject) => {
-      chrome.identity.getAuthToken({'scopes': scopes}, token => {
-        if (token) {
-          resolve(token);
-        } else {
-          reject('Unable to get access token.');
-        }
-      });
-    });
+    return this.identityAccessorProxy_.getPrimaryAccountInfo()
+        .then(account => {
+          return this.identityAccessorProxy_.getAccessToken(
+              account.accountInfo.accountId, {'scopes': scopes},
+              'kiosk_next_home');
+        })
+        .then(tokenInfo => {
+          if (tokenInfo.token) {
+            return tokenInfo.token;
+          }
+          throw 'Unable to get access token.';
+        });
   }
 
   /** @override */
diff --git a/chrome/browser/resources/chromeos/kiosk_next_home/kiosk_next_resources.grdp b/chrome/browser/resources/chromeos/kiosk_next_home/kiosk_next_resources.grdp
index 2af207ab..f78d19c 100644
--- a/chrome/browser/resources/chromeos/kiosk_next_home/kiosk_next_resources.grdp
+++ b/chrome/browser/resources/chromeos/kiosk_next_home/kiosk_next_resources.grdp
@@ -6,4 +6,5 @@
   <include name="IDR_KIOSK_NEXT_MAIN_HTML" file="chromeos/kiosk_next_home/main.html" type="chrome_html" />
   <include name="IDR_KIOSK_NEXT_API_JS" file="chromeos/kiosk_next_home/api.js" type="BINDATA" />
   <include name="IDR_KIOSK_NEXT_API_IMPL_JS" file="chromeos/kiosk_next_home/api_impl.js" type="BINDATA" />
+  <include name="IDR_KIOSK_NEXT_HOME_MOJOM_JS" file="${root_gen_dir}/chrome/browser/resources/chromeos/kiosk_next_home/mojom_bin.js" type="BINDATA" use_base_dir="false" />
 </grit-part>
diff --git a/chrome/browser/resources/chromeos/kiosk_next_home/main.html b/chrome/browser/resources/chromeos/kiosk_next_home/main.html
index e3e13d4..eeb6aa1 100644
--- a/chrome/browser/resources/chromeos/kiosk_next_home/main.html
+++ b/chrome/browser/resources/chromeos/kiosk_next_home/main.html
@@ -1,5 +1,8 @@
 <!doctype html>
 <head>
+  <script src="kiosk_next_home.mojom.js"></script>
+  <script src="api.js"></script>
+  <script src="api_impl.js"></script>
 </head>
 <body>
   <div>
diff --git a/chrome/browser/resources/chromeos/kiosk_next_home/manifest.json b/chrome/browser/resources/chromeos/kiosk_next_home/manifest.json
index c9c1d25d..17a6579 100644
--- a/chrome/browser/resources/chromeos/kiosk_next_home/manifest.json
+++ b/chrome/browser/resources/chromeos/kiosk_next_home/manifest.json
@@ -10,8 +10,7 @@
   },
   "permissions": [
     "arcAppsPrivate",
-    "https://*.googleapis.com",
-    "identity"
+    "https://*.googleapis.com"
   ],
   "app": {
     "background": {
diff --git a/chrome/browser/resources/pdf/index.html b/chrome/browser/resources/pdf/index.html
index 71b5d84..c1c3627 100644
--- a/chrome/browser/resources/pdf/index.html
+++ b/chrome/browser/resources/pdf/index.html
@@ -2,6 +2,8 @@
 <html>
 <head>
   <meta charset="utf-8">
+  <script src="chrome://resources/polymer/v1_0/html-imports/html-imports.min.js">
+  </script>
   <link rel="import" href="elements/viewer-error-screen/viewer-error-screen.html">
   <link rel="import" href="elements/viewer-page-indicator/viewer-page-indicator.html">
   <link rel="import" href="elements/viewer-page-selector/viewer-page-selector.html">
diff --git a/chrome/browser/resources/pdf/main.js b/chrome/browser/resources/pdf/main.js
index ae29c59..9d3f533 100644
--- a/chrome/browser/resources/pdf/main.js
+++ b/chrome/browser/resources/pdf/main.js
@@ -73,14 +73,16 @@
   // Set up an event listener to catch scripting messages which are sent prior
   // to the PDFViewer being created.
   window.addEventListener('message', handleScriptingMessage, false);
-  let chain = createBrowserApi();
+  HTMLImports.whenReady(() => {
+    let chain = createBrowserApi();
 
-  // Content settings may not be present in test environments.
-  if (chrome.contentSettings) {
-    chain = chain.then(configureJavaScriptContentSetting);
-  }
+    // Content settings may not be present in test environments.
+    if (chrome.contentSettings) {
+      chain = chain.then(configureJavaScriptContentSetting);
+    }
 
-  chain.then(initViewer);
+    chain = chain.then(initViewer);
+  });
 }
 
 main();
diff --git a/chrome/browser/resources/print_preview/new/model.js b/chrome/browser/resources/print_preview/new/model.js
index 3dc1f34..1026abd 100644
--- a/chrome/browser/resources/print_preview/new/model.js
+++ b/chrome/browser/resources/print_preview/new/model.js
@@ -426,7 +426,9 @@
 
     // <if expr="chromeos">
     this.set(
-        'settings.pin.available', !!caps && !!caps.pin && !!caps.pin.supported);
+        'settings.pin.available',
+        !!caps && !!caps.pin && !!caps.pin.supported &&
+            loadTimeData.getBoolean('isEnterpriseManaged'));
     // </if>
 
     if (this.documentSettings) {
@@ -783,6 +785,9 @@
     this.set('settings.duplex.setByPolicy', !!duplexPolicy);
 
     const pinPolicy = this.destination.pinPolicy;
+    if (pinPolicy == print_preview.PinModeRestriction.UNSECURE) {
+      this.set('settings.pin.available', false);
+    }
     const pinValue = pinPolicy ? pinPolicy : this.destination.defaultPinPolicy;
     if (pinValue) {
       this.set(
diff --git a/chrome/browser/scoped_visibility_tracker.h b/chrome/browser/scoped_visibility_tracker.h
index 203222a..90badf9a 100644
--- a/chrome/browser/scoped_visibility_tracker.h
+++ b/chrome/browser/scoped_visibility_tracker.h
@@ -27,6 +27,8 @@
 
   base::TimeDelta GetForegroundDuration() const;
 
+  bool currently_in_foreground() const { return currently_in_foreground_; }
+
  private:
   void Update(bool in_foreground);
 
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index fb026f3..2b4c00c 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -80,9 +80,6 @@
 // unpacked on the filesystem.)
 const char kDefaultThemeGalleryID[] = "hkacjpbfdknhflllbcmjibkdeoafencn";
 
-// Theme ID to use for autogenerated themes.
-const char kAutogeneratedThemeID[] = "autogenerated";
-
 // Wait this many seconds after startup to garbage collect unused themes.
 // Removing unused themes is done after a delay because there is no
 // reason to do it at startup.
@@ -339,13 +336,16 @@
   // there.
   const base::CommandLine* command_line =
       base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch("chrome-colors-r") &&
-      command_line->HasSwitch("chrome-colors-g") &&
-      command_line->HasSwitch("chrome-colors-b")) {
+  if (command_line->HasSwitch("install-colors-r") &&
+      command_line->HasSwitch("install-colors-g") &&
+      command_line->HasSwitch("install-colors-b")) {
     int r, g, b;
-    base::StringToInt(command_line->GetSwitchValueASCII("chrome-colors-r"), &r);
-    base::StringToInt(command_line->GetSwitchValueASCII("chrome-colors-g"), &g);
-    base::StringToInt(command_line->GetSwitchValueASCII("chrome-colors-b"), &b);
+    base::StringToInt(command_line->GetSwitchValueASCII("install-colors-r"),
+                      &r);
+    base::StringToInt(command_line->GetSwitchValueASCII("install-colors-g"),
+                      &g);
+    base::StringToInt(command_line->GetSwitchValueASCII("install-colors-b"),
+                      &b);
     BuildFromColor(SkColorSetRGB(r, g, b));
   }
 }
@@ -376,15 +376,19 @@
   DoSetTheme(extension, true);
 }
 
-void ThemeService::RevertToTheme(const Extension* extension) {
-  DCHECK(extension->is_theme());
-  extensions::ExtensionService* service =
-      extensions::ExtensionSystem::Get(profile_)->extension_service();
-  DCHECK(!service->IsExtensionEnabled(extension->id()));
-  // |extension| is disabled when reverting to the previous theme via an
-  // infobar.
-  service->EnableExtension(extension->id());
-  // Enabling the extension will call back to SetTheme().
+void ThemeService::RevertToExtensionTheme(const std::string& extension_id) {
+  const Extension* extension = extensions::ExtensionRegistry::Get(profile_)
+                                   ->disabled_extensions()
+                                   .GetByID(extension_id);
+  if (extension && extension->is_theme()) {
+    extensions::ExtensionService* service =
+        extensions::ExtensionSystem::Get(profile_)->extension_service();
+    DCHECK(!service->IsExtensionEnabled(extension->id()));
+    // |extension| is disabled when reverting to the previous theme via an
+    // infobar.
+    service->EnableExtension(extension->id());
+    // Enabling the extension will call back to SetTheme().
+  }
 }
 
 void ThemeService::UseDefaultTheme() {
@@ -505,10 +509,47 @@
                    : service->default_theme_provider_;
 }
 
+void ThemeService::BuildFromColor(SkColor color) {
+  scoped_refptr<BrowserThemePack> pack(
+      new BrowserThemePack(CustomThemeSupplier::ThemeType::AUTOGENERATED));
+  BrowserThemePack::BuildFromColor(color, pack.get());
+  SwapThemeSupplier(std::move(pack));
+  if (theme_supplier_) {
+    SetThemePrefsForColor(color);
+    NotifyThemeChanged();
+  }
+}
+
+bool ThemeService::UsingAutogenerated() const {
+  return profile_->GetPrefs()->HasPrefPath(prefs::kAutogeneratedThemeColor);
+}
+
+SkColor ThemeService::GetThemeColor() const {
+  return profile_->GetPrefs()->GetInteger(prefs::kAutogeneratedThemeColor);
+}
+
+base::OnceCallback<void()> ThemeService::GetRevertThemeCallback() {
+  const CustomThemeSupplier* theme_supplier = get_theme_supplier();
+  if (theme_supplier) {
+    const CustomThemeSupplier::ThemeType theme_type =
+        theme_supplier->get_theme_type();
+    if (theme_type == CustomThemeSupplier::ThemeType::EXTENSION) {
+      return base::BindOnce(&ThemeService::RevertToExtensionTheme,
+                            weak_ptr_factory_.GetWeakPtr(), GetThemeID());
+    } else if (theme_type == CustomThemeSupplier::ThemeType::AUTOGENERATED) {
+      return base::BindOnce(&ThemeService::BuildFromColor,
+                            weak_ptr_factory_.GetWeakPtr(), GetThemeColor());
+    }
+  }
+  return base::BindOnce(UsingSystemTheme() ? &ThemeService::UseSystemTheme
+                                           : &ThemeService::UseDefaultTheme,
+                        weak_ptr_factory_.GetWeakPtr());
+}
+
 void ThemeService::SetCustomDefaultTheme(
     scoped_refptr<CustomThemeSupplier> theme_supplier) {
   ClearAllThemeData();
-  SwapThemeSupplier(theme_supplier);
+  SwapThemeSupplier(std::move(theme_supplier));
   NotifyThemeChanged();
 }
 
@@ -615,9 +656,7 @@
     return;
 
   SwapThemeSupplier(nullptr);
-
-  profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename);
-  SaveThemeID(kDefaultThemeID);
+  ClearThemePrefs();
 
   // There should be no more infobars. This may not be the case because of
   // http://crbug.com/62154
@@ -648,6 +687,10 @@
       UseSystemTheme();
     else
       UseDefaultTheme();
+
+    if (UsingAutogenerated())
+      BuildFromColor(GetThemeColor());
+
     set_ready();
     return;
   }
@@ -896,15 +939,6 @@
     theme_supplier_->StartUsingTheme();
 }
 
-void ThemeService::SavePackName(const base::FilePath& pack_path) {
-  profile_->GetPrefs()->SetFilePath(
-      prefs::kCurrentThemePackFilename, pack_path);
-}
-
-void ThemeService::SaveThemeID(const std::string& id) {
-  profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, id);
-}
-
 void ThemeService::BuildFromExtension(const Extension* extension,
                                       bool suppress_infobar) {
   build_extension_task_tracker_.TryCancelAll();
@@ -922,15 +956,6 @@
                  suppress_infobar));
 }
 
-void ThemeService::BuildFromColor(SkColor color) {
-  scoped_refptr<BrowserThemePack> pack(
-      new BrowserThemePack(CustomThemeSupplier::ThemeType::AUTOGENERATED));
-  BrowserThemePack::BuildFromColor(color, pack.get());
-  SwapThemeSupplier(pack);
-  if (theme_supplier_)
-    SaveThemeID(kAutogeneratedThemeID);
-}
-
 void ThemeService::OnThemeBuiltFromExtension(
     const extensions::ExtensionId& extension_id,
     scoped_refptr<BrowserThemePack> pack,
@@ -956,17 +981,10 @@
   extensions::GetExtensionFileTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(&WritePackToDiskCallback,
                                 base::RetainedRef(pack), extension->path()));
-
+  base::OnceClosure callback = ThemeService::GetRevertThemeCallback();
   const std::string previous_theme_id = GetThemeID();
-  const bool previous_using_system_theme = UsingSystemTheme();
-
-  // Save only the extension path. The packed file will be loaded via
-  // LoadThemePrefs().
-  SavePackName(extension->path());
-  SwapThemeSupplier(pack);
-
-  // Clear our image cache.
-  SaveThemeID(extension->id());
+  SwapThemeSupplier(std::move(pack));
+  SetThemePrefsForExtension(extension);
   NotifyThemeChanged();
 
   // Same old theme, but the theme has changed (migrated) or auto-updated.
@@ -1002,9 +1020,8 @@
       if (web_contents) {
         ThemeInstalledInfoBarDelegate::Create(
             InfoBarService::FromWebContents(web_contents),
-            extensions::ExtensionSystem::Get(profile_)->extension_service(),
             ThemeServiceFactory::GetForProfile(profile_), extension->name(),
-            extension->id(), previous_theme_id, previous_using_system_theme);
+            extension->id(), std::move(callback));
       }
     }
   }
@@ -1022,3 +1039,25 @@
   SetCustomDefaultTheme(new SupervisedUserTheme);
 }
 #endif
+
+void ThemeService::ClearThemePrefs() {
+  profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename);
+  profile_->GetPrefs()->ClearPref(prefs::kAutogeneratedThemeColor);
+  profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, kDefaultThemeID);
+}
+
+void ThemeService::SetThemePrefsForExtension(const Extension* extension) {
+  ClearThemePrefs();
+
+  profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, extension->id());
+
+  // Save only the extension path. The packed file will be loaded via
+  // LoadThemePrefs().
+  profile_->GetPrefs()->SetFilePath(prefs::kCurrentThemePackFilename,
+                                    extension->path());
+}
+
+void ThemeService::SetThemePrefsForColor(SkColor color) {
+  ClearThemePrefs();
+  profile_->GetPrefs()->SetInteger(prefs::kAutogeneratedThemeColor, color);
+}
diff --git a/chrome/browser/themes/theme_service.h b/chrome/browser/themes/theme_service.h
index 93358a8..3e09dcb8 100644
--- a/chrome/browser/themes/theme_service.h
+++ b/chrome/browser/themes/theme_service.h
@@ -30,10 +30,6 @@
 class ThemeSyncableService;
 class Profile;
 
-namespace base {
-class FilePath;
-}
-
 namespace color_utils {
 struct HSL;
 }
@@ -78,7 +74,7 @@
   void SetTheme(const extensions::Extension* extension);
 
   // Similar to SetTheme, but doesn't show an undo infobar.
-  void RevertToTheme(const extensions::Extension* extension);
+  void RevertToExtensionTheme(const std::string& extension_id);
 
   // Reset the theme to default.
   virtual void UseDefaultTheme();
@@ -130,6 +126,15 @@
   static const ui::ThemeProvider& GetDefaultThemeProviderForProfile(
       Profile* profile);
 
+  // Builds a theme from a given |color|.
+  void BuildFromColor(SkColor color);
+
+  bool UsingAutogenerated() const;
+  SkColor GetThemeColor() const;
+
+  // Returns callback for reverting to previous theme.
+  base::OnceCallback<void()> GetRevertThemeCallback();
+
  protected:
   // Set a custom default theme instead of the normal default theme.
   virtual void SetCustomDefaultTheme(
@@ -255,21 +260,12 @@
   // StopUsingTheme() or StartUsingTheme() as appropriate.
   void SwapThemeSupplier(scoped_refptr<CustomThemeSupplier> theme_supplier);
 
-  // Saves the filename of the cached theme pack.
-  void SavePackName(const base::FilePath& pack_path);
-
-  // Save the id of the last theme installed.
-  void SaveThemeID(const std::string& id);
-
   // Implementation of SetTheme() (and the fallback from LoadThemePrefs() in
   // case we don't have a theme pack). |new_theme| indicates whether this is a
   // newly installed theme or a migration.
   void BuildFromExtension(const extensions::Extension* extension,
                           bool new_theme);
 
-  // Builds a theme from a given |color|.
-  void BuildFromColor(SkColor color);
-
   // Callback when |pack| has finished or failed building.
   void OnThemeBuiltFromExtension(const extensions::ExtensionId& extension_id,
                                  scoped_refptr<BrowserThemePack> pack,
@@ -284,6 +280,11 @@
   void SetSupervisedUserTheme();
 #endif
 
+  // Functions that modify theme prefs.
+  void ClearThemePrefs();
+  void SetThemePrefsForExtension(const extensions::Extension* extension);
+  void SetThemePrefsForColor(SkColor color);
+
   ui::ResourceBundle& rb_;
   Profile* profile_;
 
diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc
index c128e96..c509ff5 100644
--- a/chrome/browser/themes/theme_service_factory.cc
+++ b/chrome/browser/themes/theme_service_factory.cc
@@ -85,6 +85,8 @@
                                  base::FilePath());
   registry->RegisterStringPref(prefs::kCurrentThemeID,
                                ThemeService::kDefaultThemeID);
+  registry->RegisterIntegerPref(prefs::kAutogeneratedThemeColor, 0);
+
   registry->RegisterDictionaryPref(prefs::kCurrentThemeImages);
   registry->RegisterDictionaryPref(prefs::kCurrentThemeColors);
   registry->RegisterDictionaryPref(prefs::kCurrentThemeTints);
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc
index e661f85d..1c70249 100644
--- a/chrome/browser/themes/theme_service_unittest.cc
+++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -187,12 +187,10 @@
   EXPECT_TRUE(registry_->GetExtensionById(extension2_id,
                                           ExtensionRegistry::DISABLED));
 
-  // 3) Using RevertToTheme() with a disabled theme should enable and set the
-  // theme. This is the case when the user reverts to the previous theme
+  // 3) Using RevertToExtensionTheme() with a disabled theme should enable and
+  // set the theme. This is the case when the user reverts to the previous theme
   // via an infobar.
-  const extensions::Extension* extension2 =
-      service_->GetInstalledExtension(extension2_id);
-  theme_service->RevertToTheme(extension2);
+  theme_service->RevertToExtensionTheme(extension2_id);
   WaitForThemeInstall();
   EXPECT_EQ(extension2_id, theme_service->GetThemeID());
   EXPECT_TRUE(service_->IsExtensionEnabled(extension2_id));
@@ -368,15 +366,39 @@
     EXPECT_EQ(extension2_id, theme_service->GetThemeID());
   }
 
-  auto* extension1 = service_->GetInstalledExtension(extension1_id);
-  ASSERT_TRUE(extension1);
-
   // Check that it is possible to reinstall extension1.
-  ThemeServiceFactory::GetForProfile(profile_.get())->RevertToTheme(extension1);
+  ThemeServiceFactory::GetForProfile(profile_.get())
+      ->RevertToExtensionTheme(extension1_id);
   WaitForThemeInstall();
   EXPECT_EQ(extension1_id, theme_service->GetThemeID());
 }
 
+TEST_F(ThemeServiceTest, BuildFromColorTest) {
+  // Set theme from color.
+  ThemeService* theme_service =
+      ThemeServiceFactory::GetForProfile(profile_.get());
+  theme_service->UseDefaultTheme();
+  EXPECT_FALSE(theme_service->UsingAutogenerated());
+  theme_service->BuildFromColor(SkColorSetRGB(100, 100, 100));
+  EXPECT_TRUE(theme_service->UsingAutogenerated());
+
+  // Set theme from data pack and then override it with theme from color.
+  base::ScopedTempDir temp_dir1;
+  ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
+  const std::string& extension1_id = LoadUnpackedThemeAt(temp_dir1.GetPath());
+  EXPECT_EQ(extension1_id, theme_service->GetThemeID());
+  EXPECT_FALSE(theme_service->UsingAutogenerated());
+  base::FilePath path =
+      profile_->GetPrefs()->GetFilePath(prefs::kCurrentThemePackFilename);
+  EXPECT_FALSE(path.empty());
+
+  theme_service->BuildFromColor(SkColorSetRGB(100, 100, 100));
+  EXPECT_TRUE(theme_service->UsingAutogenerated());
+  EXPECT_EQ(ThemeService::kDefaultThemeID, theme_service->GetThemeID());
+  path = profile_->GetPrefs()->GetFilePath(prefs::kCurrentThemePackFilename);
+  EXPECT_TRUE(path.empty());
+}
+
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
 class ThemeServiceSupervisedUserTest : public ThemeServiceTest {
  public:
@@ -434,7 +456,7 @@
   ASSERT_EQ(extension_id, theme_service->GetThemeID());
   EXPECT_FALSE(profile_->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme));
 }
-#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
-#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
+#endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#endif  // BUILDFLAG(ENABLE_SUPERVISED_USERS)
 
 }  // namespace theme_service_internal
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 9ec6933f..08979fa9 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2079,14 +2079,6 @@
       "cocoa/main_menu_builder.h",
       "cocoa/main_menu_builder.mm",
       "cocoa/main_menu_item.h",
-      "cocoa/media_picker/desktop_media_picker_bridge.h",
-      "cocoa/media_picker/desktop_media_picker_bridge.mm",
-      "cocoa/media_picker/desktop_media_picker_cocoa.h",
-      "cocoa/media_picker/desktop_media_picker_cocoa.mm",
-      "cocoa/media_picker/desktop_media_picker_controller.h",
-      "cocoa/media_picker/desktop_media_picker_controller.mm",
-      "cocoa/media_picker/desktop_media_picker_item.h",
-      "cocoa/media_picker/desktop_media_picker_item.mm",
       "cocoa/native_window_tracker_cocoa.h",
       "cocoa/native_window_tracker_cocoa.mm",
       "cocoa/nsmenuitem_additions.h",
@@ -2470,6 +2462,12 @@
       "views/content_setting_domain_list_view.h",
       "views/cookie_info_view.cc",
       "views/cookie_info_view.h",
+      "views/desktop_capture/desktop_media_list_view.cc",
+      "views/desktop_capture/desktop_media_list_view.h",
+      "views/desktop_capture/desktop_media_picker_views.cc",
+      "views/desktop_capture/desktop_media_picker_views.h",
+      "views/desktop_capture/desktop_media_source_view.cc",
+      "views/desktop_capture/desktop_media_source_view.h",
       "views/device_chooser_content_view.cc",
       "views/device_chooser_content_view.h",
       "views/download/download_danger_prompt_views.cc",
@@ -3088,12 +3086,6 @@
       "views/apps/shaped_app_window_targeter.h",
       "views/color_chooser_aura.cc",
       "views/color_chooser_aura.h",
-      "views/desktop_capture/desktop_media_list_view.cc",
-      "views/desktop_capture/desktop_media_list_view.h",
-      "views/desktop_capture/desktop_media_picker_views.cc",
-      "views/desktop_capture/desktop_media_picker_views.h",
-      "views/desktop_capture/desktop_media_source_view.cc",
-      "views/desktop_capture/desktop_media_source_view.h",
       "views/dropdown_bar_host_aura.cc",
       "views/frame/browser_non_client_frame_view_factory_chromeos.cc",
       "views/ime/ime_window_frame_view.cc",
diff --git a/chrome/browser/ui/ash/assistant/device_actions.cc b/chrome/browser/ui/ash/assistant/device_actions.cc
index b52eea7..8101f0b 100644
--- a/chrome/browser/ui/ash/assistant/device_actions.cc
+++ b/chrome/browser/ui/ash/assistant/device_actions.cc
@@ -12,8 +12,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service_manager.h"
diff --git a/chrome/browser/ui/ash/session_controller_client.cc b/chrome/browser/ui/ash/session_controller_client.cc
index 22b170c..3de5f90 100644
--- a/chrome/browser/ui/ash/session_controller_client.cc
+++ b/chrome/browser/ui/ash/session_controller_client.cc
@@ -311,6 +311,18 @@
   }
 }
 
+void SessionControllerClient::EmitAshInitialized() {
+  // Emit the ash-initialized upstart signal to start Chrome OS tasks that
+  // expect that Ash is listening to D-Bus signals they emit. For example,
+  // hammerd, which handles detachable base state, communicates the base state
+  // purely by emitting D-Bus signals, and thus has to be run whenever Ash is
+  // started so Ash (DetachableBaseHandler in particular) gets the proper view
+  // of the current detachable base state.
+  chromeos::DBusThreadManager::Get()
+      ->GetSessionManagerClient()
+      ->EmitAshInitialized();
+}
+
 // static
 bool SessionControllerClient::IsMultiProfileAvailable() {
   if (!profiles::IsMultipleProfilesEnabled() || !UserManager::IsInitialized())
diff --git a/chrome/browser/ui/ash/session_controller_client.h b/chrome/browser/ui/ash/session_controller_client.h
index 08f7a14..fb0dfa01 100644
--- a/chrome/browser/ui/ash/session_controller_client.h
+++ b/chrome/browser/ui/ash/session_controller_client.h
@@ -79,6 +79,7 @@
   void SwitchActiveUser(const AccountId& account_id) override;
   void CycleActiveUser(ash::CycleUserDirection direction) override;
   void ShowMultiProfileLogin() override;
+  void EmitAshInitialized() override;
 
   // Returns true if a multi-profile user can be added to the session or if
   // multiple users are already signed in.
diff --git a/chrome/browser/ui/ash/test_login_screen.cc b/chrome/browser/ui/ash/test_login_screen.cc
index 9208a6d6..a4d4b24 100644
--- a/chrome/browser/ui/ash/test_login_screen.cc
+++ b/chrome/browser/ui/ash/test_login_screen.cc
@@ -78,10 +78,11 @@
 void TestLoginScreen::SetAvatarForUser(const AccountId& account_id,
                                        ::ash::mojom::UserAvatarPtr avatar) {}
 
-void TestLoginScreen::SetAuthEnabledForUser(
+void TestLoginScreen::EnableAuthForUser(const AccountId& account_id) {}
+
+void TestLoginScreen::DisableAuthForUser(
     const AccountId& account_id,
-    bool is_enabled,
-    base::Optional<base::Time> auth_reenabled_time) {}
+    ash::mojom::AuthDisabledDataPtr auth_disabled_data) {}
 
 void TestLoginScreen::HandleFocusLeavingLockScreenApps(bool reverse) {}
 
diff --git a/chrome/browser/ui/ash/test_login_screen.h b/chrome/browser/ui/ash/test_login_screen.h
index df917695..6d4c9ba 100644
--- a/chrome/browser/ui/ash/test_login_screen.h
+++ b/chrome/browser/ui/ash/test_login_screen.h
@@ -52,10 +52,10 @@
                                    bool successful) override;
   void SetAvatarForUser(const AccountId& account_id,
                         ::ash::mojom::UserAvatarPtr avatar) override;
-  void SetAuthEnabledForUser(
+  void EnableAuthForUser(const AccountId& account_id) override;
+  void DisableAuthForUser(
       const AccountId& account_id,
-      bool is_enabled,
-      base::Optional<base::Time> auth_reenabled_time) override;
+      ash::mojom::AuthDisabledDataPtr auth_disabled_data) override;
   void HandleFocusLeavingLockScreenApps(bool reverse) override;
   void SetSystemInfo(bool show_if_hidden,
                      const std::string& os_version_label_text,
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.h b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.h
deleted file mode 100644
index 6d9e336..0000000
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2013 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 CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_BRIDGE_H_
-#define CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_BRIDGE_H_
-
-#include "base/macros.h"
-#include "chrome/browser/media/webrtc/desktop_media_list.h"
-#include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
-
-// Protocol corresponding to |DesktopMediaListObserver|.
-@protocol DesktopMediaPickerObserver
-- (void)sourceAddedForList:(DesktopMediaList*)list atIndex:(int)index;
-- (void)sourceRemovedForList:(DesktopMediaList*)list atIndex:(int)index;
-- (void)sourceMovedForList:(DesktopMediaList*)list
-                      from:(int)oldIndex
-                        to:(int)newIndex;
-- (void)sourceNameChangedForList:(DesktopMediaList*)list atIndex:(int)index;
-- (void)sourceThumbnailChangedForList:(DesktopMediaList*)list
-                              atIndex:(int)index;
-@end
-
-// Provides a |DesktopMediaListObserver| implementation that forwards
-// notifications to a objective-c object implementing the
-// |DesktopMediaPickerObserver| protocol.
-class DesktopMediaPickerBridge : public DesktopMediaListObserver {
- public:
-  DesktopMediaPickerBridge(id<DesktopMediaPickerObserver> observer);
-  ~DesktopMediaPickerBridge() override;
-
-  // DesktopMediaListObserver overrides.
-  void OnSourceAdded(DesktopMediaList* list, int index) override;
-  void OnSourceRemoved(DesktopMediaList* list, int index) override;
-  void OnSourceMoved(DesktopMediaList* list,
-                     int old_index,
-                     int new_index) override;
-  void OnSourceNameChanged(DesktopMediaList* list, int index) override;
-  void OnSourceThumbnailChanged(DesktopMediaList* list, int index) override;
-
- private:
-  id<DesktopMediaPickerObserver> observer_;  // weak; owns this
-
-  DISALLOW_COPY_AND_ASSIGN(DesktopMediaPickerBridge);
-};
-
-#endif  // CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.mm
deleted file mode 100644
index 9b47b2b..0000000
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.mm
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2013 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.
-
-#import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.h"
-
-DesktopMediaPickerBridge::DesktopMediaPickerBridge(
-    id<DesktopMediaPickerObserver> observer)
-    : observer_(observer) {
-}
-
-DesktopMediaPickerBridge::~DesktopMediaPickerBridge() {
-}
-
-void DesktopMediaPickerBridge::OnSourceAdded(DesktopMediaList* list,
-                                             int index) {
-  [observer_ sourceAddedForList:list atIndex:index];
-}
-
-void DesktopMediaPickerBridge::OnSourceRemoved(DesktopMediaList* list,
-                                               int index) {
-  [observer_ sourceRemovedForList:list atIndex:index];
-}
-
-void DesktopMediaPickerBridge::OnSourceMoved(DesktopMediaList* list,
-                                             int old_index,
-                                             int new_index) {
-  [observer_ sourceMovedForList:list from:old_index to:new_index];
-}
-
-void DesktopMediaPickerBridge::OnSourceNameChanged(DesktopMediaList* list,
-                                                   int index) {
-  [observer_ sourceNameChangedForList:list atIndex:index];
-}
-
-void DesktopMediaPickerBridge::OnSourceThumbnailChanged(DesktopMediaList* list,
-                                                        int index) {
-  [observer_ sourceThumbnailChangedForList:list atIndex:index];
-}
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.h b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.h
deleted file mode 100644
index 36da5ea5..0000000
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2013 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 CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_COCOA_H_
-#define CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_COCOA_H_
-
-#include <memory>
-
-#import "base/mac/scoped_nsobject.h"
-#include "chrome/browser/media/webrtc/desktop_media_picker.h"
-
-@class DesktopMediaPickerController;
-
-// Cocoa's DesktopMediaPicker implementation.
-class DesktopMediaPickerCocoa : public DesktopMediaPicker {
- public:
-  DesktopMediaPickerCocoa();
-  ~DesktopMediaPickerCocoa() override;
-
-  // Overridden from DesktopMediaPicker:
-  void Show(const DesktopMediaPicker::Params& params,
-            std::vector<std::unique_ptr<DesktopMediaList>> source_lists,
-            const DoneCallback& done_callback) override;
-
- private:
-  base::scoped_nsobject<DesktopMediaPickerController> controller_;
-};
-
-#endif  // CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_COCOA_H_
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.mm
deleted file mode 100644
index e89714e..0000000
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.mm
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 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 "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.h"
-
-#include <utility>
-
-#import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h"
-
-DesktopMediaPickerCocoa::DesktopMediaPickerCocoa() {
-}
-
-DesktopMediaPickerCocoa::~DesktopMediaPickerCocoa() {
-}
-
-void DesktopMediaPickerCocoa::Show(
-    const DesktopMediaPicker::Params& params,
-    std::vector<std::unique_ptr<DesktopMediaList>> source_lists,
-    const DoneCallback& done_callback) {
-  controller_.reset([[DesktopMediaPickerController alloc]
-      initWithSourceLists:std::move(source_lists)
-                 callback:done_callback
-                   params:params]);
-  [controller_ showWindow:nil];
-}
-
-// static
-std::unique_ptr<DesktopMediaPicker> DesktopMediaPicker::Create() {
-  return std::unique_ptr<DesktopMediaPicker>(new DesktopMediaPickerCocoa());
-}
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h
deleted file mode 100644
index 6ad7c93..0000000
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2013 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 CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_CONTROLLER_H_
-
-#import <Cocoa/Cocoa.h>
-#import <Quartz/Quartz.h>
-
-#include <memory>
-
-#include "base/callback.h"
-#import "base/mac/scoped_nsobject.h"
-#include "base/strings/string16.h"
-#include "chrome/browser/media/webrtc/desktop_media_list.h"
-#include "chrome/browser/media/webrtc/desktop_media_picker.h"
-#import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_bridge.h"
-
-// A controller for the Desktop Media Picker. Presents the user with a list of
-// media sources for screen-capturing, and reports the result.
-@interface DesktopMediaPickerController
-    : NSWindowController<NSWindowDelegate,
-                         DesktopMediaPickerObserver,
-                         NSTableViewDataSource,
-                         NSTableViewDelegate> {
- @private
-  // The image browser view or table view to present sources to the user
-  // (thumbnails and names).
-  base::scoped_nsobject<IKImageBrowserView> screenBrowser_;
-  base::scoped_nsobject<IKImageBrowserView> windowBrowser_;
-  base::scoped_nsobject<NSTableView> tabBrowser_;
-
-  base::scoped_nsobject<NSScrollView> imageBrowserScroll_;
-
-  base::scoped_nsobject<NSSegmentedControl> sourceTypeControl_;
-
-  // The button used to confirm the selection.
-  NSButton* shareButton_;  // weak; owned by contentView
-
-  // The button used to cancel and close the dialog.
-  NSButton* cancelButton_;  // weak; owned by contentView
-
-  // The checkbox for audio share.
-  base::scoped_nsobject<NSButton> audioShareCheckbox_;
-
-  // Provides source information (including thumbnails) to fill up the array of
-  // |screenItems_|, |windowItems_| and |tabItems_|, and to render in
-  // |screenBrowser_|, |windowBrowser_| and |tabBrowser_|.
-  std::vector<std::unique_ptr<DesktopMediaList>> sourceLists_;
-
-  // To be called with the user selection.
-  DesktopMediaPicker::DoneCallback doneCallback_;
-
-  // Arrays of |DesktopMediaPickerItem| used as data for |screenBrowser_|,
-  // |windowBrowser_| and |tabBrowser_|.
-  base::scoped_nsobject<NSMutableArray> screenItems_;
-  base::scoped_nsobject<NSMutableArray> windowItems_;
-  base::scoped_nsobject<NSMutableArray> tabItems_;
-
-  // C++ bridge to use as an observer to |screenList_|, |windowList_| and
-  // |tabList_|, that forwards obj-c notifications to this object.
-  std::unique_ptr<DesktopMediaPickerBridge> bridge_;
-
-  // Used to create |DesktopMediaPickerItem|s with unique IDs.
-  int lastImageUID_;
-}
-
-// Designated initializer.
-// To show the dialog, use |NSWindowController|'s |showWindow:|.
-// |callback| will be called to report the user's selection.
-// |params| will be used to customize the dialog. |params.app_name| will be used
-// to format the dialog's title and the label, where it appears as the initiator
-// of the request. |params.target_name| will be used to format the dialog's
-// label and appear as the consumer of the requested stream.
-- (id)initWithSourceLists:
-          (std::vector<std::unique_ptr<DesktopMediaList>>)sourceLists
-                 callback:(const DesktopMediaPicker::DoneCallback&)callback
-                   params:(const DesktopMediaPicker::Params&)params;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
deleted file mode 100644
index 4529359..0000000
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
+++ /dev/null
@@ -1,846 +0,0 @@
-// Copyright 2013 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.
-
-#import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#import "base/mac/bundle_locations.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/task/post_task.h"
-#include "chrome/browser/media/webrtc/desktop_media_list.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_window.h"
-#import "chrome/browser/ui/cocoa/key_equivalent_constants.h"
-#import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
-#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-#import "ui/base/cocoa/flipped_view.h"
-#import "ui/base/cocoa/window_size_constants.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/image/image_skia_util_mac.h"
-
-using content::DesktopMediaID;
-
-namespace {
-
-const CGFloat kDesktopMediaPickerInitialContentWidth = 620;
-const CGFloat kDesktopMediaPickerMinimumContentWidth = 500;
-const CGFloat kDesktopMediaPickerMinimumContentHeight = 390;
-const CGFloat kDesktopMediaPickerThumbnailWidth = 150;
-const CGFloat kDesktopMediaPickerThumbnailHeight = 150;
-const CGFloat kDesktopMediaPickerSingleScreenWidth = 300;
-const CGFloat kDesktopMediaPickerSingleScreenHeight = 300;
-const CGFloat kDesktopMediaPickerMultipleScreenWidth = 220;
-const CGFloat kDesktopMediaPickerMultipleScreenHeight = 220;
-const CGFloat kDesktopMediaPickerFramePadding = 20;
-const CGFloat kDesktopMediaPickerControlSpacing = 10;
-const CGFloat kDesktopMediaPickerExcessButtonPadding = 6;
-const CGFloat kDesktopMediaPickerRowHeight = 20;
-const CGFloat kDesktopMediaPickerRowWidth = 500;
-const CGFloat kDesktopMediaPickerIconWidth = 20;
-const CGFloat kDesktopMediaPickerPaddedWidth =
-    kDesktopMediaPickerInitialContentWidth -
-    (kDesktopMediaPickerFramePadding * 2);
-const CGFloat kDesktopMediaPickerFontSize = 13;
-
-NSString* const kDesktopMediaPickerIconId = @"icon";
-NSString* const kDesktopMediaPickerTitleId = @"title";
-
-}  // namespace
-
-@interface DesktopMediaPickerController ()
-
-// Populate the window with controls and views.
-- (void)initializeContentsWithParams:(const DesktopMediaPicker::Params&)params;
-
-// Add |NSSegmentControl| for source type switch.
-- (void)createTypeButtonAtOrigin:(NSPoint)origin;
-
-// Add |IKImageBrowerView| for screen and window source view.
-// Add |NSTableView| for tab source view.
-- (void)createSourceViewsAtOrigin:(NSPoint)origin;
-
-// Add check box for audio sharing.
-- (void)createAudioCheckboxAtOrigin:(NSPoint)origin;
-
-// Create the share and cancel button.
-- (void)createActionButtonsAtOrigin:(NSPoint)origin;
-
-// Create a |NSTextField| with label traits given |width|. Frame height is
-// automatically adjusted to fit.
-- (NSTextField*)createTextFieldWithText:(NSString*)text
-                             frameWidth:(CGFloat)width;
-
-// Create a button with |title|, with size adjusted to fit.
-- (NSButton*)createButtonWithTitle:(NSString*)title;
-
-- (IKImageBrowserView*)createImageBrowserWithSize:(NSSize)size;
-
-// Report result by invoking |doneCallback_|. The callback is invoked only on
-// the first call to |reportResult:|. Subsequent calls will be no-ops.
-- (void)reportResult:(DesktopMediaID)sourceID;
-
-// Action handlers.
-- (void)sharePressed:(id)sender;
-- (void)cancelPressed:(id)sender;
-
-// Helper functions to get source type, or get data entities based on source
-// type.
-- (DesktopMediaID::Type)selectedSourceType;
-- (DesktopMediaID::Type)sourceTypeForBrowser:(id)browser;
-- (id)browserViewForType:(DesktopMediaID::Type)sourceType;
-- (NSMutableArray*)itemSetForType:(DesktopMediaID::Type)sourceType;
-- (NSInteger)selectedIndexForType:(DesktopMediaID::Type)sourceType;
-- (void)setTabBrowserIndex:(NSInteger)index;
-
-@end
-
-@implementation DesktopMediaPickerController
-
-- (id)initWithSourceLists:
-          (std::vector<std::unique_ptr<DesktopMediaList>>)sourceLists
-                 callback:(const DesktopMediaPicker::DoneCallback&)callback
-                   params:(const DesktopMediaPicker::Params&)params {
-  const NSUInteger kStyleMask =
-      NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
-  base::scoped_nsobject<NSWindow> window(
-      [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater
-                                  styleMask:kStyleMask
-                                    backing:NSBackingStoreBuffered
-                                      defer:NO]);
-  if ((self = [super initWithWindow:window])) {
-    NSWindow* parent = params.parent.GetNativeNSWindow();
-    [parent addChildWindow:window ordered:NSWindowAbove];
-    [window setDelegate:self];
-
-    sourceLists_ = std::move(sourceLists);
-    for (auto& sourceList : sourceLists_) {
-      switch (sourceList->GetMediaListType()) {
-        case DesktopMediaID::TYPE_NONE:
-          NOTREACHED();
-          break;
-        case DesktopMediaID::TYPE_SCREEN:
-          screenItems_.reset([[NSMutableArray alloc] init]);
-          break;
-        case DesktopMediaID::TYPE_WINDOW:
-          sourceList->SetViewDialogWindowId(DesktopMediaID(
-              DesktopMediaID::TYPE_WINDOW, [window windowNumber]));
-          windowItems_.reset([[NSMutableArray alloc] init]);
-          break;
-        case DesktopMediaID::TYPE_WEB_CONTENTS:
-          tabItems_.reset([[NSMutableArray alloc] init]);
-          break;
-      }
-    }
-
-    [self initializeContentsWithParams:params];
-    doneCallback_ = callback;
-
-    bridge_.reset(new DesktopMediaPickerBridge(self));
-  }
-  return self;
-}
-
-- (void)dealloc {
-  [shareButton_ setTarget:nil];
-  [cancelButton_ setTarget:nil];
-  [screenBrowser_ setDelegate:nil];
-  [screenBrowser_ setDataSource:nil];
-  [windowBrowser_ setDelegate:nil];
-  [windowBrowser_ setDataSource:nil];
-  [tabBrowser_ setDataSource:nil];
-  [tabBrowser_ setDelegate:nil];
-  [[self window] close];
-  [super dealloc];
-}
-
-- (void)initializeContentsWithParams:(const DesktopMediaPicker::Params&)params {
-  // Use flipped coordinates to facilitate manual layout.
-  base::scoped_nsobject<FlippedView> content(
-      [[FlippedView alloc] initWithFrame:NSZeroRect]);
-  [[self window] setContentView:content];
-  NSPoint origin = NSMakePoint(kDesktopMediaPickerFramePadding,
-                               kDesktopMediaPickerFramePadding);
-
-  // Set the dialog's title.
-  NSString* titleText = l10n_util::GetNSString(IDS_DESKTOP_MEDIA_PICKER_TITLE);
-  [[self window] setTitle:titleText];
-
-  // Set the dialog's description.
-  NSString* descriptionText;
-  if (params.app_name == params.target_name) {
-    descriptionText =
-        l10n_util::GetNSStringF(IDS_DESKTOP_MEDIA_PICKER_TEXT, params.app_name);
-  } else {
-    descriptionText =
-        l10n_util::GetNSStringF(IDS_DESKTOP_MEDIA_PICKER_TEXT_DELEGATED,
-                                params.app_name, params.target_name);
-  }
-  NSTextField* description =
-      [self createTextFieldWithText:descriptionText
-                         frameWidth:kDesktopMediaPickerPaddedWidth];
-  [description setFrameOrigin:origin];
-  [content addSubview:description];
-  origin.y += NSHeight([description frame]) + kDesktopMediaPickerControlSpacing;
-
-  [self createTypeButtonAtOrigin:origin];
-  origin.y +=
-      NSHeight([sourceTypeControl_ frame]) + kDesktopMediaPickerControlSpacing;
-
-  [self createSourceViewsAtOrigin:origin];
-  origin.y +=
-      NSHeight([imageBrowserScroll_ frame]) + kDesktopMediaPickerControlSpacing;
-
-  if (params.request_audio) {
-    [self createAudioCheckboxAtOrigin:origin];
-    origin.y += NSHeight([audioShareCheckbox_ frame]) +
-                kDesktopMediaPickerControlSpacing;
-    if (params.approve_audio_by_default) {
-      [audioShareCheckbox_ setState:NSOnState];
-    } else {
-      [audioShareCheckbox_ setState:NSOffState];
-    }
-  }
-
-  [self createActionButtonsAtOrigin:origin];
-  origin.y += kDesktopMediaPickerFramePadding +
-              (NSHeight([cancelButton_ frame]) -
-               kDesktopMediaPickerExcessButtonPadding);
-
-  // Resize window to fit.
-  [content setAutoresizesSubviews:NO];
-  [[self window]
-      setContentSize:NSMakeSize(kDesktopMediaPickerInitialContentWidth,
-                                origin.y)];
-  [[self window]
-      setContentMinSize:NSMakeSize(kDesktopMediaPickerMinimumContentWidth,
-                                   kDesktopMediaPickerMinimumContentHeight)];
-  [content setAutoresizesSubviews:YES];
-
-  // Initialize the type selection at the first segment.
-  [sourceTypeControl_ setSelected:YES forSegment:0];
-  [self typeButtonPressed:sourceTypeControl_];
-  [[self window]
-      makeFirstResponder:[self browserViewForType:[self selectedSourceType]]];
-}
-
-- (void)createTypeButtonAtOrigin:(NSPoint)origin {
-  // Create segmented button.
-  sourceTypeControl_.reset(
-      [[NSSegmentedControl alloc] initWithFrame:NSZeroRect]);
-
-  NSInteger segmentCount = sourceLists_.size();
-  [sourceTypeControl_ setSegmentCount:segmentCount];
-  NSInteger segmentIndex = 0;
-
-  for (auto& sourceList : sourceLists_) {
-    switch (sourceList->GetMediaListType()) {
-      case DesktopMediaID::TYPE_NONE:
-        NOTREACHED();
-        break;
-      case DesktopMediaID::TYPE_SCREEN:
-        [sourceTypeControl_
-              setLabel:l10n_util::GetNSString(
-                           IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_SCREEN)
-            forSegment:segmentIndex];
-
-        [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_SCREEN
-                               forSegment:segmentIndex];
-        break;
-      case DesktopMediaID::TYPE_WINDOW:
-        [sourceTypeControl_
-              setLabel:l10n_util::GetNSString(
-                           IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_WINDOW)
-            forSegment:segmentIndex];
-        [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_WINDOW
-                               forSegment:segmentIndex];
-        break;
-      case DesktopMediaID::TYPE_WEB_CONTENTS:
-        [sourceTypeControl_
-              setLabel:l10n_util::GetNSString(
-                           IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_TAB)
-            forSegment:segmentIndex];
-        [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_WEB_CONTENTS
-                               forSegment:segmentIndex];
-        break;
-    }
-    ++segmentIndex;
-  }
-
-  [sourceTypeControl_ setTarget:self];
-  [sourceTypeControl_ setAction:@selector(typeButtonPressed:)];
-
-  [[sourceTypeControl_ cell] setTrackingMode:NSSegmentSwitchTrackingSelectOne];
-
-  [[[self window] contentView] addSubview:sourceTypeControl_];
-
-  [sourceTypeControl_ sizeToFit];
-  [sourceTypeControl_ setAutoresizingMask:NSViewMaxXMargin | NSViewMinXMargin];
-  CGFloat controlWidth = NSWidth([sourceTypeControl_ frame]);
-  CGFloat controlHeight = NSHeight([sourceTypeControl_ frame]);
-  NSRect centerFrame =
-      NSMakeRect((kDesktopMediaPickerInitialContentWidth - controlWidth) / 2,
-                 origin.y, controlWidth, controlHeight);
-
-  [sourceTypeControl_ setFrame:NSIntegralRect(centerFrame)];
-}
-
-- (void)createSourceViewsAtOrigin:(NSPoint)origin {
-  for (auto& sourceList : sourceLists_) {
-    switch (sourceList->GetMediaListType()) {
-      case DesktopMediaID::TYPE_NONE: {
-        NOTREACHED();
-        break;
-      }
-      case DesktopMediaID::TYPE_SCREEN: {
-        const bool is_single = sourceList->GetSourceCount() <= 1;
-        const CGFloat width = is_single
-                                  ? kDesktopMediaPickerSingleScreenWidth
-                                  : kDesktopMediaPickerMultipleScreenWidth;
-        const CGFloat height = is_single
-                                   ? kDesktopMediaPickerSingleScreenHeight
-                                   : kDesktopMediaPickerMultipleScreenHeight;
-        screenBrowser_.reset([[self
-            createImageBrowserWithSize:NSMakeSize(width, height)] retain]);
-        break;
-      }
-
-      case DesktopMediaID::TYPE_WINDOW: {
-        windowBrowser_.reset([[self
-            createImageBrowserWithSize:NSMakeSize(
-                                           kDesktopMediaPickerThumbnailWidth,
-                                           kDesktopMediaPickerThumbnailHeight)]
-            retain]);
-        break;
-      }
-      case DesktopMediaID::TYPE_WEB_CONTENTS: {
-        tabBrowser_.reset([[NSTableView alloc] initWithFrame:NSZeroRect]);
-        [tabBrowser_ setDelegate:self];
-        [tabBrowser_ setDataSource:self];
-        [tabBrowser_ setAllowsMultipleSelection:NO];
-        [tabBrowser_ setRowHeight:kDesktopMediaPickerRowHeight];
-        [tabBrowser_ setDoubleAction:@selector(sharePressed:)];
-        base::scoped_nsobject<NSTableColumn> iconColumn([[NSTableColumn alloc]
-            initWithIdentifier:kDesktopMediaPickerIconId]);
-        [iconColumn setEditable:NO];
-        [iconColumn setWidth:kDesktopMediaPickerIconWidth];
-        [tabBrowser_ addTableColumn:iconColumn];
-        base::scoped_nsobject<NSTableColumn> titleColumn([[NSTableColumn alloc]
-            initWithIdentifier:kDesktopMediaPickerTitleId]);
-        [titleColumn setEditable:NO];
-        [titleColumn setWidth:kDesktopMediaPickerRowWidth];
-        [tabBrowser_ addTableColumn:titleColumn];
-        [tabBrowser_ setHeaderView:nil];
-        break;
-      }
-    }
-  }
-  // Create a scroll view to host the image browsers.
-  NSRect imageBrowserScrollFrame =
-      NSMakeRect(origin.x, origin.y, kDesktopMediaPickerPaddedWidth, 350);
-  imageBrowserScroll_.reset(
-      [[NSScrollView alloc] initWithFrame:imageBrowserScrollFrame]);
-  [imageBrowserScroll_ setHasVerticalScroller:YES];
-  [imageBrowserScroll_ setBorderType:NSBezelBorder];
-  [imageBrowserScroll_
-      setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
-  [[[self window] contentView] addSubview:imageBrowserScroll_];
-}
-
-- (void)createAudioCheckboxAtOrigin:(NSPoint)origin {
-  audioShareCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
-  [audioShareCheckbox_ setFrameOrigin:origin];
-  [audioShareCheckbox_ setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
-  [audioShareCheckbox_ setButtonType:NSSwitchButton];
-  [audioShareCheckbox_
-      setTitle:l10n_util::GetNSString(IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE)];
-  [audioShareCheckbox_ sizeToFit];
-  [[[self window] contentView] addSubview:audioShareCheckbox_];
-}
-
-- (void)createActionButtonsAtOrigin:(NSPoint)origin {
-  FlippedView* content = [[self window] contentView];
-
-  // Create the share button.
-  shareButton_ =
-      [self createButtonWithTitle:l10n_util::GetNSString(
-                                      IDS_DESKTOP_MEDIA_PICKER_SHARE)];
-  origin.x =
-      kDesktopMediaPickerInitialContentWidth - kDesktopMediaPickerFramePadding -
-      (NSWidth([shareButton_ frame]) - kDesktopMediaPickerExcessButtonPadding);
-  [shareButton_ setEnabled:NO];
-  [shareButton_ setFrameOrigin:origin];
-  [shareButton_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
-  [shareButton_ setTarget:self];
-  [shareButton_ setKeyEquivalent:kKeyEquivalentEscape];
-  [shareButton_ setAction:@selector(sharePressed:)];
-  [content addSubview:shareButton_];
-
-  // Create the cancel button.
-  cancelButton_ =
-      [self createButtonWithTitle:l10n_util::GetNSString(IDS_CANCEL)];
-  origin.x -= kDesktopMediaPickerControlSpacing +
-              (NSWidth([cancelButton_ frame]) -
-               (kDesktopMediaPickerExcessButtonPadding * 2));
-  [cancelButton_ setFrameOrigin:origin];
-  [cancelButton_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
-  [cancelButton_ setTarget:self];
-  [cancelButton_ setKeyEquivalent:kKeyEquivalentReturn];
-  [cancelButton_ setAction:@selector(cancelPressed:)];
-  [content addSubview:cancelButton_];
-}
-
-- (NSTextField*)createTextFieldWithText:(NSString*)text
-                             frameWidth:(CGFloat)width {
-  NSRect frame = NSMakeRect(0, 0, width, 1);
-  base::scoped_nsobject<NSTextField> textField(
-      [[NSTextField alloc] initWithFrame:frame]);
-  [textField setEditable:NO];
-  [textField setSelectable:YES];
-  [textField setDrawsBackground:NO];
-  [textField setBezeled:NO];
-  [textField setStringValue:text];
-  [textField setFont:[NSFont systemFontOfSize:kDesktopMediaPickerFontSize]];
-  [textField setAutoresizingMask:NSViewWidthSizable];
-  [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:textField];
-  return textField.autorelease();
-}
-
-- (NSButton*)createButtonWithTitle:(NSString*)title {
-  base::scoped_nsobject<NSButton> button(
-      [[NSButton alloc] initWithFrame:NSZeroRect]);
-  [button setButtonType:NSMomentaryPushInButton];
-  [button setBezelStyle:NSRoundedBezelStyle];
-  [button setTitle:title];
-  [GTMUILocalizerAndLayoutTweaker sizeToFitView:button];
-  return button.autorelease();
-}
-
-- (IKImageBrowserView*)createImageBrowserWithSize:(NSSize)size {
-  NSUInteger cellStyle = IKCellsStyleShadowed | IKCellsStyleTitled;
-  base::scoped_nsobject<IKImageBrowserView> browser(
-      [[IKImageBrowserView alloc] initWithFrame:NSZeroRect]);
-  [browser setDelegate:self];
-  [browser setDataSource:self];
-  [browser setCellsStyleMask:cellStyle];
-  [browser setCellSize:size];
-  [browser setAllowsMultipleSelection:NO];
-  return browser.autorelease();
-}
-
-#pragma mark Event Actions
-
-- (void)showWindow:(id)sender {
-  // Signal the source lists to start sending thumbnails. |bridge_| is used as
-  // the observer, and will forward notifications to this object.
-  for (auto& sourceList : sourceLists_) {
-    switch (sourceList->GetMediaListType()) {
-      case DesktopMediaID::TYPE_NONE: {
-        NOTREACHED();
-        break;
-      }
-      case DesktopMediaID::TYPE_SCREEN: {
-        sourceList->SetThumbnailSize(
-            gfx::Size(kDesktopMediaPickerSingleScreenWidth,
-                      kDesktopMediaPickerSingleScreenHeight));
-        sourceList->StartUpdating(bridge_.get());
-        break;
-      }
-      case DesktopMediaID::TYPE_WINDOW: {
-        sourceList->SetThumbnailSize(
-            gfx::Size(kDesktopMediaPickerThumbnailWidth,
-                      kDesktopMediaPickerThumbnailHeight));
-        sourceList->StartUpdating(bridge_.get());
-        break;
-      }
-      case DesktopMediaID::TYPE_WEB_CONTENTS: {
-        sourceList->SetThumbnailSize(gfx::Size(kDesktopMediaPickerIconWidth,
-                                               kDesktopMediaPickerRowHeight));
-        sourceList->StartUpdating(bridge_.get());
-        break;
-      }
-    }
-  }
-
-  [self.window center];
-  [super showWindow:sender];
-}
-
-- (void)reportResult:(DesktopMediaID)sourceID {
-  if (doneCallback_.is_null()) {
-    return;
-  }
-
-  sourceID.audio_share = ![audioShareCheckbox_ isHidden] &&
-                         [audioShareCheckbox_ state] == NSOnState;
-
-  // If the media source is an tab, activate it.
-  if (sourceID.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
-    content::WebContents* tab = content::WebContents::FromRenderFrameHost(
-        content::RenderFrameHost::FromID(
-            sourceID.web_contents_id.render_process_id,
-            sourceID.web_contents_id.main_render_frame_id));
-    if (tab) {
-      tab->GetDelegate()->ActivateContents(tab);
-      Browser* browser = chrome::FindBrowserWithWebContents(tab);
-      if (browser && browser->window())
-        browser->window()->Activate();
-    }
-  }
-
-  // Notify the |callback_| asynchronously because it may release the
-  // controller.
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::BindOnce(doneCallback_, sourceID));
-  doneCallback_.Reset();
-}
-
-- (void)sharePressed:(id)sender {
-  DesktopMediaID::Type selectedType = [self selectedSourceType];
-  NSMutableArray* items = [self itemSetForType:selectedType];
-  NSInteger selectedIndex = [self selectedIndexForType:selectedType];
-  DesktopMediaPickerItem* item = [items objectAtIndex:selectedIndex];
-  [self reportResult:[item sourceID]];
-  [self close];
-}
-
-- (void)cancelPressed:(id)sender {
-  [self reportResult:DesktopMediaID()];
-  [self close];
-}
-
-- (void)typeButtonPressed:(id)sender {
-  DesktopMediaID::Type selectedType = [self selectedSourceType];
-  id browser = [self browserViewForType:selectedType];
-
-  [audioShareCheckbox_
-      setHidden:selectedType != DesktopMediaID::TYPE_WEB_CONTENTS];
-  [imageBrowserScroll_ setDocumentView:browser];
-
-  if (selectedType == DesktopMediaID::TYPE_WEB_CONTENTS) {
-    NSInteger selectedIndex = [self selectedIndexForType:selectedType];
-    [tabBrowser_ reloadData];
-    [self setTabBrowserIndex:selectedIndex];
-  } else {
-    [browser reloadData];
-    [self imageBrowserSelectionDidChange:browser];
-  }
-}
-
-#pragma mark Data Retrieve Helper
-
-- (DesktopMediaID::Type)selectedSourceType {
-  NSInteger segment = [sourceTypeControl_ selectedSegment];
-  return static_cast<DesktopMediaID::Type>(
-      [[sourceTypeControl_ cell] tagForSegment:segment]);
-}
-
-- (DesktopMediaID::Type)sourceTypeForBrowser:(id)browser {
-  if (browser == screenBrowser_.get())
-    return DesktopMediaID::TYPE_SCREEN;
-  if (browser == windowBrowser_.get())
-    return DesktopMediaID::TYPE_WINDOW;
-  return DesktopMediaID::TYPE_WEB_CONTENTS;
-}
-
-- (id)browserViewForType:(DesktopMediaID::Type)sourceType {
-  switch (sourceType) {
-    case DesktopMediaID::TYPE_SCREEN:
-      return screenBrowser_;
-    case DesktopMediaID::TYPE_WINDOW:
-      return windowBrowser_;
-    case DesktopMediaID::TYPE_WEB_CONTENTS:
-      return tabBrowser_;
-    case DesktopMediaID::TYPE_NONE:
-      NOTREACHED();
-      return nil;
-  }
-}
-
-- (NSMutableArray*)itemSetForType:(DesktopMediaID::Type)sourceType {
-  switch (sourceType) {
-    case DesktopMediaID::TYPE_SCREEN:
-      return screenItems_;
-    case DesktopMediaID::TYPE_WINDOW:
-      return windowItems_;
-    case DesktopMediaID::TYPE_WEB_CONTENTS:
-      return tabItems_;
-    case DesktopMediaID::TYPE_NONE:
-      NOTREACHED();
-      return nil;
-  }
-}
-
-- (NSInteger)selectedIndexForType:(DesktopMediaID::Type)sourceType {
-  NSIndexSet* indexes = nil;
-  switch (sourceType) {
-    case DesktopMediaID::TYPE_SCREEN:
-      indexes = [screenBrowser_ selectionIndexes];
-      break;
-    case DesktopMediaID::TYPE_WINDOW:
-      indexes = [windowBrowser_ selectionIndexes];
-      break;
-    case DesktopMediaID::TYPE_WEB_CONTENTS:
-      indexes = [tabBrowser_ selectedRowIndexes];
-      break;
-    case DesktopMediaID::TYPE_NONE:
-      NOTREACHED();
-  }
-
-  if ([indexes count] == 0)
-    return -1;
-  return [indexes firstIndex];
-}
-
-- (void)setTabBrowserIndex:(NSInteger)index {
-  NSIndexSet* indexes;
-
-  if (index < 0)
-    indexes = [NSIndexSet indexSet];
-  else
-    indexes = [NSIndexSet indexSetWithIndex:index];
-
-  [tabBrowser_ selectRowIndexes:indexes byExtendingSelection:NO];
-
-  // Enable or disable the OK button based on whether we have a selection.
-  [shareButton_ setEnabled:(index >= 0)];
-}
-
-#pragma mark NSWindowDelegate
-
-- (void)windowWillClose:(NSNotification*)notification {
-  // Report the result if it hasn't been reported yet. |reportResult:| ensures
-  // that the result is only reported once.
-  [self reportResult:DesktopMediaID()];
-
-  // Remove self from the parent.
-  NSWindow* window = [self window];
-  [[window parentWindow] removeChildWindow:window];
-}
-
-#pragma mark IKImageBrowserDataSource
-
-- (NSUInteger)numberOfItemsInImageBrowser:(IKImageBrowserView*)browser {
-  DesktopMediaID::Type sourceType = [self sourceTypeForBrowser:browser];
-  NSMutableArray* items = [self itemSetForType:sourceType];
-  return [items count];
-}
-
-- (id)imageBrowser:(IKImageBrowserView*)browser itemAtIndex:(NSUInteger)index {
-  DesktopMediaID::Type sourceType = [self sourceTypeForBrowser:browser];
-  NSMutableArray* items = [self itemSetForType:sourceType];
-  DesktopMediaPickerItem* item = [items objectAtIndex:index];
-
-  // For screen source, if there is only one source, we can omit the label
-  // "Entire Screen", because it is redundant with tab label "Your Entire
-  // Screen".
-  [item setTitleHidden:browser == screenBrowser_ && [items count] == 1];
-  return item;
-}
-
-#pragma mark IKImageBrowserDelegate
-
-- (void)imageBrowser:(IKImageBrowserView*)browser
-    cellWasDoubleClickedAtIndex:(NSUInteger)index {
-  DesktopMediaPickerItem* item;
-  if (browser == screenBrowser_)
-    item = [screenItems_ objectAtIndex:index];
-  else
-    item = [windowItems_ objectAtIndex:index];
-  [self reportResult:[item sourceID]];
-  [self close];
-}
-
-- (void)imageBrowserSelectionDidChange:(IKImageBrowserView*)browser {
-  DesktopMediaID::Type selectedType = [self selectedSourceType];
-  NSInteger selectedIndex = [self selectedIndexForType:selectedType];
-  // Enable or disable the OK button based on whether we have a selection.
-  [shareButton_ setEnabled:(selectedIndex >= 0)];
-}
-
-#pragma mark NSTableViewDataSource
-
-- (NSInteger)numberOfRowsInTableView:(NSTableView*)table {
-  return [tabItems_ count];
-}
-
-#pragma mark NSTableViewDelegate
-
-- (NSView*)tableView:(NSTableView*)table
-    viewForTableColumn:(NSTableColumn*)column
-                   row:(NSInteger)rowIndex {
-  if ([[column identifier] isEqualToString:kDesktopMediaPickerIconId]) {
-    NSImage* image = [[tabItems_ objectAtIndex:rowIndex] imageRepresentation];
-    base::scoped_nsobject<NSImageView> iconView(
-        [[table makeViewWithIdentifier:kDesktopMediaPickerIconId owner:self]
-            retain]);
-    if (!iconView) {
-      iconView.reset([[NSImageView alloc]
-          initWithFrame:NSMakeRect(0, 0, kDesktopMediaPickerIconWidth,
-                                   kDesktopMediaPickerRowWidth)]);
-      [iconView setIdentifier:kDesktopMediaPickerIconId];
-    }
-    [iconView setImage:image];
-    return iconView.autorelease();
-  }
-
-  NSString* string = [[tabItems_ objectAtIndex:rowIndex] imageTitle];
-  base::scoped_nsobject<NSTextField> titleView(
-      [[table makeViewWithIdentifier:kDesktopMediaPickerTitleId owner:self]
-          retain]);
-  if (!titleView) {
-    titleView.reset(
-        [[self createTextFieldWithText:string
-                            frameWidth:kDesktopMediaPickerMinimumContentWidth]
-            retain]);
-    [titleView setIdentifier:kDesktopMediaPickerTitleId];
-  } else {
-    [titleView setStringValue:string];
-  }
-  return titleView.autorelease();
-}
-
-- (void)tableViewSelectionDidChange:(NSNotification*)notification {
-  NSIndexSet* indexes = [tabBrowser_ selectedRowIndexes];
-
-  // Enable or disable the OK button based on whether we have a selection.
-  [shareButton_ setEnabled:([indexes count] > 0)];
-}
-
-#pragma mark DesktopMediaPickerObserver
-
-- (void)sourceAddedForList:(DesktopMediaList*)list atIndex:(int)index {
-  DesktopMediaID::Type sourceType = list->GetMediaListType();
-  NSMutableArray* items = [self itemSetForType:sourceType];
-  id browser = [self browserViewForType:sourceType];
-  NSInteger selectedIndex = [self selectedIndexForType:sourceType];
-  if (selectedIndex >= index)
-    ++selectedIndex;
-
-  const DesktopMediaList::Source& source = list->GetSource(index);
-  NSString* imageTitle = base::SysUTF16ToNSString(source.name);
-  base::scoped_nsobject<DesktopMediaPickerItem> item(
-      [[DesktopMediaPickerItem alloc] initWithSourceId:source.id
-                                              imageUID:++lastImageUID_
-                                            imageTitle:imageTitle]);
-
-  [items insertObject:item atIndex:index];
-  [browser reloadData];
-  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) {
-    // Memorizing selection.
-    [self setTabBrowserIndex:selectedIndex];
-  } else if (sourceType == DesktopMediaID::TYPE_SCREEN) {
-    if ([items count] == 2) {
-      // Switch to multiple sources mode.
-      [browser setCellSize:NSMakeSize(kDesktopMediaPickerMultipleScreenWidth,
-                                      kDesktopMediaPickerMultipleScreenHeight)];
-    }
-  }
-
-  NSString* autoselectSource = base::SysUTF8ToNSString(
-      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          switches::kAutoSelectDesktopCaptureSource));
-
-  if ([autoselectSource isEqualToString:imageTitle]) {
-    [self reportResult:[item sourceID]];
-    [self close];
-  }
-}
-
-- (void)sourceRemovedForList:(DesktopMediaList*)list atIndex:(int)index {
-  DesktopMediaID::Type sourceType = list->GetMediaListType();
-  NSMutableArray* items = [self itemSetForType:sourceType];
-  id browser = [self browserViewForType:sourceType];
-
-  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) {
-    NSInteger selectedIndex = [self selectedIndexForType:sourceType];
-    if (selectedIndex > index)
-      --selectedIndex;
-    else if (selectedIndex == index)
-      selectedIndex = -1;
-    [tabItems_ removeObjectAtIndex:index];
-    [tabBrowser_ reloadData];
-    [self setTabBrowserIndex:selectedIndex];
-    return;
-  }
-
-  if ([[browser selectionIndexes] containsIndex:index]) {
-    // Selected item was removed. Clear selection.
-    [browser setSelectionIndexes:[NSIndexSet indexSet] byExtendingSelection:NO];
-  }
-  [items removeObjectAtIndex:index];
-  if (sourceType == DesktopMediaID::TYPE_SCREEN && [items count] == 1)
-    [browser setCellSize:NSMakeSize(kDesktopMediaPickerSingleScreenWidth,
-                                    kDesktopMediaPickerSingleScreenHeight)];
-  [browser reloadData];
-}
-
-- (void)sourceMovedForList:(DesktopMediaList*)list
-                      from:(int)oldIndex
-                        to:(int)newIndex {
-  DesktopMediaID::Type sourceType = list->GetMediaListType();
-  NSMutableArray* items = [self itemSetForType:sourceType];
-  id browser = [self browserViewForType:sourceType];
-  NSInteger selectedIndex = [self selectedIndexForType:sourceType];
-  if (selectedIndex > oldIndex && selectedIndex <= newIndex)
-    --selectedIndex;
-  else if (selectedIndex < oldIndex && selectedIndex >= newIndex)
-    ++selectedIndex;
-  else if (selectedIndex == oldIndex)
-    selectedIndex = newIndex;
-
-  base::scoped_nsobject<DesktopMediaPickerItem> item(
-      [[items objectAtIndex:oldIndex] retain]);
-  [items removeObjectAtIndex:oldIndex];
-  [items insertObject:item atIndex:newIndex];
-  [browser reloadData];
-
-  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS)
-    [self setTabBrowserIndex:selectedIndex];
-}
-
-- (void)sourceNameChangedForList:(DesktopMediaList*)list atIndex:(int)index {
-  DesktopMediaID::Type sourceType = list->GetMediaListType();
-  NSMutableArray* items = [self itemSetForType:sourceType];
-  id browser = [self browserViewForType:sourceType];
-  NSInteger selectedIndex = [self selectedIndexForType:sourceType];
-
-  DesktopMediaPickerItem* item = [items objectAtIndex:index];
-  const DesktopMediaList::Source& source = list->GetSource(index);
-  [item setImageTitle:base::SysUTF16ToNSString(source.name)];
-  [browser reloadData];
-  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS)
-    [self setTabBrowserIndex:selectedIndex];
-}
-
-- (void)sourceThumbnailChangedForList:(DesktopMediaList*)list
-                              atIndex:(int)index {
-  DesktopMediaID::Type sourceType = list->GetMediaListType();
-  NSMutableArray* items = [self itemSetForType:sourceType];
-  id browser = [self browserViewForType:sourceType];
-  NSInteger selectedIndex = [self selectedIndexForType:sourceType];
-
-  const DesktopMediaList::Source& source = list->GetSource(index);
-  NSImage* image = gfx::NSImageFromImageSkia(source.thumbnail);
-
-  DesktopMediaPickerItem* item = [items objectAtIndex:index];
-  [item setImageRepresentation:image];
-  [browser reloadData];
-
-  if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS)
-    [self setTabBrowserIndex:selectedIndex];
-}
-
-@end  // @interface DesktopMediaPickerController
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm
deleted file mode 100644
index 8ae4803d..0000000
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm
+++ /dev/null
@@ -1,446 +0,0 @@
-// Copyright 2013 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.
-
-#import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h"
-
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
-#include "chrome/browser/media/webrtc/fake_desktop_media_list.h"
-#import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h"
-#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest_mac.h"
-
-using content::DesktopMediaID;
-
-@interface DesktopMediaPickerController (ExposedForTesting)
-- (IKImageBrowserView*)screenBrowser;
-- (IKImageBrowserView*)windowBrowser;
-- (NSTableView*)tabBrowser;
-- (NSSegmentedControl*)sourceTypeControl;
-- (NSButton*)shareButton;
-- (NSButton*)audioShareCheckbox;
-- (NSArray*)screenItems;
-- (NSArray*)windowItems;
-- (NSArray*)tabItems;
-@end
-
-@implementation DesktopMediaPickerController (ExposedForTesting)
-- (IKImageBrowserView*)screenBrowser {
-  return screenBrowser_;
-}
-
-- (IKImageBrowserView*)windowBrowser {
-  return windowBrowser_;
-}
-
-- (NSTableView*)tabBrowser {
-  return tabBrowser_;
-}
-
-- (NSSegmentedControl*)sourceTypeControl {
-  return sourceTypeControl_;
-}
-
-- (NSButton*)shareButton {
-  return shareButton_;
-}
-
-- (NSButton*)cancelButton {
-  return cancelButton_;
-}
-
-- (NSButton*)audioShareCheckbox {
-  return audioShareCheckbox_;
-}
-
-- (NSArray*)screenItems {
-  return screenItems_;
-}
-
-- (NSArray*)windowItems {
-  return windowItems_;
-}
-
-- (NSArray*)tabItems {
-  return tabItems_;
-}
-
-@end
-
-class DesktopMediaPickerControllerTest : public CocoaTest {
- public:
-  DesktopMediaPickerControllerTest() {}
-
-  void SetUp() override {
-    CocoaTest::SetUp();
-
-    std::vector<DesktopMediaID::Type> source_types = {
-        DesktopMediaID::TYPE_SCREEN, DesktopMediaID::TYPE_WINDOW,
-        DesktopMediaID::TYPE_WEB_CONTENTS};
-
-    screen_list_ = new FakeDesktopMediaList(DesktopMediaID::TYPE_SCREEN);
-    window_list_ = new FakeDesktopMediaList(DesktopMediaID::TYPE_WINDOW);
-    tab_list_ = new FakeDesktopMediaList(DesktopMediaID::TYPE_WEB_CONTENTS);
-
-    std::vector<std::unique_ptr<DesktopMediaList>> source_lists;
-    source_lists.push_back(std::unique_ptr<DesktopMediaList>(screen_list_));
-    source_lists.push_back(std::unique_ptr<DesktopMediaList>(window_list_));
-    source_lists.push_back(std::unique_ptr<DesktopMediaList>(tab_list_));
-
-    DesktopMediaPicker::DoneCallback callback =
-        base::Bind(&DesktopMediaPickerControllerTest::OnResult,
-                   base::Unretained(this));
-
-    DesktopMediaPicker::Params params;
-    params.app_name = base::ASCIIToUTF16("Screenshare Test");
-    params.target_name = base::ASCIIToUTF16("https://foo.com");
-    params.request_audio = true;
-    params.approve_audio_by_default = true;
-    controller_.reset([[DesktopMediaPickerController alloc]
-        initWithSourceLists:std::move(source_lists)
-                   callback:callback
-                     params:params]);
-  }
-
-  void TearDown() override {
-    controller_.reset();
-    CocoaTest::TearDown();
-  }
-
-  bool WaitForCallback() {
-    if (!callback_called_) {
-      base::RunLoop().RunUntilIdle();
-    }
-    return callback_called_;
-  }
-
-  void ChangeType(DesktopMediaID::Type sourceType) {
-    NSSegmentedControl* control = [controller_ sourceTypeControl];
-    [control selectSegmentWithTag:sourceType];
-    // [control selectSegmentWithTag] does not trigger handler, so we need to
-    // trigger it manually.
-    [[control target] performSelector:[control action] withObject:control];
-  }
-
-  void AddWindow(int id) {
-    window_list_->AddSourceByFullMediaID(
-        DesktopMediaID(DesktopMediaID::TYPE_WINDOW, id));
-  }
-
-  void AddScreen(int id) {
-    screen_list_->AddSourceByFullMediaID(
-        DesktopMediaID(DesktopMediaID::TYPE_SCREEN, id));
-  }
-
-  void AddTab(int id) {
-    tab_list_->AddSourceByFullMediaID(
-        DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, id));
-  }
-
- protected:
-  void OnResult(DesktopMediaID source) {
-    EXPECT_FALSE(callback_called_);
-    callback_called_ = true;
-    source_reported_ = source;
-  }
-
-  content::TestBrowserThreadBundle thread_bundle_;
-  bool callback_called_ = false;
-  DesktopMediaID source_reported_;
-  FakeDesktopMediaList* screen_list_ = nullptr;
-  FakeDesktopMediaList* window_list_ = nullptr;
-  FakeDesktopMediaList* tab_list_ = nullptr;
-  base::scoped_nsobject<DesktopMediaPickerController> controller_;
-};
-
-TEST_F(DesktopMediaPickerControllerTest, ShowAndDismiss) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_SCREEN);
-
-  AddScreen(0);
-  AddScreen(1);
-  screen_list_->SetSourceThumbnail(1);
-
-  NSArray* items = [controller_ screenItems];
-  EXPECT_EQ(2U, [items count]);
-  EXPECT_NSEQ(@"0", [[items objectAtIndex:0] imageTitle]);
-  EXPECT_EQ(nil, [[items objectAtIndex:0] imageRepresentation]);
-  EXPECT_NSEQ(@"1", [[items objectAtIndex:1] imageTitle]);
-  EXPECT_TRUE([[items objectAtIndex:1] imageRepresentation] != nil);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, CancelIsDefault) {
-  [controller_ showWindow:nil];
-  EXPECT_EQ([[controller_ window] defaultButtonCell],
-            [[controller_ cancelButton] cell]);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, ClickShareScreen) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_SCREEN);
-
-  EXPECT_FALSE([[controller_ shareButton] isEnabled]);
-  AddScreen(0);
-  screen_list_->SetSourceThumbnail(0);
-  // Nothing should be selected automatically.
-  EXPECT_FALSE([[controller_ shareButton] isEnabled]);
-
-  AddScreen(1);
-  screen_list_->SetSourceThumbnail(1);
-
-  EXPECT_EQ(2U, [[controller_ screenItems] count]);
-
-  NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1];
-  [[controller_ screenBrowser] setSelectionIndexes:index_set
-                              byExtendingSelection:NO];
-  EXPECT_TRUE([[controller_ shareButton] isEnabled]);
-
-  [[controller_ shareButton] performClick:nil];
-  EXPECT_TRUE(WaitForCallback());
-  EXPECT_EQ(screen_list_->GetSource(1).id, source_reported_);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, ClickShareWindow) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_WINDOW);
-  AddWindow(0);
-  window_list_->SetSourceThumbnail(0);
-  AddWindow(1);
-  window_list_->SetSourceThumbnail(1);
-
-  EXPECT_EQ(2U, [[controller_ windowItems] count]);
-  EXPECT_FALSE([[controller_ shareButton] isEnabled]);
-
-  NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1];
-  [[controller_ windowBrowser] setSelectionIndexes:index_set
-                              byExtendingSelection:NO];
-  EXPECT_TRUE([[controller_ shareButton] isEnabled]);
-
-  [[controller_ shareButton] performClick:nil];
-  EXPECT_TRUE(WaitForCallback());
-  EXPECT_EQ(window_list_->GetSource(1).id, source_reported_);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, ClickShareTab) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
-  AddTab(0);
-  tab_list_->SetSourceThumbnail(0);
-  AddTab(1);
-  tab_list_->SetSourceThumbnail(1);
-
-  EXPECT_EQ(2U, [[controller_ tabItems] count]);
-  EXPECT_FALSE([[controller_ shareButton] isEnabled]);
-
-  NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1];
-  [[controller_ tabBrowser] selectRowIndexes:index_set byExtendingSelection:NO];
-  EXPECT_TRUE([[controller_ shareButton] isEnabled]);
-
-  // Disable audio share here, otherwise the |source_reported_| will be
-  // different from original Id, because audio share is by default on.
-  [[controller_ audioShareCheckbox] setState:NSOffState];
-  [[controller_ shareButton] performClick:nil];
-  EXPECT_TRUE(WaitForCallback());
-  EXPECT_EQ(tab_list_->GetSource(1).id, source_reported_);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, ClickCancel) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_WINDOW);
-
-  AddWindow(0);
-  window_list_->SetSourceThumbnail(0);
-  AddWindow(1);
-  window_list_->SetSourceThumbnail(1);
-
-  NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1];
-  [[controller_ windowBrowser] setSelectionIndexes:index_set
-                              byExtendingSelection:NO];
-  [[controller_ cancelButton] performClick:nil];
-  EXPECT_TRUE(WaitForCallback());
-  EXPECT_EQ(DesktopMediaID(), source_reported_);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, CloseWindow) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_SCREEN);
-
-  AddScreen(0);
-  screen_list_->SetSourceThumbnail(0);
-  AddScreen(1);
-  screen_list_->SetSourceThumbnail(1);
-
-  [controller_ close];
-  EXPECT_TRUE(WaitForCallback());
-  EXPECT_EQ(DesktopMediaID(), source_reported_);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, UpdateThumbnail) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
-
-  AddTab(0);
-  tab_list_->SetSourceThumbnail(0);
-  AddTab(1);
-  tab_list_->SetSourceThumbnail(1);
-
-  NSArray* items = [controller_ tabItems];
-  EXPECT_EQ(2U, [items count]);
-  NSUInteger version = [[items objectAtIndex:0] imageVersion];
-
-  tab_list_->SetSourceThumbnail(0);
-  EXPECT_NE(version, [[items objectAtIndex:0] imageVersion]);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, UpdateName) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_WINDOW);
-
-  AddWindow(0);
-  window_list_->SetSourceThumbnail(0);
-  AddWindow(1);
-  window_list_->SetSourceThumbnail(1);
-
-  NSArray* items = [controller_ windowItems];
-  EXPECT_EQ(2U, [items count]);
-  NSUInteger version = [[items objectAtIndex:0] imageVersion];
-
-  window_list_->SetSourceThumbnail(0);
-  EXPECT_NE(version, [[items objectAtIndex:0] imageVersion]);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, RemoveSource) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_SCREEN);
-
-  AddScreen(0);
-  AddScreen(1);
-  AddScreen(2);
-  screen_list_->SetSourceName(1, base::ASCIIToUTF16("foo"));
-
-  NSArray* items = [controller_ screenItems];
-  EXPECT_EQ(3U, [items count]);
-  EXPECT_NSEQ(@"foo", [[items objectAtIndex:1] imageTitle]);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, MoveSource) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_WINDOW);
-
-  AddWindow(0);
-  AddWindow(1);
-  window_list_->SetSourceName(1, base::ASCIIToUTF16("foo"));
-  NSArray* items = [controller_ windowItems];
-  EXPECT_NSEQ(@"foo", [[items objectAtIndex:1] imageTitle]);
-
-  window_list_->MoveSource(1, 0);
-  EXPECT_NSEQ(@"foo", [[items objectAtIndex:0] imageTitle]);
-
-  window_list_->MoveSource(0, 1);
-  EXPECT_NSEQ(@"foo", [[items objectAtIndex:1] imageTitle]);
-}
-
-// Make sure the audio share checkbox' state reacts correctly with
-// the source selection. Namely the checkbox is enabled only for tab
-// sharing on Mac.
-TEST_F(DesktopMediaPickerControllerTest, AudioShareCheckboxState) {
-  [controller_ showWindow:nil];
-
-  AddScreen(0);
-  AddWindow(1);
-  AddTab(2);
-
-  NSButton* checkbox = [controller_ audioShareCheckbox];
-  EXPECT_EQ(YES, [checkbox isHidden]);
-
-  [checkbox setHidden:NO];
-  ChangeType(DesktopMediaID::TYPE_WINDOW);
-  EXPECT_EQ(YES, [checkbox isHidden]);
-
-  [checkbox setHidden:YES];
-  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
-  EXPECT_EQ(NO, [checkbox isHidden]);
-
-  [checkbox setHidden:NO];
-  ChangeType(DesktopMediaID::TYPE_SCREEN);
-  EXPECT_EQ(YES, [checkbox isHidden]);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, TabShareWithAudio) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
-
-  DesktopMediaID origin_id =
-      DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123);
-  DesktopMediaID id_with_audio = origin_id;
-  id_with_audio.audio_share = true;
-
-  tab_list_->AddSourceByFullMediaID(origin_id);
-
-  NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:0];
-  [[controller_ tabBrowser] selectRowIndexes:index_set byExtendingSelection:NO];
-  EXPECT_TRUE([[controller_ shareButton] isEnabled]);
-
-  [[controller_ shareButton] performClick:nil];
-
-  EXPECT_TRUE(WaitForCallback());
-  EXPECT_EQ(id_with_audio, source_reported_);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, TabBrowserFocusAlgorithm) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
-  AddTab(0);
-  AddTab(1);
-  AddTab(2);
-  AddTab(3);
-
-  NSArray* items = [controller_ tabItems];
-  NSTableView* browser = [controller_ tabBrowser];
-
-  NSIndexSet* index_set = [NSIndexSet indexSetWithIndex:1];
-  [browser selectRowIndexes:index_set byExtendingSelection:NO];
-
-  // Move source [0, 1, 2, 3]-->[1, 2, 3, 0]
-  tab_list_->MoveSource(0, 3);
-  NSUInteger selected_index = [[browser selectedRowIndexes] firstIndex];
-  EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id);
-
-  // Move source [1, 2, 3, 0]-->[3, 1, 2, 0]
-  tab_list_->MoveSource(2, 0);
-  selected_index = [[browser selectedRowIndexes] firstIndex];
-  EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id);
-
-  // Remove a source [3, 1, 2, 0]-->[1, 2, 0]
-  tab_list_->RemoveSource(0);
-  selected_index = [[browser selectedRowIndexes] firstIndex];
-  EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id);
-
-  // Change source type back and forth, browser should memorize the selection.
-  ChangeType(DesktopMediaID::TYPE_SCREEN);
-  ChangeType(DesktopMediaID::TYPE_WEB_CONTENTS);
-  selected_index = [[browser selectedRowIndexes] firstIndex];
-  EXPECT_EQ(1, [[items objectAtIndex:selected_index] sourceID].id);
-}
-
-TEST_F(DesktopMediaPickerControllerTest, SingleScreenNoLabel) {
-  [controller_ showWindow:nil];
-  ChangeType(DesktopMediaID::TYPE_SCREEN);
-
-  NSArray* items = [controller_ screenItems];
-
-  AddScreen(0);
-  screen_list_->SetSourceThumbnail(0);
-  EXPECT_EQ(1U, [items count]);
-  EXPECT_EQ(nil, [[items objectAtIndex:0] imageTitle]);
-
-  AddScreen(1);
-  screen_list_->SetSourceThumbnail(1);
-  EXPECT_EQ(2U, [items count]);
-  EXPECT_NE(nil, [[items objectAtIndex:0] imageTitle]);
-  EXPECT_NE(nil, [[items objectAtIndex:1] imageTitle]);
-}
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h
deleted file mode 100644
index aff3066..0000000
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2013 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 CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_ITEM_H_
-#define CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_ITEM_H_
-
-#import <AppKit/AppKit.h>
-
-#import "base/mac/scoped_nsobject.h"
-#include "chrome/browser/media/webrtc/desktop_media_list.h"
-
-// Stores the data representing a |DesktopMediaPicker| source for displaying in
-// a |IKImageBrowserView|. Implements the |IKImageBrowserItem| informal
-// protocol.
-@interface DesktopMediaPickerItem : NSObject {
- @private
-  content::DesktopMediaID sourceID_;
-  base::scoped_nsobject<NSString> imageUID_;
-  base::scoped_nsobject<NSString> imageTitle_;
-  base::scoped_nsobject<NSImage> image_;
-  NSUInteger imageVersion_;
-  BOOL titleHidden_;
-}
-
-@property(assign, nonatomic) BOOL titleHidden;
-
-// Designated initializer.
-// |sourceID| is the corresponding source's ID as provided by the media list.
-// |imageUID| is a unique number in the context of the |IKImageBrowserView|
-// instance.
-// |imageTitle| is the source's name to be used as the label in
-// |IKImageBrowserView|.
-- (id)initWithSourceId:(content::DesktopMediaID)sourceID
-              imageUID:(int)imageUID
-            imageTitle:(NSString*)imageTitle;
-
-// Returns the source's ID.
-- (content::DesktopMediaID)sourceID;
-
-// Sets the image of the item to be displayed in |IKImageBrowserView|.
-- (void)setImageRepresentation:(NSImage*)image;
-
-// Sets the label of the item to be displayed in |IKImageBrowserView|.
-- (void)setImageTitle:(NSString*)imageTitle;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_DESKTOP_MEDIA_PICKER_ITEM_H_
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.mm
deleted file mode 100644
index f778a4a..0000000
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.mm
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2013 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.
-
-#import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h"
-
-#import <Quartz/Quartz.h>
-
-#include "chrome/browser/media/webrtc/desktop_media_list.h"
-
-@implementation DesktopMediaPickerItem
-
-@synthesize titleHidden = titleHidden_;
-
-- (id)initWithSourceId:(content::DesktopMediaID)sourceID
-              imageUID:(int)imageUID
-            imageTitle:(NSString*)imageTitle {
-  if ((self = [super init])) {
-    sourceID_ = sourceID;
-    imageUID_.reset([[NSString stringWithFormat:@"%d", imageUID] retain]);
-    imageTitle_.reset([imageTitle retain]);
-  }
-  return self;
-}
-
-- (content::DesktopMediaID)sourceID {
-  return sourceID_;
-}
-
-- (void)setImageRepresentation:(NSImage*)image {
-  image_.reset([image retain]);
-  ++imageVersion_;
-}
-
-- (void)setImageTitle:(NSString*)imageTitle {
-  imageTitle_.reset([imageTitle copy]);
-}
-
-#pragma mark IKImageBrowserItem
-
-- (NSString*)imageUID {
-  return imageUID_;
-}
-
-- (NSString*)imageRepresentationType {
-  return IKImageBrowserNSImageRepresentationType;
-}
-
-- (NSString*)imageTitle {
-  return titleHidden_ ? nil : imageTitle_;
-}
-
-- (NSUInteger)imageVersion {
-  return imageVersion_;
-}
-
-- (id)imageRepresentation {
-  return image_.get();
-}
-
-@end  // @interface DesktopMediaPickerItem
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
index 0d79e8f..3fe4d28b 100644
--- a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
+++ b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar.mm
@@ -203,6 +203,10 @@
   DISALLOW_COPY_AND_ASSIGN(TouchBarNotificationBridge);
 };
 
+id<NSAccessibility> ToNSAccessibility(id object) {
+  return [object conformsToProtocol:@protocol(NSAccessibility)] ? object : nil;
+}
+
 }  // namespace
 
 @interface BrowserWindowDefaultTouchBar () {
@@ -408,11 +412,6 @@
   return touchBar.autorelease();
 }
 
-// TODO(crbug.com/921109): Migrate to the new NSAccessibility API for this
-// method.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
 - (void)setupBackForwardControl {
   NSMutableArray* images = [NSMutableArray arrayWithArray:@[
     CreateNSImageFromIcon(vector_icons::kBackArrowIcon),
@@ -443,22 +442,18 @@
   // Use the accessibility protocol to get the children.
   // Use NSAccessibilityUnignoredDescendant to be sure we start with
   // the correct object.
-  id segmentElement = NSAccessibilityUnignoredDescendant(control);
-  NSArray* segments = [segmentElement
-      accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
-  NSEnumerator* e = [segments objectEnumerator];
-  [[e nextObject]
-      accessibilitySetOverrideValue:l10n_util::GetNSString(IDS_ACCNAME_BACK)
-                       forAttribute:NSAccessibilityTitleAttribute];
-  [[e nextObject]
-      accessibilitySetOverrideValue:l10n_util::GetNSString(IDS_ACCNAME_FORWARD)
-                       forAttribute:NSAccessibilityTitleAttribute];
+  id<NSAccessibility> segmentElement =
+      ToNSAccessibility(NSAccessibilityUnignoredDescendant(control));
+  DCHECK(segmentElement);
+  NSArray<id<NSAccessibility>>* segments = segmentElement.accessibilityChildren;
+  ToNSAccessibility(segments[0]).accessibilityTitle =
+      l10n_util::GetNSString(IDS_ACCNAME_BACK);
+  ToNSAccessibility(segments[1]).accessibilityTitle =
+      l10n_util::GetNSString(IDS_ACCNAME_FORWARD);
 
   backForwardControl_.reset([control retain]);
 }
 
-#pragma clang diagnostic pop
-
 - (void)updateWebContents:(content::WebContents*)contents {
   notificationBridge_->UpdateWebContents(contents);
 }
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm
index d126de4..ec36da0d 100644
--- a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm
+++ b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm
@@ -17,9 +17,12 @@
 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "components/strings/grit/components_strings.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
 #import "ui/base/cocoa/touch_bar_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 namespace {
 
@@ -163,3 +166,21 @@
         [back_forward_control isEnabledForSegment:kForwardSegmentIndex]);
   }
 }
+
+TEST_F(BrowserWindowDefaultTouchBarUnitTest, BackForwardAccessibilityLabels) {
+  if (@available(macOS 10.12.2, *)) {
+    NSSegmentedControl* control = touch_bar_.get().backForwardControl;
+    id<NSAccessibility> cell = NSAccessibilityUnignoredDescendant(control);
+    ASSERT_TRUE([cell conformsToProtocol:@protocol(NSAccessibility)]);
+
+    id<NSAccessibility> back = cell.accessibilityChildren[0];
+    EXPECT_TRUE([back conformsToProtocol:@protocol(NSAccessibility)]);
+    EXPECT_NSEQ(back.accessibilityTitle,
+                l10n_util::GetNSString(IDS_ACCNAME_BACK));
+
+    id<NSAccessibility> forward = cell.accessibilityChildren[1];
+    EXPECT_TRUE([forward conformsToProtocol:@protocol(NSAccessibility)]);
+    EXPECT_NSEQ(forward.accessibilityTitle,
+                l10n_util::GetNSString(IDS_ACCNAME_FORWARD));
+  }
+}
diff --git a/chrome/browser/ui/content_settings/OWNERS b/chrome/browser/ui/content_settings/OWNERS
index 8a5ed0a..04e8937 100644
--- a/chrome/browser/ui/content_settings/OWNERS
+++ b/chrome/browser/ui/content_settings/OWNERS
@@ -1,3 +1,4 @@
+engedy@chromium.org
 felt@chromium.org
 msramek@chromium.org
 raymes@chromium.org
diff --git a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc
index 76a98bf..849d1c5 100644
--- a/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc
+++ b/chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.cc
@@ -76,6 +76,7 @@
 
 bool AlternateNavInfoBarDelegate::LinkClicked(
     WindowOpenDisposition disposition) {
+  DCHECK(match_);
   history::HistoryService* const history_service =
       HistoryServiceFactory::GetForProfile(profile_,
                                            ServiceAccessType::IMPLICIT_ACCESS);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 614f718..2afa294 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -247,8 +247,7 @@
       : BookmarkButtonBase(listener, title), url_(url) {}
 
   // views::View:
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip_text) const override {
+  base::string16 GetTooltipText(const gfx::Point& p) const override {
     const views::TooltipManager* tooltip_manager =
         GetWidget()->GetTooltipManager();
     gfx::Point location(p);
@@ -261,8 +260,7 @@
       tooltip_text_ = BookmarkBarView::CreateToolTipForURLAndTitle(
           max_tooltip_width_, tooltip_manager->GetFontList(), url_, GetText());
     }
-    *tooltip_text = tooltip_text_;
-    return !tooltip_text->empty();
+    return tooltip_text_;
   }
 
   void SetText(const base::string16& text) override {
@@ -367,11 +365,10 @@
     }
   }
 
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override {
-    if (label()->GetPreferredSize().width() > label()->size().width())
-      *tooltip = GetText();
-    return !tooltip->empty();
+  base::string16 GetTooltipText(const gfx::Point& p) const override {
+    return label()->GetPreferredSize().width() > label()->size().width()
+               ? GetText()
+               : base::string16();
   }
 
   bool OnMousePressed(const ui::MouseEvent& event) override {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_unittest.cc
index 7d537b1..b5a6b47 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_unittest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_unittest.cc
@@ -399,12 +399,9 @@
   views::LabelButton* button = test_helper_->GetBookmarkButton(0);
   ASSERT_TRUE(button);
   gfx::Point p;
-  base::string16 text;
-  button->GetTooltipText(p, &text);
-  EXPECT_EQ(base::ASCIIToUTF16("a\na.com"), text);
+  EXPECT_EQ(base::ASCIIToUTF16("a\na.com"), button->GetTooltipText(p));
   button->SetText(base::ASCIIToUTF16("new title"));
-  button->GetTooltipText(p, &text);
-  EXPECT_EQ(base::ASCIIToUTF16("new title\na.com"), text);
+  EXPECT_EQ(base::ASCIIToUTF16("new title\na.com"), button->GetTooltipText(p));
 
   widget.CloseNow();
 }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
index 0a46ed0..b4df8c0 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/task/post_task.h"
+#include "build/build_config.h"
 #include "chrome/browser/media/webrtc/desktop_media_list.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -40,7 +41,7 @@
 
 namespace {
 
-#if !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS) && defined(USE_AURA)
 DesktopMediaID::Id AcceleratedWidgetToDesktopMediaId(
     gfx::AcceleratedWidget accelerated_widget) {
 #if defined(OS_WIN)
@@ -215,24 +216,40 @@
     widget =
         constrained_window::ShowWebModalDialogViews(this, params.web_contents);
   } else {
+#if defined(OS_MACOSX)
+    // On Mac, MODAL_TYPE_CHILD with a null parent isn't allowed - fall back to
+    // MODAL_TYPE_WINDOW.
+    modality_ = ui::MODAL_TYPE_WINDOW;
+#endif
     widget = DialogDelegate::CreateDialogWidget(this, params.context, nullptr);
     widget->Show();
   }
   chrome::RecordDialogCreation(chrome::DialogIdentifier::DESKTOP_MEDIA_PICKER);
 
-  // If the picker is not modal to the calling web contents then it is displayed
-  // in its own top-level window, so in that case it needs to be filtered out of
-  // the list of top-level windows available for capture, and to achieve that
-  // the Id is passed to DesktopMediaList.
+#if defined(OS_MACOSX)
+  // On Mac, even modals are shown using separate native windows.
+  bool is_separate_native_window = true;
+#else
+  bool is_separate_native_window = !modal_dialog;
+#endif
+
+  // If the picker is a separate native window, it should not be shown in the
+  // source list, so its id is passed into NativeDesktopMediaList to be ignored.
   DesktopMediaID dialog_window_id;
-  if (!modal_dialog) {
+  if (is_separate_native_window) {
     dialog_window_id = DesktopMediaID::RegisterNativeWindow(
         DesktopMediaID::TYPE_WINDOW, widget->GetNativeWindow());
 
+#if !defined(OS_CHROMEOS) && defined(USE_AURA)
     // Set native window ID if the windows is outside Ash.
-#if !defined(OS_CHROMEOS)
     dialog_window_id.id = AcceleratedWidgetToDesktopMediaId(
         widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
+#elif defined(OS_MACOSX)
+    // On Mac, the window_id in DesktopMediaID is the same as the actual native
+    // window ID. Note that assuming this is a bit of a layering violation; the
+    // fact that this code makes that assumption is documented at the code that
+    // causes it to hold, so hopefully nobody changes that :)
+    dialog_window_id.id = dialog_window_id.window_id;
 #endif
   }
 
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
index 5860758..844b9e47 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
@@ -8,8 +8,10 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/browser/media/webrtc/fake_desktop_media_list.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/desktop_capture/desktop_media_list_view.h"
@@ -18,6 +20,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/ui_base_switches.h"
 #include "ui/events/event_utils.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
@@ -44,6 +47,13 @@
     test_helper_.test_views_delegate()->set_layout_provider(
         ChromeLayoutProvider::CreateLayoutProvider());
 
+#if defined(OS_MACOSX)
+    // These tests create actual child Widgets, which normally have a closure
+    // animation on Mac; inhibit it here to avoid the tests flakily hanging.
+    base::CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kDisableModalAnimations);
+#endif
+
     std::vector<std::unique_ptr<DesktopMediaList>> source_lists;
     for (auto type : kSourceTypes) {
       media_lists_[type] = new FakeDesktopMediaList(type);
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 8a5daca9..0c51488 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -465,16 +465,8 @@
   return false;
 }
 
-bool DownloadItemView::GetTooltipText(const gfx::Point& p,
-                                      base::string16* tooltip) const {
-  if (IsShowingWarningDialog()) {
-    tooltip->clear();
-    return false;
-  }
-
-  tooltip->assign(tooltip_text_);
-
-  return true;
+base::string16 DownloadItemView::GetTooltipText(const gfx::Point& p) const {
+  return IsShowingWarningDialog() ? base::string16() : tooltip_text_;
 }
 
 void DownloadItemView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
diff --git a/chrome/browser/ui/views/download/download_item_view.h b/chrome/browser/ui/views/download/download_item_view.h
index 90842a87..dd2910a4 100644
--- a/chrome/browser/ui/views/download/download_item_view.h
+++ b/chrome/browser/ui/views/download/download_item_view.h
@@ -101,8 +101,7 @@
   void OnMouseReleased(const ui::MouseEvent& event) override;
   void OnMouseCaptureLost() override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
   // view::InkDropHostView:
diff --git a/chrome/browser/ui/views/hover_button.cc b/chrome/browser/ui/views/hover_button.cc
index d7c60585..a996bb6 100644
--- a/chrome/browser/ui/views/hover_button.cc
+++ b/chrome/browser/ui/views/hover_button.cc
@@ -338,9 +338,8 @@
   if (secondary_view_) {
     gfx::Point point_in_secondary_view(point);
     ConvertPointToTarget(this, secondary_view_, &point_in_secondary_view);
-    base::string16 tooltip;
     if (secondary_view_->HitTestPoint(point_in_secondary_view) &&
-        secondary_view_->GetTooltipText(point_in_secondary_view, &tooltip)) {
+        !secondary_view_->GetTooltipText(point_in_secondary_view).empty()) {
       return secondary_view_;
     }
   }
diff --git a/chrome/browser/ui/views/hover_button_unittest.cc b/chrome/browser/ui/views/hover_button_unittest.cc
index 93577ffc..84150a80 100644
--- a/chrome/browser/ui/views/hover_button_unittest.cc
+++ b/chrome/browser/ui/views/hover_button_unittest.cc
@@ -100,13 +100,8 @@
         base::ASCIIToUTF16("\n"));
     EXPECT_EQ(expected, base::UTF8ToUTF16(accessible_name));
 
-    base::string16 tooltip_text;
-    button->GetTooltipText(gfx::Point(), &tooltip_text);
-    if (pair.tooltip) {
-      EXPECT_EQ(expected, tooltip_text);
-    } else {
-      EXPECT_EQ(base::string16(), tooltip_text);
-    }
+    EXPECT_EQ(pair.tooltip ? expected : base::string16(),
+              button->GetTooltipText(gfx::Point()));
   }
 }
 
@@ -124,10 +119,7 @@
     button->set_auto_compute_tooltip(false);
     button->SetTooltipText(custom_tooltip);
     button->SetSize(gfx::Size(kButtonWidth, 40));
-
-    base::string16 tooltip_text;
-    button->GetTooltipText(gfx::Point(), &tooltip_text);
-    EXPECT_EQ(custom_tooltip, tooltip_text);
+    EXPECT_EQ(custom_tooltip, button->GetTooltipText(gfx::Point()));
 
     // Make sure the accessible name is still set.
     ui::AXNodeData data;
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_view.cc
index cf60c44a..cd30ce25 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_view.cc
@@ -83,12 +83,9 @@
   node_data->SetName(GetTextForTooltipAndAccessibleName());
 }
 
-bool PageActionIconView::GetTooltipText(const gfx::Point& p,
-                                        base::string16* tooltip) const {
-  if (IsBubbleShowing())
-    return false;
-  *tooltip = GetTextForTooltipAndAccessibleName();
-  return true;
+base::string16 PageActionIconView::GetTooltipText(const gfx::Point& p) const {
+  return IsBubbleShowing() ? base::string16()
+                           : GetTextForTooltipAndAccessibleName();
 }
 
 bool PageActionIconView::OnMousePressed(const ui::MouseEvent& event) {
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view.h b/chrome/browser/ui/views/page_action/page_action_icon_view.h
index 4cedcd7..ae8b5ed 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_view.h
+++ b/chrome/browser/ui/views/page_action/page_action_icon_view.h
@@ -92,8 +92,7 @@
   // views::IconLabelBubbleView:
   SkColor GetTextColor() const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   void OnMouseReleased(const ui::MouseEvent& event) override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc b/chrome/browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc
index 300b512..83071a4 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc
@@ -35,9 +35,7 @@
   }
 
   base::string16 GetTooltipText() {
-    base::string16 tooltip;
-    GetView()->GetTooltipText(gfx::Point(), &tooltip);
-    return tooltip;
+    return GetView()->GetTooltipText(gfx::Point());
   }
 
   const gfx::ImageSkia& GetImage() {
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index a24bfa5..c67f2b1 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -534,16 +534,16 @@
   event->SetHandled();
 }
 
-bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const {
+base::string16 Tab::GetTooltipText(const gfx::Point& p) const {
   // TODO(corising): Make sure that accessibility is solved properly for hover
   // cards.
   // Tab hover cards replace tooltips.
   if (base::FeatureList::IsEnabled(features::kTabHoverCards))
-    return false;
+    return base::string16();
+
   // Note: Anything that affects the tooltip text should be accounted for when
   // calling TooltipTextChanged() from Tab::SetData().
-  *tooltip = GetTooltipText(data_.title, data_.alert_state);
-  return !tooltip->empty();
+  return GetTooltipText(data_.title, data_.alert_state);
 }
 
 bool Tab::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin) const {
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index 25b0fce..28843c3c 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -89,8 +89,7 @@
   void OnMouseEntered(const ui::MouseEvent& event) override;
   void OnMouseExited(const ui::MouseEvent& event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
   bool GetTooltipTextOrigin(const gfx::Point& p,
                             gfx::Point* origin) const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc
index 7b86a69..9a042d1 100644
--- a/chrome/browser/ui/views/tabs/tab_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -521,9 +521,7 @@
       EXPECT_FALSE(child.GetTooltipHandlerForPoint(midpoint));
       const gfx::Point mouse_hover_point =
           midpoint + child.GetMirroredPosition().OffsetFromOrigin();
-      base::string16 tooltip;
-      EXPECT_TRUE(tab.GetTooltipText(mouse_hover_point, &tooltip));
-      EXPECT_EQ(expected_tooltip, tooltip);
+      EXPECT_EQ(expected_tooltip, tab.GetTooltipText(mouse_hover_point));
     }
   }
 }
diff --git a/chrome/browser/ui/views/test/view_event_test_platform_part_chromeos.cc b/chrome/browser/ui/views/test/view_event_test_platform_part_chromeos.cc
index ba0cd3c..346159e8 100644
--- a/chrome/browser/ui/views/test/view_event_test_platform_part_chromeos.cc
+++ b/chrome/browser/ui/views/test/view_event_test_platform_part_chromeos.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_factory.h"
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/network/network_handler.h"
 #include "content/public/browser/gpu_interface_provider_factory.h"
 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
diff --git a/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
index 0c7dde6..c79ace77 100644
--- a/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
+++ b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
@@ -137,11 +137,10 @@
 }
 
 std::string BrowserActionTestUtilViews::GetTooltip(int index) {
-  base::string16 text;
-  GetContainer(browser_, test_helper_.get())
-      ->GetToolbarActionViewAt(index)
-      ->GetTooltipText(gfx::Point(), &text);
-  return base::UTF16ToUTF8(text);
+  base::string16 tooltip = GetContainer(browser_, test_helper_.get())
+                               ->GetToolbarActionViewAt(index)
+                               ->GetTooltipText(gfx::Point());
+  return base::UTF16ToUTF8(tooltip);
 }
 
 gfx::NativeView BrowserActionTestUtilViews::GetPopupNativeView() {
diff --git a/chrome/browser/ui/views/toolbar/reload_button.cc b/chrome/browser/ui/views/toolbar/reload_button.cc
index 20acb5ed..8f301b3 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.cc
+++ b/chrome/browser/ui/views/toolbar/reload_button.cc
@@ -100,14 +100,11 @@
     ChangeMode(intended_mode_, true);
 }
 
-bool ReloadButton::GetTooltipText(const gfx::Point& p,
-                                  base::string16* tooltip) const {
+base::string16 ReloadButton::GetTooltipText(const gfx::Point& p) const {
   int reload_tooltip = menu_enabled_ ?
       IDS_TOOLTIP_RELOAD_WITH_MENU : IDS_TOOLTIP_RELOAD;
-  int text_id =
-      (visible_mode_ == Mode::kReload) ? reload_tooltip : IDS_TOOLTIP_STOP;
-  tooltip->assign(l10n_util::GetStringUTF16(text_id));
-  return true;
+  return l10n_util::GetStringUTF16(
+      visible_mode_ == Mode::kReload ? reload_tooltip : IDS_TOOLTIP_STOP);
 }
 
 const char* ReloadButton::GetClassName() const {
diff --git a/chrome/browser/ui/views/toolbar/reload_button.h b/chrome/browser/ui/views/toolbar/reload_button.h
index b5b441d..18d8256 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.h
+++ b/chrome/browser/ui/views/toolbar/reload_button.h
@@ -46,8 +46,7 @@
 
   // ToolbarButton:
   void OnMouseExited(const ui::MouseEvent& event) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
   const char* GetClassName() const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   bool ShouldShowMenu() override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc
index e896019..d14e29d6 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc
@@ -212,9 +212,7 @@
 
   // Check that the tooltip and accessible state of the view match the
   // controller's.
-  base::string16 tooltip_test;
-  EXPECT_TRUE(view.GetTooltipText(gfx::Point(), &tooltip_test));
-  EXPECT_EQ(tooltip, tooltip_test);
+  EXPECT_EQ(tooltip, view.GetTooltipText(gfx::Point()));
   ui::AXNodeData ax_node_data;
   view.GetAccessibleNodeData(&ax_node_data);
   EXPECT_EQ(name, ax_node_data.GetString16Attribute(
diff --git a/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc
index 10c31f5..d38da3dd 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc
@@ -185,10 +185,8 @@
   EXPECT_EQ(DismissString(),
             bubble()->GetDialogClientView()->cancel_button()->GetText());
   EXPECT_TRUE(bubble()->learn_more_button());
-  base::string16 tooltip;
-  EXPECT_TRUE(bubble()->learn_more_button()->GetTooltipText(gfx::Point(0, 0),
-                                                            &tooltip));
-  EXPECT_EQ(LearnMoreString(), tooltip);
+  EXPECT_EQ(LearnMoreString(),
+            bubble()->learn_more_button()->GetTooltipText(gfx::Point(0, 0)));
   EXPECT_FALSE(bubble()->item_list());
 
   CloseBubble();
@@ -394,10 +392,8 @@
   std::unique_ptr<views::View> extra_view(TestCreateExtraView());
   ASSERT_TRUE(extra_view);
   ASSERT_EQ("ImageButton", std::string(extra_view->GetClassName()));
-  base::string16 tooltip;
-  EXPECT_TRUE(extra_view->GetTooltipText(gfx::Point(0, 0), &tooltip));
   EXPECT_EQ(l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSTALLED_BY_ADMIN),
-            tooltip);
+            extra_view->GetTooltipText(gfx::Point(0, 0)));
   CloseBubble();
 }
 
diff --git a/chrome/browser/ui/views/update_recommended_message_box.cc b/chrome/browser/ui/views/update_recommended_message_box.cc
index ec4983e..ec3ea90 100644
--- a/chrome/browser/ui/views/update_recommended_message_box.cc
+++ b/chrome/browser/ui/views/update_recommended_message_box.cc
@@ -17,7 +17,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #endif
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
index 210336fd..40a07e8 100644
--- a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_cras_audio_client.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "content/public/browser/web_ui.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_device.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc
index 0db2527c..b21850a 100644
--- a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc
@@ -20,7 +20,7 @@
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon_client.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/login/localized_values_builder.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
index 49d1fcd..3364324 100644
--- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
@@ -32,9 +32,9 @@
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power/power_manager_client.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
-#include "chromeos/dbus/power_policy_controller.h"
 #include "components/login/localized_values_builder.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h
index 35364a3..e9ae36a 100644
--- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h
@@ -17,7 +17,7 @@
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/cryptohome_client.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/auth/user_context.h"
 #include "services/device/public/mojom/wake_lock.mojom.h"
 #include "third_party/cros_system_api/dbus/cryptohome/dbus-constants.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc
index acdcf14..b1e45c1 100644
--- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc
+++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler_unittest.cc
@@ -18,8 +18,8 @@
 #include "chromeos/cryptohome/mock_async_method_caller.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_cryptohome_client.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/util/account_identifier_operators.h"
 #include "chromeos/login/auth/key.h"
 #include "chromeos/login/auth/user_context.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index 713eb50..6cf8708 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -81,7 +81,7 @@
 #include "chromeos/components/proximity_auth/screenlock_bridge.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/auth/key.h"
 #include "chromeos/login/auth/user_context.h"
 #include "chromeos/network/network_state.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index 622c34da..1754f10 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -26,7 +26,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chromeos/components/proximity_auth/screenlock_bridge.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/network/portal_detector/network_portal_detector.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
index 943d9bd0..fb31dea 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/ui/webui/help/help_utils_chromeos.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index 3bb9116..2ae0eb80 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -64,7 +64,7 @@
 #include "chrome/browser/ui/webui/help/help_utils_chromeos.h"
 #include "chrome/browser/ui/webui/help/version_updater_chromeos.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/util/version_loader.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
index 5344ee8..78869c7 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
@@ -13,8 +13,8 @@
 #include "base/scoped_observer.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
-#include "chromeos/dbus/power_manager_client.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_manager_client.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 
 class PrefChangeRegistrar;
 class PrefService;
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
index 9206cad..c27e55cb 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
@@ -14,8 +14,8 @@
 #include "base/values.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "components/policy/policy_constants.h"
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
index 6a5bc018..b4c83f3 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -342,10 +342,11 @@
   // request to an authenticator immediately after it has been
   // discovered, or whether the embedder/UI takes charge of that by
   // invoking its RequestCallback.
+  auto transport = authenticator.AuthenticatorTransport();
   return IsWebAuthnUIEnabled() &&
-         (!authenticator.AuthenticatorTransport() ||
-          *authenticator.AuthenticatorTransport() !=
-              device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
+         (!transport ||  // Windows
+          *transport == device::FidoTransportProtocol::kInternal ||
+          *transport == device::FidoTransportProtocol::kBluetoothLowEnergy);
 }
 
 void ChromeAuthenticatorRequestDelegate::FidoAuthenticatorAdded(
diff --git a/chrome/chrome_cleaner/BUILD.gn b/chrome/chrome_cleaner/BUILD.gn
index 2f7dcd5..9d73909 100644
--- a/chrome/chrome_cleaner/BUILD.gn
+++ b/chrome/chrome_cleaner/BUILD.gn
@@ -2,22 +2,35 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//chrome/chrome_cleaner/chrome_cleaner_args.gni")
 import("//testing/test.gni")
 
+source_set("engine_definitions") {
+  if (is_official_chrome_cleaner_build) {
+    deps = [
+      "//chrome_cleaner_internal:engine_definitions",
+    ]
+  } else {
+    deps = [
+      "//chrome/chrome_cleaner/engines/common:dummy_engine_resources",
+      "//chrome/chrome_cleaner/settings:dummy_engine_settings",
+    ]
+  }
+}
+
 test("chrome_cleaner_unittests") {
   sources = [
-    "//chrome/chrome_cleaner/engines/dummy_engine_resources.cc",
     "//chrome/chrome_cleaner/test/unit_test_override_command_line.cc",
     "test/test_main.cc",
   ]
 
   deps = [
     # Dependencies of the test harness.
+    ":engine_definitions",
     ":other_executable_definitions",
     "//base",
     "//base/test:test_support",
     "//chrome/chrome_cleaner/crash:crashpad_lib",
-    "//chrome/chrome_cleaner/engines:resources",
     "//chrome/chrome_cleaner/ipc:sandbox",
     "//chrome/chrome_cleaner/logging:common",
     "//chrome/chrome_cleaner/os:cleaner_os",
diff --git a/chrome/chrome_cleaner/crash/BUILD.gn b/chrome/chrome_cleaner/crash/BUILD.gn
index eb8b7f8b..7331d8e 100644
--- a/chrome/chrome_cleaner/crash/BUILD.gn
+++ b/chrome/chrome_cleaner/crash/BUILD.gn
@@ -28,9 +28,9 @@
     "//base:base",
     "//chrome/chrome_cleaner/chrome_utils:chrome_util_lib",
     "//chrome/chrome_cleaner/constants:common_strings",
-    "//chrome/chrome_cleaner/engines:resources",
     "//chrome/chrome_cleaner/logging:common",
     "//chrome/chrome_cleaner/os:common_os",
+    "//chrome/chrome_cleaner/settings:engine_settings",
     "//chrome/chrome_cleaner/settings:settings",
     "//chrome/chrome_cleaner/settings:settings_types",
     "//third_party/crashpad/crashpad/client",
diff --git a/chrome/chrome_cleaner/crash/crashpad_crash_client.cc b/chrome/chrome_cleaner/crash/crashpad_crash_client.cc
index 19976a16..c7935b5b 100644
--- a/chrome/chrome_cleaner/crash/crashpad_crash_client.cc
+++ b/chrome/chrome_cleaner/crash/crashpad_crash_client.cc
@@ -27,9 +27,9 @@
 #include "chrome/chrome_cleaner/chrome_utils/chrome_util.h"
 #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
 #include "chrome/chrome_cleaner/crash/crash_keys.h"
-#include "chrome/chrome_cleaner/engines/engine_resources.h"
 #include "chrome/chrome_cleaner/os/disk_util.h"
 #include "chrome/chrome_cleaner/os/file_path_sanitization.h"
+#include "chrome/chrome_cleaner/settings/engine_settings.h"
 #include "chrome/chrome_cleaner/settings/settings.h"
 #include "chrome/chrome_cleaner/settings/settings_types.h"
 #include "third_party/crashpad/crashpad/client/crash_report_database.h"
diff --git a/chrome/chrome_cleaner/engines/BUILD.gn b/chrome/chrome_cleaner/engines/common/BUILD.gn
similarity index 85%
rename from chrome/chrome_cleaner/engines/BUILD.gn
rename to chrome/chrome_cleaner/engines/common/BUILD.gn
index 5e76564..02d810cd 100644
--- a/chrome/chrome_cleaner/engines/BUILD.gn
+++ b/chrome/chrome_cleaner/engines/common/BUILD.gn
@@ -13,11 +13,10 @@
 
   public_deps = [
     "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
-    "//components/chrome_cleaner/public/constants:constants",
   ]
 }
 
-source_set("dummy_resources") {
+source_set("dummy_engine_resources") {
   sources = [
     "dummy_engine_resources.cc",
   ]
diff --git a/chrome/chrome_cleaner/engines/dummy_engine_resources.cc b/chrome/chrome_cleaner/engines/common/dummy_engine_resources.cc
similarity index 67%
rename from chrome/chrome_cleaner/engines/dummy_engine_resources.cc
rename to chrome/chrome_cleaner/engines/common/dummy_engine_resources.cc
index 79eabc4..d556685 100644
--- a/chrome/chrome_cleaner/engines/dummy_engine_resources.cc
+++ b/chrome/chrome_cleaner/engines/common/dummy_engine_resources.cc
@@ -2,33 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/chrome_cleaner/engines/engine_resources.h"
+#include "chrome/chrome_cleaner/engines/common/engine_resources.h"
 
 #include "chrome/chrome_cleaner/pup_data/pup_data.h"
 #include "chrome/chrome_cleaner/test/test_uws_catalog.h"
 
 namespace chrome_cleaner {
 
-bool IsSupportedEngine(Engine::Name engine) {
-  return engine == Engine::TEST_ONLY;
-}
-
-std::string GetEngineName(Engine::Name engine) {
-  return "Test";
-}
-
-std::string GetEngineVersion(Engine::Name engine) {
-  return "0.1";
-}
-
-ProcessInformation::Process GetEngineProcessType(Engine::Name engine) {
-  return ProcessInformation::TEST_SANDBOX;
-}
-
-ResultCode GetEngineDisconnectionErrorCode(Engine::Name engine) {
-  return RESULT_CODE_TEST_ENGINE_SANDBOX_DISCONNECTED_TOO_SOON;
-}
-
 void InitializePUPDataWithCatalog(Engine::Name engine) {
   PUPData::InitializePUPData({&TestUwSCatalog::GetInstance()});
 }
diff --git a/chrome/chrome_cleaner/engines/engine_resources.h b/chrome/chrome_cleaner/engines/common/engine_resources.h
similarity index 68%
rename from chrome/chrome_cleaner/engines/engine_resources.h
rename to chrome/chrome_cleaner/engines/common/engine_resources.h
index 983715b7..3e1fb74 100644
--- a/chrome/chrome_cleaner/engines/engine_resources.h
+++ b/chrome/chrome_cleaner/engines/common/engine_resources.h
@@ -2,39 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_CHROME_CLEANER_ENGINES_ENGINE_RESOURCES_H_
-#define CHROME_CHROME_CLEANER_ENGINES_ENGINE_RESOURCES_H_
+#ifndef CHROME_CHROME_CLEANER_ENGINES_COMMON_ENGINE_RESOURCES_H_
+#define CHROME_CHROME_CLEANER_ENGINES_COMMON_ENGINE_RESOURCES_H_
 
 #include <set>
-#include <string>
 #include <unordered_map>
 #include <vector>
 
 #include "base/strings/string16.h"
 #include "chrome/chrome_cleaner/logging/proto/shared_data.pb.h"
-#include "components/chrome_cleaner/public/constants/result_codes.h"
 
 namespace chrome_cleaner {
 
-// Returns true if the engine is supported.
-bool IsSupportedEngine(Engine::Name engine);
-
-// Returns the engine's name, which is also used as the name of its sandbox
-// process. This must be in a format suitable for logging in reports and crash
-// keys.
-std::string GetEngineName(Engine::Name engine);
-
-// Returns string representation of the engine's version or an empty string if
-// not available.
-std::string GetEngineVersion(Engine::Name engine);
-
-// Returns the type of the engine's sandbox process for logging.
-ProcessInformation::Process GetEngineProcessType(Engine::Name engine);
-
-// Returns the error code that should be logged if the connection to the
-// engine's sandbox is broken.
-ResultCode GetEngineDisconnectionErrorCode(Engine::Name engine);
-
 // Initializes PUPData with the engine's catalog.
 void InitializePUPDataWithCatalog(Engine::Name engine);
 
@@ -82,4 +61,4 @@
 
 }  // namespace chrome_cleaner
 
-#endif  // CHROME_CHROME_CLEANER_ENGINES_ENGINE_RESOURCES_H_
+#endif  // CHROME_CHROME_CLEANER_ENGINES_COMMON_ENGINE_RESOURCES_H_
diff --git a/chrome/chrome_cleaner/ipc/BUILD.gn b/chrome/chrome_cleaner/ipc/BUILD.gn
index a5c66212..0d315261 100644
--- a/chrome/chrome_cleaner/ipc/BUILD.gn
+++ b/chrome/chrome_cleaner/ipc/BUILD.gn
@@ -42,8 +42,8 @@
     "//base",
     "//chrome/chrome_cleaner/constants:common_strings",
     "//chrome/chrome_cleaner/crash:crashpad_lib",
-    "//chrome/chrome_cleaner/engines:resources",
     "//chrome/chrome_cleaner/os:common_os",
+    "//chrome/chrome_cleaner/settings:engine_settings",
     "//chrome/chrome_cleaner/settings:settings",
     "//chrome/chrome_cleaner/settings:settings_types",
     "//components/chrome_cleaner/public/constants:constants",
diff --git a/chrome/chrome_cleaner/ipc/sandbox.cc b/chrome/chrome_cleaner/ipc/sandbox.cc
index 01679f8..8b57f7b 100644
--- a/chrome/chrome_cleaner/ipc/sandbox.cc
+++ b/chrome/chrome_cleaner/ipc/sandbox.cc
@@ -23,11 +23,11 @@
 #include "base/win/win_util.h"
 #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
 #include "chrome/chrome_cleaner/crash/crash_reporter.h"
-#include "chrome/chrome_cleaner/engines/engine_resources.h"
 #include "chrome/chrome_cleaner/os/disk_util.h"
 #include "chrome/chrome_cleaner/os/inheritable_event.h"
 #include "chrome/chrome_cleaner/os/initializer.h"
 #include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
+#include "chrome/chrome_cleaner/settings/engine_settings.h"
 #include "chrome/chrome_cleaner/settings/settings.h"
 #include "components/chrome_cleaner/public/constants/constants.h"
 #include "sandbox/win/src/sandbox_factory.h"
diff --git a/chrome/chrome_cleaner/logging/BUILD.gn b/chrome/chrome_cleaner/logging/BUILD.gn
index bdadbef9..39441777 100644
--- a/chrome/chrome_cleaner/logging/BUILD.gn
+++ b/chrome/chrome_cleaner/logging/BUILD.gn
@@ -40,12 +40,12 @@
     "//chrome/chrome_cleaner//http:http",  # For safe_browsing_reporter
     "//chrome/chrome_cleaner/constants:common_strings",
     "//chrome/chrome_cleaner/constants:version_header",
-    "//chrome/chrome_cleaner/engines:resources",
     "//chrome/chrome_cleaner/http:http_status_codes",
     "//chrome/chrome_cleaner/logging/proto:removal_status_proto",
     "//chrome/chrome_cleaner/os:common_os",
     "//chrome/chrome_cleaner/proto:shared_pup_enums_proto",
     "//chrome/chrome_cleaner/pup_data:pup_data_base",
+    "//chrome/chrome_cleaner/settings:engine_settings",
     "//chrome/chrome_cleaner/settings:settings",
     "//chrome/chrome_cleaner/settings:settings_types",
     "//components/chrome_cleaner/public/constants:constants",
diff --git a/chrome/chrome_cleaner/logging/noop_logging_service.h b/chrome/chrome_cleaner/logging/noop_logging_service.h
index d4315c19a..e2c217c 100644
--- a/chrome/chrome_cleaner/logging/noop_logging_service.h
+++ b/chrome/chrome_cleaner/logging/noop_logging_service.h
@@ -86,6 +86,7 @@
 
   void LogProcessInformation(SandboxType process_type,
                              const SystemResourceUsage& usage) override;
+
   bool AllExpectedRemovalsConfirmed() const override;
   std::string RawReportContent() override;
   bool ReadContentFromFile(const base::FilePath& log_file) override;
diff --git a/chrome/chrome_cleaner/logging/proto/chrome_cleaner_report.proto b/chrome/chrome_cleaner/logging/proto/chrome_cleaner_report.proto
index 9999668..e1acba14 100644
--- a/chrome/chrome_cleaner/logging/proto/chrome_cleaner_report.proto
+++ b/chrome/chrome_cleaner/logging/proto/chrome_cleaner_report.proto
@@ -14,7 +14,7 @@
 package chrome_cleaner;
 
 // A report to be sent to the Safe Browsing API.
-// Next tag: 21.
+// Next tag: 22.
 message ChromeCleanerReport {
   // Deprecated client_id field that stopped being sent after 20.113.
   reserved 2;
@@ -22,6 +22,8 @@
   reserved 3;
   // Deprecated removed_uws field that stopped being sent after 16.88.
   reserved 12;
+  // Deprecated progress_stats field that stopped being sent after 39.195.200.
+  reserved 21;
 
   // Environmental data regarding the machine and the Cleaner.
   // Next tag: 11.
diff --git a/chrome/chrome_cleaner/logging/proto/reporter_logs.proto b/chrome/chrome_cleaner/logging/proto/reporter_logs.proto
index 9823310..a811a3d 100644
--- a/chrome/chrome_cleaner/logging/proto/reporter_logs.proto
+++ b/chrome/chrome_cleaner/logging/proto/reporter_logs.proto
@@ -18,10 +18,10 @@
 // FoilReporterLogs is a legacy name that must be kept because existing
 // analysis tools use it.
 //
-// Next tag: 12.
+// Next tag: 13.
 message FoilReporterLogs {
   // Corresponded to data related to reporter experiments.
-  reserved 7, 8;
+  reserved 7, 8, 12;
 
   // Environmental data regarding the machine and the Reporter.
   // Next tag: 9.
diff --git a/chrome/chrome_cleaner/logging/reporter_logging_service.h b/chrome/chrome_cleaner/logging/reporter_logging_service.h
index 4db388c..b9c8b2ab 100644
--- a/chrome/chrome_cleaner/logging/reporter_logging_service.h
+++ b/chrome/chrome_cleaner/logging/reporter_logging_service.h
@@ -93,6 +93,7 @@
 
   void LogProcessInformation(SandboxType process_type,
                              const SystemResourceUsage& usage) override;
+
   bool AllExpectedRemovalsConfirmed() const override;
   std::string RawReportContent() override;
   bool ReadContentFromFile(const base::FilePath& log_file) override;
diff --git a/chrome/chrome_cleaner/logging/utils.cc b/chrome/chrome_cleaner/logging/utils.cc
index 9e7e177..5b2773c 100644
--- a/chrome/chrome_cleaner/logging/utils.cc
+++ b/chrome/chrome_cleaner/logging/utils.cc
@@ -15,9 +15,9 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
-#include "chrome/chrome_cleaner/engines/engine_resources.h"
 #include "chrome/chrome_cleaner/logging/proto/removal_status.pb.h"
 #include "chrome/chrome_cleaner/os/disk_util.h"
+#include "chrome/chrome_cleaner/settings/engine_settings.h"
 #include "chrome/chrome_cleaner/settings/settings.h"
 #include "components/chrome_cleaner/public/constants/constants.h"
 
diff --git a/chrome/chrome_cleaner/scanner/BUILD.gn b/chrome/chrome_cleaner/scanner/BUILD.gn
index 98a43ef..ca7d40f3 100644
--- a/chrome/chrome_cleaner/scanner/BUILD.gn
+++ b/chrome/chrome_cleaner/scanner/BUILD.gn
@@ -54,6 +54,7 @@
   deps = [
     "//base",
     "//chrome/chrome_cleaner/constants:uws_id",
+    "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
     "//components/chrome_cleaner/public/constants",
   ]
 }
diff --git a/chrome/chrome_cleaner/scanner/scanner.h b/chrome/chrome_cleaner/scanner/scanner.h
index b80c64c..6b98baf 100644
--- a/chrome/chrome_cleaner/scanner/scanner.h
+++ b/chrome/chrome_cleaner/scanner/scanner.h
@@ -31,11 +31,10 @@
   virtual ~Scanner() {}
 
   // Start scanning for UwS. When an UwS is detected and if |Stop| has not been
-  // called, |found_uws_callback| is called. If scan is done in number of tasks,
-  // |progress_callback| may be called to report ratio of completed tasks. If
-  // the scan completes before |Stop| is called, then |done_callback| is called.
-  // Returns true if startup succeeded. If the startup fails, |done_callback|
-  // will be called with the failure code.
+  // called, |found_uws_callback| is called. If the scan completes before
+  // |Stop| is called, then |done_callback| is called. Returns true if startup
+  // succeeded. If the startup fails, |done_callback| will be called with the
+  // failure code.
   virtual bool Start(const FoundUwSCallback& found_uws_callback,
                      const DoneCallback done_callback) = 0;
 
diff --git a/chrome/chrome_cleaner/scanner/scanner_controller.cc b/chrome/chrome_cleaner/scanner/scanner_controller.cc
index 35e25ca4..46bfc2d 100644
--- a/chrome/chrome_cleaner/scanner/scanner_controller.cc
+++ b/chrome/chrome_cleaner/scanner/scanner_controller.cc
@@ -213,12 +213,19 @@
           ? RESULT_CODE_WATCHDOG_TIMEOUT_WITH_REMOVABLE_UWS
           : RESULT_CODE_WATCHDOG_TIMEOUT_WITHOUT_REMOVABLE_UWS;
 
-  registry_logger_->WriteExitCode(watchdog_result_code);
-  registry_logger_->WriteEndTime();
-
+  HandleWatchdogTimeout(watchdog_result_code);
   return watchdog_result_code;
 }
 
+void ScannerController::HandleWatchdogTimeout(ResultCode result_code) {
+  {
+    base::AutoLock lock(lock_);
+    result_code_ = result_code;
+  }
+  registry_logger_->WriteExitCode(result_code);
+  registry_logger_->WriteEndTime();
+}
+
 void ScannerController::LogsUploadComplete(bool success) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::move(quit_closure_).Run();
diff --git a/chrome/chrome_cleaner/scanner/scanner_controller.h b/chrome/chrome_cleaner/scanner/scanner_controller.h
index 450c49f3..cd0aa75 100644
--- a/chrome/chrome_cleaner/scanner/scanner_controller.h
+++ b/chrome/chrome_cleaner/scanner/scanner_controller.h
@@ -47,6 +47,9 @@
   // access to result_code_.
   virtual int WatchdogTimeoutCallback();
 
+  // Write exit information to the registry on timeouts.
+  void HandleWatchdogTimeout(ResultCode result_code);
+
   RegistryLogger* registry_logger_;
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/chrome/chrome_cleaner/settings/BUILD.gn b/chrome/chrome_cleaner/settings/BUILD.gn
index aacdfbc..91479c41 100644
--- a/chrome/chrome_cleaner/settings/BUILD.gn
+++ b/chrome/chrome_cleaner/settings/BUILD.gn
@@ -2,6 +2,27 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+source_set("engine_settings") {
+  sources = [
+    "engine_settings.h",
+  ]
+
+  public_deps = [
+    "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
+    "//components/chrome_cleaner/public/constants:constants",
+  ]
+}
+
+source_set("dummy_engine_settings") {
+  sources = [
+    "dummy_engine_settings.cc",
+  ]
+
+  deps = [
+    ":engine_settings",
+  ]
+}
+
 source_set("settings_types") {
   sources = [
     "settings_types.h",
@@ -18,11 +39,11 @@
     ":settings_types",
     "//base:base",
     "//chrome/chrome_cleaner/constants:common_strings",
-    "//chrome/chrome_cleaner/engines:resources",
     "//components/chrome_cleaner/public/constants:constants",
   ]
 
   public_deps = [
+    ":engine_settings",
     ":settings_definitions",
     "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
     "//mojo/public/cpp/platform",
@@ -67,6 +88,7 @@
   ]
 
   deps = [
+    ":engine_settings",
     ":settings",
     ":settings_definitions",
     "//base:base",
diff --git a/chrome/chrome_cleaner/settings/dummy_engine_settings.cc b/chrome/chrome_cleaner/settings/dummy_engine_settings.cc
new file mode 100644
index 0000000..2e31006
--- /dev/null
+++ b/chrome/chrome_cleaner/settings/dummy_engine_settings.cc
@@ -0,0 +1,33 @@
+// Copyright 2019 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 "chrome/chrome_cleaner/settings/engine_settings.h"
+
+namespace chrome_cleaner {
+
+bool IsSupportedEngine(Engine::Name engine) {
+  return engine == Engine::TEST_ONLY;
+}
+
+Engine::Name GetDefaultEngine() {
+  return Engine::TEST_ONLY;
+}
+
+std::string GetEngineName(Engine::Name engine) {
+  return "Test";
+}
+
+std::string GetEngineVersion(Engine::Name engine) {
+  return "0.1";
+}
+
+ProcessInformation::Process GetEngineProcessType(Engine::Name engine) {
+  return ProcessInformation::TEST_SANDBOX;
+}
+
+ResultCode GetEngineDisconnectionErrorCode(Engine::Name engine) {
+  return RESULT_CODE_TEST_ENGINE_SANDBOX_DISCONNECTED_TOO_SOON;
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/settings/engine_settings.h b/chrome/chrome_cleaner/settings/engine_settings.h
new file mode 100644
index 0000000..937911d
--- /dev/null
+++ b/chrome/chrome_cleaner/settings/engine_settings.h
@@ -0,0 +1,39 @@
+// Copyright 2019 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 CHROME_CHROME_CLEANER_SETTINGS_ENGINE_SETTINGS_H_
+#define CHROME_CHROME_CLEANER_SETTINGS_ENGINE_SETTINGS_H_
+
+#include <string>
+
+#include "chrome/chrome_cleaner/logging/proto/shared_data.pb.h"
+#include "components/chrome_cleaner/public/constants/result_codes.h"
+
+namespace chrome_cleaner {
+
+// Returns true if the engine is supported.
+bool IsSupportedEngine(Engine::Name engine);
+
+// Returns the engine to use by default if none is passed on the command-line.
+Engine::Name GetDefaultEngine();
+
+// Returns the engine's name, which is also used as the name of its sandbox
+// process. This must be in a format suitable for logging in reports and crash
+// keys.
+std::string GetEngineName(Engine::Name engine);
+
+// Returns string representation of the engine's version or an empty string if
+// not available.
+std::string GetEngineVersion(Engine::Name engine);
+
+// Returns the type of the engine's sandbox process for logging.
+ProcessInformation::Process GetEngineProcessType(Engine::Name engine);
+
+// Returns the error code that should be logged if the connection to the
+// engine's sandbox is broken.
+ResultCode GetEngineDisconnectionErrorCode(Engine::Name engine);
+
+}  // namespace chrome_cleaner
+
+#endif  // CHROME_CHROME_CLEANER_SETTINGS_ENGINE_SETTINGS_H_
diff --git a/chrome/chrome_cleaner/settings/settings.cc b/chrome/chrome_cleaner/settings/settings.cc
index 6033172..b8afb420 100644
--- a/chrome/chrome_cleaner/settings/settings.cc
+++ b/chrome/chrome_cleaner/settings/settings.cc
@@ -12,7 +12,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
-#include "chrome/chrome_cleaner/engines/engine_resources.h"
+#include "chrome/chrome_cleaner/settings/engine_settings.h"
 #include "chrome/chrome_cleaner/settings/settings_definitions.h"
 #include "mojo/public/cpp/platform/platform_channel.h"
 
@@ -30,7 +30,7 @@
 Engine::Name GetEngine(const base::CommandLine& command_line) {
   if (command_line.HasSwitch(kEngineSwitch)) {
     std::string value = command_line.GetSwitchValueASCII(kEngineSwitch);
-    int numeric_value = Engine::ESET;
+    int numeric_value = Engine::UNKNOWN;
     if (base::StringToInt(value, &numeric_value) &&
         Engine_Name_IsValid(numeric_value) &&
         numeric_value != Engine::UNKNOWN &&
@@ -38,10 +38,11 @@
       return static_cast<Engine::Name>(numeric_value);
     }
 
-    LOG(WARNING) << "Invalid engine (" << value << "), using default engine";
+    LOG(WARNING) << "Invalid engine (" << value << "), using default engine "
+                 << GetDefaultEngine();
   }
 
-  return Engine::ESET;
+  return GetDefaultEngine();
 }
 
 ExecutionMode GetExecutionMode(const base::CommandLine& command_line) {
@@ -338,6 +339,7 @@
   session_id_ = GetSessionId(command_line);
   cleanup_id_ = GetCleanerRunId(command_line);
   engine_ = GetEngine(command_line);
+  DCHECK_NE(engine_, Engine::UNKNOWN);
 
   metrics_enabled_ = command_line.HasSwitch(kUmaUserSwitch);
   // WARNING: this switch is used by internal test systems, be careful when
diff --git a/chrome/chrome_cleaner/settings/settings.h b/chrome/chrome_cleaner/settings/settings.h
index 601ea99..380b861c 100644
--- a/chrome/chrome_cleaner/settings/settings.h
+++ b/chrome/chrome_cleaner/settings/settings.h
@@ -6,7 +6,6 @@
 #define CHROME_CHROME_CLEANER_SETTINGS_SETTINGS_H_
 
 #include <windows.h>
-
 #include <string>
 #include <unordered_map>
 #include <vector>
@@ -181,7 +180,7 @@
   bool has_parent_pipe_handle_ = false;
 
   // Engine selection settings.
-  Engine::Name engine_ = Engine::ESET;
+  Engine::Name engine_ = Engine::UNKNOWN;
 
   bool run_without_sandbox_for_testing_ = false;
 
diff --git a/chrome/chrome_cleaner/settings/settings_unittest.cc b/chrome/chrome_cleaner/settings/settings_unittest.cc
index 778f0475..2f1eba9 100644
--- a/chrome/chrome_cleaner/settings/settings_unittest.cc
+++ b/chrome/chrome_cleaner/settings/settings_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
+#include "chrome/chrome_cleaner/settings/engine_settings.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chrome_cleaner {
@@ -44,9 +45,12 @@
 };
 
 TEST_F(SettingsTest, EngineDefaultValue) {
+  ASSERT_NE(GetDefaultEngine(), Engine::UNKNOWN);
+  ASSERT_NE(GetDefaultEngine(), Engine::DEPRECATED_URZA);
+
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   Settings* settings = ReinitializeSettings(command_line);
-  EXPECT_EQ(Engine::ESET, settings->engine());
+  EXPECT_EQ(GetDefaultEngine(), settings->engine());
 }
 
 TEST_F(SettingsTest, ValidEngines) {
@@ -55,10 +59,12 @@
     command_line.AppendSwitchASCII(chrome_cleaner::kEngineSwitch,
                                    base::NumberToString(index));
     Settings* settings = ReinitializeSettings(command_line);
-    if (index != Engine::UNKNOWN && index != Engine::DEPRECATED_URZA)
+    if (index != Engine::UNKNOWN && index != Engine::DEPRECATED_URZA) {
       EXPECT_EQ(static_cast<Engine::Name>(index), settings->engine());
-    else
-      EXPECT_EQ(Engine::ESET, settings->engine());  // Fallback to default.
+    } else {
+      // Fall back to default.
+      EXPECT_EQ(GetDefaultEngine(), settings->engine());
+    }
   }
 }
 
@@ -67,7 +73,7 @@
   command_line.AppendSwitchASCII(chrome_cleaner::kEngineSwitch,
                                  base::NumberToString(kInvalidEngineValue));
   Settings* settings = ReinitializeSettings(command_line);
-  EXPECT_EQ(Engine::ESET, settings->engine());
+  EXPECT_EQ(GetDefaultEngine(), settings->engine());
 }
 
 TEST_F(SettingsTest, EngineNonNumericValue) {
@@ -75,7 +81,7 @@
   command_line.AppendSwitchASCII(chrome_cleaner::kEngineSwitch,
                                  kNonNumericValue);
   Settings* settings = ReinitializeSettings(command_line);
-  EXPECT_EQ(Engine::ESET, settings->engine());
+  EXPECT_EQ(GetDefaultEngine(), settings->engine());
 }
 
 TEST_F(SettingsTest, CleanerRunId_Generated) {
diff --git a/chrome/chrome_cleaner/test/BUILD.gn b/chrome/chrome_cleaner/test/BUILD.gn
index c62ce65..8426dd6 100644
--- a/chrome/chrome_cleaner/test/BUILD.gn
+++ b/chrome/chrome_cleaner/test/BUILD.gn
@@ -234,8 +234,8 @@
     "//base/test:test_support",
     "//build/win:default_exe_manifest",
     "//chrome/chrome_cleaner:other_executable_definitions",
-    "//chrome/chrome_cleaner/engines:dummy_resources",
     "//chrome/chrome_cleaner/os:common_os",
+    "//chrome/chrome_cleaner/settings:dummy_engine_settings",
   ]
 }
 
diff --git a/chrome/chrome_cleaner/test/resources/BUILD.gn b/chrome/chrome_cleaner/test/resources/BUILD.gn
index bb3b6660..2774c1a 100644
--- a/chrome/chrome_cleaner/test/resources/BUILD.gn
+++ b/chrome/chrome_cleaner/test/resources/BUILD.gn
@@ -15,6 +15,7 @@
   deps = [
     "//chrome/chrome_cleaner/proto:file_digest_proto",
     "//chrome/chrome_cleaner/test:empty_dll",
+    "//third_party/protobuf:py_proto",
   ]
 
   inputs = [
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index 065a299..4e065b1 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -279,7 +279,7 @@
   },
   "contextMenus": {
     "dependencies": ["permission:contextMenus"],
-    "contexts": ["blessed_extension"]
+    "contexts": ["blessed_extension", "extension_service_worker"]
   },
   "contextMenusInternal": {
     "internal": true,
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.cc b/chrome/common/media_router/providers/cast/cast_media_source.cc
index 4904ee0f..7d0fe5b5 100644
--- a/chrome/common/media_router/providers/cast/cast_media_source.cc
+++ b/chrome/common/media_router/providers/cast/cast_media_source.cc
@@ -8,12 +8,25 @@
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/media_router/media_source_helper.h"
+#include "components/cast_channel/enum_table.h"
 #include "net/base/url_util.h"
 #include "url/gurl.h"
 #include "url/url_util.h"
 
 using cast_channel::BroadcastRequest;
 
+namespace cast_util {
+template <>
+const EnumTable<media_router::AutoJoinPolicy>
+    EnumTable<media_router::AutoJoinPolicy>::instance({
+        {media_router::AutoJoinPolicy::kTabAndOriginScoped,
+         "tab_and_origin_scoped"},
+        {media_router::AutoJoinPolicy::kOriginScoped, "origin_scoped"},
+        {media_router::AutoJoinPolicy::kPageScoped, "page_scoped"},
+        // kNone deliberately omitted.
+    });
+}  // namespace cast_util
+
 namespace media_router {
 
 namespace {
@@ -24,6 +37,7 @@
 constexpr char kBroadcastMessageKey[] = "broadcastMessage";
 constexpr char kClientIdKey[] = "clientId";
 constexpr char kLaunchTimeoutKey[] = "launchTimeout";
+constexpr char kAutoJoinPolicyKey[] = "autoJoinPolicy";
 
 // Parameter keys used by legacy Cast URLs.
 constexpr char kLegacyAppIdKey[] = "__castAppId__";
@@ -31,6 +45,7 @@
 constexpr char kLegacyBroadcastMessageKey[] = "__castBroadcastMessage__";
 constexpr char kLegacyClientIdKey[] = "__castClientId__";
 constexpr char kLegacyLaunchTimeoutKey[] = "__castLaunchTimeout__";
+constexpr char kLegacyAutoJoinPolicyKey[] = "__castAutoJoinPolicy__";
 
 // TODO(imcheng): Move to common utils?
 std::string DecodeURLComponent(const std::string& encoded) {
@@ -80,6 +95,7 @@
 std::unique_ptr<CastMediaSource> CreateFromURLParams(
     const MediaSource::Id& source_id,
     const std::vector<CastAppInfo>& app_infos,
+    const std::string& auto_join_policy_str,
     const std::string& client_id,
     const std::string& broadcast_namespace,
     const std::string& broadcast_message,
@@ -87,7 +103,10 @@
   if (app_infos.empty())
     return nullptr;
 
-  auto cast_source = std::make_unique<CastMediaSource>(source_id, app_infos);
+  auto cast_source = std::make_unique<CastMediaSource>(
+      source_id, app_infos,
+      cast_util::StringToEnum<AutoJoinPolicy>(auto_join_policy_str)
+          .value_or(AutoJoinPolicy::kNone));
   cast_source->set_client_id(client_id);
   if (!broadcast_namespace.empty() && !broadcast_message.empty()) {
     cast_source->set_broadcast_request(
@@ -106,7 +125,7 @@
     return nullptr;
 
   std::string broadcast_namespace, broadcast_message, capabilities;
-  std::string client_id;
+  std::string client_id, auto_join_policy;
   int launch_timeout_millis = 0;
   for (net::QueryIterator query_it(url); !query_it.IsAtEnd();
        query_it.Advance()) {
@@ -127,6 +146,8 @@
       if (!base::StringToInt(value, &launch_timeout_millis) ||
           launch_timeout_millis < 0)
         launch_timeout_millis = 0;
+    } else if (key == kAutoJoinPolicyKey) {
+      auto_join_policy = value;
     }
   }
 
@@ -141,7 +162,8 @@
   }
 
   return CreateFromURLParams(
-      source_id, {app_info}, client_id, broadcast_namespace, broadcast_message,
+      source_id, {app_info}, auto_join_policy, client_id, broadcast_namespace,
+      broadcast_message,
       base::TimeDelta::FromMilliseconds(launch_timeout_millis));
 }
 
@@ -153,7 +175,7 @@
   // Legacy URLs can specify multiple apps.
   std::vector<std::string> app_id_params;
   std::string broadcast_namespace, broadcast_message;
-  std::string client_id;
+  std::string client_id, auto_join_policy;
   int launch_timeout_millis = 0;
   for (const auto& key_value : parameters) {
     const auto& key = key_value.first;
@@ -171,6 +193,8 @@
       if (!base::StringToInt(value, &launch_timeout_millis) ||
           launch_timeout_millis < 0)
         launch_timeout_millis = 0;
+    } else if (key == kLegacyAutoJoinPolicyKey) {
+      auto_join_policy = value;
     }
   }
 
@@ -208,7 +232,8 @@
     return nullptr;
 
   return CreateFromURLParams(
-      source_id, app_infos, client_id, broadcast_namespace, broadcast_message,
+      source_id, app_infos, auto_join_policy, client_id, broadcast_namespace,
+      broadcast_message,
       base::TimeDelta::FromMilliseconds(launch_timeout_millis));
 }
 
@@ -253,8 +278,11 @@
 }
 
 CastMediaSource::CastMediaSource(const MediaSource::Id& source_id,
-                                 const std::vector<CastAppInfo>& app_infos)
-    : source_id_(source_id), app_infos_(app_infos) {}
+                                 const std::vector<CastAppInfo>& app_infos,
+                                 AutoJoinPolicy auto_join_policy)
+    : source_id_(source_id),
+      app_infos_(app_infos),
+      auto_join_policy_(auto_join_policy) {}
 CastMediaSource::CastMediaSource(const CastMediaSource& other) = default;
 CastMediaSource::~CastMediaSource() = default;
 
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.h b/chrome/common/media_router/providers/cast/cast_media_source.h
index 2bd2942..bda28af 100644
--- a/chrome/common/media_router/providers/cast/cast_media_source.h
+++ b/chrome/common/media_router/providers/cast/cast_media_source.h
@@ -39,6 +39,21 @@
   int required_capabilities = cast_channel::CastDeviceCapability::NONE;
 };
 
+// Auto-join policy determines when the SDK will automatically connect a sender
+// application to an existing session after API initialization.
+enum class AutoJoinPolicy {
+  // Automatically connects when the session was started with the same app ID,
+  // in the same tab and page origin.
+  kTabAndOriginScoped,
+  // Automatically connects when the session was started with the same app ID
+  // and the same page origin (regardless of tab).
+  kOriginScoped,
+  // No automatic connection.
+  kPageScoped,
+  // No policy was specified.  Generally treated the same as kPageScoped.
+  kNone,
+};
+
 // Represents a MediaSource parsed into structured, Cast specific data. The
 // following MediaSources can be parsed into CastMediaSource:
 // - Cast Presentation URLs
@@ -53,7 +68,8 @@
   static std::unique_ptr<CastMediaSource> FromAppId(const std::string& app_id);
 
   CastMediaSource(const MediaSource::Id& source_id,
-                  const std::vector<CastAppInfo>& app_infos);
+                  const std::vector<CastAppInfo>& app_infos,
+                  AutoJoinPolicy auto_join_policy = AutoJoinPolicy::kNone);
   CastMediaSource(const CastMediaSource& other);
   ~CastMediaSource();
 
@@ -81,10 +97,12 @@
     broadcast_request_ = request;
   }
 
+  AutoJoinPolicy auto_join_policy() const { return auto_join_policy_; }
+
  private:
-  // TODO(imcheng): Fill in other parameters.
   MediaSource::Id source_id_;
   std::vector<CastAppInfo> app_infos_;
+  AutoJoinPolicy auto_join_policy_;
   base::TimeDelta launch_timeout_ = kDefaultLaunchTimeout;
   // Empty if not set.
   std::string client_id_;
diff --git a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
index dabbeff..a9f9747 100644
--- a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
+++ b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
@@ -15,7 +15,8 @@
       "&broadcastNamespace=namespace"
       "&broadcastMessage=message"
       "&clientId=12345"
-      "&launchTimeout=30000");
+      "&launchTimeout=30000"
+      "&autoJoinPolicy=tab_and_origin_scoped");
   std::unique_ptr<CastMediaSource> source =
       CastMediaSource::FromMediaSourceId(source_id);
   ASSERT_TRUE(source);
@@ -32,6 +33,7 @@
   EXPECT_EQ("message", broadcast_request->message);
   EXPECT_EQ("12345", source->client_id());
   EXPECT_EQ(base::TimeDelta::FromMilliseconds(30000), source->launch_timeout());
+  EXPECT_EQ(AutoJoinPolicy::kTabAndOriginScoped, source->auto_join_policy());
 }
 
 TEST(CastMediaSourceTest, FromLegacyCastURL) {
@@ -40,7 +42,8 @@
       "/__castBroadcastNamespace__=namespace"
       "/__castBroadcastMessage__=message"
       "/__castClientId__=12345"
-      "/__castLaunchTimeout__=30000");
+      "/__castLaunchTimeout__=30000"
+      "/__castAutoJoinPolicy__=origin_scoped");
   std::unique_ptr<CastMediaSource> source =
       CastMediaSource::FromMediaSourceId(source_id);
   ASSERT_TRUE(source);
@@ -57,6 +60,7 @@
   EXPECT_EQ("message", broadcast_request->message);
   EXPECT_EQ("12345", source->client_id());
   EXPECT_EQ(base::TimeDelta::FromMilliseconds(30000), source->launch_timeout());
+  EXPECT_EQ(AutoJoinPolicy::kOriginScoped, source->auto_join_policy());
 }
 
 TEST(CastMediaSourceTest, FromPresentationURL) {
@@ -70,6 +74,7 @@
   EXPECT_EQ(kCastStreamingAudioAppId, source->app_infos()[1].app_id);
   EXPECT_TRUE(source->client_id().empty());
   EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout());
+  EXPECT_EQ(AutoJoinPolicy::kNone, source->auto_join_policy());
 }
 
 TEST(CastMediaSourceTest, FromMirroringURN) {
@@ -83,6 +88,7 @@
   EXPECT_EQ(kCastStreamingAudioAppId, source->app_infos()[1].app_id);
   EXPECT_TRUE(source->client_id().empty());
   EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout());
+  EXPECT_EQ(AutoJoinPolicy::kNone, source->auto_join_policy());
 }
 
 TEST(CastMediaSourceTest, FromDesktopUrn) {
@@ -95,6 +101,7 @@
   EXPECT_EQ(kCastStreamingAppId, source->app_infos()[0].app_id);
   EXPECT_TRUE(source->client_id().empty());
   EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout());
+  EXPECT_EQ(AutoJoinPolicy::kNone, source->auto_join_policy());
 }
 
 TEST(CastMediaSourceTest, FromInvalidSource) {
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index e499334a8f..7926ebc 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -952,6 +952,9 @@
 #endif
 const char kCurrentThemePackFilename[] = "extensions.theme.pack";
 const char kCurrentThemeID[] = "extensions.theme.id";
+const char kAutogeneratedThemeColor[] = "autogenerated.theme.color";
+
+// TODO(crbug.com/937956): These prefs are unused and should be removed.
 const char kCurrentThemeImages[] = "extensions.theme.images";
 const char kCurrentThemeColors[] = "extensions.theme.colors";
 const char kCurrentThemeTints[] = "extensions.theme.tints";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 6456f191..5d34f1a 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -306,6 +306,7 @@
 #endif
 extern const char kCurrentThemePackFilename[];
 extern const char kCurrentThemeID[];
+extern const char kAutogeneratedThemeColor[];
 extern const char kCurrentThemeImages[];
 extern const char kCurrentThemeColors[];
 extern const char kCurrentThemeTints[];
diff --git a/chrome/common/safe_browsing/rar_analyzer.cc b/chrome/common/safe_browsing/rar_analyzer.cc
index a9161d4..48594337 100644
--- a/chrome/common/safe_browsing/rar_analyzer.cc
+++ b/chrome/common/safe_browsing/rar_analyzer.cc
@@ -49,6 +49,9 @@
     return;
   }
 
+  UMA_HISTOGRAM_BOOLEAN("SBClientDownload.RarHeadersEncrypted",
+                        archive->Encrypted);
+
   // If the file is too big to unpack, fall back to the old method.
   bool too_big_to_unpack =
       base::checked_cast<uint64_t>(rar_file.GetLength()) >
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base.cc b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
index 49f9597..9142051 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
@@ -1147,18 +1147,6 @@
                                          puiprocinfo, 0, &wait_thread_id);
   if (wait_thread != 0) {
     LOGFN(INFO) << "Started wait thread id=" << wait_thread_id;
-
-    // CreateAndRunLogonStub() is called from GetSerialization().  Winlogon
-    // will block the UI and show a spinner until the latter returns.  In most
-    // cases GetSerialization() should return immediately so that users don't
-    // get blocked out of the winlogon UX.  For example users could decide to
-    // sign in with another user or another credential provider.  However, in
-    // case where enrollment to Google MDM is required, the UI should be
-    // blocked until the enrollment either succeeds or fails.  To perform this
-    // CreateAndRunLogonStub() waits for WaitForLoginUI() to complete.
-    if (MdmEnrollmentEnabled())
-      ::WaitForSingleObject(reinterpret_cast<HANDLE>(wait_thread), INFINITE);
-
     ::CloseHandle(reinterpret_cast<HANDLE>(wait_thread));
   } else {
     HRESULT hr = HRESULT_FROM_WIN32(::GetLastError());
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 382f7ba2..57303fb2 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1613,6 +1613,7 @@
         "../browser/ui/views/bookmarks/bookmark_editor_view_browsertest.cc",
         "../browser/ui/views/certificate_selector_dialog_browsertest.cc",
         "../browser/ui/views/collected_cookies_views_browsertest.cc",
+        "../browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc",
         "../browser/ui/views/extensions/bookmark_override_browsertest.cc",
         "../browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc",
         "../browser/ui/views/extensions/extension_message_bubble_view_browsertest.cc",
@@ -2314,7 +2315,6 @@
     }
 
     if (use_aura) {
-      sources += [ "../browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc" ]
       if (enable_wifi_display) {
         sources += [
           "../../extensions/browser/api/display_source/display_source_apitestbase.cc",
@@ -4409,7 +4409,6 @@
       "../browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm",
       "../browser/ui/cocoa/history_overlay_controller_unittest.mm",
       "../browser/ui/cocoa/main_menu_builder_unittest.mm",
-      "../browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm",
       "../browser/ui/cocoa/notifications/notification_builder_mac_unittest.mm",
       "../browser/ui/cocoa/notifications/notification_response_builder_mac_unittest.mm",
       "../browser/ui/cocoa/nsmenuitem_additions_unittest.mm",
@@ -4552,6 +4551,7 @@
       "../browser/ui/views/bookmarks/bookmark_editor_view_unittest.cc",
       "../browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc",
       "../browser/ui/views/confirm_bubble_views_unittest.cc",
+      "../browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc",
       "../browser/ui/views/device_chooser_content_view_unittest.cc",
       "../browser/ui/views/download/download_item_view_unittest.cc",
       "../browser/ui/views/extensions/chooser_dialog_view_unittest.cc",
@@ -4623,9 +4623,7 @@
     if (use_aura) {
       sources += [
         "../browser/ui/views/apps/shaped_app_window_targeter_unittest.cc",
-
         # Get this compiling on Mac - see http://crbug.com/657883.
-        "../browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc",
       ]
       if (use_nss_certs) {
         sources += [
@@ -5951,9 +5949,15 @@
   test("usage_time_limit_unittests") {
     testonly = true
     sources = [
+      "../browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc",
+      "../browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h",
+      "../browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc",
       "../browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_loader.cc",
       "../browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_loader.h",
       "../browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_loader_unittest.cc",
+      "../browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test.cc",
+      "../browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.cc",
+      "../browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h",
       "../browser/chromeos/child_accounts/time_limit_consistency_test/proto_matcher.h",
       "../browser/chromeos/child_accounts/time_limit_consistency_test/run_all_unittests.cc",
       "../browser/chromeos/child_accounts/time_limit_override.cc",
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc
index a610a86..5188181f 100644
--- a/chrome/test/chromedriver/chrome_launcher.cc
+++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -417,8 +417,8 @@
     VLOG(0) << "Minidump generation specified. Will save dumps to: "
             << capabilities.minidump_path;
 
-    options.environ["CHROME_HEADLESS"] = 1;
-    options.environ["BREAKPAD_DUMP_LOCATION"] = capabilities.minidump_path;
+    options.environment["CHROME_HEADLESS"] = 1;
+    options.environment["BREAKPAD_DUMP_LOCATION"] = capabilities.minidump_path;
 
     if (!command.HasSwitch(kEnableCrashReport))
       command.AppendSwitch(kEnableCrashReport);
@@ -430,7 +430,7 @@
 
 #if !defined(OS_WIN)
   if (!capabilities.log_path.empty())
-    options.environ["CHROME_LOG_FILE"] = capabilities.log_path;
+    options.environment["CHROME_LOG_FILE"] = capabilities.log_path;
   if (capabilities.detach)
     options.new_process_group = true;
 #endif
diff --git a/chrome/test/data/extensions/context_menus/checkboxes/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/checkboxes/service_worker/manifest.json
new file mode 100644
index 0000000..355c958
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/checkboxes/service_worker/manifest.json
@@ -0,0 +1,8 @@
+{
+  "name" : "Context Menus Test Extension",
+  "description": "Tests context menu checkbox update",
+  "version" : "0.1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus"],
+  "background": { "service_worker_script": "test.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/checkboxes/service_worker/test.js b/chrome/test/data/extensions/context_menus/checkboxes/service_worker/test.js
new file mode 100644
index 0000000..9f44aff
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/checkboxes/service_worker/test.js
@@ -0,0 +1,58 @@
+// Copyright 2019 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.
+
+function createFirstCheckbox() {
+  return new Promise(function(resolve, reject) {
+    chrome.contextMenus.create({
+      id: 'checkbox1',
+      type: 'checkbox',
+      title: 'Checkbox 1',
+      onclick: function() {
+        chrome.test.sendMessage('onclick checkbox 1');
+      }
+    }, resolve);
+  });
+}
+
+function createSecondCheckbox() {
+  return new Promise(function(resolve, reject) {
+    chrome.contextMenus.create({
+      id: 'checkbox2',
+      type: 'checkbox',
+      title: 'Checkbox 2',
+      onclick: function() {
+        chrome.test.sendMessage('onclick checkbox 2');
+      }
+    }, resolve);
+  });
+}
+
+function checkSecondCheckbox() {
+  return new Promise(function(resolve, reject) {
+    chrome.contextMenus.update('checkbox2', {checked: true}, resolve);
+  });
+}
+
+function createNormalMenuItem() {
+  return new Promise(function(resolve, reject) {
+    chrome.contextMenus.create({
+      id: 'item1',
+      title: 'Item 1',
+      onclick: function() {
+        chrome.test.sendMessage('onclick normal item');
+        chrome.contextMenus.update('checkbox2', {checked: false}, function() {
+          chrome.test.sendMessage('checkbox2 unchecked');
+        });
+      }
+    }, resolve);
+  });
+}
+
+createFirstCheckbox()
+    .then(createSecondCheckbox)
+    .then(checkSecondCheckbox)
+    .then(createNormalMenuItem)
+    .then(function() {
+      chrome.test.sendMessage('Menu created');
+    });
diff --git a/chrome/test/data/extensions/context_menus/enabled/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/enabled/service_worker/manifest.json
new file mode 100644
index 0000000..19d6c4be
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/enabled/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name" : "Context Menus Test Extension",
+  "version" : "0.1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus", "tabs" ],
+  "background": { "service_worker_script": "test.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/enabled/service_worker/test.js b/chrome/test/data/extensions/context_menus/enabled/service_worker/test.js
new file mode 100644
index 0000000..bae33f5
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/enabled/service_worker/test.js
@@ -0,0 +1,17 @@
+// Copyright 2019 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.
+
+var onMessageReply = function(message) {
+  var enabled = (message == 'start enabled');
+  var id = chrome.contextMenus.create({title: 'Extension Item 1',
+                                       enabled: enabled}, function() {
+    chrome.test.sendMessage('create', function(message) {
+      chrome.contextMenus.update(id, {enabled: !enabled}, function() {
+        chrome.test.sendMessage('update');
+      });
+    });
+  });
+};
+
+chrome.test.sendMessage('begin', onMessageReply);
diff --git a/chrome/test/data/extensions/context_menus/frames/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/frames/service_worker/manifest.json
new file mode 100644
index 0000000..19d6c4be
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/frames/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name" : "Context Menus Test Extension",
+  "version" : "0.1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus", "tabs" ],
+  "background": { "service_worker_script": "test.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/frames/service_worker/test.js b/chrome/test/data/extensions/context_menus/frames/service_worker/test.js
new file mode 100644
index 0000000..e4dbbb02
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/frames/service_worker/test.js
@@ -0,0 +1,22 @@
+// Copyright (c) 2019 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.
+
+function onclick(info, tab) {
+  chrome.test.sendMessage('pageUrl=' + info.pageUrl +
+      ', frameUrl=' + info.frameUrl +
+      ', frameId=' + info.frameId);
+}
+chrome.contextMenus.create(
+    {title:'Page item', contexts: ['page'], id: 'item1', onclick: onclick},
+    function() {
+      if (!chrome.runtime.lastError) {
+        chrome.contextMenus.create(
+        {title: 'Frame item', contexts: ['frame']},
+        function() {
+          if (!chrome.runtime.lastError) {
+            chrome.test.sendMessage('created items');
+          }
+        });
+      }
+    });
diff --git a/chrome/test/data/extensions/context_menus/long_title/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/long_title/service_worker/manifest.json
new file mode 100644
index 0000000..19d6c4be
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/long_title/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name" : "Context Menus Test Extension",
+  "version" : "0.1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus", "tabs" ],
+  "background": { "service_worker_script": "test.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/long_title/service_worker/test.js b/chrome/test/data/extensions/context_menus/long_title/service_worker/test.js
new file mode 100644
index 0000000..a66b079e
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/long_title/service_worker/test.js
@@ -0,0 +1,15 @@
+// Copyright (c) 2010 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.
+
+// Make a 1000-character long title.
+var title = '';
+for (var i = 0; i < 1000; i++) {
+  title += 'x';
+}
+chrome.test.log('creating item');
+chrome.contextMenus.create({title: title}, function() {
+  if (!chrome.runtime.lastError) {
+    chrome.test.sendMessage('created');
+  }
+});
diff --git a/chrome/test/data/extensions/context_menus/onclick_null/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/onclick_null/service_worker/manifest.json
new file mode 100644
index 0000000..19d6c4be
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/onclick_null/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name" : "Context Menus Test Extension",
+  "version" : "0.1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus", "tabs" ],
+  "background": { "service_worker_script": "test.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/onclick_null/service_worker/test.js b/chrome/test/data/extensions/context_menus/onclick_null/service_worker/test.js
new file mode 100644
index 0000000..575dca7
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/onclick_null/service_worker/test.js
@@ -0,0 +1,43 @@
+// Copyright 2019 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.
+
+function onCreatedFirstMenu() {
+  chrome.contextMenus.update('id1', {
+    onclick: null
+  }, function() {
+    chrome.test.sendMessage('update1', function() {
+      // Now create another context menu item, to test whether adding and
+      // updating a context menu with a new onclick handler works.
+      // Upon completing that test, we will also know whether menu 1's initial
+      // onclick attribute has been triggered unexpectedly.
+      createSecondMenu();
+    });
+  });
+}
+
+function createSecondMenu() {
+  chrome.contextMenus.create({
+    id: 'id2',
+    title: 'Menu item 2',
+    onclick: function() {
+      chrome.test.sendMessage('onclick2-unexpected');
+    }
+  }, function() {
+    chrome.contextMenus.update('id2', {
+      onclick: function() {
+        chrome.test.sendMessage('onclick2');
+      }
+    }, function() {
+      chrome.test.sendMessage('update2');
+    });
+  });
+}
+
+chrome.contextMenus.create({
+  id: 'id1',
+  title: 'Menu item 1',
+  onclick: function() {
+    chrome.test.sendMessage('onclick1-unexpected');
+  }
+}, onCreatedFirstMenu);
diff --git a/chrome/test/data/extensions/context_menus/patterns/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/patterns/service_worker/manifest.json
new file mode 100644
index 0000000..d0c954d3
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/patterns/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name": "Tests for the url patterns to restrict context menu items.",
+  "version": "0.1",
+  "manifest_version": 2,
+  "permissions": ["contextMenus", "tabs"],
+  "background": { "service_worker_script": "test.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/patterns/service_worker/test.js b/chrome/test/data/extensions/context_menus/patterns/service_worker/test.js
new file mode 100644
index 0000000..1ef1bfc0
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/patterns/service_worker/test.js
@@ -0,0 +1,28 @@
+// Copyright 2019 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.
+
+var make_browsertest_proceed = function() {
+  if (!chrome.runtime.lastError) {
+    chrome.test.sendMessage('created items');
+  }
+};
+
+var patterns = ['http://*.google.com/*', 'https://*.google.com/*'];
+
+// Create one item that does have a documentUrlPattern.
+var properties1 = {
+  title: 'test_item1', documentUrlPatterns: patterns
+};
+chrome.contextMenus.create(properties1);
+
+// Create an item that initially doesn't have a documentUrlPattern, then
+// update it, and then proceed with the c++ code in the browser test.
+var properties2 = { title: 'test_item2' };
+
+var id2 = chrome.contextMenus.create(properties2,
+                                     function() {
+  var update_properties = { documentUrlPatterns: patterns };
+  chrome.contextMenus.update(id2, update_properties,
+                             make_browsertest_proceed);
+});
diff --git a/chrome/test/data/extensions/context_menus/radio_check/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/radio_check/service_worker/manifest.json
new file mode 100644
index 0000000..19d6c4be
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/radio_check/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name" : "Context Menus Test Extension",
+  "version" : "0.1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus", "tabs" ],
+  "background": { "service_worker_script": "test.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/radio_check/service_worker/test.js b/chrome/test/data/extensions/context_menus/radio_check/service_worker/test.js
new file mode 100644
index 0000000..27c91b3
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/radio_check/service_worker/test.js
@@ -0,0 +1,63 @@
+// Copyright 2019 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.
+
+function createSecondRadioButton() {
+  chrome.contextMenus.create({
+    id: 'radio2',
+    type: 'radio',
+    title: 'Radio 2',
+    onclick: function() {
+      chrome.test.sendMessage('onclick radio2');
+    }
+  }, function() {
+    chrome.test.sendMessage('created radio2 item', function() {
+      createNormalMenuItem();
+    });
+  });
+}
+
+function createNormalMenuItem() {
+  chrome.contextMenus.create({
+    id: 'item1',
+    title: 'Item 1',
+    onclick: function() {
+      chrome.test.sendMessage('onclick normal item');
+      chrome.contextMenus.update('radio1', {checked: false}, function() {
+        chrome.test.sendMessage('radio1 updated');
+      });
+    }
+  }, function() {
+    chrome.test.sendMessage('created normal item', function() {
+      createSecondNormalMenuItem();
+    });
+  });
+}
+
+function createSecondNormalMenuItem() {
+  chrome.contextMenus.create({
+    id: 'item2',
+    title: 'Item 2',
+    onclick: function() {
+      chrome.test.sendMessage('onclick second normal item');
+      chrome.contextMenus.update('radio2', {checked: false}, function() {
+        chrome.test.sendMessage('radio2 updated');
+      });
+    }
+  }, function() {
+    chrome.test.sendMessage('created second normal item');
+  });
+}
+
+chrome.contextMenus.create({
+  id: 'radio1',
+  type: 'radio',
+  title: 'Radio 1',
+  onclick: function() {
+    chrome.test.sendMessage('onclick radio1');
+  }
+}, function() {
+  chrome.test.sendMessage('created radio1 item', function() {
+    createSecondRadioButton();
+  });
+});
diff --git a/chrome/test/data/extensions/context_menus/simple/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/simple/service_worker/manifest.json
new file mode 100644
index 0000000..19d6c4be
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/simple/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name" : "Context Menus Test Extension",
+  "version" : "0.1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus", "tabs" ],
+  "background": { "service_worker_script": "test.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/simple/service_worker/test.js b/chrome/test/data/extensions/context_menus/simple/service_worker/test.js
new file mode 100644
index 0000000..1418c128
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/simple/service_worker/test.js
@@ -0,0 +1,16 @@
+// Copyright 2019 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.
+
+function onclick(info) {
+  chrome.test.sendMessage('onclick fired');
+}
+
+chrome.contextMenus.create(
+    {title: 'Extension Item 1', onclick: onclick},
+    function() {
+      if (!chrome.runtime.lastError) {
+        chrome.test.sendMessage('created item');
+      }
+    }
+);
diff --git a/chrome/test/data/extensions/context_menus/target_urls/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/target_urls/service_worker/manifest.json
new file mode 100644
index 0000000..1966590
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/target_urls/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name" : "targetUrlPatterns test",
+  "version" : "0.1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus", "tabs" ],
+  "background": { "service_worker_script": "test.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/target_urls/service_worker/test.js b/chrome/test/data/extensions/context_menus/target_urls/service_worker/test.js
new file mode 100644
index 0000000..a6a2c60
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/target_urls/service_worker/test.js
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+var patterns = [ 'http://*.google.com/*' ];
+chrome.contextMenus.create({title: 'item1', contexts: ['link'],
+                            targetUrlPatterns: patterns}, function() {
+  if (!chrome.runtime.lastError) {
+    chrome.test.sendMessage('created items');
+  }
+});
diff --git a/chrome/test/data/extensions/context_menus/top_level/multi4/service_worker/background.js b/chrome/test/data/extensions/context_menus/top_level/multi4/service_worker/background.js
new file mode 100644
index 0000000..f0c38b4
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/multi4/service_worker/background.js
@@ -0,0 +1,13 @@
+// Copyright 2019 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.
+
+chrome.contextMenus.create({ title: 'Context Menu #1' }, function() {
+  if (!chrome.runtime.lastError) {
+    chrome.contextMenus.create({ title: 'Context Menu #2' }, function() {
+      if (!chrome.runtime.lastError) {
+        chrome.test.sendMessage('created items');
+      }
+    });
+  }
+});
diff --git a/chrome/test/data/extensions/context_menus/top_level/multi4/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/top_level/multi4/service_worker/manifest.json
new file mode 100644
index 0000000..24d1006
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/multi4/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name": "An Extension with multiple Context Menus",
+  "version": "1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus" ],
+  "background": { "service_worker_script": "background.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/top_level/multi5/service_worker/background.js b/chrome/test/data/extensions/context_menus/top_level/multi5/service_worker/background.js
new file mode 100644
index 0000000..f0c38b4
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/multi5/service_worker/background.js
@@ -0,0 +1,13 @@
+// Copyright 2019 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.
+
+chrome.contextMenus.create({ title: 'Context Menu #1' }, function() {
+  if (!chrome.runtime.lastError) {
+    chrome.contextMenus.create({ title: 'Context Menu #2' }, function() {
+      if (!chrome.runtime.lastError) {
+        chrome.test.sendMessage('created items');
+      }
+    });
+  }
+});
diff --git a/chrome/test/data/extensions/context_menus/top_level/multi5/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/top_level/multi5/service_worker/manifest.json
new file mode 100644
index 0000000..4aae772
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/multi5/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name": "Ze Extension with multiple Context Menus",
+  "version": "1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus" ],
+  "background": { "service_worker_script": "background.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/top_level/single1/service_worker/background.js b/chrome/test/data/extensions/context_menus/top_level/single1/service_worker/background.js
new file mode 100644
index 0000000..6173ca3d
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/single1/service_worker/background.js
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+var contextMenuTitle = 'Context Menu #3 - Extension #1';
+
+chrome.contextMenus.create({ title: contextMenuTitle }, function() {
+  if (!chrome.runtime.lastError) {
+    chrome.test.sendMessage('created item');
+  }
+});
diff --git a/chrome/test/data/extensions/context_menus/top_level/single1/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/top_level/single1/service_worker/manifest.json
new file mode 100644
index 0000000..ff2c3bd
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/single1/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name": "Top Level Context Menus Extension #1",
+  "version": "1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus" ],
+  "background": { "service_worker_script": "background.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/top_level/single2/service_worker/background.js b/chrome/test/data/extensions/context_menus/top_level/single2/service_worker/background.js
new file mode 100644
index 0000000..9943df6
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/single2/service_worker/background.js
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+var contextMenuTitle = 'Context Menu #1 - Extension #2';
+
+chrome.contextMenus.create({ title: contextMenuTitle }, function() {
+  if (!chrome.runtime.lastError) {
+    chrome.test.sendMessage('created item');
+  }
+});
diff --git a/chrome/test/data/extensions/context_menus/top_level/single2/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/top_level/single2/service_worker/manifest.json
new file mode 100644
index 0000000..3bdd92c
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/single2/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name": "Top Level Context Menus Test Extension #2",
+  "version": "1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus" ],
+  "background": { "service_worker_script": "background.js" }
+}
diff --git a/chrome/test/data/extensions/context_menus/top_level/single3/service_worker/background.js b/chrome/test/data/extensions/context_menus/top_level/single3/service_worker/background.js
new file mode 100644
index 0000000..d51a76a
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/single3/service_worker/background.js
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+var contextMenuTitle = 'Context Menu #2 - Extension #3';
+
+chrome.contextMenus.create({ title: contextMenuTitle }, function() {
+  if (!chrome.runtime.lastError) {
+    chrome.test.sendMessage('created item');
+  }
+});
diff --git a/chrome/test/data/extensions/context_menus/top_level/single3/service_worker/manifest.json b/chrome/test/data/extensions/context_menus/top_level/single3/service_worker/manifest.json
new file mode 100644
index 0000000..41f41b83
--- /dev/null
+++ b/chrome/test/data/extensions/context_menus/top_level/single3/service_worker/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name": "Top Level Context Menus Test Extension #3",
+  "version": "1",
+  "manifest_version": 2,
+  "permissions": [ "contextMenus" ],
+  "background": { "service_worker_script": "background.js" }
+}
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index b1b5c54..e83d623 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -3962,7 +3962,8 @@
   "TPMFirmwareUpdateSettings": {
     "os": ["chromeos"],
     "test_policy": {
-      "allow-user-initiated-powerwash": true
+      "allow-user-initiated-powerwash": true,
+      "auto-update-mode": 2
     },
     "pref_mappings": [
       { "pref": "cros.tpm_firmware_update_settings" }
@@ -4298,6 +4299,74 @@
     }
   },
 
+  "DevicePowerPeakShiftEnabled": {
+    "os": ["chromeos"],
+    "test_policy": { "DevicePowerPeakShiftEnabled": true },
+    "pref_mappings": [
+      {
+        "pref": "ash.power.peak_shift_enabled",
+        "local_state": true
+      }
+    ]
+  },
+
+  "DevicePowerPeakShiftBatteryThreshold": {
+    "os": ["chromeos"],
+    "test_policy": { "DevicePowerPeakShiftBatteryThreshold": 20 },
+    "pref_mappings": [
+      {
+        "pref": "ash.power.peak_shift_battery_threshold",
+        "local_state": true
+      }
+    ]
+  },
+
+  "DevicePowerPeakShiftDayConfig": {
+    "os": ["chromeos"],
+    "test_policy": {
+      "DevicePowerPeakShiftDayConfig": {
+        "entries":[
+           {
+              "charge_start_time":{
+                 "hour": 20,
+                 "minute": 0
+              },
+              "day":"MONDAY",
+              "end_time":{
+                 "hour": 10,
+                 "minute": 15
+              },
+              "start_time":{
+                 "hour": 7,
+                 "minute": 30
+              }
+           },
+           {
+              "charge_start_time":{
+                 "hour": 22,
+                 "minute": 30
+              },
+              "day":"FRIDAY",
+              "end_time":{
+                 "hour": 9,
+                 "minute": 45
+              },
+              "start_time":{
+                 "hour": 4,
+                 "minute": 0
+              }
+           }
+        ]
+      }
+    },
+    "pref_mappings": [
+      {
+        "pref": "ash.power.peak_shift_day_config",
+        "local_state": true
+      }
+    ]
+  },
+
   "----- Chrome Frame policies -------------------------------------------": {},
 
   "ChromeFrameRendererSettings": {
diff --git a/chrome/test/data/webui/print_preview/model_settings_availability_test.js b/chrome/test/data/webui/print_preview/model_settings_availability_test.js
index 53906dc3..76fc0f86 100644
--- a/chrome/test/data/webui/print_preview/model_settings_availability_test.js
+++ b/chrome/test/data/webui/print_preview/model_settings_availability_test.js
@@ -481,6 +481,18 @@
 
     if (cr.isChromeOS) {
       test('pin', function() {
+        // Make device unmanaged.
+        loadTimeData.overrideValues({isEnterpriseManaged: false});
+        // Check that pin setting is unavailable on unmanaged devices.
+        assertFalse(model.settings.pin.available);
+
+        // Make device enterprise managed.
+        loadTimeData.overrideValues({isEnterpriseManaged: true});
+        // Set capabilities again to update pin availability.
+        model.set(
+            'destination.capabilities',
+            print_preview_test_utils.getCddTemplate(model.destination.id)
+                .capabilities);
         assertTrue(model.settings.pin.available);
 
         // Remove pin capability.
diff --git a/chrome/test/data/webui/print_preview/model_settings_policy_test.js b/chrome/test/data/webui/print_preview/model_settings_policy_test.js
index 563132c4..ebfc2ece 100644
--- a/chrome/test/data/webui/print_preview/model_settings_policy_test.js
+++ b/chrome/test/data/webui/print_preview/model_settings_policy_test.js
@@ -202,6 +202,10 @@
               .capabilities;
       delete capabilities.printer.pin;
 
+      // Make device enterprise managed since pin setting is available only on
+      // managed devices.
+      loadTimeData.overrideValues({isEnterpriseManaged: true});
+
       [{
         // No policies, settings is modifiable.
         pinCap: {supported: true},
@@ -231,6 +235,15 @@
          expectedEnforced: false,
        },
        {
+         // Policy is UNSECURE, setting is not available.
+         pinCap: {supported: true},
+         pinPolicy: print_preview.PinModeRestriction.UNSECURE,
+         expectedValue: false,
+         expectedAvailable: false,
+         expectedManaged: false,
+         expectedEnforced: true,
+       },
+       {
          // No restriction policy, setting is modifiable.
          pinCap: {supported: true},
          pinPolicy: print_preview.PinModeRestriction.NONE,
diff --git a/chrome/test/vr/OWNERS b/chrome/test/vr/OWNERS
index 38aae66d..56462b4 100644
--- a/chrome/test/vr/OWNERS
+++ b/chrome/test/vr/OWNERS
@@ -1,4 +1,3 @@
-acondor@chromium.org
 bsheedy@chromium.org
 cjgrant@chromium.org
 mthiesse@chromium.org
diff --git a/chrome/utility/importer/firefox_importer_unittest_utils_mac.cc b/chrome/utility/importer/firefox_importer_unittest_utils_mac.cc
index 3e922a6f..90e9a9b 100644
--- a/chrome/utility/importer/firefox_importer_unittest_utils_mac.cc
+++ b/chrome/utility/importer/firefox_importer_unittest_utils_mac.cc
@@ -53,7 +53,7 @@
   // See "chrome/utility/importer/nss_decryptor_mac.mm" for an explanation of
   // why we need this.
   base::LaunchOptions options;
-  options.environ["DYLD_FALLBACK_LIBRARY_PATH"] = nss_path.value();
+  options.environment["DYLD_FALLBACK_LIBRARY_PATH"] = nss_path.value();
   options.fds_to_remap.push_back(std::pair<int, int>(
       mojo_channel_fd.get(), service_manager::kMojoIPCChannel +
                                  base::GlobalDescriptors::kBaseDescriptor));
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 31e79e3..60df8f1 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -19,6 +19,7 @@
 
 declare_args() {
   cast_test_extra_flags = ""
+  vendor_cast_media_gtest_excludes = []
 }
 
 # Depends on all non-test targets that should be built by the Chromecast
@@ -123,6 +124,8 @@
       #   (internal : b/115400220)
       gtest_excludes = [ "AudioVideoPipelineDeviceTest.Mp4Playback" ]
 
+      gtest_excludes += vendor_cast_media_gtest_excludes
+
       # --test-launcher-jobs=1 => so internal code can bind to port
       args = [ "--test-launcher-jobs=1" ]
     }
diff --git a/chromecast/device/bluetooth/le/gatt_client_manager_impl.cc b/chromecast/device/bluetooth/le/gatt_client_manager_impl.cc
index c5aa4321..3daa2d11 100644
--- a/chromecast/device/bluetooth/le/gatt_client_manager_impl.cc
+++ b/chromecast/device/bluetooth/le/gatt_client_manager_impl.cc
@@ -47,6 +47,7 @@
 
 // static
 constexpr base::TimeDelta GattClientManagerImpl::kConnectTimeout;
+constexpr base::TimeDelta GattClientManagerImpl::kDisconnectTimeout;
 constexpr base::TimeDelta GattClientManagerImpl::kReadRemoteRssiTimeout;
 
 GattClientManagerImpl::GattClientManagerImpl(
@@ -135,9 +136,10 @@
 }
 
 void GattClientManagerImpl::EnqueueConnectRequest(
-    const bluetooth_v2_shlib::Addr& addr) {
+    const bluetooth_v2_shlib::Addr& addr,
+    bool is_connect) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-  pending_connect_requests_.push_back(addr);
+  pending_connect_requests_.push_back(std::make_pair(addr, is_connect));
 
   // Run the request if this is the only request in the queue. Otherwise, it
   // will be run when all previous requests complete.
@@ -158,6 +160,26 @@
   }
 }
 
+void GattClientManagerImpl::DisconnectAll(StatusCallback cb) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  if (disconnect_all_pending_) {
+    LOG(ERROR) << "Already have a pending DisconectAll request";
+    std::move(cb).Run(false);
+    return;
+  }
+
+  if (connected_devices_.empty()) {
+    std::move(cb).Run(true);
+    return;
+  }
+
+  disconnect_all_pending_ = true;
+  disconnect_all_cb_ = std::move(cb);
+  for (const auto& addr : connected_devices_) {
+    EnqueueConnectRequest(addr, false);
+  }
+}
+
 bool GattClientManagerImpl::IsConnectedLeDevice(
     const bluetooth_v2_shlib::Addr& addr) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
@@ -189,16 +211,22 @@
   } else {
     connected_devices_.erase(addr);
     if (!pending_connect_requests_.empty() &&
-        addr == pending_connect_requests_.front()) {
+        addr == pending_connect_requests_.front().first) {
       pending_connect_requests_.pop_front();
       connect_timeout_timer_.Stop();
+      disconnect_timeout_timer_.Stop();
       RunQueuedConnectRequest();
     } else {
-      base::Erase(pending_connect_requests_, addr);
+      base::Erase(pending_connect_requests_, std::make_pair(addr, true));
+      base::Erase(pending_connect_requests_, std::make_pair(addr, false));
     }
 
     base::Erase(pending_read_remote_rssi_requests_, addr);
     read_remote_rssi_timeout_timer_.Stop();
+
+    if (connected_devices_.empty()) {
+      DisconnectAllComplete(true);
+    }
   }
 
   // We won't declare the device connected until service discovery completes.
@@ -339,7 +367,8 @@
                      it->second->GetServicesSync());
 
   if (pending_connect_requests_.empty() ||
-      addr != pending_connect_requests_.front()) {
+      addr != pending_connect_requests_.front().first ||
+      !pending_connect_requests_.front().second) {
     NOTREACHED() << "Unexpected call to " << __func__;
     return;
   }
@@ -377,31 +406,37 @@
 void GattClientManagerImpl::RunQueuedConnectRequest() {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
 
-  if (pending_connect_requests_.empty()) {
-    return;
-  }
+  while (!pending_connect_requests_.empty()) {
+    auto addr = pending_connect_requests_.front().first;
+    bool is_connect = pending_connect_requests_.front().second;
+    if (is_connect) {
+      if (gatt_client_->Connect(addr)) {
+        connect_timeout_timer_.Start(
+            FROM_HERE, kConnectTimeout,
+            base::BindOnce(&GattClientManagerImpl::OnConnectTimeout, weak_this_,
+                           addr));
+        return;
+      }
+      LOG(ERROR) << "Connect failed";
+      auto it = addr_to_device_.find(addr);
+      if (it != addr_to_device_.end()) {
+        it->second->SetConnected(false);
+      }
+    } else {
+      if (gatt_client_->Disconnect(addr)) {
+        disconnect_timeout_timer_.Start(
+            FROM_HERE, kDisconnectTimeout,
+            base::BindOnce(&GattClientManagerImpl::OnDisconnectTimeout,
+                           weak_this_, addr));
+        return;
+      }
+      LOG(ERROR) << "Disconnect failed";
+      DisconnectAllComplete(false);
+    }
 
-  auto addr = pending_connect_requests_.front();
-  while (!gatt_client_->Connect(addr)) {
     // If current request fails, run the next request
-    LOG(ERROR) << "Connect failed";
-    auto it = addr_to_device_.find(addr);
-    if (it != addr_to_device_.end()) {
-      it->second->SetConnected(false);
-    }
     pending_connect_requests_.pop_front();
-
-    if (pending_connect_requests_.empty()) {
-      return;
-    }
-
-    addr = pending_connect_requests_.front();
   }
-
-  connect_timeout_timer_.Start(
-      FROM_HERE, kConnectTimeout,
-      base::BindRepeating(&GattClientManagerImpl::OnConnectTimeout, weak_this_,
-                          addr));
 }
 
 void GattClientManagerImpl::RunQueuedReadRemoteRssiRequest() {
@@ -434,6 +469,18 @@
                           weak_this_, addr));
 }
 
+void GattClientManagerImpl::DisconnectAllComplete(bool success) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  if (!disconnect_all_pending_) {
+    return;
+  }
+  disconnect_all_pending_ = false;
+
+  if (disconnect_all_cb_) {
+    std::move(disconnect_all_cb_).Run(success);
+  }
+}
+
 void GattClientManagerImpl::OnConnectTimeout(
     const bluetooth_v2_shlib::Addr& addr) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
@@ -453,6 +500,22 @@
   }
 }
 
+void GattClientManagerImpl::OnDisconnectTimeout(
+    const bluetooth_v2_shlib::Addr& addr) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  // Get the last byte because whole address is PII.
+  std::string addr_str = util::AddrLastByteString(addr);
+
+  LOG(ERROR) << "Disconnect (" << addr_str << ")"
+             << " timed out.";
+
+  DisconnectAllComplete(false);
+
+  // Treat device as disconnected for this unknown case.
+  RUN_ON_IO_THREAD(OnConnectChanged, addr, false /* status */,
+                   false /* connected */);
+}
+
 void GattClientManagerImpl::OnReadRemoteRssiTimeout(
     const bluetooth_v2_shlib::Addr& addr) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
diff --git a/chromecast/device/bluetooth/le/gatt_client_manager_impl.h b/chromecast/device/bluetooth/le/gatt_client_manager_impl.h
index 4ccab6d..1b68163 100644
--- a/chromecast/device/bluetooth/le/gatt_client_manager_impl.h
+++ b/chromecast/device/bluetooth/le/gatt_client_manager_impl.h
@@ -8,6 +8,7 @@
 #include <deque>
 #include <map>
 #include <set>
+#include <utility>
 #include <vector>
 
 #include "base/observer_list_threadsafe.h"
@@ -30,11 +31,17 @@
   // it as a failure.
   static constexpr base::TimeDelta kConnectTimeout =
       base::TimeDelta::FromSeconds(40);
+  // If a Disconnect request takes longer than this amount of time, we will
+  // treat it as a failure.
+  static constexpr base::TimeDelta kDisconnectTimeout =
+      base::TimeDelta::FromSeconds(10);
   // If a ReadRemoteRssi request takes longer than this amount of time, we will
   // treat it as a failure.
   static constexpr base::TimeDelta kReadRemoteRssiTimeout =
       base::TimeDelta::FromSeconds(10);
 
+  using StatusCallback = base::OnceCallback<void(bool)>;
+
   explicit GattClientManagerImpl(bluetooth_v2_shlib::GattClient* gatt_client);
   ~GattClientManagerImpl() override;
 
@@ -55,13 +62,20 @@
   void NotifyBonded(const bluetooth_v2_shlib::Addr& addr) override;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner() override;
 
-  // Add a Connect request to the queue. They can only be executed serially.
-  void EnqueueConnectRequest(const bluetooth_v2_shlib::Addr& addr);
+  // Add a Connect or Disconnect request to the queue. |is_connect| is true for
+  // Connect request and false for Disconnect request. They can only be executed
+  // serially.
+  void EnqueueConnectRequest(const bluetooth_v2_shlib::Addr& addr,
+                             bool is_connect);
 
   // Add a ReadRemoteRssi request to the queue. They can only be executed
   // serially.
   void EnqueueReadRemoteRssiRequest(const bluetooth_v2_shlib::Addr& addr);
 
+  // Disconnect all connected devices. Callback will return |true| if all
+  // devices are disconnected, otherwise false.
+  void DisconnectAll(StatusCallback cb);
+
   // True if it is a connected BLE device. Must be called on IO task runner.
   bool IsConnectedLeDevice(const bluetooth_v2_shlib::Addr& addr);
 
@@ -112,8 +126,10 @@
 
   void RunQueuedConnectRequest();
   void RunQueuedReadRemoteRssiRequest();
+  void DisconnectAllComplete(bool success);
 
   void OnConnectTimeout(const bluetooth_v2_shlib::Addr& addr);
+  void OnDisconnectTimeout(const bluetooth_v2_shlib::Addr& addr);
   void OnReadRemoteRssiTimeout(const bluetooth_v2_shlib::Addr& addr);
 
   static void FinalizeOnIoThread(
@@ -137,12 +153,24 @@
   // will treat it as a failure.
   base::OneShotTimer connect_timeout_timer_;
 
+  // Timer for pending Disconnect requests. If any Disconnect request times out,
+  // we will treat it as a failure.
+  base::OneShotTimer disconnect_timeout_timer_;
+
   // Timer for pending ReadRemoteRssi requests. If any ReadRemoteRssi request
   // times out, we will treat it as a failure.
   base::OneShotTimer read_remote_rssi_timeout_timer_;
 
-  // Queue for concurrent Connect requests.
-  std::deque<bluetooth_v2_shlib::Addr> pending_connect_requests_;
+  // Queue for concurrent Connect/Disconnect requests. Each request is
+  // represented using a <addr, is_connect> pair. |is_connect| is true for
+  // Connect requests and false for Disconnect requests.
+  std::deque<std::pair<bluetooth_v2_shlib::Addr, bool>>
+      pending_connect_requests_;
+
+  bool disconnect_all_pending_ = false;
+
+  // Callback of DisconnectAll request.
+  StatusCallback disconnect_all_cb_;
 
   // Queue for concurrent ReadRemoteRssi requests.
   std::deque<bluetooth_v2_shlib::Addr> pending_read_remote_rssi_requests_;
diff --git a/chromecast/device/bluetooth/le/gatt_client_manager_impl_test.cc b/chromecast/device/bluetooth/le/gatt_client_manager_impl_test.cc
index d95511a0..5fa032d 100644
--- a/chromecast/device/bluetooth/le/gatt_client_manager_impl_test.cc
+++ b/chromecast/device/bluetooth/le/gatt_client_manager_impl_test.cc
@@ -36,6 +36,8 @@
     {0x20, 0x21, 0x22, 0x23, 0x24, 0x25}};
 const bluetooth_v2_shlib::Addr kTestAddr4 = {
     {0x30, 0x31, 0x32, 0x33, 0x34, 0x35}};
+const bluetooth_v2_shlib::Addr kTestAddr5 = {
+    {0x40, 0x41, 0x42, 0x43, 0x44, 0x45}};
 
 class MockGattClientManagerObserver : public GattClientManager::Observer {
  public:
@@ -228,7 +230,7 @@
     device->Connect(cb_.Get());
     bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
         gatt_client_->delegate();
-    EXPECT_CALL(*gatt_client_, GetServices(kTestAddr1)).WillOnce(Return(true));
+    EXPECT_CALL(*gatt_client_, GetServices(addr)).WillOnce(Return(true));
     delegate->OnConnectChanged(addr, true /* status */, true /* connected */);
     delegate->OnGetServices(addr, {});
     ASSERT_TRUE(device->IsConnected());
@@ -400,11 +402,16 @@
   scoped_refptr<RemoteDevice> device2 = GetDevice(kTestAddr2);
   scoped_refptr<RemoteDevice> device3 = GetDevice(kTestAddr3);
   scoped_refptr<RemoteDevice> device4 = GetDevice(kTestAddr4);
+  scoped_refptr<RemoteDevice> device5 = GetDevice(kTestAddr5);
 
   base::MockCallback<RemoteDevice::StatusCallback> cb1;
   base::MockCallback<RemoteDevice::StatusCallback> cb2;
   base::MockCallback<RemoteDevice::StatusCallback> cb3;
   base::MockCallback<RemoteDevice::StatusCallback> cb4;
+  base::MockCallback<RemoteDevice::StatusCallback> cb5;
+
+  // Device5 is already connected at the beginning.
+  Connect(kTestAddr5);
 
   // Only the 1st Connect request will be executed immediately. The rest will be
   // queued.
@@ -413,6 +420,7 @@
   device2->Connect(cb2.Get());
   device3->Connect(cb3.Get());
   device4->Connect(cb4.Get());
+  device5->Disconnect(cb5.Get());
 
   EXPECT_CALL(*gatt_client_, GetServices(kTestAddr1)).WillOnce(Return(true));
   delegate->OnConnectChanged(kTestAddr1, true /* status */,
@@ -438,12 +446,18 @@
                              true /* connected */);
 
   EXPECT_CALL(cb4, Run(true));
+  EXPECT_CALL(*gatt_client_, Disconnect(kTestAddr5)).WillOnce(Return(true));
   delegate->OnGetServices(kTestAddr4, {});
 
+  EXPECT_CALL(cb5, Run(true));
+  delegate->OnConnectChanged(kTestAddr5, true /* status */,
+                             false /* connected */);
+
   EXPECT_TRUE(device1->IsConnected());
   EXPECT_FALSE(device2->IsConnected());
   EXPECT_FALSE(device3->IsConnected());
   EXPECT_TRUE(device4->IsConnected());
+  EXPECT_FALSE(device5->IsConnected());
 
   base::MockCallback<base::OnceCallback<void(size_t)>>
       get_num_connected_callback;
@@ -514,6 +528,84 @@
   delegate->OnReadRemoteRssi(kTestAddr1, true /* status */, kRssi);
 }
 
+TEST_F(GattClientManagerTest, DisconnectAll) {
+  bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+      gatt_client_->delegate();
+  base::MockCallback<GattClientManagerImpl::StatusCallback> cb;
+
+  // No connected devices, DisconnectAll should be successful.
+  EXPECT_CALL(cb, Run(true));
+  gatt_client_manager_->DisconnectAll(cb.Get());
+
+  scoped_refptr<RemoteDevice> device1 = GetDevice(kTestAddr1);
+  scoped_refptr<RemoteDevice> device2 = GetDevice(kTestAddr2);
+  scoped_refptr<RemoteDevice> device3 = GetDevice(kTestAddr3);
+
+  // Connect all 3 devices.
+  Connect(kTestAddr1);
+  Connect(kTestAddr2);
+  Connect(kTestAddr3);
+
+  // Disconnect requests will be queued.
+  EXPECT_CALL(*gatt_client_, Disconnect(kTestAddr1)).WillOnce(Return(true));
+  gatt_client_manager_->DisconnectAll(cb.Get());
+
+  // cb will be run when last device got disconnected.
+  EXPECT_CALL(*gatt_client_, Disconnect(kTestAddr2)).WillOnce(Return(true));
+  delegate->OnConnectChanged(kTestAddr1, true /* status */,
+                             false /* connected */);
+  EXPECT_CALL(*gatt_client_, Disconnect(kTestAddr3)).WillOnce(Return(true));
+  delegate->OnConnectChanged(kTestAddr2, true /* status */,
+                             false /* connected */);
+
+  EXPECT_CALL(cb, Run(true));
+  delegate->OnConnectChanged(kTestAddr3, true /* status */,
+                             false /* connected */);
+
+  base::MockCallback<base::OnceCallback<void(size_t)>>
+      get_num_connected_callback;
+  EXPECT_CALL(get_num_connected_callback, Run(0));
+  gatt_client_manager_->GetNumConnected(get_num_connected_callback.Get());
+
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(GattClientManagerTest, DisconnectAllTimeout) {
+  bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+      gatt_client_->delegate();
+  base::MockCallback<GattClientManagerImpl::StatusCallback> cb;
+
+  scoped_refptr<RemoteDevice> device1 = GetDevice(kTestAddr1);
+  scoped_refptr<RemoteDevice> device2 = GetDevice(kTestAddr2);
+  Connect(kTestAddr1);
+  Connect(kTestAddr2);
+
+  // Issue a DisconnectAll request.
+  EXPECT_CALL(*gatt_client_, Disconnect(kTestAddr1)).WillOnce(Return(true));
+  gatt_client_manager_->DisconnectAll(cb.Get());
+
+  // Let the fist Disconnect request timeout
+  base::TestMockTimeTaskRunner::ScopedContext context(fake_task_runner_);
+
+  // We should expect to receive DisconnectAll failure message
+  EXPECT_CALL(cb, Run(false));
+  // Run second Disconnect request in the queue.
+  EXPECT_CALL(*gatt_client_, Disconnect(kTestAddr2)).WillOnce(Return(true));
+  fake_task_runner_->FastForwardBy(GattClientManagerImpl::kDisconnectTimeout);
+
+  // We should treat device as disconnected for this unknown case
+  EXPECT_FALSE(device1->IsConnected());
+
+  // Second Disconnect request succeeds.
+  delegate->OnConnectChanged(kTestAddr2, true /* status */,
+                             false /* connected */);
+
+  base::MockCallback<base::OnceCallback<void(size_t)>>
+      get_num_connected_callback;
+  EXPECT_CALL(get_num_connected_callback, Run(0));
+  gatt_client_manager_->GetNumConnected(get_num_connected_callback.Get());
+}
+
 TEST_F(GattClientManagerTest, ReadRemoteRssiTimeout) {
   static const int kRssi = -34;
 
diff --git a/chromecast/device/bluetooth/le/remote_device_impl.cc b/chromecast/device/bluetooth/le/remote_device_impl.cc
index 74eec537..369290a 100644
--- a/chromecast/device/bluetooth/le/remote_device_impl.cc
+++ b/chromecast/device/bluetooth/le/remote_device_impl.cc
@@ -94,7 +94,7 @@
   gatt_client_manager_->NotifyConnect(addr_);
 
   connect_pending_ = true;
-  gatt_client_manager_->EnqueueConnectRequest(addr_);
+  gatt_client_manager_->EnqueueConnectRequest(addr_, true);
 
   return true;
 }
@@ -122,11 +122,8 @@
     return false;
   }
 
-  if (!gatt_client_manager_->gatt_client()->Disconnect(addr_)) {
-    LOG(ERROR) << __func__ << " failed";
-    return false;
-  }
   disconnect_pending_ = true;
+  gatt_client_manager_->EnqueueConnectRequest(addr_, false);
 
   return true;
 }
diff --git a/chromeos/components/proximity_auth/unlock_manager_impl.h b/chromeos/components/proximity_auth/unlock_manager_impl.h
index 497913e..1671320 100644
--- a/chromeos/components/proximity_auth/unlock_manager_impl.h
+++ b/chromeos/components/proximity_auth/unlock_manager_impl.h
@@ -19,7 +19,7 @@
 #include "chromeos/components/proximity_auth/screenlock_state.h"
 #include "chromeos/components/proximity_auth/smart_lock_metrics_recorder.h"
 #include "chromeos/components/proximity_auth/unlock_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 
diff --git a/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc b/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc
index 3ef66d3..7187d80 100644
--- a/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc
+++ b/chromeos/components/tether/host_scan_scheduler_impl_unittest.cc
@@ -14,7 +14,7 @@
 #include "base/test/test_simple_task_runner.h"
 #include "base/timer/mock_timer.h"
 #include "chromeos/components/tether/fake_host_scanner.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn
index 4ab6f83..acfb172d 100644
--- a/chromeos/dbus/BUILD.gn
+++ b/chromeos/dbus/BUILD.gn
@@ -135,8 +135,6 @@
     "fake_oobe_configuration_client.h",
     "fake_permission_broker_client.cc",
     "fake_permission_broker_client.h",
-    "fake_power_manager_client.cc",
-    "fake_power_manager_client.h",
     "fake_runtime_probe_client.cc",
     "fake_runtime_probe_client.h",
     "fake_seneschal_client.cc",
@@ -181,18 +179,20 @@
     "media_analytics_client.h",
     "modem_messaging_client.cc",
     "modem_messaging_client.h",
-    "native_timer.cc",
-    "native_timer.h",
     "oobe_configuration_client.cc",
     "oobe_configuration_client.h",
     "permission_broker_client.cc",
     "permission_broker_client.h",
     "pipe_reader.cc",
     "pipe_reader.h",
-    "power_manager_client.cc",
-    "power_manager_client.h",
-    "power_policy_controller.cc",
-    "power_policy_controller.h",
+    "power/fake_power_manager_client.cc",
+    "power/fake_power_manager_client.h",
+    "power/native_timer.cc",
+    "power/native_timer.h",
+    "power/power_manager_client.cc",
+    "power/power_manager_client.h",
+    "power/power_policy_controller.cc",
+    "power/power_policy_controller.h",
     "runtime_probe_client.cc",
     "runtime_probe_client.h",
     "seneschal_client.cc",
@@ -287,14 +287,14 @@
     "fake_auth_policy_client_unittest.cc",
     "fake_cryptohome_client_unittest.cc",
     "fake_easy_unlock_client_unittest.cc",
-    "fake_power_manager_client_unittest.cc",
     "gsm_sms_client_unittest.cc",
     "modem_messaging_client_unittest.cc",
     "native_timer_unittest.cc",
     "oobe_configuration_client_unittest.cc",
     "pipe_reader_unittest.cc",
-    "power_manager_client_unittest.cc",
-    "power_policy_controller_unittest.cc",
+    "power/fake_power_manager_client_unittest.cc",
+    "power/power_manager_client_unittest.cc",
+    "power/power_policy_controller_unittest.cc",
     "shill_client_unittest_base.cc",
     "shill_client_unittest_base.h",
     "shill_device_client_unittest.cc",
diff --git a/chromeos/dbus/biod/biod_client.h b/chromeos/dbus/biod/biod_client.h
index da81fe8..1846a99 100644
--- a/chromeos/dbus/biod/biod_client.h
+++ b/chromeos/dbus/biod/biod_client.h
@@ -65,8 +65,6 @@
     virtual ~Observer() {}
   };
 
-  virtual ~BiodClient();
-
   // Creates and initializes the global instance. |bus| must not be null.
   static void Initialize(dbus::Bus* bus);
 
@@ -154,8 +152,9 @@
  protected:
   friend class BiodClientTest;
 
-  // Use Initialize() instead.
+  // Initialize/Shutdown should be used instead.
   BiodClient();
+  virtual ~BiodClient();
 
  private:
   DISALLOW_COPY_AND_ASSIGN(BiodClient);
diff --git a/chromeos/dbus/hammerd/fake_hammerd_client.cc b/chromeos/dbus/hammerd/fake_hammerd_client.cc
index b8eb0ab76..8d0580d 100644
--- a/chromeos/dbus/hammerd/fake_hammerd_client.cc
+++ b/chromeos/dbus/hammerd/fake_hammerd_client.cc
@@ -16,7 +16,7 @@
 }
 
 FakeHammerdClient::~FakeHammerdClient() {
-  CHECK_EQ(g_instance, this);
+  CHECK_EQ(this, g_instance);
   g_instance = nullptr;
 }
 
diff --git a/chromeos/dbus/hammerd/hammerd_client.cc b/chromeos/dbus/hammerd/hammerd_client.cc
index acd200a..02d2187 100644
--- a/chromeos/dbus/hammerd/hammerd_client.cc
+++ b/chromeos/dbus/hammerd/hammerd_client.cc
@@ -26,7 +26,8 @@
 
 class HammerdClientImpl : public HammerdClient {
  public:
-  HammerdClientImpl() = default;
+  explicit HammerdClientImpl(dbus::Bus* bus) { Init(bus); }
+
   ~HammerdClientImpl() override = default;
 
   // HammerdClient:
@@ -159,27 +160,31 @@
 
 }  // namespace
 
-HammerdClient::HammerdClient() = default;
+HammerdClient::HammerdClient() {
+  CHECK(!g_instance);
+  g_instance = this;
+}
 
-HammerdClient::~HammerdClient() = default;
+HammerdClient::~HammerdClient() {
+  CHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
 
 // static
 void HammerdClient::Initialize(dbus::Bus* bus) {
-  CHECK(!g_instance);
-  if (bus) {
-    auto* instance = new HammerdClientImpl();
-    instance->Init(bus);
-    g_instance = instance;
-  } else {
-    g_instance = new FakeHammerdClient();
-  }
+  CHECK(bus);
+  new HammerdClientImpl(bus);
+}
+
+// static
+void HammerdClient::InitializeFake() {
+  new FakeHammerdClient();
 }
 
 // static
 void HammerdClient::Shutdown() {
   CHECK(g_instance);
   delete g_instance;
-  g_instance = nullptr;
 }
 
 // static
diff --git a/chromeos/dbus/hammerd/hammerd_client.h b/chromeos/dbus/hammerd/hammerd_client.h
index f855ec1..2ce2bb4 100644
--- a/chromeos/dbus/hammerd/hammerd_client.h
+++ b/chromeos/dbus/hammerd/hammerd_client.h
@@ -57,10 +57,16 @@
   HammerdClient();
   virtual ~HammerdClient();
 
-  // Creates and initializes the global instance. If |bus| is null, a
-  // FakeHammerdClient instance will be created.
+  // Creates and initializes the global instance. |bus| must not be null.
   static void Initialize(dbus::Bus* bus);
+
+  // Creates and initializes a fake global instance if not already created.
+  static void InitializeFake();
+
+  // Destroys the global instance which must have been initialized.
   static void Shutdown();
+
+  // Returns the global instance if initialized. May return null.
   static HammerdClient* Get();
 
   virtual void AddObserver(Observer* observer) = 0;
diff --git a/chromeos/dbus/native_timer_unittest.cc b/chromeos/dbus/native_timer_unittest.cc
index 2026a35..3a8b43b 100644
--- a/chromeos/dbus/native_timer_unittest.cc
+++ b/chromeos/dbus/native_timer_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/native_timer.h"
+#include "chromeos/dbus/power/native_timer.h"
 
 #include <memory>
 #include <utility>
@@ -10,7 +10,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chromeos/dbus/fake_power_manager_client.cc b/chromeos/dbus/power/fake_power_manager_client.cc
similarity index 99%
rename from chromeos/dbus/fake_power_manager_client.cc
rename to chromeos/dbus/power/fake_power_manager_client.cc
index 6ec6c4b0..ef025fe 100644
--- a/chromeos/dbus/fake_power_manager_client.cc
+++ b/chromeos/dbus/power/fake_power_manager_client.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 
 #include <set>
 #include <utility>
diff --git a/chromeos/dbus/fake_power_manager_client.h b/chromeos/dbus/power/fake_power_manager_client.h
similarity index 97%
rename from chromeos/dbus/fake_power_manager_client.h
rename to chromeos/dbus/power/fake_power_manager_client.h
index cbe19008..cdc3fdf 100644
--- a/chromeos/dbus/fake_power_manager_client.h
+++ b/chromeos/dbus/power/fake_power_manager_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_FAKE_POWER_MANAGER_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_POWER_MANAGER_CLIENT_H_
+#ifndef CHROMEOS_DBUS_POWER_FAKE_POWER_MANAGER_CLIENT_H_
+#define CHROMEOS_DBUS_POWER_FAKE_POWER_MANAGER_CLIENT_H_
 
 #include <map>
 #include <memory>
@@ -20,11 +20,11 @@
 #include "base/observer_list.h"
 #include "base/optional.h"
 #include "base/time/time.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "chromeos/dbus/power_manager/policy.pb.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 
 namespace chromeos {
 
@@ -290,4 +290,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_POWER_MANAGER_CLIENT_H_
+#endif  // CHROMEOS_DBUS_POWER_FAKE_POWER_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_power_manager_client_unittest.cc b/chromeos/dbus/power/fake_power_manager_client_unittest.cc
similarity index 98%
rename from chromeos/dbus/fake_power_manager_client_unittest.cc
rename to chromeos/dbus/power/fake_power_manager_client_unittest.cc
index 62e7d7a..a758db9 100644
--- a/chromeos/dbus/fake_power_manager_client_unittest.cc
+++ b/chromeos/dbus/power/fake_power_manager_client_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
diff --git a/chromeos/dbus/native_timer.cc b/chromeos/dbus/power/native_timer.cc
similarity index 98%
rename from chromeos/dbus/native_timer.cc
rename to chromeos/dbus/power/native_timer.cc
index 418a14dd..f7cad4a 100644
--- a/chromeos/dbus/native_timer.cc
+++ b/chromeos/dbus/power/native_timer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/native_timer.h"
+#include "chromeos/dbus/power/native_timer.h"
 
 #include <memory>
 #include <utility>
@@ -21,7 +21,7 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace chromeos {
 
diff --git a/chromeos/dbus/native_timer.h b/chromeos/dbus/power/native_timer.h
similarity index 94%
rename from chromeos/dbus/native_timer.h
rename to chromeos/dbus/power/native_timer.h
index c6248f3..242a192da 100644
--- a/chromeos/dbus/native_timer.h
+++ b/chromeos/dbus/power/native_timer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_NATIVE_TIMER_H_
-#define CHROMEOS_DBUS_NATIVE_TIMER_H_
+#ifndef CHROMEOS_DBUS_POWER_NATIVE_TIMER_H_
+#define CHROMEOS_DBUS_POWER_NATIVE_TIMER_H_
 
 #include <memory>
 #include <string>
@@ -19,7 +19,7 @@
 #include "base/threading/thread.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace chromeos {
 
@@ -99,4 +99,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_NATIVE_TIMER_H_
+#endif  // CHROMEOS_DBUS_POWER_NATIVE_TIMER_H_
diff --git a/chromeos/dbus/power_manager_client.cc b/chromeos/dbus/power/power_manager_client.cc
similarity index 99%
rename from chromeos/dbus/power_manager_client.cc
rename to chromeos/dbus/power/power_manager_client.cc
index f0965db..c367149 100644
--- a/chromeos/dbus/power_manager_client.cc
+++ b/chromeos/dbus/power/power_manager_client.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 #include <stdint.h>
 
@@ -24,7 +24,7 @@
 #include "base/threading/platform_thread.h"
 #include "base/timer/timer.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/power_manager/input_event.pb.h"
diff --git a/chromeos/dbus/power_manager_client.h b/chromeos/dbus/power/power_manager_client.h
similarity index 98%
rename from chromeos/dbus/power_manager_client.h
rename to chromeos/dbus/power/power_manager_client.h
index 297841f..e22e35c4 100644
--- a/chromeos/dbus/power_manager_client.h
+++ b/chromeos/dbus/power/power_manager_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_POWER_MANAGER_CLIENT_H_
-#define CHROMEOS_DBUS_POWER_MANAGER_CLIENT_H_
+#ifndef CHROMEOS_DBUS_POWER_POWER_MANAGER_CLIENT_H_
+#define CHROMEOS_DBUS_POWER_POWER_MANAGER_CLIENT_H_
 
 #include <map>
 #include <string>
@@ -333,4 +333,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_POWER_MANAGER_CLIENT_H_
+#endif  // CHROMEOS_DBUS_POWER_POWER_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/power_manager_client_unittest.cc b/chromeos/dbus/power/power_manager_client_unittest.cc
similarity index 99%
rename from chromeos/dbus/power_manager_client_unittest.cc
rename to chromeos/dbus/power/power_manager_client_unittest.cc
index e8c7260..255f167 100644
--- a/chromeos/dbus/power_manager_client_unittest.cc
+++ b/chromeos/dbus/power/power_manager_client_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 #include <map>
 #include <memory>
diff --git a/chromeos/dbus/power_policy_controller.cc b/chromeos/dbus/power/power_policy_controller.cc
similarity index 98%
rename from chromeos/dbus/power_policy_controller.cc
rename to chromeos/dbus/power/power_policy_controller.cc
index 4215f9ab..34a02d37 100644
--- a/chromeos/dbus/power_policy_controller.cc
+++ b/chromeos/dbus/power/power_policy_controller.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 
 #include <stdint.h>
 
@@ -335,8 +335,7 @@
 PowerPolicyController::WakeLock::WakeLock(Type type,
                                           WakeLockReason reason,
                                           const std::string& description)
-    : type(type), reason(reason), description(description) {
-}
+    : type(type), reason(reason), description(description) {}
 
 PowerPolicyController::WakeLock::~WakeLock() = default;
 
diff --git a/chromeos/dbus/power_policy_controller.h b/chromeos/dbus/power/power_policy_controller.h
similarity index 95%
rename from chromeos/dbus/power_policy_controller.h
rename to chromeos/dbus/power/power_policy_controller.h
index bedf493e..d120420 100644
--- a/chromeos/dbus/power_policy_controller.h
+++ b/chromeos/dbus/power/power_policy_controller.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_POWER_POLICY_CONTROLLER_H_
-#define CHROMEOS_DBUS_POWER_POLICY_CONTROLLER_H_
+#ifndef CHROMEOS_DBUS_POWER_POWER_POLICY_CONTROLLER_H_
+#define CHROMEOS_DBUS_POWER_POWER_POLICY_CONTROLLER_H_
 
 #include <map>
 #include <string>
 
 #include "base/component_export.h"
 #include "base/macros.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/policy.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 
 namespace chromeos {
 
@@ -44,10 +44,10 @@
 
   // Note: Do not change these values; they are used by preferences.
   enum Action {
-    ACTION_SUSPEND      = 0,
+    ACTION_SUSPEND = 0,
     ACTION_STOP_SESSION = 1,
-    ACTION_SHUT_DOWN    = 2,
-    ACTION_DO_NOTHING   = 3,
+    ACTION_SHUT_DOWN = 2,
+    ACTION_DO_NOTHING = 3,
   };
 
   // Values of various power-management-related preferences.
@@ -218,4 +218,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_POWER_POLICY_CONTROLLER_H_
+#endif  // CHROMEOS_DBUS_POWER_POWER_POLICY_CONTROLLER_H_
diff --git a/chromeos/dbus/power_policy_controller_unittest.cc b/chromeos/dbus/power/power_policy_controller_unittest.cc
similarity index 99%
rename from chromeos/dbus/power_policy_controller_unittest.cc
rename to chromeos/dbus/power/power_policy_controller_unittest.cc
index c3ae86fa..bdc3e451 100644
--- a/chromeos/dbus/power_policy_controller_unittest.cc
+++ b/chromeos/dbus/power/power_policy_controller_unittest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 
 #include <memory>
 
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chromeos/dbus/system_clock/system_clock_client.cc b/chromeos/dbus/system_clock/system_clock_client.cc
index 0abd5043..e99614e 100644
--- a/chromeos/dbus/system_clock/system_clock_client.cc
+++ b/chromeos/dbus/system_clock/system_clock_client.cc
@@ -191,24 +191,31 @@
   DISALLOW_COPY_AND_ASSIGN(SystemClockClientImpl);
 };
 
-SystemClockClient::SystemClockClient() = default;
+SystemClockClient::SystemClockClient() {
+  CHECK(!g_instance);
+  g_instance = this;
+}
 
-SystemClockClient::~SystemClockClient() = default;
+SystemClockClient::~SystemClockClient() {
+  CHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
 
 // static
 void SystemClockClient::Initialize(dbus::Bus* bus) {
-  CHECK(!g_instance);
-  if (bus)
-    g_instance = new SystemClockClientImpl(bus);
-  else
-    g_instance = new FakeSystemClockClient();
+  CHECK(bus);
+  new SystemClockClientImpl(bus);
+}
+
+// static
+void SystemClockClient::InitializeFake() {
+  new FakeSystemClockClient();
 }
 
 // static
 void SystemClockClient::Shutdown() {
   CHECK(g_instance);
   delete g_instance;
-  g_instance = nullptr;
 }
 
 // static
diff --git a/chromeos/dbus/system_clock/system_clock_client.h b/chromeos/dbus/system_clock/system_clock_client.h
index 3758a1e..019f9f5 100644
--- a/chromeos/dbus/system_clock/system_clock_client.h
+++ b/chromeos/dbus/system_clock/system_clock_client.h
@@ -48,13 +48,16 @@
     virtual void NotifyObserversSystemClockUpdated() = 0;
   };
 
-  // Creates the global instance. If |bus| is null, a fake client is created.
+  // Creates and initializes the global instance. |bus| must not be null.
   static void Initialize(dbus::Bus* bus);
 
-  // Destroys the global instance.
+  // Creates and initializes a fake global instance if not already created.
+  static void InitializeFake();
+
+  // Destroys the global instance which must have been initialized.
   static void Shutdown();
 
-  // Returns the global instance which may be null if not initialized.
+  // Returns the global instance if initialized. May return null.
   static SystemClockClient* Get();
 
   // Adds the given observer.
diff --git a/chromeos/disks/disk_mount_manager_unittest.cc b/chromeos/disks/disk_mount_manager_unittest.cc
index fe1e4fa5..73628e4 100644
--- a/chromeos/disks/disk_mount_manager_unittest.cc
+++ b/chromeos/disks/disk_mount_manager_unittest.cc
@@ -17,7 +17,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_cros_disks_client.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/disks/disk.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/disks/suspend_unmount_manager.h b/chromeos/disks/suspend_unmount_manager.h
index 353067b..6a78b92 100644
--- a/chromeos/disks/suspend_unmount_manager.h
+++ b/chromeos/disks/suspend_unmount_manager.h
@@ -11,7 +11,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "chromeos/dbus/cros_disks_client.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 
 namespace chromeos {
 namespace disks {
diff --git a/chromeos/disks/suspend_unmount_manager_unittest.cc b/chromeos/disks/suspend_unmount_manager_unittest.cc
index 093a1af..b2e513e 100644
--- a/chromeos/disks/suspend_unmount_manager_unittest.cc
+++ b/chromeos/disks/suspend_unmount_manager_unittest.cc
@@ -6,7 +6,7 @@
 #include <string>
 #include <vector>
 
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "chromeos/disks/mock_disk_mount_manager.h"
diff --git a/chromeos/process_proxy/process_proxy.cc b/chromeos/process_proxy/process_proxy.cc
index 87d1bc4..2d5c045 100644
--- a/chromeos/process_proxy/process_proxy.cc
+++ b/chromeos/process_proxy/process_proxy.cc
@@ -243,8 +243,8 @@
   // TODO(vapier): Ideally we'd just use the env settings from hterm itself.
   // We can't let the user inject any env var they want, but we should be able
   // to filter the $TERM value dynamically.
-  options.environ["TERM"] = "xterm-256color";
-  options.environ["CROS_USER_ID_HASH"] = user_id_hash;
+  options.environment["TERM"] = "xterm-256color";
+  options.environment["CROS_USER_ID_HASH"] = user_id_hash;
 
   // Launch the process.
   process_ = base::LaunchProcess(cmdline, options);
diff --git a/chromeos/services/assistant/platform/audio_input_impl.cc b/chromeos/services/assistant/platform/audio_input_impl.cc
index 0997623e..f5a4774 100644
--- a/chromeos/services/assistant/platform/audio_input_impl.cc
+++ b/chromeos/services/assistant/platform/audio_input_impl.cc
@@ -198,8 +198,13 @@
                               audio_source->frames());
   audio_source->ToInterleaved<media::SignedInt16SampleTypeTraits>(
       audio_source->frames(), buffer.data());
-  int64_t time = base::TimeTicks::Now().since_origin().InMicroseconds() -
-                 1000 * audio_delay_milliseconds;
+  int64_t time = 0;
+  // Only provide accurate timestamp when eraser is enabled, otherwise it seems
+  // break normal libassistant voice recognition.
+  if (features::IsAudioEraserEnabled()) {
+    time = base::TimeTicks::Now().since_origin().InMicroseconds() -
+           1000 * audio_delay_milliseconds;
+  }
   AudioInputBufferImpl input_buffer(buffer.data(), audio_source->frames());
   {
     base::AutoLock lock(lock_);
@@ -239,6 +244,15 @@
     assistant_client::AudioInput::Observer* observer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(observer_sequence_checker_);
   VLOG(1) << device_id_ << " add observer";
+
+  // Feed the observer one frame of empty data to work around crbug/942268
+  std::vector<int16_t> buffer(g_current_format.num_channels);
+  int64_t time = features::IsAudioEraserEnabled()
+                     ? base::TimeTicks::Now().since_origin().InMicroseconds()
+                     : 0;
+  AudioInputBufferImpl input_buffer(buffer.data(), /*frame_count=*/1);
+  observer->OnAudioBufferAvailable(input_buffer, time);
+
   bool have_first_observer = false;
   {
     base::AutoLock lock(lock_);
diff --git a/chromeos/services/assistant/platform/power_manager_provider_impl.h b/chromeos/services/assistant/platform/power_manager_provider_impl.h
index fdb177c..4d3a176 100644
--- a/chromeos/services/assistant/platform/power_manager_provider_impl.h
+++ b/chromeos/services/assistant/platform/power_manager_provider_impl.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
-#include "chromeos/dbus/native_timer.h"
+#include "chromeos/dbus/power/native_timer.h"
 #include "libassistant/shared/public/platform_system.h"
 #include "services/device/public/mojom/wake_lock.mojom.h"
 
diff --git a/chromeos/services/assistant/platform/power_manager_provider_impl_unittest.cc b/chromeos/services/assistant/platform/power_manager_provider_impl_unittest.cc
index 0852c2e..97762126 100644
--- a/chromeos/services/assistant/platform/power_manager_provider_impl_unittest.cc
+++ b/chromeos/services/assistant/platform/power_manager_provider_impl_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/logging.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "services/device/public/cpp/test/test_wake_lock_provider.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/test/test_connector_factory.h"
diff --git a/chromeos/services/assistant/service.h b/chromeos/services/assistant/service.h
index 92ee647..57784d9 100644
--- a/chromeos/services/assistant/service.h
+++ b/chromeos/services/assistant/service.h
@@ -20,7 +20,7 @@
 #include "base/scoped_observer.h"
 #include "base/single_thread_task_runner.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
 #include "chromeos/services/assistant/public/mojom/settings.mojom.h"
 #include "components/account_id/account_id.h"
diff --git a/chromeos/services/assistant/service_unittest.cc b/chromeos/services/assistant/service_unittest.cc
index 585334e73..0224667f 100644
--- a/chromeos/services/assistant/service_unittest.cc
+++ b/chromeos/services/assistant/service_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/services/assistant/fake_assistant_manager_service_impl.h"
 #include "chromeos/services/assistant/public/mojom/constants.mojom.h"
 #include "services/identity/public/mojom/identity_accessor.mojom.h"
diff --git a/chromeos/system/dark_resume_controller.h b/chromeos/system/dark_resume_controller.h
index 20eff94..3004f34 100644
--- a/chromeos/system/dark_resume_controller.h
+++ b/chromeos/system/dark_resume_controller.h
@@ -11,7 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
 #include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/device/public/mojom/wake_lock.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
diff --git a/chromeos/system/dark_resume_controller_unittest.cc b/chromeos/system/dark_resume_controller_unittest.cc
index 188e60f4..70cfce5e 100644
--- a/chromeos/system/dark_resume_controller_unittest.cc
+++ b/chromeos/system/dark_resume_controller_unittest.cc
@@ -9,7 +9,7 @@
 
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "services/device/public/cpp/test/test_wake_lock_provider.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/test/test_connector_factory.h"
diff --git a/components/arc/common/net.mojom b/components/arc/common/net.mojom
index d1d3557..eb59299 100644
--- a/components/arc/common/net.mojom
+++ b/components/arc/common/net.mojom
@@ -4,20 +4,32 @@
 
 // Next MinVersion: 10
 
+// This file defines the mojo interface between the ARC networking stack and
+// Chrome OS. There are three different groups of interactions:
+//  - WiFi RPCs for scanning and manipulating saved network configurations,
+//  - Layer 3 RPCs for configuring and registering IP networks inside ARC,
+//  - VPN RPCs for integrating Always-on-VPNs and ARC as a VPN provider.
+
 module arc.mojom;
 
+// Indicates if a request send by ARC to the host has successfully completed.
 [Extensible]
 enum NetworkResult {
   SUCCESS = 0,
   FAILURE = 1,
 };
 
+// Additional argument to GetNetworks to specify the type of WiFi networks the
+// host is interested to learn about.
 [Extensible]
 enum GetNetworksRequestType {
+  // All configured WiFi networks saved on the host.
   CONFIGURED_ONLY = 0,
+  // All WiFi networks currently visible by scanning.
   VISIBLE_ONLY = 1,
 };
 
+// Represents the possible connection states of a network service.
 [Extensible]
 enum ConnectionStateType {
   CONNECTED = 0,
@@ -25,12 +37,15 @@
   NOT_CONNECTED = 2,
 };
 
+// Additional WiFi network information provided by scan results.
 struct VisibleNetworkDetails {
   int32 frequency;
   int32 signal_strength;
   string bssid;
 };
 
+// Additional configuration information needed for creating and saving
+// WiFi network configuration on the host.
 struct ConfiguredNetworkDetails {
   string? passphrase;
   bool autoconnect;
@@ -41,21 +56,38 @@
   ConfiguredNetworkDetails configured;
 };
 
+// The two possible Internet Procol families.
 [Extensible]
 enum IPAddressType {
   IPV4,
   IPV6,
 };
 
+// Layer 3 and proxy configuration information for an IP network.
 struct IPConfiguration {
+
+  // Literal representation of the IP address of the ARC gateway.
   string gateway;
+
+  // Literal representation of the IP address of ARC for that network.
   string ip_address;
+
+  // List of literal IP addresses of name servers to use on that network.
   array<string> name_servers;
+
+  // Length of the routing prefix.
   int32 routing_prefix;
+
+  // IP family for that configuration
   IPAddressType type;
+
+  // URL of the HTTP proxy to use for that network.
   string web_proxy_auto_discovery_url;
 };
 
+// The subset of wireless security protocols that Android defines in
+// android.net.wifi.WifiConfiguration and that can be supported by the
+// host.
 [Extensible]
 enum SecurityType {
   NONE,
@@ -78,15 +110,34 @@
   SUSPECTED,
 };
 
+// Describes properties of a WiFi networks used to create Android's
+// android.net.wifi.Wificonfiguration objects and android.net.wifi.WifiInfo
+// objects.
 struct WiFi {
+  // The network BSSID in the format of an Ethernet MAC address.
   string bssid;
+
+  // The frequency of this network, in MHz.
   int32 frequency;
+
+  // The network SSID encoded as an hexadecimal string.
   string hex_ssid;
+
+  // True if the network does not broadcast its ssid.
   bool hidden_ssid;
+
+  // The type of wireless security protocol used by this network.
   SecurityType security;
+
+  // The current RSSI of this network. Updates for this value are not sent to
+  // ARC for connected WiFi networks and should be considered precise only for
+  // scanning results.
   int32 signal_strength;
 };
 
+// The physical network types exposed to ARC by the host,
+// corresponding to a subset of shill technology types defined
+// in platform2/system_api/dbus/shill/dbus-constants.h.
 [Extensible]
 enum NetworkType {
   CELLULAR,
@@ -96,19 +147,33 @@
   WIMAX,
 };
 
+// Used by ARC to request a network configuration to be created on the host.
 struct NetworkConfiguration {
-  // These correspond to ONC properties returned by
-  // chrome.networkingPrivate.getProperties().
-  // See components/onc/docs/onc_spec.html
+  // The connection state of the network service.
   ConnectionStateType connection_state;
+
+  // A string token that uniquely identifies this network service.
   string guid;
+
+  // IP configuration for the network service inside ARC.
   array<IPConfiguration>? ip_configs;
+
+  // MAC address of the network interface inside the ARC.
   string? mac_address;
+
+  // The type of the underlying physical network.
   NetworkType type;
+
+  // Additional WiFi properties for WiFi network services.
   WiFi? wifi;
+
+  // Indicates if the physical network is known to have upstream Internet
+  // access through tethering on a metered network.
   [MinVersion=8] TetheringClientState tethering_client_state;
 };
 
+// Describes a Wifi network configuration that ARC has requested the host to
+// create.
 struct WifiConfiguration {
   // These correspond to ONC properties returned by
   // chrome.networkingPrivate.getNetworks() and createNetwork().
@@ -133,11 +198,9 @@
   string ssid@0;
 };
 
-struct NetworkData {
-  NetworkResult status;
-  array<WifiConfiguration> networks;
-};
-
+// Response object sent back to ARC when it queries existing networks on
+// Chrome OS side. The kind of networks returned by Chrome OS is specified
+// with the GetNetworksRequestType enum.
 struct GetNetworksResponseType {
   NetworkResult status;
   array<NetworkConfiguration> networks;
@@ -210,8 +273,14 @@
       NetworkConfiguration? logical_default,
       NetworkConfiguration? physical_default);
 
-  // Sends a request to get configured or visible WiFi networks based on the
-  // request type.
+  // Sends a request to get the subset of network services existing on Chrome OS
+  // that match the kind specified with GetNetworksRequestType. This call
+  // supports two usages:
+  //  - querying the list of saved WiFi network configurations, which is used
+  //    for bootstrapping the state of the Android WifiManager implementation
+  //    on ARC.
+  //  - querying visible WiFi networks, which is used to implement Android
+  //    WifiManager public scanning APIs used by third party applications.
   [MinVersion=6] GetNetworks@10(GetNetworksRequestType type) =>
       (GetNetworksResponseType response);
 
diff --git a/components/arc/metrics/arc_metrics_service.h b/components/arc/metrics/arc_metrics_service.h
index 6c4d88fa..282a4c5 100644
--- a/components/arc/metrics/arc_metrics_service.h
+++ b/components/arc/metrics/arc_metrics_service.h
@@ -14,7 +14,7 @@
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/common/metrics.mojom.h"
 #include "components/arc/common/process.mojom.h"
 #include "components/arc/connection_observer.h"
diff --git a/components/arc/metrics/arc_metrics_service_unittest.cc b/components/arc/metrics/arc_metrics_service_unittest.cc
index 4e7d091..8e95523 100644
--- a/components/arc/metrics/arc_metrics_service_unittest.cc
+++ b/components/arc/metrics/arc_metrics_service_unittest.cc
@@ -17,8 +17,8 @@
 #include "base/time/clock.h"
 #include "base/time/tick_clock.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "components/arc/arc_prefs.h"
 #include "components/arc/arc_service_manager.h"
diff --git a/components/arc/power/arc_power_bridge.cc b/components/arc/power/arc_power_bridge.cc
index 518fc56..24eca4b8 100644
--- a/components/arc/power/arc_power_bridge.cc
+++ b/components/arc/power/arc_power_bridge.cc
@@ -13,8 +13,8 @@
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
-#include "chromeos/dbus/power_policy_controller.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "components/arc/arc_service_manager.h"
diff --git a/components/arc/power/arc_power_bridge.h b/components/arc/power/arc_power_bridge.h
index 34df4abe..1223adb 100644
--- a/components/arc/power/arc_power_bridge.h
+++ b/components/arc/power/arc_power_bridge.h
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "base/optional.h"
 #include "base/timer/timer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/common/power.mojom.h"
 #include "components/arc/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
diff --git a/components/arc/power/arc_power_bridge_unittest.cc b/components/arc/power/arc_power_bridge_unittest.cc
index f6dc18d3..21c34971 100644
--- a/components/arc/power/arc_power_bridge_unittest.cc
+++ b/components/arc/power/arc_power_bridge_unittest.cc
@@ -8,7 +8,7 @@
 
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/common/power.mojom.h"
diff --git a/components/arc/timer/arc_timer_bridge.cc b/components/arc/timer/arc_timer_bridge.cc
index fffe9ed0..1f89a27 100644
--- a/components/arc/timer/arc_timer_bridge.cc
+++ b/components/arc/timer/arc_timer_bridge.cc
@@ -12,7 +12,7 @@
 #include "base/task_runner_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "components/arc/arc_service_manager.h"
diff --git a/components/arc/timer/arc_timer_bridge_unittest.cc b/components/arc/timer/arc_timer_bridge_unittest.cc
index 7f126b3..7a6f173 100644
--- a/components/arc/timer/arc_timer_bridge_unittest.cc
+++ b/components/arc/timer/arc_timer_bridge_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/posix/unix_domain_socket.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/common/timer.mojom.h"
diff --git a/components/arc/wake_lock/arc_wake_lock_bridge.cc b/components/arc/wake_lock/arc_wake_lock_bridge.cc
index 8c526ca..c4c256f2a 100644
--- a/components/arc/wake_lock/arc_wake_lock_bridge.cc
+++ b/components/arc/wake_lock/arc_wake_lock_bridge.cc
@@ -8,7 +8,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "components/arc/arc_service_manager.h"
diff --git a/components/autofill/core/browser/autofill_profile_sync_util.cc b/components/autofill/core/browser/autofill_profile_sync_util.cc
index 8f6b3ca..0d6a67f 100644
--- a/components/autofill/core/browser/autofill_profile_sync_util.cc
+++ b/components/autofill/core/browser/autofill_profile_sync_util.cc
@@ -58,72 +58,40 @@
       entry.is_client_validity_states_updated());
 
   // Set repeated fields.
-  if (entry.HasRawInfo(NAME_FIRST)) {
-    specifics->add_name_first(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_FIRST))));
-  }
-  if (entry.HasRawInfo(NAME_MIDDLE)) {
-    specifics->add_name_middle(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_MIDDLE))));
-  }
-  if (entry.HasRawInfo(NAME_LAST)) {
-    specifics->add_name_last(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_LAST))));
-  }
-  if (entry.HasRawInfo(NAME_FULL)) {
-    specifics->add_name_full(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_FULL))));
-  }
-  if (entry.HasRawInfo(EMAIL_ADDRESS)) {
-    specifics->add_email_address(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(EMAIL_ADDRESS))));
-  }
-  if (entry.HasRawInfo(PHONE_HOME_WHOLE_NUMBER)) {
-    specifics->add_phone_home_whole_number(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(PHONE_HOME_WHOLE_NUMBER))));
-  }
+  specifics->add_name_first(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_FIRST))));
+  specifics->add_name_middle(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_MIDDLE))));
+  specifics->add_name_last(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_LAST))));
+  specifics->add_name_full(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_FULL))));
+  specifics->add_email_address(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(EMAIL_ADDRESS))));
+  specifics->add_phone_home_whole_number(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(PHONE_HOME_WHOLE_NUMBER))));
 
   // Set simple single-valued fields.
-  if (entry.HasRawInfo(COMPANY_NAME)) {
-    specifics->set_company_name(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(COMPANY_NAME))));
-  }
-  if (entry.HasRawInfo(ADDRESS_HOME_CITY)) {
-    specifics->set_address_home_city(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_CITY))));
-  }
-  if (entry.HasRawInfo(ADDRESS_HOME_STATE)) {
-    specifics->set_address_home_state(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_STATE))));
-  }
-  if (entry.HasRawInfo(ADDRESS_HOME_ZIP)) {
-    specifics->set_address_home_zip(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_ZIP))));
-  }
-  if (entry.HasRawInfo(ADDRESS_HOME_SORTING_CODE)) {
-    specifics->set_address_home_sorting_code(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_SORTING_CODE))));
-  }
-  if (entry.HasRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)) {
-    specifics->set_address_home_dependent_locality(TruncateUTF8(
-        UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY))));
-  }
-  if (entry.HasRawInfo(ADDRESS_HOME_COUNTRY)) {
-    specifics->set_address_home_country(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_COUNTRY))));
-  }
-  if (entry.HasRawInfo(ADDRESS_HOME_STREET_ADDRESS)) {
-    specifics->set_address_home_street_address(TruncateUTF8(
-        UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS))));
-  }
-  if (entry.HasRawInfo(ADDRESS_HOME_LINE1)) {
-    specifics->set_address_home_line1(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_LINE1))));
-  }
-  if (entry.HasRawInfo(ADDRESS_HOME_LINE2)) {
-    specifics->set_address_home_line2(
-        TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_LINE2))));
-  }
+  specifics->set_company_name(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(COMPANY_NAME))));
+  specifics->set_address_home_city(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_CITY))));
+  specifics->set_address_home_state(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_STATE))));
+  specifics->set_address_home_zip(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_ZIP))));
+  specifics->set_address_home_sorting_code(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_SORTING_CODE))));
+  specifics->set_address_home_dependent_locality(TruncateUTF8(
+      UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY))));
+  specifics->set_address_home_country(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_COUNTRY))));
+  specifics->set_address_home_street_address(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS))));
+  specifics->set_address_home_line1(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_LINE1))));
+  specifics->set_address_home_line2(
+      TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_LINE2))));
 
   return entity_data;
 }
@@ -145,77 +113,64 @@
       specifics.validity_state_bitfield());
 
   // Set repeated fields.
-  if (specifics.name_first_size() > 0) {
-    profile->SetRawInfo(NAME_FIRST, UTF8ToUTF16(specifics.name_first(0)));
-  }
-  if (specifics.name_middle_size() > 0) {
-    profile->SetRawInfo(NAME_MIDDLE, UTF8ToUTF16(specifics.name_middle(0)));
-  }
-  if (specifics.name_last_size() > 0) {
-    profile->SetRawInfo(NAME_LAST, UTF8ToUTF16(specifics.name_last(0)));
-  }
+  profile->SetRawInfo(NAME_FIRST, UTF8ToUTF16(specifics.name_first_size()
+                                                  ? specifics.name_first(0)
+                                                  : std::string()));
+  profile->SetRawInfo(NAME_MIDDLE, UTF8ToUTF16(specifics.name_middle_size()
+                                                   ? specifics.name_middle(0)
+                                                   : std::string()));
+  profile->SetRawInfo(
+      NAME_LAST, UTF8ToUTF16(specifics.name_last_size() ? specifics.name_last(0)
+                                                        : std::string()));
+  profile->SetRawInfo(
+      EMAIL_ADDRESS,
+      UTF8ToUTF16(specifics.email_address_size() ? specifics.email_address(0)
+                                                 : std::string()));
+  profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
+                      UTF8ToUTF16(specifics.phone_home_whole_number_size()
+                                      ? specifics.phone_home_whole_number(0)
+                                      : std::string()));
+
+  // Older versions don't have a separate full name; don't overwrite full name
+  // in this case.
   if (specifics.name_full_size() > 0) {
     profile->SetRawInfo(NAME_FULL, UTF8ToUTF16(specifics.name_full(0)));
   }
-  if (specifics.email_address_size() > 0) {
-    profile->SetRawInfo(EMAIL_ADDRESS, UTF8ToUTF16(specifics.email_address(0)));
-  }
-  if (specifics.phone_home_whole_number_size() > 0) {
-    profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
-                        UTF8ToUTF16(specifics.phone_home_whole_number(0)));
-  }
 
   // Set simple single-valued fields.
-  if (specifics.has_company_name()) {
-    profile->SetRawInfo(COMPANY_NAME, UTF8ToUTF16(specifics.company_name()));
-  }
-  if (specifics.has_address_home_city()) {
-    profile->SetRawInfo(ADDRESS_HOME_CITY,
-                        UTF8ToUTF16(specifics.address_home_city()));
-  }
-  if (specifics.has_address_home_state()) {
-    profile->SetRawInfo(ADDRESS_HOME_STATE,
-                        UTF8ToUTF16(specifics.address_home_state()));
-  }
-  if (specifics.has_address_home_zip()) {
-    profile->SetRawInfo(ADDRESS_HOME_ZIP,
-                        UTF8ToUTF16(specifics.address_home_zip()));
-  }
-  if (specifics.has_address_home_sorting_code()) {
-    profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE,
-                        UTF8ToUTF16(specifics.address_home_sorting_code()));
-  }
-  if (specifics.has_address_home_dependent_locality()) {
-    profile->SetRawInfo(
-        ADDRESS_HOME_DEPENDENT_LOCALITY,
-        UTF8ToUTF16(specifics.address_home_dependent_locality()));
-  }
-  if (specifics.has_address_home_country()) {
-    // Update the country field, which can contain either a country code (if set
-    // by a newer version of Chrome), or a country name (if set by an older
-    // version of Chrome).
-    // TODO(jkrcal): Move this migration logic into Address::SetRawInfo()?
-    base::string16 country_name_or_code =
-        base::ASCIIToUTF16(specifics.address_home_country());
-    std::string country_code =
-        CountryNames::GetInstance()->GetCountryCode(country_name_or_code);
-    profile->SetRawInfo(ADDRESS_HOME_COUNTRY, UTF8ToUTF16(country_code));
-  }
-  if (specifics.has_address_home_line1()) {
-    profile->SetRawInfo(ADDRESS_HOME_LINE1,
-                        UTF8ToUTF16(specifics.address_home_line1()));
-  }
-  if (specifics.has_address_home_line2()) {
-    profile->SetRawInfo(ADDRESS_HOME_LINE2,
-                        UTF8ToUTF16(specifics.address_home_line2()));
-  }
-  // Set first the deprecated subparts (line1 & line2) and only after that the
-  // full address (street_address) so that the latter wins in case of conflict.
-  // This is needed because all the address fields are backed by the same
-  // storage.
+  profile->SetRawInfo(COMPANY_NAME, UTF8ToUTF16(specifics.company_name()));
+  profile->SetRawInfo(ADDRESS_HOME_CITY,
+                      UTF8ToUTF16(specifics.address_home_city()));
+  profile->SetRawInfo(ADDRESS_HOME_STATE,
+                      UTF8ToUTF16(specifics.address_home_state()));
+  profile->SetRawInfo(ADDRESS_HOME_ZIP,
+                      UTF8ToUTF16(specifics.address_home_zip()));
+  profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE,
+                      UTF8ToUTF16(specifics.address_home_sorting_code()));
+  profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
+                      UTF8ToUTF16(specifics.address_home_dependent_locality()));
+
+  // Update the country field, which can contain either a country code (if set
+  // by a newer version of Chrome), or a country name (if set by an older
+  // version of Chrome).
+  // TODO(jkrcal): Move this migration logic into Address::SetRawInfo()?
+  base::string16 country_name_or_code =
+      base::ASCIIToUTF16(specifics.address_home_country());
+  std::string country_code =
+      CountryNames::GetInstance()->GetCountryCode(country_name_or_code);
+  profile->SetRawInfo(ADDRESS_HOME_COUNTRY, UTF8ToUTF16(country_code));
+
+  // Set either the deprecated subparts (line1 & line2) or the full address
+  // (street_address) if it is present. This is needed because all the address
+  // fields are backed by the same storage.
   if (specifics.has_address_home_street_address()) {
     profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
                         UTF8ToUTF16(specifics.address_home_street_address()));
+  } else {
+    profile->SetRawInfo(ADDRESS_HOME_LINE1,
+                        UTF8ToUTF16(specifics.address_home_line1()));
+    profile->SetRawInfo(ADDRESS_HOME_LINE2,
+                        UTF8ToUTF16(specifics.address_home_line2()));
   }
 
   // This has to be the last one, otherwise setting the raw info may change it.
diff --git a/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc b/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
index b9677d5..3925a7e 100644
--- a/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
+++ b/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
@@ -133,7 +133,7 @@
             entity_data->specifics.autofill_profile().SerializeAsString());
 }
 
-// Test that fields not set for the input are also not set on the output.
+// Test that fields not set for the input are empty in the output.
 TEST_F(AutofillProfileSyncUtilTest, CreateEntityDataFromAutofillProfile_Empty) {
   AutofillProfile profile(kGuid, std::string());
   ASSERT_FALSE(profile.HasRawInfo(NAME_FULL));
@@ -141,8 +141,10 @@
 
   std::unique_ptr<EntityData> entity_data =
       CreateEntityDataFromAutofillProfile(profile);
-  EXPECT_EQ(0, entity_data->specifics.autofill_profile().name_full_size());
-  EXPECT_FALSE(entity_data->specifics.autofill_profile().has_company_name());
+  EXPECT_EQ(1, entity_data->specifics.autofill_profile().name_full_size());
+  EXPECT_EQ("", entity_data->specifics.autofill_profile().name_full(0));
+  EXPECT_TRUE(entity_data->specifics.autofill_profile().has_company_name());
+  EXPECT_EQ("", entity_data->specifics.autofill_profile().company_name());
 }
 
 // Test that long fields get trimmed.
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
index d5eab46..60d37de6 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
@@ -285,7 +285,6 @@
 bool UpdateServerMetadata(AutofillTable* table,
                           WalletMetadataSpecifics::Type type,
                           const AutofillMetadata& metadata) {
-  // TODO: Create UpdateServerAddressMetadata() that takes metadata as arg.
   switch (type) {
     case WalletMetadataSpecifics::ADDRESS:
       return table->UpdateServerAddressMetadata(metadata);
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
index 203acff..c76ea95 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -347,6 +347,13 @@
   wallet_data_changed |= SetWalletAddresses(
       std::move(wallet_addresses), should_log_diff, notify_metadata_bridge);
 
+  // Commit the transaction to make sure the data and the metadata with the
+  // new progress marker is written down (especially on Android where we
+  // cannot rely on commiting transactions on shutdown). We need to commit
+  // even if the wallet data has not changed because the model type state incl.
+  // the progress marker always changes.
+  web_data_backend_->CommitChanges();
+
   if (web_data_backend_ && wallet_data_changed)
     web_data_backend_->NotifyOfMultipleAutofillChanges();
 }
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
index abcc0b2..54ed391 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -487,6 +487,7 @@
                                                      &customer_data_specifics);
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+  EXPECT_CALL(*backend(), CommitChanges());
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
                               AddChange(address2.server_id(), address2)));
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
@@ -533,6 +534,7 @@
                                                      &customer_data_specifics);
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+  EXPECT_CALL(*backend(), CommitChanges());
   StartSyncing({profile_specifics, card_specifics, customer_data_specifics});
 
   if (IsWalletMetadataOnUSS()) {
@@ -573,6 +575,7 @@
                                                      &customer_data_specifics2);
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+  EXPECT_CALL(*backend(), CommitChanges());
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(_)).Times(0);
   EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(_)).Times(0);
   StartSyncing({profile_specifics, card_specifics, customer_data_specifics2});
@@ -596,6 +599,7 @@
   table()->SetServerCreditCards({local_card});
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+  EXPECT_CALL(*backend(), CommitChanges());
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
                               RemoveChange(local_profile.server_id())));
   EXPECT_CALL(*backend(),
@@ -636,6 +640,8 @@
                                                      &customer_data_specifics);
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()).Times(0);
+  // We still need to commit the updated progress marker on the client.
+  EXPECT_CALL(*backend(), CommitChanges());
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(_)).Times(0);
   EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(_)).Times(0);
   StartSyncing({profile_specifics, card_specifics, customer_data_specifics});
@@ -672,6 +678,7 @@
   SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data,
                                                      &customer_data_specifics);
 
+  EXPECT_CALL(*backend(), CommitChanges());
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
                               RemoveChange(profile2.server_id())));
@@ -817,6 +824,7 @@
   CreditCard local_card = test::GetMaskedServerCard();
   table()->SetServerCreditCards({local_card});
 
+  EXPECT_CALL(*backend(), CommitChanges());
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(_)).Times(0);
   EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(_)).Times(0);
@@ -845,6 +853,8 @@
   CreditCard local_card = test::GetMaskedServerCard();
   table()->SetServerCreditCards({local_card});
 
+  // We do not write to DB at all, so we should not commit any changes.
+  EXPECT_CALL(*backend(), CommitChanges()).Times(0);
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()).Times(0);
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(_)).Times(0);
   EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(_)).Times(0);
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend.h b/components/autofill/core/browser/webdata/autofill_webdata_backend.h
index 43ff06e9..aa37b89 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend.h
@@ -34,6 +34,12 @@
   // Remove expired elements from the database and commit if needed.
   virtual void RemoveExpiredFormElements() = 0;
 
+  // Commits the currently open transaction in the database. Should be only used
+  // by parties that talk directly to the database and not through the
+  // WebDatabase backend (notably Sync reacting to remote changes coming from
+  // the server).
+  virtual void CommitChanges() = 0;
+
   // Notifies listeners on the DB sequence that an AutofillProfile has been
   // added/removed/updated in the WebDatabase.
   // NOTE: This method is intended to be called from the DB sequence. The UI
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
index e69f683..d7cb6af4 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -25,6 +25,12 @@
 
 namespace autofill {
 
+namespace {
+WebDatabase::State DoNothingAndCommit(WebDatabase* db) {
+  return WebDatabase::COMMIT_NEEDED;
+}
+}  // namespace
+
 AutofillWebDataBackendImpl::AutofillWebDataBackendImpl(
     scoped_refptr<WebDatabaseBackend> web_database_backend,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
@@ -64,6 +70,10 @@
   return web_database_backend_->database();
 }
 
+void AutofillWebDataBackendImpl::CommitChanges() {
+  web_database_backend_->ExecuteWriteTask(Bind(&DoNothingAndCommit));
+}
+
 void AutofillWebDataBackendImpl::RemoveExpiredFormElements() {
   web_database_backend_->ExecuteWriteTask(
       Bind(&AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl, this));
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
index 9b4a5a2..b508bda9 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
@@ -70,6 +70,7 @@
   void NotifyOfCreditCardChanged(const CreditCardChange& change) override;
   void NotifyOfMultipleAutofillChanges() override;
   void NotifyThatSyncHasStarted(syncer::ModelType model_type) override;
+  void CommitChanges() override;
 
   // TODO(crbug.com/920214): Deprecated, will be removed when
   // autocomplete retention policy shipped. Replaced by
diff --git a/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h b/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h
index 7b747246..3368878 100644
--- a/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h
+++ b/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h
@@ -27,6 +27,7 @@
   MOCK_METHOD1(RemoveObserver,
                void(AutofillWebDataServiceObserverOnDBSequence* observer));
   MOCK_METHOD0(RemoveExpiredFormElements, void());
+  MOCK_METHOD0(CommitChanges, void());
   MOCK_METHOD1(NotifyOfAutofillProfileChanged,
                void(const AutofillProfileChange& change));
   MOCK_METHOD1(NotifyOfCreditCardChanged, void(const CreditCardChange& change));
diff --git a/components/browser_sync/profile_sync_service_autofill_unittest.cc b/components/browser_sync/profile_sync_service_autofill_unittest.cc
index a192f7af..0944b520 100644
--- a/components/browser_sync/profile_sync_service_autofill_unittest.cc
+++ b/components/browser_sync/profile_sync_service_autofill_unittest.cc
@@ -188,6 +188,7 @@
   void RemoveObserver(
       autofill::AutofillWebDataServiceObserverOnDBSequence* observer) override {
   }
+  void CommitChanges() override {}
   void RemoveExpiredFormElements() override {}
 
   void NotifyOfAutofillProfileChanged(
diff --git a/components/content_settings/OWNERS b/components/content_settings/OWNERS
index 5da6865..728b3dc0 100644
--- a/components/content_settings/OWNERS
+++ b/components/content_settings/OWNERS
@@ -1,3 +1,4 @@
+engedy@chromium.org
 jochen@chromium.org
 msramek@chromium.org
 raymes@chromium.org
diff --git a/components/nacl/zygote/nacl_fork_delegate_linux.cc b/components/nacl/zygote/nacl_fork_delegate_linux.cc
index 27b2222..f91db4c 100644
--- a/components/nacl/zygote/nacl_fork_delegate_linux.cc
+++ b/components/nacl/zygote/nacl_fork_delegate_linux.cc
@@ -277,7 +277,7 @@
 
     // To avoid information leaks in Non-SFI mode, clear the environment for
     // the NaCl Helper process.
-    options.clear_environ = true;
+    options.clear_environment = true;
     AddPassthroughEnvToOptions(&options);
 
     base::Process process =
@@ -458,7 +458,7 @@
   for (size_t i = 0; i < pass_through_vars.size(); ++i) {
     std::string temp;
     if (env->GetVar(pass_through_vars[i], &temp))
-      options->environ[pass_through_vars[i]] = temp;
+      options->environment[pass_through_vars[i]] = temp;
   }
 }
 
diff --git a/components/nacl/zygote/nacl_fork_delegate_linux_unittest.cc b/components/nacl/zygote/nacl_fork_delegate_linux_unittest.cc
index a66e42c..07411e49 100644
--- a/components/nacl/zygote/nacl_fork_delegate_linux_unittest.cc
+++ b/components/nacl/zygote/nacl_fork_delegate_linux_unittest.cc
@@ -40,11 +40,11 @@
 
   base::LaunchOptions options;
   NaClForkDelegate::AddPassthroughEnvToOptions(&options);
-  EXPECT_EQ(value1, options.environ[passthrough1]);
-  EXPECT_EQ(0U, options.environ.count(passthrough2));
-  EXPECT_EQ(value3, options.environ[passthrough3]);
-  EXPECT_EQ(0U, options.environ.count(passthrough4));
-  EXPECT_EQ(value5, options.environ[passthrough5]);
+  EXPECT_EQ(value1, options.environment[passthrough1]);
+  EXPECT_EQ(0U, options.environment.count(passthrough2));
+  EXPECT_EQ(value3, options.environment[passthrough3]);
+  EXPECT_EQ(0U, options.environment.count(passthrough4));
+  EXPECT_EQ(value5, options.environment[passthrough5]);
 }
 
 }  // namespace nacl
diff --git a/components/neterror/resources/neterror.js b/components/neterror/resources/neterror.js
index fb1edde..d1f7c46 100644
--- a/components/neterror/resources/neterror.js
+++ b/components/neterror/resources/neterror.js
@@ -323,6 +323,7 @@
 function onDocumentLoadOrUpdate() {
   var downloadButtonVisible = loadTimeData.valueExists('downloadButton') &&
       loadTimeData.getValue('downloadButton').msg;
+  var detailsButton = document.getElementById('details-button');
 
   // If offline content suggestions will be visible, the usual buttons will not
   // be presented.
@@ -358,7 +359,6 @@
   var downloadButton = document.getElementById('download-button');
   if (reloadButton.style.display == 'none' &&
       downloadButton.style.display == 'none') {
-    var detailsButton = document.getElementById('details-button');
     detailsButton.classList.add('singular');
   }
 
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index 0823251..29cf80b 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -373,6 +373,7 @@
     "//components/test/data/password_manager/login_db_v2.sql",
     "//components/test/data/password_manager/login_db_v20.sql",
     "//components/test/data/password_manager/login_db_v21.sql",
+    "//components/test/data/password_manager/login_db_v22.sql",
     "//components/test/data/password_manager/login_db_v2_broken.sql",
     "//components/test/data/password_manager/login_db_v3.sql",
     "//components/test/data/password_manager/login_db_v3_broken.sql",
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc
index b134dc6..de4f10e 100644
--- a/components/password_manager/core/browser/login_database.cc
+++ b/components/password_manager/core/browser/login_database.cc
@@ -25,6 +25,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/autofill/core/common/password_form.h"
@@ -52,7 +53,7 @@
 namespace password_manager {
 
 // The current version number of the login database schema.
-const int kCurrentVersionNumber = 21;
+const int kCurrentVersionNumber = 22;
 // The oldest version of the schema such that a legacy Chrome client using that
 // version can still read/write the current database.
 const int kCompatibleVersionNumber = 19;
@@ -374,6 +375,16 @@
   }
 }
 
+bool ClearAllSyncMetadata(sql::Database* db) {
+  sql::Statement s1(
+      db->GetCachedStatement(SQL_FROM_HERE, "DELETE FROM sync_model_metadata"));
+
+  sql::Statement s2(db->GetCachedStatement(
+      SQL_FROM_HERE, "DELETE FROM sync_entities_metadata"));
+
+  return s1.Run() && s2.Run();
+}
+
 // Seals the version of the given builders. This is method should be always used
 // to seal versions of all builder to make sure all builders are at the same
 // version.
@@ -488,6 +499,9 @@
   builders.sync_model_metadata->AddColumn("model_metadata", "VARCHAR NOT NULL");
   SealVersion(builders, /*expected_version=*/21u);
 
+  // Version 22. Changes in Sync metadata encryption.
+  SealVersion(builders, /*expected_version=*/22u);
+
   DCHECK_EQ(static_cast<size_t>(COLUMN_NUM), builders.logins->NumberOfColumns())
       << "Adjust LoginDatabaseTableColumns if you change column definitions "
          "here.";
@@ -527,6 +541,13 @@
       return false;
   }
 
+  // Sync Metadata tables have been introduced in version 21. It is enough to
+  // drop all data because Sync would populate the tables properly at startup.
+  if (current_version == 21) {
+    if (!ClearAllSyncMetadata(db))
+      return false;
+  }
+
   return true;
 }
 
@@ -1610,13 +1631,20 @@
     return false;
   }
 
+  std::string encrypted_metadata;
+  if (!OSCrypt::EncryptString(metadata.SerializeAsString(),
+                              &encrypted_metadata)) {
+    DLOG(ERROR) << "Cannot encrypt the sync metadata";
+    return false;
+  }
+
   sql::Statement s(
       db_.GetCachedStatement(SQL_FROM_HERE,
                              "INSERT OR REPLACE INTO sync_entities_metadata "
                              "(storage_key, metadata) VALUES(?, ?)"));
 
   s.BindInt(0, storage_key_int);
-  s.BindString(1, metadata.SerializeAsString());
+  s.BindString(1, encrypted_metadata);
 
   return s.Run();
 }
@@ -1700,9 +1728,17 @@
 
   while (s.Step()) {
     std::string storage_key = s.ColumnString(0);
-    std::string serialized_metadata = s.ColumnString(1);
+    std::string encrypted_serialized_metadata = s.ColumnString(1);
+    std::string decrypted_serialized_metadata;
+    if (!OSCrypt::DecryptString(encrypted_serialized_metadata,
+                                &decrypted_serialized_metadata)) {
+      DLOG(WARNING) << "Failed to decrypt PASSWORD model type "
+                       "sync_pb::EntityMetadata.";
+      return nullptr;
+    }
+
     sync_pb::EntityMetadata entity_metadata;
-    if (entity_metadata.ParseFromString(serialized_metadata)) {
+    if (entity_metadata.ParseFromString(decrypted_serialized_metadata)) {
       metadata_batch->AddMetadata(storage_key, entity_metadata);
     } else {
       DLOG(WARNING) << "Failed to deserialize PASSWORD model type "
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto
index 35f3225..d2607a8 100644
--- a/components/policy/proto/chrome_device_policy.proto
+++ b/components/policy/proto/chrome_device_policy.proto
@@ -1002,6 +1002,23 @@
   // clears the TPM to install the firmware update, but preserves device-wide
   // state (including enrollment). User data will not be preserved in this flow.
   optional bool allow_user_initiated_preserve_device_state = 2;
+
+  enum AutoUpdateMode {
+    // No value set. Default is NEVER.
+    AUTO_UPDATE_MODE_UNSPECIFIED = 0;
+    // Don't auto update TPM firmware.
+    NEVER = 1;
+    // Update firmware at the next reboot after user acknowledges the update.
+    USER_ACKNOWLEDGMENT = 2;
+    // Update firmware at the next reboot.
+    WITHOUT_ACKNOWLEDGMENT = 3;
+    // Update firmware after enrollment.
+    ENROLLMENT = 4;
+  }
+
+  // Controls how automatic firmware updates are enforced for vulnerable
+  // firmware. All flows preserve local device state.
+  optional AutoUpdateMode auto_update_mode = 3 [default = NEVER];
 }
 
 // Settings to control the minimum version that is allowed to sign in / stay
@@ -1164,6 +1181,23 @@
   optional string device_wilco_dtc_configuration = 1;
 }
 
+// Settings that control power peak shift policy.
+message DevicePowerPeakShiftProto {
+  // Setting that controls whether power peak shift is enabled on this device.
+  // For details see "DevicePowerPeakShiftEnabled" in policy_templates.json.
+  optional bool enabled = 1;
+
+  // Setting that controls power peak shift battery threshold on this device.
+  // For details see "DevicePowerPeakShiftBatteryThreshold" in
+  // policy_templates.json.
+  optional int32 battery_threshold = 2;
+
+  // Setting that controls power peak shift day configs on this device.
+  // This is a JSON string, for details see "DevicePowerPeakShiftDayConfig" in
+  // policy_templates.json.
+  optional string day_configs = 3;
+}
+
 message ChromeDeviceSettingsProto {
   reserved 61;
   optional DevicePolicyRefreshRateProto device_policy_refresh_rate = 1;
@@ -1268,4 +1302,5 @@
   optional DeviceWilcoDtcAllowedProto device_wilco_dtc_allowed = 80;
   optional DeviceWilcoDtcConfigurationProto device_wilco_dtc_configuration = 81;
   optional DeviceWiFiAllowedProto device_wifi_allowed = 82;
+  optional DevicePowerPeakShiftProto device_power_peak_shift = 83;
 }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 9baa254..0acc9138 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -576,6 +576,9 @@
         'ScreenLockDelays',
         'PowerSmartDimEnabled',
         'ScreenBrightnessPercent',
+        'DevicePowerPeakShiftBatteryThreshold',
+        'DevicePowerPeakShiftDayConfig',
+        'DevicePowerPeakShiftEnabled',
       ],
     },
     {
@@ -11666,6 +11669,10 @@
           'allow-user-initiated-preserve-device-state': {
             'type': 'boolean',
           },
+          'auto-update-mode': {
+            'type': 'integer',
+            'enum': [ 1, 2, 3, 4 ],
+          },
         },
       },
       'features': {
@@ -11675,6 +11682,7 @@
       'example_value': {
         'allow-user-initiated-powerwash': True,
         'allow-user-initiated-preserve-device-state': True,
+        'auto-update-mode': 1,
       },
       'caption': '''Configure <ph name="TPM_FIRMWARE_UPDATE_TPM">TPM</ph> firmware update behavior''',
       'tags': [],
@@ -11686,6 +11694,13 @@
 
       <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_ALLOW_USER_INITIATED_PRESERVE_DEVICE_STATE">allow-user-initiated-preserve-device-state</ph>: If set to <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_ALLOW_USER_INITIATED_PRESERVE_DEVICE_STATE_TRUE">true</ph>, users will be able to invoke the <ph name="TPM_FIRMWARE_UPDATE_TPM">TPM</ph> firmware update flow that preserves device-wide state (including enterprise enrollment), but loses user data. This update flow is available starting from version 68.
 
+      <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_AUTO_UPDATE_MODE">auto-update-mode</ph>: Controls how automatic <ph name="TPM_FIRMWARE_UPDATE_TPM">TPM</ph> firmware updates are enforced for vulnerable <ph name="TPM_FIRMWARE_UPDATE_TPM">TPM</ph> firmware. All flows preserve local device state.
+        If set to 1 or left not set, TPM firmware updates are not enforced.
+        If set to 2, <ph name="TPM_FIRMWARE_UPDATE_TPM">TPM</ph> firmware will be updated at the next reboot after user acknowledges the update.
+        If set to 3, <ph name="TPM_FIRMWARE_UPDATE_TPM">TPM</ph> firmware will be updated at the next reboot.
+        If set to 4, <ph name="TPM_FIRMWARE_UPDATE_TPM">TPM</ph> firmware will be updated after enrollment, before user sign-in.
+        This option is available starting from version 74.
+
       If the policy is not set, <ph name="TPM_FIRMWARE_UPDATE_TPM">TPM</ph> firmware update functionality will not be available.''',
     },
     {
@@ -15083,7 +15098,138 @@
 
       If you set this policy, users cannot change or override it.''',
     },
+    {
+      'name': 'DevicePowerPeakShiftEnabled',
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'supported_on': ['chrome_os:75-'],
+      'device_only': True,
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': False
+      },
+      'example_value': False,
+      'id': 538,
+      'caption': '''Enable power peak shift''',
+      'tags': [],
+      'desc': '''Enable the power peak shift power management policy.
 
+          Peak Shift is power saving policy that minimizes alternating current usage during the peak usage times during the day. For each weekday a start and end time to run in power Peak Shift mode can be set. During these times the system will run from the battery even if the alternating current is attached as long as the battery stays above the threshold specified. After the end time specified the system will run from alternating current if attached but will not charge the battery. The system will again function normally using alternating current and recharging the battery after the specified Charge Start time.
+
+          If this policy is set to true, and DevicePowerPeakShiftBatteryThreshold, DevicePowerPeakShiftDayConfig are set, then power peak shift will always be enabled if supported on the device.
+
+          If this policy is set to false, power peak shift will always be disabled.
+
+          If you set this policy, users cannot change or override it.
+
+          If this policy is left unset, power peak shift is disabled initially and cannot be enabled by the user.'''
+    },
+    {
+      'name': 'DevicePowerPeakShiftBatteryThreshold',
+      'type': 'int',
+      'schema': {
+        'type': 'integer',
+        'minimum': 15,
+        'maximum': 100
+      },
+      'supported_on': ['chrome_os:75-'],
+      'device_only': True,
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': False
+      },
+      'example_value': 20,
+      'id': 539,
+      'caption': '''Set power peak shift battery threshold in percent''',
+      'tags': [],
+      'desc': '''Set power peak shift battery threshold in percent.
+
+          This policy is only used if DevicePowerPeakShiftEnabled is set to true.
+
+          If this policy is not configured or left unset, power peak shift will always be disabled.'''
+    },
+    {
+      'name': 'DevicePowerPeakShiftDayConfig',
+      'type': 'dict',
+      'schema': {
+        'type': 'object',
+        'properties': {
+          'entries': {
+            'type': 'array',
+            'items': {
+              'type': 'object',
+              'properties': {
+                'day': {
+                  'type': 'string',
+                  'enum': [
+                    'MONDAY',
+                    'TUESDAY',
+                    'WEDNESDAY',
+                    'THURSDAY',
+                    'FRIDAY',
+                    'SATURDAY',
+                    'SUNDAY'
+                  ]
+                },
+                'start_time': { '$ref': 'Time' },
+                'end_time': { '$ref': 'Time' },
+                'charge_start_time': { '$ref': 'Time' }
+              }
+            }
+          }
+        }
+      },
+      'supported_on': ['chrome_os:75-'],
+      'device_only': True,
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': False
+      },
+      'example_value': {
+        'entries': [
+          {
+            'day': 'MONDAY',
+            'start_time': {
+              'hour': 9,
+              'minute': 0
+            },
+            'end_time': {
+              'hour': 15,
+              'minute': 15
+            },
+            'charge_start_time': {
+              'hour': 20,
+              'minute': 45
+            }
+          },
+          {
+            'day': 'FRIDAY',
+            'start_time': {
+              'hour': 2,
+              'minute': 30
+            },
+            'end_time': {
+              'hour': 21,
+              'minute': 0
+            },
+            'charge_start_time': {
+              'hour': 23,
+              'minute': 45
+            }
+          }
+        ],
+      },
+      'id': 540,
+      'caption': '''Set power peak shift day config''',
+      'tags': [],
+      'desc': '''Set power peak shift day config.
+
+          This policy is only used if DevicePowerPeakShiftEnabled is set to true.
+
+          If this policy is not configured or left unset, power peak shift will always be disabled.
+
+          Note: allowed values for <ph name="MINUTE_FIELD_NAME">minute</ph> field in <ph name="START_TIME_FIELD_NAME">start_time</ph>, <ph name="END_TIME_FIELD_NAME">end_time</ph> and <ph name="CHARGE_START_TIME_FIELD_NAME">charge_start_time</ph> are 0, 15, 30, 45.'''
+    },
   ],
 
   'messages': {
@@ -15249,5 +15395,5 @@
   },
   'placeholders': [],
   'deleted_policy_ids': [412],
-  'highest_id_currently_used':  537
+  'highest_id_currently_used':  540
 }
diff --git a/components/search_engines/prepopulated_engines.json b/components/search_engines/prepopulated_engines.json
index 64e8cb5..9d7af2b 100644
--- a/components/search_engines/prepopulated_engines.json
+++ b/components/search_engines/prepopulated_engines.json
@@ -28,7 +28,7 @@
     // Increment this if you change the data in ways that mean users with
     // existing data should get a new version. Otherwise, existing data may
     // continue to be used and updates made here will not always appear.
-    "kCurrentDataVersion": 110
+    "kCurrentDataVersion": 111
   },
 
   // The following engines are included in country lists and are added to the
@@ -69,9 +69,9 @@
       "favicon_url": "https://www.bing.com/sa/simg/bing_p_rr_teal_min.ico",
       "search_url": "https://www.bing.com/search?q={searchTerms}&PC=U316&FORM=CHROMN",
       "suggest_url": "https://www.bing.com/osjson.aspx?query={searchTerms}&language={language}&PC=U316",
-      "image_url": "https://www.bing.com/images/detail/search?iss=sbi&FORM=CHROMI#enterInsights",
+      "image_url": "https://www.bing.com/images/detail/search?iss=sbiupload&FORM=CHROMI#enterInsights",
       "new_tab_url": "https://www.bing.com/chrome/newtab",
-      "image_url_post_params": "imgurl={google:imageURL}",
+      "image_url_post_params": "imageBin={google:imageThumbnailBase64}",
       "type": "SEARCH_ENGINE_BING",
       "id": 3
     },
diff --git a/components/search_engines/template_url.cc b/components/search_engines/template_url.cc
index 0de7442..1895362 100644
--- a/components/search_engines/template_url.cc
+++ b/components/search_engines/template_url.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <vector>
 
+#include "base/base64.h"
 #include "base/command_line.h"
 #include "base/format_macros.h"
 #include "base/i18n/case_conversion.h"
@@ -662,6 +663,9 @@
   } else if (parameter == "google:imageThumbnail") {
     replacements->push_back(
         Replacement(TemplateURLRef::GOOGLE_IMAGE_THUMBNAIL, start));
+  } else if (parameter == "google:imageThumbnailBase64") {
+    replacements->push_back(
+        Replacement(TemplateURLRef::GOOGLE_IMAGE_THUMBNAIL_BASE64, start));
   } else if (parameter == "google:imageURL") {
     replacements->push_back(Replacement(TemplateURLRef::GOOGLE_IMAGE_URL,
                                         start));
@@ -1157,6 +1161,16 @@
           post_params_[i->index].content_type = "image/jpeg";
         break;
 
+      case GOOGLE_IMAGE_THUMBNAIL_BASE64: {
+        std::string base64_thumbnail_content;
+        base::Base64Encode(search_terms_args.image_thumbnail_content,
+                           &base64_thumbnail_content);
+        HandleReplacement(std::string(), base64_thumbnail_content, *i, &url);
+        if (i->is_post_param)
+          post_params_[i->index].content_type = "image/jpeg";
+        break;
+      }
+
       case GOOGLE_IMAGE_URL:
         if (search_terms_args.image_url.is_valid()) {
           HandleReplacement(
diff --git a/components/search_engines/template_url.h b/components/search_engines/template_url.h
index dab99567..21c68f02 100644
--- a/components/search_engines/template_url.h
+++ b/components/search_engines/template_url.h
@@ -329,6 +329,7 @@
     GOOGLE_IMAGE_ORIGINAL_WIDTH,
     GOOGLE_IMAGE_SEARCH_SOURCE,
     GOOGLE_IMAGE_THUMBNAIL,
+    GOOGLE_IMAGE_THUMBNAIL_BASE64,
     GOOGLE_IMAGE_URL,
     GOOGLE_INPUT_TYPE,
     GOOGLE_IOS_SEARCH_LANGUAGE,
diff --git a/components/search_engines/template_url_unittest.cc b/components/search_engines/template_url_unittest.cc
index 4dc754e..b4a4c96 100644
--- a/components/search_engines/template_url_unittest.cc
+++ b/components/search_engines/template_url_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <stddef.h>
 
+#include "base/base64.h"
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/i18n/case_conversion.h"
@@ -172,7 +173,8 @@
   const char kValidPostParamsString[] =
       "image_content={google:imageThumbnail},image_url={google:imageURL},"
       "sbisrc={google:imageSearchSource},language={language},empty_param=,"
-      "constant_param=constant,width={google:imageOriginalWidth}";
+      "constant_param=constant,width={google:imageOriginalWidth},"
+      "base64_image_content={google:imageThumbnailBase64}";
   const char KImageSearchURL[] = "http://foo.com/sbi";
 
   TemplateURLData data;
@@ -220,7 +222,7 @@
       url.image_url_ref().replacements_;
   const TemplateURLRef::PostParams& post_params =
       url.image_url_ref().post_params_;
-  EXPECT_EQ(7U, post_params.size());
+  EXPECT_EQ(8U, post_params.size());
   for (auto i = post_params.begin(); i != post_params.end(); ++i) {
     auto j = replacements.begin();
     for (; j != replacements.end(); ++j) {
@@ -241,6 +243,14 @@
                               search_args.image_thumbnail_content,
                               "image/jpeg");
             break;
+          case TemplateURLRef::GOOGLE_IMAGE_THUMBNAIL_BASE64: {
+            std::string base64_image_content;
+            base::Base64Encode(search_args.image_thumbnail_content,
+                               &base64_image_content);
+            ExpectPostParamIs(*i, "base64_image_content", base64_image_content,
+                              "image/jpeg");
+            break;
+          }
           case TemplateURLRef::GOOGLE_IMAGE_URL:
             ExpectPostParamIs(*i, "image_url", search_args.image_url.spec());
             break;
diff --git a/components/security_interstitials/content/security_interstitial_tab_helper.cc b/components/security_interstitials/content/security_interstitial_tab_helper.cc
index 4458f5db..d4b02ef 100644
--- a/components/security_interstitials/content/security_interstitial_tab_helper.cc
+++ b/components/security_interstitials/content/security_interstitial_tab_helper.cc
@@ -37,6 +37,9 @@
   if (it != blocking_pages_for_navigations_.end()) {
     blocking_pages_for_navigations_.erase(it);
   }
+
+  // Interstitials may change the visibility of the URL or other security state.
+  web_contents()->DidChangeVisibleSecurityState();
 }
 
 void SecurityInterstitialTabHelper::WebContentsDestroyed() {
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountTrackerService.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountTrackerService.java
index 07b9957..1f3b3fe 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountTrackerService.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountTrackerService.java
@@ -52,7 +52,7 @@
         // Called at the end of seedSystemAccounts().
         void onSystemAccountsSeedingComplete();
         // Called in invalidateAccountSeedStatus() indicating that accounts have changed.
-        void onSystemAccountsChanged();
+        default void onSystemAccountsChanged() {}
     }
 
     private final ObserverList<OnSystemAccountsSeededListener> mSystemAccountsSeedingObservers =
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
index c1f25744..2158328d 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
@@ -79,8 +79,7 @@
     private final AccountTrackerService mAccountTrackerService;
     private final ObserverList<OAuth2TokenServiceObserver> mObservers = new ObserverList<>();
 
-    private boolean mPendingValidation;
-    private boolean mPendingValidationForceNotifications;
+    private boolean mPendingUpdate;
 
     private OAuth2TokenService(
             long nativeOAuth2TokenServiceDelegate, AccountTrackerService accountTrackerService) {
@@ -141,7 +140,7 @@
     /**
      * Called by native to list the accounts Id with OAuth2 refresh tokens.
      * This can differ from getSystemAccountNames as the user add/remove accounts
-     * from the OS. validateAccounts should be called to keep these two
+     * from the OS. updateAccountList should be called to keep these two
      * in sync.
      */
     @CalledByNative
@@ -323,35 +322,24 @@
      */
     @Override
     public void onSystemAccountsSeedingComplete() {
-        if (mPendingValidation) {
-            validateAccountsWithSignedInAccountName(mPendingValidationForceNotifications);
-            mPendingValidation = false;
-            mPendingValidationForceNotifications = false;
+        if (mPendingUpdate) {
+            updateAccountListInternal();
+            mPendingUpdate = false;
         }
     }
 
-    /**
-     * Clear pending accounts validation when system accounts in AccountTrackerService were
-     * refreshed.
-     */
-    @Override
-    public void onSystemAccountsChanged() {
-        mPendingValidationForceNotifications = false;
-    }
-
     @CalledByNative
-    public void validateAccounts(boolean forceNotifications) {
+    public void updateAccountList() {
         ThreadUtils.assertOnUiThread();
         if (!mAccountTrackerService.checkAndSeedSystemAccounts()) {
-            mPendingValidation = true;
-            mPendingValidationForceNotifications = forceNotifications;
+            mPendingUpdate = true;
             return;
         }
 
-        validateAccountsWithSignedInAccountName(forceNotifications);
+        updateAccountListInternal();
     }
 
-    private void validateAccountsWithSignedInAccountName(boolean forceNotifications) {
+    private void updateAccountListInternal() {
         String currentlySignedInAccount = ChromeSigninController.get().getSignedInAccountName();
         if (currentlySignedInAccount != null
                 && isSignedInAccountChanged(currentlySignedInAccount)) {
@@ -363,8 +351,7 @@
             // change (re-signin or sign out signed-in account).
             currentlySignedInAccount = null;
         }
-        nativeValidateAccounts(
-                mNativeOAuth2TokenServiceDelegate, currentlySignedInAccount, forceNotifications);
+        nativeUpdateAccountList(mNativeOAuth2TokenServiceDelegate, currentlySignedInAccount);
     }
 
     private boolean isSignedInAccountChanged(String signedInAccountName) {
@@ -495,6 +482,6 @@
 
     private static native void nativeOAuth2TokenFetched(
             String authToken, boolean isTransientError, long nativeCallback);
-    private native void nativeValidateAccounts(long nativeOAuth2TokenServiceDelegateAndroid,
-            String currentlySignedInAccount, boolean forceNotifications);
+    private native void nativeUpdateAccountList(
+            long nativeOAuth2TokenServiceDelegateAndroid, String currentlySignedInAccount);
 }
diff --git a/components/signin/core/browser/oauth2_token_service_delegate_android.cc b/components/signin/core/browser/oauth2_token_service_delegate_android.cc
index 4f1df012..575b6123 100644
--- a/components/signin/core/browser/oauth2_token_service_delegate_android.cc
+++ b/components/signin/core/browser/oauth2_token_service_delegate_android.cc
@@ -11,6 +11,7 @@
 #include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
 #include "components/signin/core/browser/account_consistency_method.h"
@@ -162,8 +163,7 @@
   }
 
   if (!disable_interaction_with_system_accounts_) {
-    Java_OAuth2TokenService_validateAccounts(AttachCurrentThread(), java_ref_,
-                                             JNI_TRUE);
+    Java_OAuth2TokenService_updateAccountList(AttachCurrentThread(), java_ref_);
   }
 }
 
@@ -270,13 +270,12 @@
   Java_OAuth2TokenService_invalidateAccessToken(env, j_access_token);
 }
 
-void OAuth2TokenServiceDelegateAndroid::ValidateAccounts(
+void OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jstring>& j_current_acc,
-    jboolean j_force_notifications) {
+    const JavaParamRef<jstring>& j_current_acc) {
   std::string signed_in_account_name;
-  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts from java";
+  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList from java";
   if (j_current_acc)
     signed_in_account_name = ConvertJavaStringToUTF8(env, j_current_acc);
   if (!signed_in_account_name.empty())
@@ -285,13 +284,11 @@
   // Clear any auth errors so that client can retry to get access tokens.
   errors_.clear();
 
-  ValidateAccounts(MapAccountNameToAccountId(signed_in_account_name),
-                   j_force_notifications != JNI_FALSE);
+  UpdateAccountList(MapAccountNameToAccountId(signed_in_account_name));
 }
 
-void OAuth2TokenServiceDelegateAndroid::ValidateAccounts(
-    const std::string& signed_in_account_id,
-    bool force_notifications) {
+void OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
+    const std::string& signed_in_account_id) {
   std::vector<std::string> curr_ids;
   for (const std::string& curr_name : GetSystemAccountNames()) {
     std::string curr_id(MapAccountNameToAccountId(curr_name));
@@ -305,16 +302,15 @@
       prev_ids.push_back(prev_id);
   }
 
-  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
+  DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
            << " sigined_in_account_id=" << signed_in_account_id
-           << " prev_ids=" << prev_ids.size() << " curr_ids=" << curr_ids.size()
-           << " force=" << (force_notifications ? "true" : "false");
+           << " prev_ids=" << prev_ids.size()
+           << " curr_ids=" << curr_ids.size();
 
   std::vector<std::string> refreshed_ids;
   std::vector<std::string> revoked_ids;
-  bool keep_accounts =
-      ValidateAccounts(signed_in_account_id, prev_ids, curr_ids, &refreshed_ids,
-                       &revoked_ids, force_notifications);
+  bool keep_accounts = UpdateAccountList(
+      signed_in_account_id, prev_ids, curr_ids, &refreshed_ids, &revoked_ids);
 
   ScopedBatchChange batch(this);
   JNIEnv* env = AttachCurrentThread();
@@ -356,15 +352,20 @@
       signed_in_account_id.empty()) {
     account_tracker_service_->SetMigrationDone();
   }
+
+  if (!last_update_accounts_time_.is_null()) {
+    base::TimeDelta sample = base::Time::Now() - last_update_accounts_time_;
+    UmaHistogramLongTimes("Signin.AndroidTimeBetweenUpdateAccountList", sample);
+  }
+  last_update_accounts_time_ = base::Time::Now();
 }
 
-bool OAuth2TokenServiceDelegateAndroid::ValidateAccounts(
+bool OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
     const std::string& signed_in_id,
     const std::vector<std::string>& prev_ids,
     const std::vector<std::string>& curr_ids,
     std::vector<std::string>* refreshed_ids,
-    std::vector<std::string>* revoked_ids,
-    bool force_notifications) {
+    std::vector<std::string>* revoked_ids) {
   bool keep_accounts = base::FeatureList::IsEnabled(signin::kMiceFeature) ||
                        base::ContainsValue(curr_ids, signed_in_id);
   if (keep_accounts) {
@@ -373,40 +374,36 @@
       if (prev_id == signed_in_id)
         continue;
       if (!base::ContainsValue(curr_ids, prev_id)) {
-        DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
+        DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
                  << "revoked=" << prev_id;
         revoked_ids->push_back(prev_id);
       }
     }
 
-    // Refresh token for new ids or all ids if |force_notifications|.
-    if (!signed_in_id.empty() &&
-        (force_notifications || !base::ContainsValue(prev_ids, signed_in_id))) {
+    if (!signed_in_id.empty()) {
       // Always fire the primary signed in account first.
-      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
+      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
                << "refreshed=" << signed_in_id;
       refreshed_ids->push_back(signed_in_id);
     }
     for (const std::string& curr_id : curr_ids) {
       if (curr_id == signed_in_id)
         continue;
-      if (force_notifications || !base::ContainsValue(prev_ids, curr_id)) {
-        DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
-                 << "refreshed=" << curr_id;
-        refreshed_ids->push_back(curr_id);
-      }
+      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
+               << "refreshed=" << curr_id;
+      refreshed_ids->push_back(curr_id);
     }
   } else {
     // Revoke all ids.
     if (base::ContainsValue(prev_ids, signed_in_id)) {
-      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
+      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
                << "revoked=" << signed_in_id;
       revoked_ids->push_back(signed_in_id);
     }
     for (const std::string& prev_id : prev_ids) {
       if (prev_id == signed_in_id)
         continue;
-      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::ValidateAccounts:"
+      DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
                << "revoked=" << prev_id;
       revoked_ids->push_back(prev_id);
     }
@@ -500,9 +497,9 @@
 
 void OAuth2TokenServiceDelegateAndroid::ReloadAccountsFromSystem(
     const std::string& primary_account_id) {
-  // ValidateAccounts() effectively synchronizes the accounts in the Token
+  // UpdateAccountList() effectively synchronizes the accounts in the Token
   // Service with those present at the system level.
-  ValidateAccounts(primary_account_id, /*force_notifications=*/true);
+  UpdateAccountList(primary_account_id);
 }
 
 std::string OAuth2TokenServiceDelegateAndroid::MapAccountIdToAccountName(
diff --git a/components/signin/core/browser/oauth2_token_service_delegate_android.h b/components/signin/core/browser/oauth2_token_service_delegate_android.h
index 3f8ced9..8808eea 100644
--- a/components/signin/core/browser/oauth2_token_service_delegate_android.h
+++ b/components/signin/core/browser/oauth2_token_service_delegate_android.h
@@ -8,6 +8,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/android/jni_weak_ref.h"
 #include "base/android/scoped_java_ref.h"
@@ -57,18 +58,16 @@
   // Lists account names at the OS level.
   std::vector<std::string> GetSystemAccountNames();
 
-  void ValidateAccounts(
+  void UpdateAccountList(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
-      const base::android::JavaParamRef<jstring>& current_account,
-      jboolean force_notifications);
+      const base::android::JavaParamRef<jstring>& current_account);
 
   // Takes a the signed in sync account as well as all the other
-  // android account ids and check the token status of each.  If
-  // |force_notifications| is true, TokenAvailable notifications will
-  // be sent anyway, even if the account was already known.
-  void ValidateAccounts(const std::string& signed_in_account_id,
-                        bool force_notifications);
+  // android account ids and check the token status of each.
+  // NOTE: TokenAvailable notifications will be sent for all accounts, even if
+  // they were already known. See https://crbug.com/939470 for details.
+  void UpdateAccountList(const std::string& signed_in_account_id);
 
   // Overridden from OAuth2TokenService to complete signout of all
   // OA2TService aware accounts.
@@ -110,14 +109,12 @@
   };
 
   // Return whether accounts are valid and we have access to all the tokens in
-  // |curr_ids|. If |force_notifications| is true, TokenAvailable notifications
-  // will be sent anyway, even if the account was already known.
-  bool ValidateAccounts(const std::string& signed_in_id,
-                        const std::vector<std::string>& prev_ids,
-                        const std::vector<std::string>& curr_ids,
-                        std::vector<std::string>* refreshed_ids,
-                        std::vector<std::string>* revoked_ids,
-                        bool force_notifications);
+  // |curr_ids|.
+  bool UpdateAccountList(const std::string& signed_in_id,
+                         const std::vector<std::string>& prev_ids,
+                         const std::vector<std::string>& curr_ids,
+                         std::vector<std::string>* refreshed_ids,
+                         std::vector<std::string>* revoked_ids);
 
   base::android::ScopedJavaGlobalRef<jobject> java_ref_;
 
@@ -126,6 +123,7 @@
 
   AccountTrackerService* account_tracker_service_;
   RefreshTokenLoadStatus fire_refresh_token_loaded_;
+  base::Time last_update_accounts_time_;
 
   static bool disable_interaction_with_system_accounts_;
 
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index 2b9aeb40..6d227399 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -800,6 +800,8 @@
     "driver/fake_sync_service.h",
     "driver/frontend_data_type_controller_mock.cc",
     "driver/frontend_data_type_controller_mock.h",
+    "driver/mock_sync_service.cc",
+    "driver/mock_sync_service.h",
     "driver/model_associator_mock.cc",
     "driver/model_associator_mock.h",
     "driver/sync_api_component_factory_mock.cc",
diff --git a/components/sync/driver/mock_sync_service.cc b/components/sync/driver/mock_sync_service.cc
new file mode 100644
index 0000000..333ed42
--- /dev/null
+++ b/components/sync/driver/mock_sync_service.cc
@@ -0,0 +1,25 @@
+// Copyright 2019 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 "components/sync/driver/mock_sync_service.h"
+
+namespace syncer {
+
+MockSyncService::MockSyncService() = default;
+
+MockSyncService::~MockSyncService() = default;
+
+syncer::SyncUserSettingsMock* MockSyncService::GetMockUserSettings() {
+  return &user_settings_;
+}
+
+syncer::SyncUserSettings* MockSyncService::GetUserSettings() {
+  return &user_settings_;
+}
+
+const syncer::SyncUserSettings* MockSyncService::GetUserSettings() const {
+  return &user_settings_;
+}
+
+}  // namespace syncer
diff --git a/components/sync/driver/mock_sync_service.h b/components/sync/driver/mock_sync_service.h
new file mode 100644
index 0000000..872f3e5
--- /dev/null
+++ b/components/sync/driver/mock_sync_service.h
@@ -0,0 +1,99 @@
+// Copyright 2019 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 COMPONENTS_SYNC_DRIVER_MOCK_SYNC_SERVICE_H_
+#define COMPONENTS_SYNC_DRIVER_MOCK_SYNC_SERVICE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/values.h"
+#include "components/signin/core/browser/account_info.h"
+#include "components/sync/driver/sync_service.h"
+#include "components/sync/driver/sync_token_status.h"
+#include "components/sync/driver/sync_user_settings_mock.h"
+#include "components/sync/engine/cycle/sync_cycle_snapshot.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace syncer {
+
+// Mock implementation of SyncService. You probably don't need this; look at
+// TestSyncService instead!
+// As one special case compared to a regular mock, the GetUserSettings() methods
+// are not mocked. Instead, they return a mock version of SyncUserSettings.
+class MockSyncService : public SyncService {
+ public:
+  MockSyncService();
+  ~MockSyncService() override;
+
+  syncer::SyncUserSettingsMock* GetMockUserSettings();
+
+  // SyncService implementation.
+  syncer::SyncUserSettings* GetUserSettings() override;
+  const syncer::SyncUserSettings* GetUserSettings() const override;
+  MOCK_CONST_METHOD0(GetDisableReasons, int());
+  MOCK_CONST_METHOD0(GetTransportState, TransportState());
+  MOCK_CONST_METHOD0(IsLocalSyncEnabled, bool());
+  MOCK_CONST_METHOD0(GetAuthenticatedAccountInfo, CoreAccountInfo());
+  MOCK_CONST_METHOD0(IsAuthenticatedAccountPrimary, bool());
+  MOCK_CONST_METHOD0(GetAuthError, GoogleServiceAuthError());
+
+  MOCK_METHOD0(GetSetupInProgressHandle,
+               std::unique_ptr<SyncSetupInProgressHandle>());
+  MOCK_CONST_METHOD0(IsSetupInProgress, bool());
+
+  MOCK_CONST_METHOD0(GetRegisteredDataTypes, ModelTypeSet());
+  MOCK_CONST_METHOD0(GetForcedDataTypes, ModelTypeSet());
+  MOCK_CONST_METHOD0(GetPreferredDataTypes, ModelTypeSet());
+  MOCK_CONST_METHOD0(GetActiveDataTypes, ModelTypeSet());
+
+  MOCK_METHOD0(StopAndClear, void());
+  MOCK_METHOD1(OnDataTypeRequestsSyncStartup, void(ModelType type));
+  MOCK_METHOD1(TriggerRefresh, void(const ModelTypeSet& types));
+  MOCK_METHOD1(ReenableDatatype, void(ModelType type));
+  MOCK_METHOD1(ReadyForStartChanged, void(syncer::ModelType type));
+  MOCK_METHOD1(SetInvalidationsForSessionsEnabled, void(bool enabled));
+
+  MOCK_METHOD1(AddObserver, void(SyncServiceObserver* observer));
+  MOCK_METHOD1(RemoveObserver, void(SyncServiceObserver* observer));
+  MOCK_CONST_METHOD1(HasObserver, bool(const SyncServiceObserver* observer));
+
+  MOCK_METHOD1(AddPreferenceProvider,
+               void(SyncTypePreferenceProvider* provider));
+  MOCK_METHOD1(RemovePreferenceProvider,
+               void(SyncTypePreferenceProvider* provider));
+  MOCK_CONST_METHOD1(HasPreferenceProvider,
+                     bool(SyncTypePreferenceProvider* provider));
+
+  MOCK_CONST_METHOD0(GetUserShare, UserShare*());
+
+  MOCK_CONST_METHOD0(GetSyncTokenStatus, SyncTokenStatus());
+  MOCK_CONST_METHOD1(QueryDetailedSyncStatus, bool(SyncStatus* result));
+  MOCK_CONST_METHOD0(GetLastSyncedTime, base::Time());
+  MOCK_CONST_METHOD0(GetLastCycleSnapshot, SyncCycleSnapshot());
+  MOCK_METHOD0(GetTypeStatusMap, std::unique_ptr<base::Value>());
+  MOCK_CONST_METHOD0(sync_service_url, const GURL&());
+  MOCK_CONST_METHOD0(unrecoverable_error_message, std::string());
+  MOCK_CONST_METHOD0(unrecoverable_error_location, base::Location());
+  MOCK_METHOD1(AddProtocolEventObserver, void(ProtocolEventObserver* observer));
+  MOCK_METHOD1(RemoveProtocolEventObserver,
+               void(ProtocolEventObserver* observer));
+  MOCK_METHOD1(AddTypeDebugInfoObserver, void(TypeDebugInfoObserver* observer));
+  MOCK_METHOD1(RemoveTypeDebugInfoObserver,
+               void(TypeDebugInfoObserver* observer));
+  MOCK_METHOD0(GetJsController, base::WeakPtr<JsController>());
+  MOCK_METHOD1(GetAllNodes,
+               void(const base::Callback<
+                    void(std::unique_ptr<base::ListValue>)>& callback));
+
+  // KeyedService implementation.
+  MOCK_METHOD0(Shutdown, void());
+
+ private:
+  testing::NiceMock<syncer::SyncUserSettingsMock> user_settings_;
+};
+
+}  // namespace syncer
+
+#endif  // COMPONENTS_SYNC_DRIVER_MOCK_SYNC_SERVICE_H_
diff --git a/components/test/data/password_manager/login_db_v22.sql b/components/test/data/password_manager/login_db_v22.sql
new file mode 100644
index 0000000..749b5bdf
--- /dev/null
+++ b/components/test/data/password_manager/login_db_v22.sql
@@ -0,0 +1,122 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('last_compatible_version','19');
+INSERT INTO "meta" VALUES('version','22');
+CREATE TABLE logins (
+origin_url VARCHAR NOT NULL,
+action_url VARCHAR,
+username_element VARCHAR,
+username_value VARCHAR,
+password_element VARCHAR,
+password_value BLOB,
+submit_element VARCHAR,
+signon_realm VARCHAR NOT NULL,
+preferred INTEGER NOT NULL,
+date_created INTEGER NOT NULL,
+blacklisted_by_user INTEGER NOT NULL,
+scheme INTEGER NOT NULL,
+password_type INTEGER,
+times_used INTEGER,
+form_data BLOB,
+date_synced INTEGER,
+display_name VARCHAR,
+icon_url VARCHAR,
+federation_url VARCHAR,
+skip_zero_click INTEGER,
+generation_upload_status INTEGER,
+possible_username_pairs BLOB,
+id INTEGER,
+UNIQUE (origin_url, username_element, username_value, password_element, signon_realm),
+PRIMARY KEY (id));
+INSERT INTO "logins" (origin_url,action_url,username_element,username_value,password_element,password_value,submit_element,signon_realm,preferred,date_created,blacklisted_by_user,scheme,password_type,times_used,form_data,date_synced,display_name,icon_url,federation_url,skip_zero_click,generation_upload_status,possible_username_pairs) VALUES(
+'https://accounts.google.com/ServiceLogin', /* origin_url */
+'https://accounts.google.com/ServiceLoginAuth', /* action_url */
+'Email', /* username_element */
+'theerikchen', /* username_value */
+'Passwd', /* password_element */
+X'', /* password_value */
+'', /* submit_element */
+'https://accounts.google.com/', /* signon_realm */
+1, /* preferred */
+13047429345000000, /* date_created */
+0, /* blacklisted_by_user */
+0, /* scheme */
+0, /* password_type */
+1, /* times_used */
+X'18000000020000000000000000000000000000000000000000000000', /* form_data */
+0, /* date_synced */
+'', /* display_name */
+'', /* icon_url */
+'', /* federation_url */
+1,  /* skip_zero_click */
+0,  /* generation_upload_status */
+X'00000000' /* possible_username_pairs */
+);
+INSERT INTO "logins" (origin_url,action_url,username_element,username_value,password_element,password_value,submit_element,signon_realm,preferred,date_created,blacklisted_by_user,scheme,password_type,times_used,form_data,date_synced,display_name,icon_url,federation_url,skip_zero_click,generation_upload_status,possible_username_pairs) VALUES(
+'https://accounts.google.com/ServiceLogin', /* origin_url */
+'https://accounts.google.com/ServiceLoginAuth', /* action_url */
+'Email', /* username_element */
+'theerikchen2', /* username_value */
+'Passwd', /* password_element */
+X'', /* password_value */
+'non-empty', /* submit_element */
+'https://accounts.google.com/', /* signon_realm */
+1, /* preferred */
+13047423600000000, /* date_created */
+0, /* blacklisted_by_user */
+0, /* scheme */
+0, /* password_type */
+1, /* times_used */
+X'18000000020000000000000000000000000000000000000000000000', /* form_data */
+0, /* date_synced */
+'', /* display_name */
+'https://www.google.com/icon', /* icon_url */
+'', /* federation_url */
+1,  /* skip_zero_click */
+0,  /* generation_upload_status */
+X'00000000' /* possible_username_pairs */
+);
+INSERT INTO "logins" (origin_url,action_url,username_element,username_value,password_element,password_value,submit_element,signon_realm,preferred,date_created,blacklisted_by_user,scheme,password_type,times_used,form_data,date_synced,display_name,icon_url,federation_url,skip_zero_click,generation_upload_status,possible_username_pairs) VALUES(
+'http://example.com', /* origin_url */
+'http://example.com/landing', /* action_url */
+'', /* username_element */
+'user', /* username_value */
+'', /* password_element */
+X'', /* password_value */
+'non-empty', /* submit_element */
+'http://example.com', /* signon_realm */
+1, /* preferred */
+13047423600000000, /* date_created */
+0, /* blacklisted_by_user */
+1, /* scheme */
+0, /* password_type */
+1, /* times_used */
+X'18000000020000000000000000000000000000000000000000000000', /* form_data */
+0, /* date_synced */
+'', /* display_name */
+'https://www.google.com/icon', /* icon_url */
+'', /* federation_url */
+1,  /* skip_zero_click */
+0,  /* generation_upload_status */
+X'00000000' /* possible_username_pairs */
+);
+CREATE INDEX logins_signon ON logins (signon_realm);
+CREATE TABLE stats (
+origin_domain VARCHAR NOT NULL,
+username_value VARCHAR,
+dismissal_count INTEGER,
+update_time INTEGER NOT NULL,
+UNIQUE(origin_domain, username_value));
+CREATE INDEX stats_origin ON stats(origin_domain);
+CREATE TABLE sync_entities_metadata (
+  storage_key INTEGER,
+  metadata VARCHAR NOT NULL,
+  PRIMARY KEY (storage_key)
+);
+CREATE TABLE sync_model_metadata (
+  id INTEGER,
+  metadata VARCHAR NOT NULL,
+  PRIMARY KEY (id)
+);
+COMMIT;
diff --git a/components/test/data/payments/initiated_test.html b/components/test/data/payments/initiated_test.html
index bc8ab7e..11b6c626 100644
--- a/components/test/data/payments/initiated_test.html
+++ b/components/test/data/payments/initiated_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Initiated Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_abort_test.html b/components/test/data/payments/payment_request_abort_test.html
index e81a8c4..11d08ebc 100644
--- a/components/test/data/payments/payment_request_abort_test.html
+++ b/components/test/data/payments/payment_request_abort_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Abort Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 </head>
 <body>
 <div><button onclick="buy()" id="buy">Buy</button></div>
diff --git a/components/test/data/payments/payment_request_alicepay_bobpay_charliepay_and_cards_test.html b/components/test/data/payments/payment_request_alicepay_bobpay_charliepay_and_cards_test.html
index d5ad667..ffc4815 100644
--- a/components/test/data/payments/payment_request_alicepay_bobpay_charliepay_and_cards_test.html
+++ b/components/test/data/payments/payment_request_alicepay_bobpay_charliepay_and_cards_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Alice Pay, Bob Pay, Charlie Pay and Cards Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_blob_url_test.html b/components/test/data/payments/payment_request_blob_url_test.html
index 58b2768..8e20008 100644
--- a/components/test/data/payments/payment_request_blob_url_test.html
+++ b/components/test/data/payments/payment_request_blob_url_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Blob URL Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 </head>
 <body>
 <button onclick="buy()" id="buy">Blob URL Test</button>
diff --git a/components/test/data/payments/payment_request_bobpay_and_basic_card_with_modifier_optional_data_test.html b/components/test/data/payments/payment_request_bobpay_and_basic_card_with_modifier_optional_data_test.html
index d92f3cb..ff4a60e 100644
--- a/components/test/data/payments/payment_request_bobpay_and_basic_card_with_modifier_optional_data_test.html
+++ b/components/test/data/payments/payment_request_bobpay_and_basic_card_with_modifier_optional_data_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Bob Pay and basic-card with modifier optional data test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
@@ -22,4 +22,4 @@
 <script src="util.js"></script>
 <script src="bobpay_and_basic_card_with_modifier_optional_data.js"></script>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/components/test/data/payments/payment_request_bobpay_and_basic_card_with_modifiers_test.html b/components/test/data/payments/payment_request_bobpay_and_basic_card_with_modifiers_test.html
index 6df3f07e..d1a0b87f 100644
--- a/components/test/data/payments/payment_request_bobpay_and_basic_card_with_modifiers_test.html
+++ b/components/test/data/payments/payment_request_bobpay_and_basic_card_with_modifiers_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Bob Pay and basic-card with Basic-Card modifiers Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_bobpay_and_cards_test.html b/components/test/data/payments/payment_request_bobpay_and_cards_test.html
index 93bde4c2..71a9c95 100644
--- a/components/test/data/payments/payment_request_bobpay_and_cards_test.html
+++ b/components/test/data/payments/payment_request_bobpay_and_cards_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Bob Pay and Cards Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_bobpay_test.html b/components/test/data/payments/payment_request_bobpay_test.html
index cb2d45b..77549db5 100644
--- a/components/test/data/payments/payment_request_bobpay_test.html
+++ b/components/test/data/payments/payment_request_bobpay_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Bob Pay Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_bobpay_ui_skip_preload_test.html b/components/test/data/payments/payment_request_bobpay_ui_skip_preload_test.html
index 2cd1f28b..c675329 100644
--- a/components/test/data/payments/payment_request_bobpay_ui_skip_preload_test.html
+++ b/components/test/data/payments/payment_request_bobpay_ui_skip_preload_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>UI skip, preload test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_bobpay_ui_skip_test.html b/components/test/data/payments/payment_request_bobpay_ui_skip_test.html
index d4bd9d3..d4cfea8b 100644
--- a/components/test/data/payments/payment_request_bobpay_ui_skip_test.html
+++ b/components/test/data/payments/payment_request_bobpay_ui_skip_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Bob Pay UI skip Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_can_make_payment_metrics_test.html b/components/test/data/payments/payment_request_can_make_payment_metrics_test.html
index 481c74f..730d56a9 100644
--- a/components/test/data/payments/payment_request_can_make_payment_metrics_test.html
+++ b/components/test/data/payments/payment_request_can_make_payment_metrics_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Can Make Payment Metrics Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_can_make_payment_query_bobpay_test.html b/components/test/data/payments/payment_request_can_make_payment_query_bobpay_test.html
index 1b25517..252fc736 100644
--- a/components/test/data/payments/payment_request_can_make_payment_query_bobpay_test.html
+++ b/components/test/data/payments/payment_request_can_make_payment_query_bobpay_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Active Payment Query Bob Pay Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 </head>
 <body>
 <button onclick="buy()" id="buy">Check BobPay Twice</button>
diff --git a/components/test/data/payments/payment_request_can_make_payment_query_cc_test.html b/components/test/data/payments/payment_request_can_make_payment_query_cc_test.html
index ebef094..06def99 100644
--- a/components/test/data/payments/payment_request_can_make_payment_query_cc_test.html
+++ b/components/test/data/payments/payment_request_can_make_payment_query_cc_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Active Payment Query Credit Card Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 </head>
 <body>
 <button onclick="buy()" id="buy">VISA Test</button>
diff --git a/components/test/data/payments/payment_request_can_make_payment_query_test.html b/components/test/data/payments/payment_request_can_make_payment_query_test.html
index 9c5ddf6..3ffb277 100644
--- a/components/test/data/payments/payment_request_can_make_payment_query_test.html
+++ b/components/test/data/payments/payment_request_can_make_payment_query_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Active Payment Query Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_contact_details_and_free_shipping_test.html b/components/test/data/payments/payment_request_contact_details_and_free_shipping_test.html
index f6ce82f..770671bd 100644
--- a/components/test/data/payments/payment_request_contact_details_and_free_shipping_test.html
+++ b/components/test/data/payments/payment_request_contact_details_and_free_shipping_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Contact Details and Free Shipping Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_contact_details_test.html b/components/test/data/payments/payment_request_contact_details_test.html
index a1b6812b..2384baf 100644
--- a/components/test/data/payments/payment_request_contact_details_test.html
+++ b/components/test/data/payments/payment_request_contact_details_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Contact Details Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_debit_test.html b/components/test/data/payments/payment_request_debit_test.html
index 33c8ae5c..21df7d61 100644
--- a/components/test/data/payments/payment_request_debit_test.html
+++ b/components/test/data/payments/payment_request_debit_test.html
@@ -9,7 +9,7 @@
 <head>
   <title>Debit Test</title>
   <meta charset="utf-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
   <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 
diff --git a/components/test/data/payments/payment_request_dynamic_shipping_test.html b/components/test/data/payments/payment_request_dynamic_shipping_test.html
index 0cbc2fe..e477c43 100644
--- a/components/test/data/payments/payment_request_dynamic_shipping_test.html
+++ b/components/test/data/payments/payment_request_dynamic_shipping_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Dynamic Shipping Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_email_and_free_shipping_test.html b/components/test/data/payments/payment_request_email_and_free_shipping_test.html
index f3f6b0c..25a25c8 100644
--- a/components/test/data/payments/payment_request_email_and_free_shipping_test.html
+++ b/components/test/data/payments/payment_request_email_and_free_shipping_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Email and Free Shipping Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_email_and_phone_test.html b/components/test/data/payments/payment_request_email_and_phone_test.html
index 2c65337..2067be73 100644
--- a/components/test/data/payments/payment_request_email_and_phone_test.html
+++ b/components/test/data/payments/payment_request_email_and_phone_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Email and Phone Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_email_test.html b/components/test/data/payments/payment_request_email_test.html
index 62458cc..cc16cd1 100644
--- a/components/test/data/payments/payment_request_email_test.html
+++ b/components/test/data/payments/payment_request_email_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Email Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_empty_update_test.html b/components/test/data/payments/payment_request_empty_update_test.html
index e37004ea..96203fd 100644
--- a/components/test/data/payments/payment_request_empty_update_test.html
+++ b/components/test/data/payments/payment_request_empty_update_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Empty Update Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_extra_shipping_options_test.html b/components/test/data/payments/payment_request_extra_shipping_options_test.html
index 78cf3e7..b448657 100644
--- a/components/test/data/payments/payment_request_extra_shipping_options_test.html
+++ b/components/test/data/payments/payment_request_extra_shipping_options_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Extra Shipping Options Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_fail_complete_test.html b/components/test/data/payments/payment_request_fail_complete_test.html
index 9e7dcd9..fd83c25 100644
--- a/components/test/data/payments/payment_request_fail_complete_test.html
+++ b/components/test/data/payments/payment_request_fail_complete_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>No Shipping Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_free_shipping_test.html b/components/test/data/payments/payment_request_free_shipping_test.html
index 5aa5c0f..b92c013e 100644
--- a/components/test/data/payments/payment_request_free_shipping_test.html
+++ b/components/test/data/payments/payment_request_free_shipping_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Free Shipping Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_free_shipping_with_iframe_test.html b/components/test/data/payments/payment_request_free_shipping_with_iframe_test.html
index 77e26fbc..7712c32 100644
--- a/components/test/data/payments/payment_request_free_shipping_with_iframe_test.html
+++ b/components/test/data/payments/payment_request_free_shipping_with_iframe_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Free Shipping With Iframe Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_id_test.html b/components/test/data/payments/payment_request_id_test.html
index 922c9d0..c6e4fe9 100644
--- a/components/test/data/payments/payment_request_id_test.html
+++ b/components/test/data/payments/payment_request_id_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Payment Request Id Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_long_id_test.html b/components/test/data/payments/payment_request_long_id_test.html
index b1e1d028..77c533d0 100644
--- a/components/test/data/payments/payment_request_long_id_test.html
+++ b/components/test/data/payments/payment_request_long_id_test.html
@@ -9,7 +9,7 @@
 <head>
   <meta charset="utf-8">
   <title>Long ID Test</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
   <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 
diff --git a/components/test/data/payments/payment_request_metrics_test.html b/components/test/data/payments/payment_request_metrics_test.html
index 19d8d81..96685df 100644
--- a/components/test/data/payments/payment_request_metrics_test.html
+++ b/components/test/data/payments/payment_request_metrics_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Metrics Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 </head>
 <body>
 <div> <button onclick="ccBuy()" id="ccBuy">CC Buy Test</button> </div>
diff --git a/components/test/data/payments/payment_request_modifier_test.html b/components/test/data/payments/payment_request_modifier_test.html
index 6e515b0..6b503588 100644
--- a/components/test/data/payments/payment_request_modifier_test.html
+++ b/components/test/data/payments/payment_request_modifier_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Modifier Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 </head>
 <body>
 <div><button onclick="buy()" id="buy">Modifier Test</button></div>
diff --git a/components/test/data/payments/payment_request_multiple_show_test.html b/components/test/data/payments/payment_request_multiple_show_test.html
index aee2321..8724d4ed 100644
--- a/components/test/data/payments/payment_request_multiple_show_test.html
+++ b/components/test/data/payments/payment_request_multiple_show_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Multiple Show Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
@@ -19,4 +19,4 @@
 <script src="util.js"></script>
 <script src="multiple_show.js"></script>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/components/test/data/payments/payment_request_name_and_free_shipping_test.html b/components/test/data/payments/payment_request_name_and_free_shipping_test.html
index 72bba4d..8942cf2 100644
--- a/components/test/data/payments/payment_request_name_and_free_shipping_test.html
+++ b/components/test/data/payments/payment_request_name_and_free_shipping_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Name and Free Shipping Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_name_test.html b/components/test/data/payments/payment_request_name_test.html
index 3e47ec1f..0867ca4 100644
--- a/components/test/data/payments/payment_request_name_test.html
+++ b/components/test/data/payments/payment_request_name_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Name Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_no_shipping_test.html b/components/test/data/payments/payment_request_no_shipping_test.html
index 09b9bda23..b0db05b 100644
--- a/components/test/data/payments/payment_request_no_shipping_test.html
+++ b/components/test/data/payments/payment_request_no_shipping_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>No Shipping Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_no_update_with_test.html b/components/test/data/payments/payment_request_no_update_with_test.html
index 54c4edb..5044a0d 100644
--- a/components/test/data/payments/payment_request_no_update_with_test.html
+++ b/components/test/data/payments/payment_request_no_update_with_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>No updateWith() Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
@@ -19,4 +19,4 @@
 <script src="util.js"></script>
 <script src="no_update_with.js"></script>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/components/test/data/payments/payment_request_payment_method_identifier_test.html b/components/test/data/payments/payment_request_payment_method_identifier_test.html
index 98a8725..6868984 100644
--- a/components/test/data/payments/payment_request_payment_method_identifier_test.html
+++ b/components/test/data/payments/payment_request_payment_method_identifier_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>PMI Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 </head>
 <body>
 <button onclick="checkBasicCard()" id="checkBasicCard">Check Basic Card</button>
diff --git a/components/test/data/payments/payment_request_phone_and_free_shipping_test.html b/components/test/data/payments/payment_request_phone_and_free_shipping_test.html
index 6803628..ace4e7b 100644
--- a/components/test/data/payments/payment_request_phone_and_free_shipping_test.html
+++ b/components/test/data/payments/payment_request_phone_and_free_shipping_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Phone and Free Shipping Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_phone_test.html b/components/test/data/payments/payment_request_phone_test.html
index f6566501..f442682 100644
--- a/components/test/data/payments/payment_request_phone_test.html
+++ b/components/test/data/payments/payment_request_phone_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Phone Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_retry.html b/components/test/data/payments/payment_request_retry.html
index 1e81db4..71e2dd11 100644
--- a/components/test/data/payments/payment_request_retry.html
+++ b/components/test/data/payments/payment_request_retry.html
@@ -8,7 +8,7 @@
 <head>
 <title>Retry test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_retry_with_no_payment_options.html b/components/test/data/payments/payment_request_retry_with_no_payment_options.html
index c8b6111..d2464d32 100644
--- a/components/test/data/payments/payment_request_retry_with_no_payment_options.html
+++ b/components/test/data/payments/payment_request_retry_with_no_payment_options.html
@@ -8,7 +8,7 @@
 <head>
 <title>Retry with no payment options test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_retry_with_payer_errors.html b/components/test/data/payments/payment_request_retry_with_payer_errors.html
index 3b6f5d11..1f682d8 100644
--- a/components/test/data/payments/payment_request_retry_with_payer_errors.html
+++ b/components/test/data/payments/payment_request_retry_with_payer_errors.html
@@ -8,7 +8,7 @@
 <head>
 <title>Retry with payer errors test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_retry_with_shipping_address_errors.html b/components/test/data/payments/payment_request_retry_with_shipping_address_errors.html
index 3c832fd..94013bd8 100644
--- a/components/test/data/payments/payment_request_retry_with_shipping_address_errors.html
+++ b/components/test/data/payments/payment_request_retry_with_shipping_address_errors.html
@@ -8,7 +8,7 @@
 <head>
 <title>Retry with shipping address errors test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_shipping_address_change_test.html b/components/test/data/payments/payment_request_shipping_address_change_test.html
index c366e4b..971f98b 100644
--- a/components/test/data/payments/payment_request_shipping_address_change_test.html
+++ b/components/test/data/payments/payment_request_shipping_address_change_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Shipping Address Change Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_shipping_address_instance_test.html b/components/test/data/payments/payment_request_shipping_address_instance_test.html
index 977b742b..427b16d4 100644
--- a/components/test/data/payments/payment_request_shipping_address_instance_test.html
+++ b/components/test/data/payments/payment_request_shipping_address_instance_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Shipping Address Instance Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_show_promise.html b/components/test/data/payments/payment_request_show_promise.html
index 43a3b4f..6d4b4ea2 100644
--- a/components/test/data/payments/payment_request_show_promise.html
+++ b/components/test/data/payments/payment_request_show_promise.html
@@ -8,7 +8,7 @@
 <head>
 <title>Show Promise Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
@@ -19,4 +19,4 @@
 <script src="util.js"></script>
 <script src="show_promise.js"></script>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/components/test/data/payments/payment_request_show_twice_test.html b/components/test/data/payments/payment_request_show_twice_test.html
index 7f50095..9fa8bbd 100644
--- a/components/test/data/payments/payment_request_show_twice_test.html
+++ b/components/test/data/payments/payment_request_show_twice_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>Show Twice Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/test/data/payments/payment_request_update_with_test.html b/components/test/data/payments/payment_request_update_with_test.html
index 7ee44c9..f14725a5 100644
--- a/components/test/data/payments/payment_request_update_with_test.html
+++ b/components/test/data/payments/payment_request_update_with_test.html
@@ -8,7 +8,7 @@
 <head>
 <title>updateWith() Test</title>
 <meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
diff --git a/components/tracing/common/trace_startup_config.cc b/components/tracing/common/trace_startup_config.cc
index 0ccaff2..47b396fd 100644
--- a/components/tracing/common/trace_startup_config.cc
+++ b/components/tracing/common/trace_startup_config.cc
@@ -85,7 +85,8 @@
       is_enabled_from_background_tracing_(false),
       trace_config_(base::trace_event::TraceConfig()),
       startup_duration_(0),
-      should_trace_to_result_file_(false) {
+      should_trace_to_result_file_(false),
+      finished_writing_to_file_(false) {
   if (EnableFromCommandLine()) {
     DCHECK(IsEnabled());
   } else if (EnableFromConfigFile()) {
@@ -137,6 +138,10 @@
   return result_file_;
 }
 
+void TraceStartupConfig::OnTraceToResultFileFinished() {
+  finished_writing_to_file_ = true;
+}
+
 bool TraceStartupConfig::GetBackgroundStartupTracingEnabled() const {
   return is_enabled_from_background_tracing_;
 }
diff --git a/components/tracing/common/trace_startup_config.h b/components/tracing/common/trace_startup_config.h
index 1b0c7da2..675ce3e 100644
--- a/components/tracing/common/trace_startup_config.h
+++ b/components/tracing/common/trace_startup_config.h
@@ -16,6 +16,10 @@
 struct DefaultSingletonTraits;
 }  // namespace base
 
+namespace content {
+class StartupTracingControllerTest;
+}
+
 namespace tracing {
 
 // TraceStartupConfig is a singleton that contains the configurations of startup
@@ -100,6 +104,7 @@
   // saved to result file.
   bool ShouldTraceToResultFile() const;
   base::FilePath GetResultFile() const;
+  void OnTraceToResultFileFinished();
 
   // Get the background tracing config set in application preferences on the
   // previous session, for current session.
@@ -108,15 +113,23 @@
   // Set the background tracing config in preferences for the next session.
   void SetBackgroundStartupTracingEnabled(bool enabled);
 
- private:
-  bool IsUsingPerfettoOutput() const;
+  // Returns when the startup tracing is finished and written to file, false on
+  // all other cases.
+  bool finished_writing_to_file_for_testing() const {
+    return finished_writing_to_file_;
+  }
 
+ private:
   // This allows constructor and destructor to be private and usable only
   // by the Singleton class.
   friend struct base::DefaultSingletonTraits<TraceStartupConfig>;
+  friend class content::StartupTracingControllerTest;
+
   TraceStartupConfig();
   ~TraceStartupConfig();
 
+  bool IsUsingPerfettoOutput() const;
+
   bool EnableFromCommandLine();
   bool EnableFromConfigFile();
   bool EnableFromBackgroundTracing();
@@ -129,6 +142,7 @@
   int startup_duration_;
   bool should_trace_to_result_file_;
   base::FilePath result_file_;
+  bool finished_writing_to_file_;
 
   DISALLOW_COPY_AND_ASSIGN(TraceStartupConfig);
 };
diff --git a/components/ui_devtools/views/view_element.cc b/components/ui_devtools/views/view_element.cc
index 2872741c8..0595923 100644
--- a/components/ui_devtools/views/view_element.cc
+++ b/components/ui_devtools/views/view_element.cc
@@ -59,12 +59,10 @@
 
 std::vector<std::pair<std::string, std::string>>
 ViewElement::GetCustomProperties() const {
-  base::string16 description;
-  if (view_->GetTooltipText(gfx::Point(), &description)) {
-    return {std::make_pair<std::string, std::string>(
-        "tooltip", base::UTF16ToUTF8(description))};
-  }
-  return {};
+  base::string16 description = view_->GetTooltipText(gfx::Point());
+  if (description.empty())
+    return {};
+  return {{"tooltip", base::UTF16ToUTF8(description)}};
 }
 
 void ViewElement::GetBounds(gfx::Rect* bounds) const {
diff --git a/components/ui_devtools/views/view_element_unittest.cc b/components/ui_devtools/views/view_element_unittest.cc
index ab63de0a..5b97459 100644
--- a/components/ui_devtools/views/view_element_unittest.cc
+++ b/components/ui_devtools/views/view_element_unittest.cc
@@ -19,10 +19,8 @@
   const char* GetClassName() const override { return kViewClassName; }
 
   // For custom properties test.
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override {
-    *tooltip = base::ASCIIToUTF16("This is the tooltip");
-    return true;
+  base::string16 GetTooltipText(const gfx::Point& p) const override {
+    return base::ASCIIToUTF16("This is the tooltip");
   }
 };
 const char NamedTestView::kViewClassName[] = "NamedTestView";
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 0fb8ca1c..c105b90 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -1009,10 +1009,18 @@
 void SkiaOutputSurfaceImplOnGpu::DestroySkImages(
     std::vector<sk_sp<SkImage>>&& images,
     uint64_t sync_fence_release) {
+  DCHECK(!images.empty());
   // The window could be destroyed already, and the MakeCurrent will fail with
   // an destroyed window, so MakeCurrent without requiring the fbo0.
   MakeCurrent(false /* need_fbo0 */);
+#if DCHECK_IS_ON()
+  for (const auto& image : images)
+    DCHECK(image->unique());
+#endif
   images.clear();
+  // Flush the gr_context() to make sure images are released, and the release
+  // and done callbacks are called.
+  gr_context()->flush();
   ReleaseFenceSyncAndPushTextureUpdates(sync_fence_release);
 }
 
diff --git a/components/zucchini/algorithm.h b/components/zucchini/algorithm.h
index 463aca38..898859f3 100644
--- a/components/zucchini/algorithm.h
+++ b/components/zucchini/algorithm.h
@@ -53,6 +53,20 @@
   return T((x + m - 1) / m) * m;
 }
 
+// Specialized alignment helpers that returns the increment to |pos| to get the
+// next n-aligned value, where n is in {2, 4}. This is useful for aligning
+// iterators relative to a base iterator using:
+//   it += IncrementForAlignCeil2(it - base);
+template <class T>
+inline int IncrementForAlignCeil2(T pos) {
+  return static_cast<int>(pos & 1);  // Optimized from (-pos) & 1.
+}
+
+template <class T>
+inline int IncrementForAlignCeil4(T pos) {
+  return static_cast<int>((-pos) & 3);
+}
+
 // Sorts values in |container| and removes duplicates.
 template <class T>
 void SortAndUniquify(std::vector<T>* container) {
diff --git a/components/zucchini/algorithm_unittest.cc b/components/zucchini/algorithm_unittest.cc
index a395b1e..ad5b9b8 100644
--- a/components/zucchini/algorithm_unittest.cc
+++ b/components/zucchini/algorithm_unittest.cc
@@ -145,6 +145,33 @@
   EXPECT_EQ(33U, AlignCeil<uint32_t>(23U, 11U));
 }
 
+TEST(AlgorithmTest, IncrementForAlignCeil) {
+  struct TestCase {
+    int exp;  // Increment to |pos| to get the next nearest aligned value.
+    int pos;
+  };
+  TestCase kTestCases2[] = {
+      {0, 0},    {1, 1},    {0, 2},   {1, 3},   {0, 4},   {1, 5},
+      {1, 97},   {0, 98},   {1, 99},  {0, 100}, {1, -1},  {0, -2},
+      {1, -101}, {0, -100}, {1, -99}, {0, -98}, {1, -97}, {0, -96},
+  };
+  for (const auto& test_case : kTestCases2) {
+    EXPECT_EQ(test_case.exp, IncrementForAlignCeil2<int32_t>(test_case.pos));
+    if (test_case.pos >= 0)
+      EXPECT_EQ(test_case.exp, IncrementForAlignCeil2<uint32_t>(test_case.pos));
+  }
+  TestCase kTestCases4[] = {
+      {0, 0},    {3, 1},    {2, 2},   {1, 3},   {0, 4},   {3, 5},
+      {3, 97},   {2, 98},   {1, 99},  {0, 100}, {1, -1},  {2, -2},
+      {1, -101}, {0, -100}, {3, -99}, {2, -98}, {1, -97}, {0, -96},
+  };
+  for (const auto& test_case : kTestCases4) {
+    EXPECT_EQ(test_case.exp, IncrementForAlignCeil4<int32_t>(test_case.pos));
+    if (test_case.pos >= 0)
+      EXPECT_EQ(test_case.exp, IncrementForAlignCeil4<uint32_t>(test_case.pos));
+  }
+}
+
 TEST(AlgorithmTest, GetBit) {
   // 0xC5 = 0b1100'0101.
   constexpr uint8_t v = 0xC5;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index b6852b7..cbf1b1d 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -200,6 +200,7 @@
     "//ui/base",
     "//ui/base:buildflags",
     "//ui/base/clipboard",
+    "//ui/base/idle",
     "//ui/base/ime",
     "//ui/base/mpris/buildflags",
     "//ui/display",
@@ -1182,6 +1183,7 @@
     "media/desktop_media_window_registry.cc",
     "media/desktop_media_window_registry.h",
     "media/desktop_media_window_registry_aura.cc",
+    "media/desktop_media_window_registry_mac.mm",
     "media/flinging_renderer.cc",
     "media/flinging_renderer.h",
     "media/forwarding_audio_stream_factory.cc",
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index c964fa6..f79b1a6 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -305,6 +305,7 @@
 
 void OnStoppedStartupTracing(const base::FilePath& trace_file) {
   VLOG(0) << "Completed startup tracing to " << trace_file.value();
+  tracing::TraceStartupConfig::GetInstance()->OnTraceToResultFileFinished();
 }
 
 // Tell compiler not to inline this function so it's possible to tell what
diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc
index c715a86d0..1a404400 100644
--- a/content/browser/child_process_launcher_helper_linux.cc
+++ b/content/browser/child_process_launcher_helper_linux.cc
@@ -56,7 +56,7 @@
         std::make_pair(sandbox_fd, service_manager::GetSandboxFD()));
   }
 
-  options->environ = delegate_->GetEnvironment();
+  options->environment = delegate_->GetEnvironment();
 
   return true;
 }
diff --git a/content/browser/child_process_launcher_helper_mac.cc b/content/browser/child_process_launcher_helper_mac.cc
index c69c3d3..2262c88 100644
--- a/content/browser/child_process_launcher_helper_mac.cc
+++ b/content/browser/child_process_launcher_helper_mac.cc
@@ -69,7 +69,7 @@
   base::FieldTrialList::InsertFieldTrialHandleIfNeeded(
       &options->mach_ports_for_rendezvous);
 
-  options->environ = delegate_->GetEnvironment();
+  options->environment = delegate_->GetEnvironment();
 
   auto sandbox_type =
       service_manager::SandboxTypeFromCommandLine(*command_line_);
@@ -124,7 +124,7 @@
 
     // Disable os logging to com.apple.diagnosticd which is a performance
     // problem.
-    options->environ.insert(std::make_pair("OS_ACTIVITY_MODE", "disable"));
+    options->environment.insert(std::make_pair("OS_ACTIVITY_MODE", "disable"));
 
     seatbelt_exec_client_ = std::make_unique<sandbox::SeatbeltExecClient>();
     seatbelt_exec_client_->SetProfile(profile);
diff --git a/content/browser/media/desktop_media_window_registry_mac.mm b/content/browser/media/desktop_media_window_registry_mac.mm
new file mode 100644
index 0000000..1f11643
--- /dev/null
+++ b/content/browser/media/desktop_media_window_registry_mac.mm
@@ -0,0 +1,43 @@
+// Copyright 2019 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 <Cocoa/Cocoa.h>
+
+#include "base/no_destructor.h"
+#include "content/browser/media/desktop_media_window_registry.h"
+
+namespace content {
+
+class DesktopMediaWindowRegistryMac : public DesktopMediaWindowRegistry {
+ public:
+  static DesktopMediaWindowRegistryMac* GetInstance() {
+    static base::NoDestructor<DesktopMediaWindowRegistryMac> instance;
+    return instance.get();
+  }
+
+  DesktopMediaWindowRegistryMac() = default;
+
+  Id RegisterWindow(gfx::NativeWindow window) final {
+    // Note that DesktopMediaPickerViews in //chrome depends on the fact that
+    // the Id returned from this function is the NSWindow's windowNumber, but
+    // that invariant is *not* part of the general contract for DesktopMediaID.
+    return window.GetNativeNSWindow().windowNumber;
+  }
+
+  gfx::NativeWindow GetWindowById(Id id) final {
+    return gfx::NativeWindow([NSApp windowWithWindowNumber:id]);
+  }
+
+ private:
+  ~DesktopMediaWindowRegistryMac() final = default;
+
+  DISALLOW_COPY_AND_ASSIGN(DesktopMediaWindowRegistryMac);
+};
+
+// static
+DesktopMediaWindowRegistry* DesktopMediaWindowRegistry::GetInstance() {
+  return DesktopMediaWindowRegistryMac::GetInstance();
+}
+
+}  // namespace content
diff --git a/content/browser/media/hardware_key_media_controller.h b/content/browser/media/hardware_key_media_controller.h
index 94dbb0fe..873f146 100644
--- a/content/browser/media/hardware_key_media_controller.h
+++ b/content/browser/media/hardware_key_media_controller.h
@@ -38,6 +38,8 @@
   void MediaSessionActionsChanged(
       const std::vector<media_session::mojom::MediaSessionAction>& actions)
       override;
+  void MediaSessionChanged(
+      const base::Optional<base::UnguessableToken>& request_id) override {}
 
   // ui::MediaKeysListener::Delegate:
   void OnMediaKeysAccelerator(const ui::Accelerator& accelerator) override;
diff --git a/content/browser/media/media_internals_audio_focus_helper.h b/content/browser/media/media_internals_audio_focus_helper.h
index 272ea209..ad77879 100644
--- a/content/browser/media/media_internals_audio_focus_helper.h
+++ b/content/browser/media/media_internals_audio_focus_helper.h
@@ -29,8 +29,6 @@
       media_session::mojom::AudioFocusRequestStatePtr session) override;
   void OnFocusLost(
       media_session::mojom::AudioFocusRequestStatePtr session) override;
-  void OnActiveSessionChanged(
-      media_session::mojom::AudioFocusRequestStatePtr session) override {}
 
   // Sets whether we should listen to audio focus events.
   void SetEnabled(bool enabled);
diff --git a/content/browser/renderer_host/media/ref_counted_video_source_provider.cc b/content/browser/renderer_host/media/ref_counted_video_source_provider.cc
index 4414c7c..d2782c2b 100644
--- a/content/browser/renderer_host/media/ref_counted_video_source_provider.cc
+++ b/content/browser/renderer_host/media/ref_counted_video_source_provider.cc
@@ -28,6 +28,10 @@
   device_factory_provider_->ShutdownServiceAsap();
 }
 
+void RefCountedVideoSourceProvider::SetRetryCount(int32_t count) {
+  device_factory_provider_->SetRetryCount(count);
+}
+
 void RefCountedVideoSourceProvider::ReleaseProviderForTesting() {
   source_provider_.reset();
 }
diff --git a/content/browser/renderer_host/media/ref_counted_video_source_provider.h b/content/browser/renderer_host/media/ref_counted_video_source_provider.h
index cb6320c..5b8bfae 100644
--- a/content/browser/renderer_host/media/ref_counted_video_source_provider.h
+++ b/content/browser/renderer_host/media/ref_counted_video_source_provider.h
@@ -32,6 +32,7 @@
   }
 
   void ShutdownServiceAsap();
+  void SetRetryCount(int32_t count);
   void ReleaseProviderForTesting();
 
  private:
diff --git a/content/browser/renderer_host/media/service_video_capture_provider.cc b/content/browser/renderer_host/media/service_video_capture_provider.cc
index 55c56ec..39483fd 100644
--- a/content/browser/renderer_host/media/service_video_capture_provider.cc
+++ b/content/browser/renderer_host/media/service_video_capture_provider.cc
@@ -123,6 +123,8 @@
         TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
         "Video capture service has shut down. Retrying GetDeviceInfos.",
         TRACE_EVENT_SCOPE_PROCESS);
+    video_capture::uma::LogMacbookRetryGetDeviceInfosEvent(
+        video_capture::uma::PROVIDER_SERVICE_STOPPED_ISSUING_RETRY);
     GetDeviceInfosAsyncForRetry(std::move(stashed_result_callback_for_retry_),
                                 stashed_retry_count_ + 1);
   }
@@ -209,6 +211,7 @@
     int retry_count) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   auto service_connection = LazyConnectToService();
+  service_connection->SetRetryCount(retry_count);
   // Use a ScopedCallbackRunner to make sure that |result_callback| gets
   // invoked with an empty result in case that the service drops the request.
   service_connection->source_provider()->GetSourceInfos(
@@ -226,29 +229,37 @@
     const std::vector<media::VideoCaptureDeviceInfo>& infos) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 #if defined(OS_MACOSX)
-  if (retry_count > 0) {
-    UMA_HISTOGRAM_COUNTS_1M(
-        "Media.VideoCapture.MacBook.NumberOfDevicesAfterServiceRestart",
-        infos.size());
-  }
-
   std::string model = base::mac::GetModelIdentifier();
   if (base::FeatureList::IsEnabled(
           features::kRetryGetVideoCaptureDeviceInfos) &&
-      infos.empty() &&
       base::StartsWith(model, "MacBook",
-                       base::CompareCase::INSENSITIVE_ASCII) &&
-      retry_count < kMaxRetriesForGetDeviceInfos &&
-      !stashed_result_callback_for_retry_) {
-    TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
-                         "Asking video capture service to shut down.",
-                         TRACE_EVENT_SCOPE_PROCESS);
-    service_connection->ShutdownServiceAsap();
-    stashed_result_callback_for_retry_ = std::move(result_callback);
-    stashed_retry_count_ = retry_count;
-    // Continue when service manager reports that service has shut down via
-    // OnServiceStopped().
-    return;
+                       base::CompareCase::INSENSITIVE_ASCII)) {
+    if (retry_count > 0) {
+      video_capture::uma::LogMacbookRetryGetDeviceInfosEvent(
+          infos.empty()
+              ? video_capture::uma::
+                    PROVIDER_RECEIVED_ZERO_INFOS_FROM_RETRY_GIVING_UP
+              : video_capture::uma::PROVIDER_RECEIVED_NONZERO_INFOS_FROM_RETRY);
+    }
+    if (infos.empty() && stashed_result_callback_for_retry_) {
+      video_capture::uma::LogMacbookRetryGetDeviceInfosEvent(
+          video_capture::uma::
+              PROVIDER_NOT_ATTEMPTING_RETRY_BECAUSE_ALREADY_PENDING);
+    }
+    if (infos.empty() && retry_count < kMaxRetriesForGetDeviceInfos &&
+        !stashed_result_callback_for_retry_) {
+      video_capture::uma::LogMacbookRetryGetDeviceInfosEvent(
+          video_capture::uma::PROVIDER_RECEIVED_ZERO_INFOS_STOPPING_SERVICE);
+      TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
+                           "Asking video capture service to shut down.",
+                           TRACE_EVENT_SCOPE_PROCESS);
+      service_connection->ShutdownServiceAsap();
+      stashed_result_callback_for_retry_ = std::move(result_callback);
+      stashed_retry_count_ = retry_count;
+      // Continue when service manager reports that service has shut down via
+      // OnServiceStopped().
+      return;
+    }
   }
 #endif
   base::ResetAndReturn(&result_callback).Run(infos);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 798c104..2f18a9e9 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2948,7 +2948,6 @@
     switches::kDisableBackgroundTimerThrottling,
     switches::kDisableBestEffortTasks,
     switches::kDisableBreakpad,
-    switches::kDisableCompositorUkmForTests,
     switches::kDisablePreferCompositingToLCDText,
     switches::kDisableDatabases,
     switches::kDisableFileSystem,
diff --git a/content/browser/renderer_host/render_widget_host_browsertest.cc b/content/browser/renderer_host/render_widget_host_browsertest.cc
index d88f2fb..4d86c87 100644
--- a/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -150,10 +150,10 @@
 
 // Synthetic mouse events not allowed on Android.
 #if !defined(OS_ANDROID)
-// This test makes sure that TouchEmulator doesn't emit a GestureScrollEnd without a valid
-// unique_touch_event_id when it sees a GestureFlingStart terminating the underlying mouse
-// scroll sequence. If the GestureScrollEnd is given a unique_touch_event_id of 0, then a
-// crash will occur.
+// This test makes sure that TouchEmulator doesn't emit a GestureScrollEnd
+// without a valid unique_touch_event_id when it sees a GestureFlingStart
+// terminating the underlying mouse scroll sequence. If the GestureScrollEnd is
+// given a unique_touch_event_id of 0, then a crash will occur.
 IN_PROC_BROWSER_TEST_F(RenderWidgetHostTouchEmulatorBrowserTest,
                        TouchEmulatorPinchWithGestureFling) {
   auto* touch_emulator = host()->GetTouchEmulator();
@@ -173,30 +173,39 @@
   params.distances.push_back(gfx::Vector2d(0, -10));
   params.speed_in_pixels_s = 1200;
 
-  std::unique_ptr<SyntheticSmoothDragGesture> gesture(
-      new SyntheticSmoothDragGesture(params));
+  // On slow bots (e.g. ChromeOS DBG) the synthetic gesture sequence events may
+  // be delivered slowly/erratically-timed so that the velocity_tracker in the
+  // TouchEmulator's GestureDetector may either (i) drop some scroll updates
+  // from the velocity estimate, or (ii) create an unexpectedly low velocity
+  // estimate. In either case, the minimum fling start velocity may not be
+  // achieved, meaning the condition we're trying to test never occurs. To
+  // avoid that, we'll keep trying until it happens. The failure mode for the
+  // test is that it times out.
+  do {
+    std::unique_ptr<SyntheticSmoothDragGesture> gesture(
+        new SyntheticSmoothDragGesture(params));
 
-  InputEventAckWaiter scroll_end_ack_waiter(
-      host(), blink::WebInputEvent::kGestureScrollEnd);
-  base::RunLoop run_loop;
-  host()->QueueSyntheticGesture(
-      std::move(gesture),
-      base::BindOnce(
-          base::BindLambdaForTesting([&](SyntheticGesture::Result result) {
-            EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
-            run_loop.Quit();
-          })));
-  run_loop.Run();
-  scroll_end_ack_waiter.Wait();
+    InputEventAckWaiter scroll_end_ack_waiter(
+        host(), blink::WebInputEvent::kGestureScrollEnd);
+    base::RunLoop run_loop;
+    host()->QueueSyntheticGesture(
+        std::move(gesture),
+        base::BindOnce(
+            base::BindLambdaForTesting([&](SyntheticGesture::Result result) {
+              EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+              run_loop.Quit();
+            })));
+    run_loop.Run();
+    scroll_end_ack_waiter.Wait();
 
-  // Verify that a GestureFlingStart was suppressed by the TouchEmulator, and
-  // that we generated a GestureScrollEnd and routed it without crashing.
-  TestInputEventObserver::EventTypeVector dispatched_events =
-      observer.GetAndResetDispatchedEventTypes();
-  auto it_gse = std::find(dispatched_events.begin(), dispatched_events.end(),
-                          blink::WebInputEvent::kGestureScrollEnd);
-  EXPECT_NE(dispatched_events.end(), it_gse);
-  EXPECT_TRUE(touch_emulator->suppress_next_fling_cancel_for_testing());
+    // Verify that a GestureFlingStart was suppressed by the TouchEmulator, and
+    // that we generated a GestureScrollEnd and routed it without crashing.
+    TestInputEventObserver::EventTypeVector dispatched_events =
+        observer.GetAndResetDispatchedEventTypes();
+    auto it_gse = std::find(dispatched_events.begin(), dispatched_events.end(),
+                            blink::WebInputEvent::kGestureScrollEnd);
+    EXPECT_NE(dispatched_events.end(), it_gse);
+  } while (!touch_emulator->suppress_next_fling_cancel_for_testing());
 }
 #endif  // !defined(OS_ANDROID)
 
diff --git a/content/browser/scheduler/browser_ui_thread_scheduler.cc b/content/browser/scheduler/browser_ui_thread_scheduler.cc
index 1eb51fb3..67cac4c 100644
--- a/content/browser/scheduler/browser_ui_thread_scheduler.cc
+++ b/content/browser/scheduler/browser_ui_thread_scheduler.cc
@@ -62,6 +62,9 @@
 
 void BrowserUIThreadScheduler::InitialiseTaskQueues() {
   DCHECK(sequence_manager_);
+  sequence_manager_->EnableCrashKeys("ui_scheduler_task_file_name",
+                                     "ui_scheduler_task_function_name",
+                                     "ui_scheduler_async_stack");
 
   // To avoid locks in BrowserUIThreadScheduler::GetTaskRunner, eagerly
   // create all the well known task queues.
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 70b1ec6..c03b3bf 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -125,6 +125,7 @@
 #include "ui/display/display_switches.h"
 #include "ui/display/screen.h"
 #include "ui/events/base_event_utils.h"
+#include "ui/events/blink/blink_features.h"
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
@@ -12452,7 +12453,9 @@
 
 class SitePerProcessBrowserTouchActionTest : public SitePerProcessBrowserTest {
  public:
-  SitePerProcessBrowserTouchActionTest() = default;
+  SitePerProcessBrowserTouchActionTest()
+      : compositor_touch_action_enabled_(
+            base::FeatureList::IsEnabled(features::kCompositorTouchAction)) {}
 
   // Computes the effective and white-listed touch action for |rwhv_child| by
   // dispatching a touch to it through |rwhv_root|. |rwhv_root| is the root
@@ -12489,6 +12492,9 @@
     router->RouteTouchEvent(rwhv_root, &touch_event,
                             ui::LatencyInfo(ui::SourceEventType::TOUCH));
     ack_observer.Wait();
+    // Reset them to get the new value.
+    effective_touch_action.reset();
+    whitelisted_touch_action.reset();
     effective_touch_action =
         input_router->touch_action_filter_.allowed_touch_action_;
     // Effective touch action are sent from a separate IPC
@@ -12496,10 +12502,14 @@
     // touch start arrived because the ACK is from the main thread.
     whitelisted_touch_action =
         input_router->touch_action_filter_.white_listed_touch_action_;
-    while (!effective_touch_action.has_value()) {
-      GiveItSomeTime(TestTimeouts::tiny_timeout());
-      effective_touch_action =
-          input_router->touch_action_filter_.allowed_touch_action_;
+    // When flag is enabled, we may not have the value for the effective touch
+    // action when ack is received.
+    if (!compositor_touch_action_enabled_) {
+      while (!effective_touch_action.has_value()) {
+        GiveItSomeTime(TestTimeouts::tiny_timeout());
+        effective_touch_action =
+            input_router->touch_action_filter_.allowed_touch_action_;
+      }
     }
 
     // Send a touch move and touch end to complete the sequence, this also
@@ -12543,6 +12553,9 @@
     // thread, upon return it should have handled any touch action update.
     root_thread_observer->Wait();
   }
+
+ protected:
+  const bool compositor_touch_action_enabled_;
 };
 
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
@@ -12594,9 +12607,11 @@
   // kTouchActionAuto in iframe's child.
   GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
                           effective_touch_action, whitelisted_touch_action);
-  EXPECT_EQ(expected_touch_action, effective_touch_action.has_value()
-                                       ? effective_touch_action.value()
-                                       : cc::kTouchActionAuto);
+  if (!compositor_touch_action_enabled_) {
+    EXPECT_EQ(expected_touch_action, effective_touch_action.has_value()
+                                         ? effective_touch_action.value()
+                                         : cc::kTouchActionAuto);
+  }
   if (whitelisted_touch_action.has_value())
     EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
 
@@ -12607,9 +12622,11 @@
   expected_touch_action = cc::kTouchActionAuto;
   GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
                           effective_touch_action, whitelisted_touch_action);
-  EXPECT_EQ(expected_touch_action, effective_touch_action.has_value()
-                                       ? effective_touch_action.value()
-                                       : cc::kTouchActionAuto);
+  if (compositor_touch_action_enabled_) {
+    EXPECT_EQ(expected_touch_action, effective_touch_action.has_value()
+                                         ? effective_touch_action.value()
+                                         : cc::kTouchActionAuto);
+  }
   if (whitelisted_touch_action.has_value())
     EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
 }
@@ -12676,12 +12693,14 @@
                                          : cc::kTouchActionAuto;
   // TouchAction might have not been propagated to child frames yet, loop until
   // we get the expected touch action value.
-  while (expected_touch_action != effective_touch_action_result) {
-    GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
-                            effective_touch_action, whitelisted_touch_action);
-    effective_touch_action_result = effective_touch_action.has_value()
-                                        ? effective_touch_action.value()
-                                        : cc::kTouchActionAuto;
+  if (!compositor_touch_action_enabled_) {
+    while (expected_touch_action != effective_touch_action_result) {
+      GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
+                              effective_touch_action, whitelisted_touch_action);
+      effective_touch_action_result = effective_touch_action.has_value()
+                                          ? effective_touch_action.value()
+                                          : cc::kTouchActionAuto;
+    }
   }
   if (whitelisted_touch_action.has_value())
     EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
@@ -12699,12 +12718,14 @@
   effective_touch_action_result = effective_touch_action.has_value()
                                       ? effective_touch_action.value()
                                       : cc::kTouchActionAuto;
-  while (expected_touch_action != effective_touch_action_result) {
-    GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
-                            effective_touch_action, whitelisted_touch_action);
-    effective_touch_action_result = effective_touch_action.has_value()
-                                        ? effective_touch_action.value()
-                                        : cc::kTouchActionAuto;
+  if (!compositor_touch_action_enabled_) {
+    while (expected_touch_action != effective_touch_action_result) {
+      GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
+                              effective_touch_action, whitelisted_touch_action);
+      effective_touch_action_result = effective_touch_action.has_value()
+                                          ? effective_touch_action.value()
+                                          : cc::kTouchActionAuto;
+    }
   }
   if (whitelisted_touch_action.has_value())
     EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
@@ -12721,12 +12742,14 @@
   effective_touch_action_result = effective_touch_action.has_value()
                                       ? effective_touch_action.value()
                                       : cc::kTouchActionAuto;
-  while (expected_touch_action != effective_touch_action_result) {
-    GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
-                            effective_touch_action, whitelisted_touch_action);
-    effective_touch_action_result = effective_touch_action.has_value()
-                                        ? effective_touch_action.value()
-                                        : cc::kTouchActionAuto;
+  if (!compositor_touch_action_enabled_) {
+    while (expected_touch_action != effective_touch_action_result) {
+      GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
+                              effective_touch_action, whitelisted_touch_action);
+      effective_touch_action_result = effective_touch_action.has_value()
+                                          ? effective_touch_action.value()
+                                          : cc::kTouchActionAuto;
+    }
   }
   if (whitelisted_touch_action.has_value())
     EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
@@ -12783,9 +12806,11 @@
   cc::TouchAction expected_touch_action = cc::kTouchActionPan;
   GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
                           effective_touch_action, whitelisted_touch_action);
-  EXPECT_EQ(expected_touch_action, effective_touch_action.has_value()
-                                       ? effective_touch_action.value()
-                                       : cc::kTouchActionAuto);
+  if (!compositor_touch_action_enabled_) {
+    EXPECT_EQ(expected_touch_action, effective_touch_action.has_value()
+                                         ? effective_touch_action.value()
+                                         : cc::kTouchActionAuto);
+  }
   if (whitelisted_touch_action.has_value())
     EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
 
@@ -12809,9 +12834,11 @@
                             child_thread_observer.get());
   GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child,
                           effective_touch_action, whitelisted_touch_action);
-  EXPECT_EQ(expected_touch_action, effective_touch_action.has_value()
-                                       ? effective_touch_action.value()
-                                       : cc::kTouchActionAuto);
+  if (!compositor_touch_action_enabled_) {
+    EXPECT_EQ(expected_touch_action, effective_touch_action.has_value()
+                                         ? effective_touch_action.value()
+                                         : cc::kTouchActionAuto);
+  }
   if (whitelisted_touch_action.has_value())
     EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
 }
diff --git a/content/browser/tracing/startup_tracing_browsertest.cc b/content/browser/tracing/startup_tracing_browsertest.cc
new file mode 100644
index 0000000..cba2622
--- /dev/null
+++ b/content/browser/tracing/startup_tracing_browsertest.cc
@@ -0,0 +1,81 @@
+// Copyright 2019 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 "base/files/file_util.h"
+#include "base/run_loop.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "components/tracing/common/trace_startup_config.h"
+#include "components/tracing/common/tracing_switches.h"
+#include "content/public/browser/tracing_controller.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "services/tracing/public/cpp/trace_startup.h"
+
+namespace content {
+
+namespace {
+
+// Wait until |condition| returns true.
+void WaitForCondition(base::RepeatingCallback<bool()> condition,
+                      const std::string& description) {
+  const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(30);
+  const base::TimeTicks start_time = base::TimeTicks::Now();
+  while (!condition.Run() && (base::TimeTicks::Now() - start_time < kTimeout)) {
+    base::RunLoop run_loop;
+    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
+    run_loop.Run();
+  }
+  ASSERT_TRUE(condition.Run())
+      << "Timeout waiting for condition: " << description;
+}
+
+}  // namespace
+
+class StartupTracingControllerTest : public ContentBrowserTest {
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    base::CreateTemporaryFile(&temp_file_path_);
+    command_line->AppendSwitch(switches::kTraceStartup);
+    command_line->AppendSwitchASCII(switches::kTraceStartupDuration, "3");
+    command_line->AppendSwitchASCII(switches::kTraceStartupFile,
+                                    temp_file_path_.AsUTF8Unsafe());
+
+#if defined(OS_ANDROID)
+    // On Android the startup tracing is initialized as soon as library load
+    // time, earlier than this point. So, reset the config and enable startup
+    // tracing here.
+    tracing::TraceStartupConfig::GetInstance()->EnableFromCommandLine();
+    tracing::EnableStartupTracingIfNeeded();
+#endif
+  }
+
+ protected:
+  base::FilePath temp_file_path_;
+};
+
+IN_PROC_BROWSER_TEST_F(StartupTracingControllerTest, TestStartupTracing) {
+  NavigateToURL(shell(), GetTestUrl("", "title.html"));
+  WaitForCondition(base::BindRepeating([]() {
+                     return !TracingController::GetInstance()->IsTracing();
+                   }),
+                   "trace end");
+  EXPECT_FALSE(tracing::TraceStartupConfig::GetInstance()->IsEnabled());
+  EXPECT_FALSE(TracingController::GetInstance()->IsTracing());
+  WaitForCondition(base::BindRepeating([]() {
+                     return tracing::TraceStartupConfig::GetInstance()
+                         ->finished_writing_to_file_for_testing();
+                   }),
+                   "finish file write");
+
+  std::string trace;
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  ASSERT_TRUE(base::ReadFileToString(temp_file_path_, &trace));
+  EXPECT_TRUE(trace.find("BrowserMainLoop::InitStartupTracingForDuration") !=
+              std::string::npos);
+}
+
+}  // namespace content
diff --git a/content/public/browser/desktop_media_id.cc b/content/public/browser/desktop_media_id.cc
index b2d53c94..9330ec6 100644
--- a/content/public/browser/desktop_media_id.cc
+++ b/content/public/browser/desktop_media_id.cc
@@ -14,6 +14,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "build/build_config.h"
 #include "content/browser/media/desktop_media_window_registry.h"
 
 namespace content {
@@ -26,7 +27,7 @@
 // static
 const DesktopMediaID::Id DesktopMediaID::kFakeId = -3;
 
-#if defined(USE_AURA)
+#if defined(USE_AURA) || defined(OS_MACOSX)
 // static
 DesktopMediaID DesktopMediaID::RegisterNativeWindow(DesktopMediaID::Type type,
                                                     gfx::NativeWindow window) {
diff --git a/content/public/browser/desktop_media_id.h b/content/public/browser/desktop_media_id.h
index fc84715..c9791b4 100644
--- a/content/public/browser/desktop_media_id.h
+++ b/content/public/browser/desktop_media_id.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <tuple>
 
+#include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/web_contents_media_capture_id.h"
 #include "ui/gfx/native_widget_types.h"
@@ -27,7 +28,7 @@
   // Represents a fake id to create a dummy capturer for autotests.
   static const Id kFakeId;
 
-#if defined(USE_AURA)
+#if defined(USE_AURA) || defined(OS_MACOSX)
   // Assigns integer identifier to the |window| and returns its DesktopMediaID.
   static DesktopMediaID RegisterNativeWindow(Type type,
                                              gfx::NativeWindow window);
@@ -35,7 +36,7 @@
   // Returns the Window that was previously registered using
   // RegisterNativeWindow(), else nullptr.
   static gfx::NativeWindow GetNativeWindowById(const DesktopMediaID& id);
-#endif  // USE_AURA
+#endif  // USE_AURA || OS_MACOSX
 
   constexpr DesktopMediaID() = default;
 
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 6f34b5b..cd97e47 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -105,10 +105,6 @@
 // permission prompt for testing.
 const char kEnableWebBluetoothScanning[] = "enable-web-bluetooth-scanning";
 
-// Disables compositor Ukm recording in browser tests.
-// TODO(khushalsagar): Remove once crbug.com/761524 is resolved.
-const char kDisableCompositorUkmForTests[] = "disable-compositor-ukm-for-tests";
-
 // Disables HTML5 DB support.
 const char kDisableDatabases[]              = "disable-databases";
 
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 69ad632..abbfebe 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -41,7 +41,6 @@
     kDisableBackgroundingOccludedWindowsForTesting[];
 CONTENT_EXPORT extern const char kDisableBackgroundTimerThrottling[];
 CONTENT_EXPORT extern const char kDisableBlinkFeatures[];
-CONTENT_EXPORT extern const char kDisableCompositorUkmForTests[];
 CONTENT_EXPORT extern const char kDisableDatabases[];
 CONTENT_EXPORT extern const char kDisableDisplayList2dCanvas[];
 extern const char kDisableDomainBlockingFor3DAPIs[];
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/DOMUtils.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/DOMUtils.java
index b8152e6..ec17396 100644
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/DOMUtils.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/DOMUtils.java
@@ -574,6 +574,8 @@
      * @return the click target of the node in the form of a [ x, y ] array.
      */
     private static int[] getClickTargetForBounds(WebContents webContents, Rect bounds) {
+        // TODO(nburris): This converts from CSS pixels to physical pixels, but
+        // does not account for visual viewport offset.
         RenderCoordinatesImpl coord = ((WebContentsImpl) webContents).getRenderCoordinates();
         int clickX = (int) coord.fromLocalCssToPix(bounds.exactCenterX());
         int clickY = (int) coord.fromLocalCssToPix(bounds.exactCenterY())
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index ed5ea5b..19381d2 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -266,9 +266,6 @@
   // not affect the results.
   command_line->AppendSwitchASCII(switches::kForceDisplayColorProfile, "srgb");
 
-  // Disable compositor Ukm in browser tests until crbug.com/761524 is resolved.
-  command_line->AppendSwitch(switches::kDisableCompositorUkmForTests);
-
   test_host_resolver_ = std::make_unique<TestHostResolver>();
 
   ContentBrowserSanityChecker scoped_enable_sanity_checks;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index c899a26..822c12e 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -1585,11 +1585,6 @@
 
 std::unique_ptr<cc::UkmRecorderFactory>
 RenderThreadImpl::CreateUkmRecorderFactory() {
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableCompositorUkmForTests)) {
-    return nullptr;
-  }
-
   return std::make_unique<UkmRecorderFactoryImpl>(GetConnector()->Clone());
 }
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index e8b8450..07b60600 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -907,6 +907,7 @@
     "../browser/tracing/background_tracing_manager_browsertest.cc",
     "../browser/tracing/memory_instrumentation_browsertest.cc",
     "../browser/tracing/memory_tracing_browsertest.cc",
+    "../browser/tracing/startup_tracing_browsertest.cc",
     "../browser/tracing/tracing_controller_browsertest.cc",
     "../browser/utility_process_host_browsertest.cc",
     "../browser/vibration_browsertest.cc",
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 80455c2..c740efb 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -90,6 +90,15 @@
     self.Fail('conformance/rendering/rendering-sampling-feedback-loop.html',
         bug=660844) # WebGL 2.0.1
 
+    # TODO(jdarpinian): This is a temporary failure expectation while the test
+    # is being fixed. But the test needs to be skipped on one platform, and
+    # there's no easy way to mark it as skipped on one and failing on all
+    # others, so skip it everywhere. When removing this, uncomment the
+    # matching skip expectation below in the AMD section.
+    self.Skip('conformance2/uniforms/' +
+        'incompatible-texture-type-for-sampler.html',
+        bug=809237)
+
     # Nvidia bugs fixed in latest driver
     # TODO(http://crbug.com/887241): Upgrade the drivers on the bots.
     self.Fail('conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html',
@@ -434,8 +443,6 @@
         ['linux', 'passthrough', 'opengl', 'nvidia'], bug=927407)
 
     # Passthrough command decoder / Linux / OpenGL / Intel
-    self.Flaky('conformance/extensions/webgl-compressed-texture-s3tc.html',
-        ['linux', 'passthrough', 'opengl', 'intel'], bug=872302)
     self.Fail('conformance2/renderbuffers/' +
         'multisampled-depth-renderbuffer-initialization.html',
         ['linux', 'passthrough', 'opengl', 'intel'], bug=2760) # ANGLE bug
@@ -889,7 +896,7 @@
     # Linux Multi-vendor failures.
     self.Flaky('deqp/functional/gles3/texturespecification/' +
         'random_teximage2d_2d.html',
-        ['linux', 'amd', 'intel'], bug=618447)
+        ['linux', 'amd'], bug=618447)
     self.Fail('conformance2/rendering/clipping-wide-points.html',
         ['linux', 'amd'], bug=662644) # WebGL 2.0.1
 
@@ -1319,9 +1326,11 @@
     self.Fail('conformance2/textures/misc/' +
         'generate-mipmap-with-large-base-level.html',
         ['linux', ('amd', 0x6613)], bug=913301)
-    self.Skip('conformance2/uniforms/' +
-        'incompatible-texture-type-for-sampler.html',
-        ['linux', ('amd', 0x6613)], bug=809237)
+    # TODO(jdarpinian): Uncomment after this test is re-enabled on all
+    # platforms when bug 940080 is fixed.
+    # self.Skip('conformance2/uniforms/' +
+    #     'incompatible-texture-type-for-sampler.html',
+    #     ['linux', ('amd', 0x6613)], bug=809237)
 
     ####################
     # Android failures #
diff --git a/device/fido/cable/fido_cable_device.cc b/device/fido/cable/fido_cable_device.cc
index 198d98fc..1da2ed7 100644
--- a/device/fido/cable/fido_cable_device.cc
+++ b/device/fido/cable/fido_cable_device.cc
@@ -61,6 +61,7 @@
     return false;
 
   message_to_encrypt->assign(ciphertext.begin(), ciphertext.end());
+  VLOG(2) << "Successfully encrypted outgoing caBLE message.";
   return true;
 }
 
@@ -133,6 +134,7 @@
 
   ++encryption_data_->write_sequence_num;
 
+  VLOG(2) << "Sending encrypted message to caBLE client";
   AddToPendingFrames(FidoBleDeviceCommand::kMsg, std::move(command),
                      std::move(callback));
 }
diff --git a/device/fido/cable/fido_cable_discovery.cc b/device/fido/cable/fido_cable_discovery.cc
index 2934fa7..6929f21 100644
--- a/device/fido/cable/fido_cable_discovery.cc
+++ b/device/fido/cable/fido_cable_discovery.cc
@@ -154,7 +154,7 @@
   if (!IsCableDevice(device))
     return;
 
-  DVLOG(2) << "Discovered Cable device: " << device->GetAddress();
+  VLOG(2) << "Discovered Cable device: " << device->GetAddress();
   CableDeviceFound(adapter, device);
 }
 
@@ -169,7 +169,7 @@
 
 void FidoCableDiscovery::DeviceRemoved(BluetoothAdapter* adapter,
                                        BluetoothDevice* device) {
-  if (IsCableDevice(device) && GetFoundCableDiscoveryData(device)) {
+  if (IsCableDevice(device) && GetCableDiscoveryData(device)) {
     const auto& device_address = device->GetAddress();
     VLOG(2) << "Cable device removed: " << device_address;
     RemoveDevice(FidoBleDevice::GetId(device_address));
@@ -215,13 +215,13 @@
 void FidoCableDiscovery::OnStartDiscoverySessionWithFilter(
     std::unique_ptr<BluetoothDiscoverySession> session) {
   SetDiscoverySession(std::move(session));
-  DVLOG(2) << "Discovery session started.";
+  VLOG(2) << "Discovery session started.";
   StartAdvertisement();
 }
 
 void FidoCableDiscovery::StartAdvertisement() {
   DCHECK(adapter());
-
+  VLOG(2) << "Starting to advertise clientEID.";
   for (const auto& data : discovery_data_) {
     adapter()->RegisterAdvertisement(
         ConstructAdvertisementData(data.version, data.client_eid),
@@ -237,8 +237,10 @@
 void FidoCableDiscovery::StopAdvertisements(base::OnceClosure callback) {
   auto barrier_closure =
       base::BarrierClosure(advertisement_success_counter_, std::move(callback));
-  for (auto advertisement : advertisements_)
+  for (auto advertisement : advertisements_) {
     advertisement.second->Unregister(barrier_closure, base::DoNothing());
+    VLOG(2) << "Stopped caBLE advertisement.";
+  }
 
 #if !defined(OS_WIN)
   // On Windows the discovery is the only owner of the advertisements, meaning
@@ -251,7 +253,7 @@
 void FidoCableDiscovery::OnAdvertisementRegistered(
     const EidArray& client_eid,
     scoped_refptr<BluetoothAdvertisement> advertisement) {
-  DVLOG(2) << "Advertisement registered.";
+  VLOG(2) << "Advertisement registered.";
   advertisements_.emplace(client_eid, std::move(advertisement));
   RecordAdvertisementResult(true /* is_success */);
 }
@@ -277,11 +279,11 @@
 
 void FidoCableDiscovery::CableDeviceFound(BluetoothAdapter* adapter,
                                           BluetoothDevice* device) {
-  const auto* found_cable_device_data = GetFoundCableDiscoveryData(device);
+  const auto* found_cable_device_data = GetCableDiscoveryData(device);
   if (!found_cable_device_data)
     return;
 
-  DVLOG(2) << "Found new Cable device.";
+  VLOG(2) << "Found new Cable device.";
   // Nonce is embedded as first 8 bytes of client EID.
   std::array<uint8_t, 8> nonce;
   bool extract_success = fido_parsing_utils::ExtractArray(
@@ -302,8 +304,10 @@
     base::span<const uint8_t, kSessionPreKeySize> session_pre_key,
     base::span<const uint8_t, 8> nonce) {
   // At most one handshake messages should be exchanged for each Cable device.
-  if (base::ContainsKey(cable_handshake_handlers_, cable_device->GetId()))
+  if (base::ContainsKey(cable_handshake_handlers_, cable_device->GetId())) {
+    VLOG(2) << "We've already exchanged a handshake with this device.";
     return;
+  }
 
   auto handshake_handler =
       CreateHandshakeHandler(cable_device.get(), session_pre_key, nonce);
@@ -326,26 +330,29 @@
 
   if (handshake_handler->ValidateAuthenticatorHandshakeMessage(
           *handshake_response)) {
-    DVLOG(2) << "Authenticator handshake validated";
+    VLOG(2) << "Authenticator handshake validated";
     AddDevice(std::move(cable_device));
   } else {
-    DVLOG(2) << "Authenticator handshake invalid";
+    VLOG(2) << "Authenticator handshake invalid";
   }
 }
 
-const CableDiscoveryData* FidoCableDiscovery::GetFoundCableDiscoveryData(
+const CableDiscoveryData* FidoCableDiscovery::GetCableDiscoveryData(
     const BluetoothDevice* device) const {
-  const auto* discovery_data =
-      GetFoundCableDiscoveryDataFromServiceData(device);
+  const auto* discovery_data = GetCableDiscoveryDataFromServiceData(device);
   if (discovery_data != nullptr) {
+    VLOG(2) << "Found caBLE service data.";
     return discovery_data;
   }
 
-  return GetFoundCableDiscoveryDataFromServiceUUIDs(device);
+  VLOG(2) << "caBLE service data not found. Searching for caBLE UUIDs instead.";
+  // iOS devices cannot advertise service data. These devices instead put the
+  // authenticator EID as a second UUID in addition to the caBLE UUID.
+  return GetCableDiscoveryDataFromServiceUUIDs(device);
 }
 
 const CableDiscoveryData*
-FidoCableDiscovery::GetFoundCableDiscoveryDataFromServiceData(
+FidoCableDiscovery::GetCableDiscoveryDataFromServiceData(
     const BluetoothDevice* device) const {
   const auto* service_data =
       device->GetServiceDataForUUID(CableAdvertisementUUID());
@@ -377,7 +384,7 @@
 }
 
 const CableDiscoveryData*
-FidoCableDiscovery::GetFoundCableDiscoveryDataFromServiceUUIDs(
+FidoCableDiscovery::GetCableDiscoveryDataFromServiceUUIDs(
     const BluetoothDevice* device) const {
   const auto service_uuids = device->GetUUIDs();
   for (const auto& uuid : service_uuids) {
diff --git a/device/fido/cable/fido_cable_discovery.h b/device/fido/cable/fido_cable_discovery.h
index 9bbad3b..40ba135 100644
--- a/device/fido/cable/fido_cable_discovery.h
+++ b/device/fido/cable/fido_cable_discovery.h
@@ -85,11 +85,11 @@
       FidoCableHandshakeHandler* handshake_handler,
       base::Optional<std::vector<uint8_t>> handshake_response);
 
-  const CableDiscoveryData* GetFoundCableDiscoveryData(
+  const CableDiscoveryData* GetCableDiscoveryData(
       const BluetoothDevice* device) const;
-  const CableDiscoveryData* GetFoundCableDiscoveryDataFromServiceData(
+  const CableDiscoveryData* GetCableDiscoveryDataFromServiceData(
       const BluetoothDevice* device) const;
-  const CableDiscoveryData* GetFoundCableDiscoveryDataFromServiceUUIDs(
+  const CableDiscoveryData* GetCableDiscoveryDataFromServiceUUIDs(
       const BluetoothDevice* device) const;
 
   std::vector<CableDiscoveryData> discovery_data_;
diff --git a/device/fido/cable/fido_cable_handshake_handler.cc b/device/fido/cable/fido_cable_handshake_handler.cc
index 2a57227..7cafc1c5 100644
--- a/device/fido/cable/fido_cable_handshake_handler.cc
+++ b/device/fido/cable/fido_cable_handshake_handler.cc
@@ -103,6 +103,7 @@
     return;
   }
 
+  VLOG(2) << "Sending the caBLE handshake message";
   cable_device_->SendHandshakeMessage(
       fido_parsing_utils::Materialize(*handshake_message), std::move(callback));
 }
diff --git a/device/fido/fido_device.cc b/device/fido/fido_device.cc
index 58a4151b..026b7755 100644
--- a/device/fido/fido_device.cc
+++ b/device/fido/fido_device.cc
@@ -36,6 +36,7 @@
   // request. The correct value will be set in the callback based on the
   // device response.
   supported_protocol_ = ProtocolVersion::kCtap;
+  VLOG(2) << "Sending CTAP2 AuthenticatorGetInfo request to authenticator.";
   DeviceTransact(AuthenticatorGetInfoRequest().Serialize(),
                  base::BindOnce(&FidoDevice::OnDeviceInfoReceived, GetWeakPtr(),
                                 std::move(done)));
@@ -54,15 +55,16 @@
     return;
 
   state_ = FidoDevice::State::kReady;
-
   base::Optional<AuthenticatorGetInfoResponse> get_info_response =
       response ? ReadCTAPGetInfoResponse(*response) : base::nullopt;
   if (!get_info_response || !base::ContainsKey(get_info_response->versions(),
                                                ProtocolVersion::kCtap)) {
     supported_protocol_ = ProtocolVersion::kU2f;
+    VLOG(2) << "The device only supports the U2F protocol.";
   } else {
     supported_protocol_ = ProtocolVersion::kCtap;
     device_info_ = std::move(*get_info_response);
+    VLOG(2) << "The device supports the CTAP2 protocol.";
   }
   std::move(done).Run();
 }
diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc
index 58f09110..1987e50 100644
--- a/device/fido/fido_request_handler_base.cc
+++ b/device/fido/fido_request_handler_base.cc
@@ -329,11 +329,15 @@
     // Post |InitializeAuthenticatorAndDispatchRequest| into its own task. This
     // avoids hairpinning, even if the authenticator immediately invokes the
     // request callback.
+    VLOG(2)
+        << "Request handler dispatching request to authenticator immediately.";
     base::SequencedTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::BindOnce(
             &FidoRequestHandlerBase::InitializeAuthenticatorAndDispatchRequest,
             GetWeakPtr(), authenticator));
+  } else {
+    VLOG(2) << "Embedder controls the dispatch.";
   }
 
 #if defined(OS_WIN)
diff --git a/docs/ios/running_against_tot_webkit.md b/docs/ios/running_against_tot_webkit.md
new file mode 100644
index 0000000..508af04d
--- /dev/null
+++ b/docs/ios/running_against_tot_webkit.md
@@ -0,0 +1,102 @@
+# Running Against ToT WebKit in the Simulator
+
+This is a simplified workflow intended to make it as easy as possible to compile
+and run against ToT WebKit locally. If you intend to do daily development in a
+WebKit tree, you may want to consider an alternate workflow as described
+[here](https://docs.google.com/document/d/1l74JNYr9dniUnT5aKUS1_EswlDmuQghlEfyVCiPh9a4).
+
+A design doc explaining the details behind these steps can be found
+[here](https://docs.google.com/document/d/15HCmvC_yKNpmcrgHaGUA5LWWwROCmOz7qyYnMmhQkBQ)
+
+Note: this only works on Simulator.  At present, we do not have the ability to
+compile WebKit for devices.
+
+## Warning: do this in a new checkout
+
+The changes below will substantially increase compile times, for both clean and
+incremental builds.  No-op builds will jump from ~0s to ~60s, which will
+likely be an unacceptable regression in a daily development checkout.
+
+By pulling a separate, new checkout for WebKit, you sidestep these issues at the
+expense of greater disk usage.
+
+## Updating .gclient to pull WebKit
+
+To start, edit your `.gclient` file to checkout WebKit @HEAD. Both of the custom
+variables are necessary, as by default webkit.git is pinned to a revision in the
+distant past.
+
+```
+solutions = [
+  {
+    "url": "https://chromium.googlesource.com/chromium/src.git",
+    "name": "src",
+
+    "custom_vars": {
+      "checkout_ios_webkit": True,
+      "ios_webkit_revision": "refs/heads/master",
+    },
+
+  },
+]
+target_os = ["ios"]
+target_os_only = "True"
+````
+
+Add the `custom_vars` section as above and re-run `gclient sync`.  After it
+completes, you should have a WebKit checkout in `ios/third_party/webkit/src`.
+
+## Building
+
+WebKit-enabled checkouts expose a `webkit` target via GN/ninja. The WebKit
+libraries will automatically be built as part of the default set of targets, or
+you can build it individually.
+
+```
+# Builds all targets, including webkit.
+ninja -C out/Debug-iphonesimulator
+
+# Builds just the webkit target.
+ninja -C out/Debug-iphonesimulator webkit
+```
+
+The WebKit build output can be found at
+`out/Debug-iphonesimulator/obj/ios/third_aparty/webkit/`.
+
+### Speeding up clean builds by building WebKit first
+
+We build using a set of scripts provided by WebKit; they set up an environment
+and then invoke xcodebuild directly.  To prevent xcodebuild from competing with
+ninja for CPU/RAM, we limit the WebKit build to four parallel jobs. This is
+generally sufficient for incremental builds, but for clean builds (or after a
+sync) it may be faster to build WebKit without this limitation.
+
+```
+# After a sync, build WebKit first.
+ios/third_party/webkit/build-webkit.py
+
+# Once WebKit is built, invoke ninja as usual to build Chromium.
+ninja -C out/Debug-iphonesimulator
+```
+
+### One-time setup (per machine, per version of Xcode)
+
+If you move to a new machine or install a new version of Xcode, you'll need to
+run a setup script in order to copy some headers from the macOS SDK into the iOS
+SDK.
+
+```
+sudo ios/third_party/webkit/src/Tools/Scripts/configure-xcode-for-ios-development
+```
+
+
+## Running against locally-built libraries
+
+To run against the libraries you've just built, set the `DYLD_FRAMEWORK_PATH`
+environment variable to the directory containing the WebKit build output.  This
+is usually easiest to do in the Xcode UI.
+
+```
+DYLD_FRAMEWORK_PATH = /path/to/out/Debug-iphonesimulator/obj/ios/third_party/webkit/
+```
+
diff --git a/extensions/browser/api/idle/BUILD.gn b/extensions/browser/api/idle/BUILD.gn
index edc5714..a635a4f0 100644
--- a/extensions/browser/api/idle/BUILD.gn
+++ b/extensions/browser/api/idle/BUILD.gn
@@ -21,6 +21,7 @@
 
   deps = [
     "//extensions/common/api",
+    "//ui/base/idle",
   ]
 
   public_deps = [
diff --git a/extensions/browser/api/idle/idle_manager.cc b/extensions/browser/api/idle/idle_manager.cc
index b616b88..8b82b48 100644
--- a/extensions/browser/api/idle/idle_manager.cc
+++ b/extensions/browser/api/idle/idle_manager.cc
@@ -15,7 +15,7 @@
 #include "extensions/common/extension.h"
 
 #if defined(OS_CHROMEOS)
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #endif
 
 namespace keys = extensions::idle_api_constants;
diff --git a/extensions/browser/api/socket/socket.cc b/extensions/browser/api/socket/socket.cc
index 4c7b777c..d2b38dac 100644
--- a/extensions/browser/api/socket/socket.cc
+++ b/extensions/browser/api/socket/socket.cc
@@ -39,9 +39,9 @@
 
 void Socket::Write(scoped_refptr<net::IOBuffer> io_buffer,
                    int byte_count,
-                   const net::CompletionCallback& callback) {
+                   net::CompletionOnceCallback callback) {
   DCHECK(!callback.is_null());
-  write_queue_.push(WriteRequest(io_buffer, byte_count, callback));
+  write_queue_.emplace(io_buffer, byte_count, std::move(callback));
   WriteData();
 }
 
@@ -57,7 +57,7 @@
       request.io_buffer->data() + request.bytes_written);
   int result = WriteImpl(
       io_buffer_write_.get(), request.byte_count - request.bytes_written,
-      base::Bind(&Socket::OnWriteComplete, base::Unretained(this)));
+      base::BindOnce(&Socket::OnWriteComplete, base::Unretained(this)));
 
   if (result != net::ERR_IO_PENDING)
     OnWriteComplete(result);
@@ -78,7 +78,7 @@
     result = request.bytes_written;
   }
 
-  request.callback.Run(result);
+  std::move(request.callback).Run(result);
   write_queue_.pop();
 
   if (!write_queue_.empty())
@@ -136,13 +136,13 @@
 
 Socket::WriteRequest::WriteRequest(scoped_refptr<net::IOBuffer> io_buffer,
                                    int byte_count,
-                                   const net::CompletionCallback& callback)
+                                   net::CompletionOnceCallback callback)
     : io_buffer(io_buffer),
       byte_count(byte_count),
-      callback(callback),
+      callback(std::move(callback)),
       bytes_written(0) {}
 
-Socket::WriteRequest::WriteRequest(const WriteRequest& other) = default;
+Socket::WriteRequest::WriteRequest(WriteRequest&& other) = default;
 
 Socket::WriteRequest::~WriteRequest() {}
 
diff --git a/extensions/browser/api/socket/socket.h b/extensions/browser/api/socket/socket.h
index 3839099..a46a9617 100644
--- a/extensions/browser/api/socket/socket.h
+++ b/extensions/browser/api/socket/socket.h
@@ -18,7 +18,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/api/api_resource.h"
 #include "extensions/browser/api/api_resource_manager.h"
-#include "net/base/completion_callback.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/ip_endpoint.h"
@@ -106,7 +105,7 @@
   // error occurred.
   void Write(scoped_refptr<net::IOBuffer> io_buffer,
              int byte_count,
-             const net::CompletionCallback& callback);
+             net::CompletionOnceCallback callback);
 
   virtual void RecvFrom(int count, RecvFromCompletionCallback callback) = 0;
   virtual void SendTo(scoped_refptr<net::IOBuffer> io_buffer,
@@ -146,7 +145,7 @@
   void WriteData();
   virtual int WriteImpl(net::IOBuffer* io_buffer,
                         int io_buffer_size,
-                        const net::CompletionCallback& callback) = 0;
+                        net::CompletionOnceCallback callback) = 0;
 
   std::string hostname_;
   bool is_connected_;
@@ -158,12 +157,12 @@
   struct WriteRequest {
     WriteRequest(scoped_refptr<net::IOBuffer> io_buffer,
                  int byte_count,
-                 const net::CompletionCallback& callback);
-    WriteRequest(const WriteRequest& other);
+                 net::CompletionOnceCallback callback);
+    WriteRequest(WriteRequest&& other);
     ~WriteRequest();
     scoped_refptr<net::IOBuffer> io_buffer;
     int byte_count;
-    net::CompletionCallback callback;
+    net::CompletionOnceCallback callback;
     int bytes_written;
   };
 
diff --git a/extensions/browser/api/socket/socket_api.cc b/extensions/browser/api/socket/socket_api.cc
index a1a13a4..c1a68371 100644
--- a/extensions/browser/api/socket/socket_api.cc
+++ b/extensions/browser/api/socket/socket_api.cc
@@ -604,7 +604,7 @@
   }
 
   socket->Write(io_buffer_, io_buffer_size_,
-                base::BindRepeating(&SocketWriteFunction::OnCompleted, this));
+                base::BindOnce(&SocketWriteFunction::OnCompleted, this));
 }
 
 void SocketWriteFunction::OnCompleted(int bytes_written) {
diff --git a/extensions/browser/api/socket/tcp_socket.cc b/extensions/browser/api/socket/tcp_socket.cc
index 645725d..12a980ed 100644
--- a/extensions/browser/api/socket/tcp_socket.cc
+++ b/extensions/browser/api/socket/tcp_socket.cc
@@ -313,13 +313,14 @@
 
 int TCPSocket::WriteImpl(net::IOBuffer* io_buffer,
                          int io_buffer_size,
-                         const net::CompletionCallback& callback) {
+                         net::CompletionOnceCallback callback) {
   if (!mojo_data_pump_)
     return net::ERR_SOCKET_NOT_CONNECTED;
 
-  mojo_data_pump_->Write(io_buffer, io_buffer_size,
-                         base::BindOnce(&TCPSocket::OnWriteComplete,
-                                        base::Unretained(this), callback));
+  mojo_data_pump_->Write(
+      io_buffer, io_buffer_size,
+      base::BindOnce(&TCPSocket::OnWriteComplete, base::Unretained(this),
+                     std::move(callback)));
   return net::ERR_IO_PENDING;
 }
 
@@ -449,14 +450,14 @@
            std::move(receive_stream), std::move(send_stream));
 }
 
-void TCPSocket::OnWriteComplete(const net::CompletionCallback& callback,
+void TCPSocket::OnWriteComplete(net::CompletionOnceCallback callback,
                                 int result) {
   if (result < 0) {
     // Write side has terminated. This can be an error or a graceful close.
     // TCPSocketEventDispatcher doesn't distinguish between the two.
     Disconnect(false /* socket_destroying */);
   }
-  callback.Run(result);
+  std::move(callback).Run(result);
 }
 
 void TCPSocket::OnReadComplete(int result,
diff --git a/extensions/browser/api/socket/tcp_socket.h b/extensions/browser/api/socket/tcp_socket.h
index 57f62c77..c67fc67 100644
--- a/extensions/browser/api/socket/tcp_socket.h
+++ b/extensions/browser/api/socket/tcp_socket.h
@@ -93,7 +93,7 @@
  protected:
   int WriteImpl(net::IOBuffer* io_buffer,
                 int io_buffer_size,
-                const net::CompletionCallback& callback) override;
+                net::CompletionOnceCallback callback) override;
 
  private:
   // Connects a client TCP socket. This is done on the UI thread because
@@ -142,7 +142,7 @@
                 network::mojom::TCPConnectedSocketPtr connected_socket,
                 mojo::ScopedDataPipeConsumerHandle receive_stream,
                 mojo::ScopedDataPipeProducerHandle send_stream);
-  void OnWriteComplete(const net::CompletionCallback& callback, int result);
+  void OnWriteComplete(net::CompletionOnceCallback callback, int result);
   void OnReadComplete(int result, scoped_refptr<net::IOBuffer> io_buffer);
   void OnUpgradeToTLSComplete(UpgradeToTLSCallback callback,
                               network::mojom::TLSClientSocketPtr tls_socket,
diff --git a/extensions/browser/api/socket/tls_socket.cc b/extensions/browser/api/socket/tls_socket.cc
index 432dcf3..c89339d 100644
--- a/extensions/browser/api/socket/tls_socket.cc
+++ b/extensions/browser/api/socket/tls_socket.cc
@@ -115,23 +115,24 @@
 
 int TLSSocket::WriteImpl(net::IOBuffer* io_buffer,
                          int io_buffer_size,
-                         const net::CompletionCallback& callback) {
+                         net::CompletionOnceCallback callback) {
   if (!mojo_data_pump_)
     return net::ERR_SOCKET_NOT_CONNECTED;
-  mojo_data_pump_->Write(io_buffer, io_buffer_size,
-                         base::BindOnce(&TLSSocket::OnWriteComplete,
-                                        base::Unretained(this), callback));
+  mojo_data_pump_->Write(
+      io_buffer, io_buffer_size,
+      base::BindOnce(&TLSSocket::OnWriteComplete, base::Unretained(this),
+                     std::move(callback)));
   return net::ERR_IO_PENDING;
 }
 
-void TLSSocket::OnWriteComplete(const net::CompletionCallback& callback,
+void TLSSocket::OnWriteComplete(net::CompletionOnceCallback callback,
                                 int result) {
   if (result < 0) {
     // Write side has terminated. This can be an error or a graceful close.
     // TCPSocketEventDispatcher doesn't distinguish between the two.
     Disconnect(false /* socket_destroying */);
   }
-  callback.Run(result);
+  std::move(callback).Run(result);
 }
 
 void TLSSocket::OnReadComplete(int result,
diff --git a/extensions/browser/api/socket/tls_socket.h b/extensions/browser/api/socket/tls_socket.h
index 99846ea..7d85f0d 100644
--- a/extensions/browser/api/socket/tls_socket.h
+++ b/extensions/browser/api/socket/tls_socket.h
@@ -71,8 +71,8 @@
  private:
   int WriteImpl(net::IOBuffer* io_buffer,
                 int io_buffer_size,
-                const net::CompletionCallback& callback) override;
-  void OnWriteComplete(const net::CompletionCallback& callback, int result);
+                net::CompletionOnceCallback callback) override;
+  void OnWriteComplete(net::CompletionOnceCallback callback, int result);
   void OnReadComplete(int result, scoped_refptr<net::IOBuffer> io_buffer);
 
   network::mojom::TLSClientSocketPtr tls_socket_;
@@ -87,4 +87,3 @@
 }  // namespace extensions
 
 #endif  // EXTENSIONS_BROWSER_API_SOCKET_TLS_SOCKET_H_
-
diff --git a/extensions/browser/api/socket/udp_socket.cc b/extensions/browser/api/socket/udp_socket.cc
index 4e362575..b0f3ca8 100644
--- a/extensions/browser/api/socket/udp_socket.cc
+++ b/extensions/browser/api/socket/udp_socket.cc
@@ -124,17 +124,18 @@
 
 int UDPSocket::WriteImpl(net::IOBuffer* io_buffer,
                          int io_buffer_size,
-                         const net::CompletionCallback& callback) {
+                         net::CompletionOnceCallback callback) {
   if (!IsConnected())
     return net::ERR_SOCKET_NOT_CONNECTED;
   base::span<const uint8_t> data(
       reinterpret_cast<const uint8_t*>(io_buffer->data()),
       static_cast<size_t>(io_buffer_size));
-  socket_->Send(data,
-                net::MutableNetworkTrafficAnnotationTag(
-                    Socket::GetNetworkTrafficAnnotationTag()),
-                base::BindOnce(&UDPSocket::OnWriteCompleted,
-                               base::Unretained(this), callback, data.size()));
+  socket_->Send(
+      data,
+      net::MutableNetworkTrafficAnnotationTag(
+          Socket::GetNetworkTrafficAnnotationTag()),
+      base::BindOnce(&UDPSocket::OnWriteCompleted, base::Unretained(this),
+                     std::move(callback), data.size()));
   return net::ERR_IO_PENDING;
 }
 
@@ -284,14 +285,14 @@
   std::move(callback).Run(result);
 }
 
-void UDPSocket::OnWriteCompleted(const net::CompletionCallback& callback,
+void UDPSocket::OnWriteCompleted(net::CompletionOnceCallback callback,
                                  size_t byte_count,
                                  int result) {
   if (result == net::OK) {
-    callback.Run(byte_count);
+    std::move(callback).Run(byte_count);
     return;
   }
-  callback.Run(result);
+  std::move(callback).Run(result);
 }
 
 void UDPSocket::OnJoinGroupCompleted(net::CompletionOnceCallback callback,
diff --git a/extensions/browser/api/socket/udp_socket.h b/extensions/browser/api/socket/udp_socket.h
index f323d51..ab6f9305 100644
--- a/extensions/browser/api/socket/udp_socket.h
+++ b/extensions/browser/api/socket/udp_socket.h
@@ -63,7 +63,7 @@
  protected:
   int WriteImpl(net::IOBuffer* io_buffer,
                 int io_buffer_size,
-                const net::CompletionCallback& callback) override;
+                net::CompletionOnceCallback callback) override;
 
  private:
   // Make net::IPEndPoint can be refcounted
@@ -86,7 +86,7 @@
   void OnSendToCompleted(net::CompletionOnceCallback user_callback,
                          size_t byte_count,
                          int result);
-  void OnWriteCompleted(const net::CompletionCallback& user_callback,
+  void OnWriteCompleted(net::CompletionOnceCallback user_callback,
                         size_t byte_count,
                         int result);
   void OnJoinGroupCompleted(net::CompletionOnceCallback user_callback,
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
index a3799aa..47044972 100644
--- a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
+++ b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
@@ -380,9 +380,8 @@
     return;
   }
 
-  socket->Write(io_buffer_,
-                io_buffer_size_,
-                base::Bind(&SocketsTcpSendFunction::OnCompleted, this));
+  socket->Write(io_buffer_, io_buffer_size_,
+                base::BindOnce(&SocketsTcpSendFunction::OnCompleted, this));
 }
 
 void SocketsTcpSendFunction::OnCompleted(int net_result) {
diff --git a/extensions/browser/api/system_power_source/system_power_source_api.cc b/extensions/browser/api/system_power_source/system_power_source_api.cc
index cb5f912d..e99e4fc 100644
--- a/extensions/browser/api/system_power_source/system_power_source_api.cc
+++ b/extensions/browser/api/system_power_source/system_power_source_api.cc
@@ -7,7 +7,7 @@
 #include <cmath>
 
 #include "base/no_destructor.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/common/api/system_power_source.h"
 
diff --git a/extensions/browser/api/system_power_source/system_power_source_api.h b/extensions/browser/api/system_power_source/system_power_source_api.h
index 6698d9b..523e9a00 100644
--- a/extensions/browser/api/system_power_source/system_power_source_api.h
+++ b/extensions/browser/api/system_power_source/system_power_source_api.h
@@ -6,7 +6,7 @@
 #define EXTENSIONS_BROWSER_API_SYSTEM_POWER_SOURCE_SYSTEM_POWER_SOURCE_API_H_
 
 #include "base/scoped_observer.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
 #include "extensions/browser/extension_function.h"
 #include "extensions/browser/extension_function_histogram_value.h"
diff --git a/extensions/browser/api/system_power_source/system_power_source_api_unittest.cc b/extensions/browser/api/system_power_source/system_power_source_api_unittest.cc
index e7d50ac..e08502c4 100644
--- a/extensions/browser/api/system_power_source/system_power_source_api_unittest.cc
+++ b/extensions/browser/api/system_power_source/system_power_source_api_unittest.cc
@@ -5,7 +5,7 @@
 #include <limits>
 
 #include "base/bind.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "extensions/browser/api/system_power_source/system_power_source_api.h"
 #include "extensions/browser/api_test_utils.h"
 #include "extensions/browser/api_unittest.h"
diff --git a/extensions/browser/api/system_power_source/system_power_source_apitest.cc b/extensions/browser/api/system_power_source/system_power_source_apitest.cc
index 89a6251..f38a0cd 100644
--- a/extensions/browser/api/system_power_source/system_power_source_apitest.cc
+++ b/extensions/browser/api/system_power_source/system_power_source_apitest.cc
@@ -6,7 +6,7 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
 #include "extensions/common/features/feature_session_type.h"
 #include "extensions/shell/test/shell_apitest.h"
diff --git a/extensions/renderer/context_menus_custom_bindings.cc b/extensions/renderer/context_menus_custom_bindings.cc
index 72fec49..f51f195 100644
--- a/extensions/renderer/context_menus_custom_bindings.cc
+++ b/extensions/renderer/context_menus_custom_bindings.cc
@@ -9,14 +9,24 @@
 #include "base/bind.h"
 #include "content/public/renderer/render_thread.h"
 #include "extensions/common/extension_messages.h"
+#include "extensions/renderer/worker_thread_dispatcher.h"
 #include "v8/include/v8.h"
 
 namespace {
 
 void GetNextContextMenuId(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  // TODO(crbug.com/942373): We should use base::UnguessableToken or base::GUID
+  // here, rather than sending a synchronous RPC to the browser process to
+  // generate a unique ID.
   int context_menu_id = -1;
-  content::RenderThread::Get()->Send(
-      new ExtensionHostMsg_GenerateUniqueID(&context_menu_id));
+  content::RenderThread* const render_thread = content::RenderThread::Get();
+  if (render_thread) {
+    render_thread->Send(
+        new ExtensionHostMsg_GenerateUniqueID(&context_menu_id));
+  } else {
+    extensions::WorkerThreadDispatcher::Get()->Send(
+        new ExtensionHostMsg_GenerateUniqueID(&context_menu_id));
+  }
   args.GetReturnValue().Set(static_cast<int32_t>(context_menu_id));
 }
 
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index fe5b10e1..e837506 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -880,9 +880,13 @@
   // use the old web APIs.
   // After completion of the migration, we should remove this.
   // See crbug.com/924031 for detail.
-  if (extension_id == extension_misc::kPdfExtensionId ||
-      // chrome/common/extensions/extension_constants.h::kZipArchiverExtensionId
-      extension_id == "dmboannefpncccogfdikhmhpmdnddgoe") {
+  if (extension_id == extension_misc::kPdfExtensionId) {
+    blink::WebRuntimeFeatures::EnableShadowDOMV0(true);
+    blink::WebRuntimeFeatures::EnableCustomElementsV0(true);
+  }
+  // Zip archiver support.
+  // ID: chrome/common/extensions/extension_constants.h::kZipArchiverExtensionId
+  if (extension_id == "dmboannefpncccogfdikhmhpmdnddgoe") {
     blink::WebRuntimeFeatures::EnableShadowDOMV0(true);
     blink::WebRuntimeFeatures::EnableCustomElementsV0(true);
     blink::WebRuntimeFeatures::EnableHTMLImports(true);
diff --git a/extensions/shell/browser/api/runtime/shell_runtime_api_delegate.cc b/extensions/shell/browser/api/runtime/shell_runtime_api_delegate.cc
index 2ea95e6..d77010c 100644
--- a/extensions/shell/browser/api/runtime/shell_runtime_api_delegate.cc
+++ b/extensions/shell/browser/api/runtime/shell_runtime_api_delegate.cc
@@ -9,7 +9,7 @@
 #include "extensions/shell/browser/shell_extension_system.h"
 
 #if defined(OS_CHROMEOS)
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #endif
 
diff --git a/extensions/shell/browser/shell_browser_main_parts.cc b/extensions/shell/browser/shell_browser_main_parts.cc
index 781c851..a6ec8749 100644
--- a/extensions/shell/browser/shell_browser_main_parts.cc
+++ b/extensions/shell/browser/shell_browser_main_parts.cc
@@ -65,7 +65,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #elif defined(OS_LINUX)
 #include "device/bluetooth/dbus/bluez_dbus_thread_manager.h"
 #endif
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc
index 618e423..73abaf0 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura.cc
+++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -33,7 +33,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "base/command_line.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "extensions/shell/browser/shell_screen.h"
 #include "extensions/shell/common/switches.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.h b/extensions/shell/browser/shell_desktop_controller_aura.h
index 3617a47..35ca079 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura.h
+++ b/extensions/shell/browser/shell_desktop_controller_aura.h
@@ -19,7 +19,7 @@
 #include "ui/display/display.h"
 
 #if defined(OS_CHROMEOS)
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/display/manager/display_configurator.h"
 #endif
 
diff --git a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc
index a68584c..6857b8ff 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc
+++ b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc
@@ -36,7 +36,7 @@
 #include "ui/gfx/geometry/rect.h"
 
 #if defined(OS_CHROMEOS)
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #endif
 
 namespace extensions {
diff --git a/fuchsia/engine/browser/frame_impl.cc b/fuchsia/engine/browser/frame_impl.cc
index 648b7b9..9a53837b 100644
--- a/fuchsia/engine/browser/frame_impl.cc
+++ b/fuchsia/engine/browser/frame_impl.cc
@@ -479,24 +479,6 @@
   web_contents_->GetController().LoadURLWithParams(params_converted);
 }
 
-void FrameImpl::LoadUrl2(std::string url,
-                         chromium::web::LoadUrlParams2 params) {
-  chromium::web::LoadUrlParams converted_params;
-  if (params.has_type()) {
-    converted_params.set_type(*params.type());
-  }
-  if (params.has_referrer_url()) {
-    converted_params.set_referrer_url(std::move(*params.referrer_url()));
-  }
-  if (params.has_was_user_activated()) {
-    converted_params.set_was_user_activated(*params.was_user_activated());
-  }
-  if (params.has_headers()) {
-    converted_params.set_headers(std::move(*params.headers()));
-  }
-  LoadUrl(std::move(url), std::move(converted_params));
-}
-
 void FrameImpl::GoBack() {
   if (web_contents_->GetController().CanGoBack())
     web_contents_->GetController().GoBack();
diff --git a/fuchsia/engine/browser/frame_impl.h b/fuchsia/engine/browser/frame_impl.h
index 361109e..915714e 100644
--- a/fuchsia/engine/browser/frame_impl.h
+++ b/fuchsia/engine/browser/frame_impl.h
@@ -106,7 +106,6 @@
 
   // chromium::web::NavigationController implementation.
   void LoadUrl(std::string url, chromium::web::LoadUrlParams params) override;
-  void LoadUrl2(std::string url, chromium::web::LoadUrlParams2 params) override;
   void GoBack() override;
   void GoForward() override;
   void Stop() override;
diff --git a/fuchsia/engine/browser/frame_impl_browsertest.cc b/fuchsia/engine/browser/frame_impl_browsertest.cc
index 9d5d28d2..d0b8e919 100644
--- a/fuchsia/engine/browser/frame_impl_browsertest.cc
+++ b/fuchsia/engine/browser/frame_impl_browsertest.cc
@@ -116,25 +116,6 @@
                chromium::web::LoadUrlParams(), controller.get());
 }
 
-// TODO(crbug.com/931831): Remove this test once the transition is complete.
-IN_PROC_BROWSER_TEST_F(FrameImplTest, DeprecatedNavigateFrame) {
-  chromium::web::FramePtr frame = CreateFrame();
-
-  chromium::web::NavigationControllerPtr controller;
-  frame->GetNavigationController(controller.NewRequest());
-
-  base::RunLoop run_loop;
-  EXPECT_CALL(navigation_observer_,
-              MockableOnNavigationStateChanged(testing::AllOf(
-                  Field(&NavigationDetails::title, url::kAboutBlankURL),
-                  Field(&NavigationDetails::url, url::kAboutBlankURL))))
-      .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-  controller->LoadUrl2(url::kAboutBlankURL, chromium::web::LoadUrlParams2());
-  run_loop.Run();
-  Mock::VerifyAndClearExpectations(this);
-  navigation_observer_.Acknowledge();
-}
-
 IN_PROC_BROWSER_TEST_F(FrameImplTest, NavigateDataFrame) {
   chromium::web::FramePtr frame = CreateFrame();
 
@@ -1169,40 +1150,3 @@
   EXPECT_THAT(iter->second.headers,
               testing::Contains(testing::Key("X-2ExtraHeaders")));
 }
-
-// TODO(crbug.com/931831): Remove this test once the transition is complete.
-IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest,
-                       DeprecatedExtraHeaders) {
-  chromium::web::FramePtr frame = CreateFrame();
-
-  chromium::web::LoadUrlParams2 load_url_params;
-  load_url_params.set_headers({StringToUnsignedVector("X-ExtraHeaders: 1"),
-                               StringToUnsignedVector("X-2ExtraHeaders: 2")});
-
-  chromium::web::NavigationControllerPtr controller;
-  frame->GetNavigationController(controller.NewRequest());
-
-  const GURL page_url(embedded_test_server()->GetURL(kPage1Path));
-
-  base::RunLoop run_loop;
-  EXPECT_CALL(navigation_observer_,
-              MockableOnNavigationStateChanged(testing::AllOf(
-                  Field(&NavigationDetails::title, kPage1Title),
-                  Field(&NavigationDetails::url, page_url.spec()))))
-      .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-  controller->LoadUrl2(page_url.spec(), std::move(load_url_params));
-  run_loop.Run();
-  Mock::VerifyAndClearExpectations(this);
-  navigation_observer_.Acknowledge();
-
-  base::RunLoop().RunUntilIdle();
-
-  // At this point, the page should be loaded, the server should have received
-  // the request and the request should be in the map.
-  const auto iter = accumulated_requests_.find(page_url);
-  ASSERT_NE(iter, accumulated_requests_.end());
-  EXPECT_THAT(iter->second.headers,
-              testing::Contains(testing::Key("X-ExtraHeaders")));
-  EXPECT_THAT(iter->second.headers,
-              testing::Contains(testing::Key("X-2ExtraHeaders")));
-}
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc
index b1c5597..5921227 100644
--- a/fuchsia/engine/context_provider_impl.cc
+++ b/fuchsia/engine/context_provider_impl.cc
@@ -121,21 +121,6 @@
   ignore_result(context_handle.release());
 }
 
-void ContextProviderImpl::Create2(
-    chromium::web::CreateContextParams2 params,
-    ::fidl::InterfaceRequest<chromium::web::Context> context_request) {
-  chromium::web::CreateContextParams converted_params;
-  if (params.has_service_directory()) {
-    converted_params.set_service_directory(
-        std::move(*params.mutable_service_directory()));
-  }
-  if (params.has_data_directory()) {
-    converted_params.set_data_directory(
-        std::move(*params.mutable_data_directory()));
-  }
-  Create(std::move(converted_params), std::move(context_request));
-}
-
 void ContextProviderImpl::Bind(
     fidl::InterfaceRequest<chromium::web::ContextProvider> request) {
   bindings_.AddBinding(this, std::move(request));
diff --git a/fuchsia/engine/context_provider_impl.h b/fuchsia/engine/context_provider_impl.h
index fd7c152..0f39756d 100644
--- a/fuchsia/engine/context_provider_impl.h
+++ b/fuchsia/engine/context_provider_impl.h
@@ -38,9 +38,6 @@
   void Create(chromium::web::CreateContextParams params,
               ::fidl::InterfaceRequest<chromium::web::Context> context_request)
       override;
-  void Create2(chromium::web::CreateContextParams2 params,
-               ::fidl::InterfaceRequest<chromium::web::Context> context_request)
-      override;
 
   // Sets a |launch| callback to use instead of calling LaunchProcess() to
   // create Context processes.
diff --git a/fuchsia/engine/context_provider_impl_unittest.cc b/fuchsia/engine/context_provider_impl_unittest.cc
index 1f1aa778..bd9e7bf 100644
--- a/fuchsia/engine/context_provider_impl_unittest.cc
+++ b/fuchsia/engine/context_provider_impl_unittest.cc
@@ -157,19 +157,6 @@
     return output;
   }
 
-  // TODO(crbug.com/931831): Remove this method once the transition is complete.
-  chromium::web::CreateContextParams2 BuildDeprecatedCreateContextParams() {
-    fidl::InterfaceHandle<fuchsia::io::Directory> directory;
-    zx_status_t result =
-        fdio_service_connect(base::fuchsia::kServiceDirectoryPath,
-                             directory.NewRequest().TakeChannel().release());
-    ZX_CHECK(result == ZX_OK, result) << "Failed to open /svc";
-
-    chromium::web::CreateContextParams2 output;
-    output.set_service_directory(std::move(directory));
-    return output;
-  }
-
   // Checks that the Context channel was dropped.
   void CheckContextUnresponsive(
       fidl::InterfacePtr<chromium::web::Context>* context) {
@@ -224,16 +211,6 @@
   CheckContextResponsive(&context);
 }
 
-// TODO(crbug.com/931831): Remove this test once the transition is complete.
-TEST_F(ContextProviderImplTest, DeprecatedLaunchContext) {
-  // Connect to a new context process.
-  fidl::InterfacePtr<chromium::web::Context> context;
-  chromium::web::CreateContextParams2 create_params =
-      BuildDeprecatedCreateContextParams();
-  provider_ptr_->Create2(std::move(create_params), context.NewRequest());
-  CheckContextResponsive(&context);
-}
-
 TEST_F(ContextProviderImplTest, MultipleConcurrentClients) {
   // Bind a Provider connection, and create a Context from it.
   chromium::web::ContextProviderPtr provider_1_ptr;
@@ -284,35 +261,6 @@
       profile_temp_dir.GetPath().AppendASCII(kTestDataFileOut)));
 }
 
-// TODO(crbug.com/931831): Remove this test once the transition is complete.
-TEST_F(ContextProviderImplTest, DeprecatedWithProfileDir) {
-  base::ScopedTempDir profile_temp_dir;
-
-  // Connect to a new context process.
-  fidl::InterfacePtr<chromium::web::Context> context;
-  chromium::web::CreateContextParams2 create_params =
-      BuildDeprecatedCreateContextParams();
-
-  // Setup data dir.
-  EXPECT_TRUE(profile_temp_dir.CreateUniqueTempDir());
-  ASSERT_EQ(
-      base::WriteFile(profile_temp_dir.GetPath().AppendASCII(kTestDataFileIn),
-                      nullptr, 0),
-      0);
-
-  // Pass a handle data dir to the context.
-  create_params.set_data_directory(
-      base::fuchsia::OpenDirectory(profile_temp_dir.GetPath()));
-
-  provider_ptr_->Create2(std::move(create_params), context.NewRequest());
-
-  CheckContextResponsive(&context);
-
-  // Verify that the context process can write to the data dir.
-  EXPECT_TRUE(base::PathExists(
-      profile_temp_dir.GetPath().AppendASCII(kTestDataFileOut)));
-}
-
 TEST_F(ContextProviderImplTest, FailsDataDirectoryIsFile) {
   base::FilePath temp_file_path;
 
diff --git a/fuchsia/fidl/web/context_provider.fidl b/fuchsia/fidl/web/context_provider.fidl
index 1092d64..26491fa 100644
--- a/fuchsia/fidl/web/context_provider.fidl
+++ b/fuchsia/fidl/web/context_provider.fidl
@@ -16,9 +16,6 @@
   /// context: An interface request which will receive a bound Context
   ///          service.
   Create(CreateContextParams params, request<Context> context);
-
-  // DEPRECATED Use Create instead.
-  Create2(CreateContextParams2 params, request<Context> context);
 };
 
 table CreateContextParams {
@@ -32,16 +29,3 @@
   /// stateless, with all of its data discarded upon Context destruction.
   2: fuchsia.io.Directory data_directory;
 };
-
-// DEPRECATED Use CreateContextParams instead.
-table CreateContextParams2 {
-  /// Service directory to be used by the context.
-  // TODO(https://crbug.com/870057): Document required and optional services
-  // that Context needs.
-  1: fuchsia.io.Directory service_directory;
-
-  /// Handle to the directory that will contain the Context's
-  /// persistent data. If it is left unset, then the created Context will be
-  /// stateless, with all of its data discarded upon Context destruction.
-  2: fuchsia.io.Directory data_directory;
-};
diff --git a/fuchsia/fidl/web/navigation_controller.fidl b/fuchsia/fidl/web/navigation_controller.fidl
index eb3e149..2ac1009 100644
--- a/fuchsia/fidl/web/navigation_controller.fidl
+++ b/fuchsia/fidl/web/navigation_controller.fidl
@@ -14,9 +14,6 @@
   ///           loaded (e.g. cookies, HTTP headers, etc.)
   LoadUrl(string url, LoadUrlParams params);
 
-  // DEPRECATED Use LoadUrl instead.
-  LoadUrl2(string url, LoadUrlParams2 params);
-
   GoBack();
   GoForward();
   Stop();
@@ -45,25 +42,6 @@
   4: vector<bytes> headers;
 };
 
-/// Additional parameters for modifying the behavior of LoadUrl().
-// DEPRECATED Use LoadUrlParams instead.
-table LoadUrlParams2 {
-  /// Provides a hint to the browser UI about how LoadUrl was triggered.
-  1: LoadUrlReason type;
-
-  /// The URL that linked to the resource being requested.
-  2: string referrer_url;
-
-  /// Should be set to true to propagate user activation to the frame. User
-  /// activation implies that the user is interacting with the web frame. It
-  /// enables some web features that are not available otherwise. For example
-  /// autoplay will work only when this flag is set to true.
-  3: bool was_user_activated;
-
-  /// Custom HTTP headers.
-  4: vector<bytes> headers;
-};
-
 /// Characterizes the origin of a LoadUrl request.
 enum LoadUrlReason {
   /// Navigation was initiated by the user following a link.
diff --git a/fuchsia/runners/common/web_content_runner.cc b/fuchsia/runners/common/web_content_runner.cc
index 80b9a91..aba2e03 100644
--- a/fuchsia/runners/common/web_content_runner.cc
+++ b/fuchsia/runners/common/web_content_runner.cc
@@ -36,7 +36,7 @@
       base::fuchsia::ServiceDirectoryClient::ForCurrentProcess()
           ->ConnectToService<chromium::web::ContextProvider>();
 
-  chromium::web::CreateContextParams2 create_params;
+  chromium::web::CreateContextParams create_params;
 
   // Pass /svc and /data to the context.
   create_params.set_service_directory(OpenDirectoryOrFail(
@@ -45,8 +45,8 @@
     create_params.set_data_directory(std::move(data_directory));
 
   chromium::web::ContextPtr web_context;
-  web_context_provider->Create2(std::move(create_params),
-                                web_context.NewRequest());
+  web_context_provider->Create(std::move(create_params),
+                               web_context.NewRequest());
   web_context.set_error_handler([](zx_status_t status) {
     // If the browser instance died, then exit everything and do not attempt
     // to recover. appmgr will relaunch the runner when it is needed again.
diff --git a/google_apis/build/check_internal.py b/google_apis/build/check_internal.py
index da0ddae..89514c53 100755
--- a/google_apis/build/check_internal.py
+++ b/google_apis/build/check_internal.py
@@ -8,6 +8,7 @@
 Takes one argument, a path.  Prints 1 if the path exists, 0 if not.
 """
 
+from __future__ import print_function
 
 import os
 import sys
@@ -15,6 +16,6 @@
 
 if __name__ == '__main__':
   if os.path.exists(sys.argv[1]):
-    print 1
+    print(1)
   else:
-    print 0
+    print(0)
diff --git a/gpu/command_buffer/service/external_vk_image_backing.cc b/gpu/command_buffer/service/external_vk_image_backing.cc
index 7a80d6f..d2dc343a 100644
--- a/gpu/command_buffer/service/external_vk_image_backing.cc
+++ b/gpu/command_buffer/service/external_vk_image_backing.cc
@@ -66,8 +66,8 @@
 bool ExternalVkImageBacking::BeginVulkanReadAccess(
     VkSemaphore* gl_write_finished_semaphore) {
   if (is_write_in_progress_) {
-    LOG(ERROR) << "Unable to begin read access for ExternalVkImageBacking "
-               << "because a write access is in progress";
+    LOG(ERROR) << "Unable to begin Vulkan read access because a write access "
+               << "is in progress";
     return false;
   }
   ++reads_in_progress_;
@@ -94,9 +94,14 @@
 
 bool ExternalVkImageBacking::BeginGlWriteAccess(
     VkSemaphore* vulkan_read_finished_semaphore) {
-  if (is_write_in_progress_ || reads_in_progress_) {
-    LOG(ERROR) << "Unable to begin write access for ExternalVkImageBacking "
-               << "because another read or write access is in progress";
+  if (is_write_in_progress_) {
+    LOG(ERROR) << "Unable to begin GL write access "
+               << "because another write access is in progress";
+    return false;
+  }
+  if (reads_in_progress_) {
+    LOG(ERROR) << "Unable to begin GL write access "
+               << "because a read access is in progress";
     return false;
   }
   is_write_in_progress_ = true;
@@ -120,8 +125,11 @@
 }
 
 bool ExternalVkImageBacking::BeginGlReadAccess() {
-  if (is_write_in_progress_)
+  if (is_write_in_progress_) {
+    LOG(ERROR) << "Unable to begin GL read access because a write access is in "
+               << "progress";
     return false;
+  }
   ++reads_in_progress_;
   return true;
 }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 9f11a25..8722070 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -10710,19 +10710,6 @@
                 " incompatible texture filtering.");
           }
           continue;
-        } else if (!texture_ref->texture()->CompatibleWithSamplerUniformType(
-                       uniform_info->type)) {
-          LOCAL_SET_GL_ERROR(
-              GL_INVALID_OPERATION, function_name,
-              (std::string("Texture bound to texture unit ") +
-               base::NumberToString(texture_unit_index) +
-               " with internal format " +
-               GLES2Util::GetStringEnum(
-                   texture_ref->texture()->GetInternalFormatOfBaseLevel()) +
-               " is not compatible with sampler type " +
-               GLES2Util::GetStringEnum(uniform_info->type))
-                  .c_str());
-          return false;
         }
 
         if (textarget != GL_TEXTURE_CUBE_MAP) {
diff --git a/gpu/ipc/service/DEPS b/gpu/ipc/service/DEPS
index 0f692245..2a760c7 100644
--- a/gpu/ipc/service/DEPS
+++ b/gpu/ipc/service/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+cc/paint",
+  "+components/crash/core/common/crash_key.h",
   "+components/viz/common/features.h",
   "+components/viz/common/resources/resource_format.h",
   "+third_party/skia",
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc
index 9a5ad2bef..ea3e326 100644
--- a/gpu/ipc/service/direct_composition_surface_win.cc
+++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -19,6 +19,7 @@
 #include "base/win/scoped_handle.h"
 #include "base/win/windows_types.h"
 #include "base/win/windows_version.h"
+#include "components/crash/core/common/crash_key.h"
 #include "gpu/command_buffer/service/feature_info.h"
 #include "gpu/config/gpu_finch_features.h"
 #include "gpu/ipc/service/direct_composition_child_surface_win.h"
@@ -759,6 +760,10 @@
     return false;
   }
 
+  static crash_reporter::CrashKeyString<32> texture_size_key(
+      "video-texture-size");
+  texture_size_key.Set(texture_size.ToString());
+
   if (!staging_texture_ || (staging_texture_size_ != texture_size)) {
     staging_texture_.Reset();
     D3D11_TEXTURE2D_DESC desc = {};
diff --git a/ios/chrome/app/DEPS b/ios/chrome/app/DEPS
index 8c2ddbfb..7ab3eb3 100644
--- a/ios/chrome/app/DEPS
+++ b/ios/chrome/app/DEPS
@@ -35,13 +35,3 @@
   "+components/strings",
   "+ios/chrome/grit",
 ]
-
-specific_include_rules = {
-  "main_controller.mm": [
-    # TODO(crbug.com/585700): Remove ios/web/net exceptions, once request
-    # tracker is removed.
-    "+ios/web/net/request_tracker_factory_impl.h",
-    "+ios/web/net/request_tracker_impl.h",
-    "+ios/web/net/web_http_protocol_handler_delegate.h",
-  ],
-}
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 5f5e905c..87bf01d1 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -53,7 +53,6 @@
 #include "ios/chrome/app/startup/client_registration.h"
 #import "ios/chrome/app/startup/content_suggestions_scheduler_notifications.h"
 #include "ios/chrome/app/startup/ios_chrome_main.h"
-#include "ios/chrome/app/startup/network_stack_setup.h"
 #include "ios/chrome/app/startup/provider_registration.h"
 #include "ios/chrome/app/startup/register_experimental_settings.h"
 #include "ios/chrome/app/startup/setup_debugging.h"
@@ -145,6 +144,7 @@
 #include "ios/chrome/common/app_group/app_group_utils.h"
 #include "ios/net/cookies/cookie_store_ios.h"
 #import "ios/net/crn_http_protocol_handler.h"
+#import "ios/net/empty_nsurlcache.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 #include "ios/public/provider/chrome/browser/distribution/app_distribution_provider.h"
 #include "ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h"
@@ -153,12 +153,10 @@
 #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
 #import "ios/third_party/material_roboto_font_loader_ios/src/src/MDCTypographyAdditions/MDFRobotoFontLoader+MDCTypographyAdditions.h"
 #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h"
-#include "ios/web/net/request_tracker_factory_impl.h"
-#include "ios/web/net/request_tracker_impl.h"
-#include "ios/web/net/web_http_protocol_handler_delegate.h"
 #import "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
 #import "ios/web/public/web_state/web_state.h"
+#include "ios/web/public/web_task_traits.h"
 #import "ios/web/public/web_view_creation_util.h"
 #include "ios/web/public/webui/web_ui_ios_controller_factory.h"
 #include "mojo/core/embedder/embedder.h"
@@ -363,13 +361,6 @@
   // An object to record metrics related to the user's first action.
   std::unique_ptr<FirstUserActionRecorder> _firstUserActionRecorder;
 
-  // RequestTrackerFactory to customize the behavior of the network stack.
-  std::unique_ptr<web::RequestTrackerFactoryImpl> _requestTrackerFactory;
-
-  // Configuration for the HTTP protocol handler.
-  std::unique_ptr<web::WebHTTPProtocolHandlerDelegate>
-      _httpProtocolHandlerDelegate;
-
   // True if First Run UI (terms of service & sync sign-in) is being presented
   // in a modal dialog.
   BOOL _isPresentingFirstRunUI;
@@ -682,11 +673,7 @@
   web::WebUIIOSControllerFactory::RegisterFactory(
       ChromeWebUIIOSControllerFactory::GetInstance());
 
-  // TODO(crbug.com/546171): Audit all the following code to see if some of it
-  // should move into BrowserMainParts or BrowserProcess.
-
-  [NetworkStackSetup setUpChromeNetworkStack:&_requestTrackerFactory
-                 httpProtocolHandlerDelegate:&_httpProtocolHandlerDelegate];
+  [NSURLCache setSharedURLCache:[EmptyNSURLCache emptyNSURLCache]];
 }
 
 - (void)startUpBrowserForegroundInitialization {
@@ -990,7 +977,6 @@
   _historyCoordinator = nil;
 
   [_mainCoordinator stop];
-  _httpProtocolHandlerDelegate.reset();
 
   ios::GetChromeBrowserProvider()
       ->GetMailtoHandlerProvider()
@@ -1958,13 +1944,11 @@
   [self clearIOSSpecificIncognitoData];
 
   // OffTheRecordProfileIOData cannot be deleted before all the requests are
-  // deleted. All of the request trackers associated with the closed OTR tabs
-  // will have posted CancelRequest calls to the IO thread by now; this just
-  // waits for those calls to run before calling
-  // |destroyAndRebuildIncognitoBrowserState|.
-  web::RequestTrackerImpl::RunAfterRequestsCancel(base::BindRepeating(^{
-    [self destroyAndRebuildIncognitoBrowserState];
-  }));
+  // deleted. Queue browser state recreation on IO thread.
+  base::PostTaskWithTraitsAndReply(
+      FROM_HERE, {web::WebThread::IO}, base::DoNothing(), base::BindRepeating(^{
+        [self destroyAndRebuildIncognitoBrowserState];
+      }));
 
   // a) The first condition can happen when the last incognito tab is closed
   // from the tab switcher.
diff --git a/ios/chrome/app/startup/BUILD.gn b/ios/chrome/app/startup/BUILD.gn
index e85121be..67cd14fc 100644
--- a/ios/chrome/app/startup/BUILD.gn
+++ b/ios/chrome/app/startup/BUILD.gn
@@ -41,8 +41,6 @@
     "client_registration.mm",
     "content_suggestions_scheduler_notifications.h",
     "content_suggestions_scheduler_notifications.mm",
-    "network_stack_setup.h",
-    "network_stack_setup.mm",
     "provider_registration.h",
     "provider_registration.mm",
   ]
@@ -59,7 +57,6 @@
     "//ios/chrome/browser/first_run",
     "//ios/chrome/browser/net:net",
     "//ios/chrome/browser/ntp_snippets",
-    "//ios/chrome/browser/web",
     "//ios/chrome/browser/web:web_internal",
     "//ios/chrome/common",
     "//ios/chrome/common/app_group",
diff --git a/ios/chrome/app/startup/DEPS b/ios/chrome/app/startup/DEPS
deleted file mode 100644
index 4444723..0000000
--- a/ios/chrome/app/startup/DEPS
+++ /dev/null
@@ -1,9 +0,0 @@
-specific_include_rules = {
-  "network_stack_setup.mm": [
-    # TODO(crbug.com/585700): Remove ios/web/net exceptions, once request
-    # tracker is removed.
-    "+ios/web/net/request_tracker_factory_impl.h",
-    "+ios/web/net/request_tracker_impl.h",
-    "+ios/web/net/web_http_protocol_handler_delegate.h",
-  ],
-}
diff --git a/ios/chrome/app/startup/network_stack_setup.h b/ios/chrome/app/startup/network_stack_setup.h
deleted file mode 100644
index 8bdfbe0c7..0000000
--- a/ios/chrome/app/startup/network_stack_setup.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_APP_STARTUP_NETWORK_STACK_SETUP_H_
-#define IOS_CHROME_APP_STARTUP_NETWORK_STACK_SETUP_H_
-
-#import <UIKit/UIKit.h>
-
-#import <memory>
-
-namespace web {
-class RequestTrackerFactoryImpl;
-class WebHTTPProtocolHandlerDelegate;
-}  // namespace web
-
-@interface NetworkStackSetup : NSObject
-
-// Sets up the network stack: protocol handler and cache.
-// TODO(crbug.com/585700): Remove the first parameter.
-+ (void)setUpChromeNetworkStack:
-            (std::unique_ptr<web::RequestTrackerFactoryImpl>*)
-                requestTrackerFactory
-    httpProtocolHandlerDelegate:
-        (std::unique_ptr<web::WebHTTPProtocolHandlerDelegate>*)
-            httpProtocolHandlerDelegate;
-
-@end
-
-#endif  // IOS_CHROME_APP_STARTUP_NETWORK_STACK_SETUP_H_
diff --git a/ios/chrome/app/startup/network_stack_setup.mm b/ios/chrome/app/startup/network_stack_setup.mm
deleted file mode 100644
index 9b81f7b..0000000
--- a/ios/chrome/app/startup/network_stack_setup.mm
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ios/chrome/app/startup/network_stack_setup.h"
-
-#include <memory>
-
-#include "ios/chrome/browser/application_context.h"
-#include "ios/chrome/browser/chrome_url_constants.h"
-#import "ios/net/empty_nsurlcache.h"
-#include "ios/web/net/request_tracker_factory_impl.h"
-#include "ios/web/net/web_http_protocol_handler_delegate.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@implementation NetworkStackSetup
-
-+ (void)setUpChromeNetworkStack:
-            (std::unique_ptr<web::RequestTrackerFactoryImpl>*)
-                requestTrackerFactory
-    httpProtocolHandlerDelegate:
-        (std::unique_ptr<web::WebHTTPProtocolHandlerDelegate>*)
-            httpProtocolHandlerDelegate {
-  // Disable the default cache.
-  [NSURLCache setSharedURLCache:[EmptyNSURLCache emptyNSURLCache]];
-
-  // Configuration for the HTTP protocol handler.
-  //  TODO(crbug.com/585700): Remove this code.
-  *httpProtocolHandlerDelegate =
-      std::make_unique<web::WebHTTPProtocolHandlerDelegate>(
-          GetApplicationContext()->GetSystemURLRequestContext());
-  net::HTTPProtocolHandlerDelegate::SetInstance(
-      httpProtocolHandlerDelegate->get());
-
-  // Register the chrome http protocol handler to replace the default one.
-  // TODO(crbug.com/665036): Move the network stack initialization to the web
-  // layer.
-  BOOL success = [NSURLProtocol registerClass:[CRNHTTPProtocolHandler class]];
-  DCHECK(success);
-  *requestTrackerFactory =
-      std::make_unique<web::RequestTrackerFactoryImpl>(kChromeUIScheme);
-  net::RequestTracker::SetRequestTrackerFactory(requestTrackerFactory->get());
-
-  DCHECK(success);
-}
-
-@end
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index 50de8e3..a4d7e8a 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -306,6 +306,7 @@
     "//ios/chrome/browser/ui/alert_coordinator",
     "//ios/chrome/browser/ui/autofill:autofill",
     "//ios/chrome/browser/ui/autofill/manual_fill",
+    "//ios/chrome/browser/ui/autofill/manual_fill:manual_fill_ui",
     "//ios/chrome/browser/ui/bookmarks",
     "//ios/chrome/browser/ui/browser_container",
     "//ios/chrome/browser/ui/browser_container:ui",
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm b/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm
index 2fef18231..f8c26c43 100644
--- a/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm
+++ b/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm
@@ -23,8 +23,8 @@
 #import "ios/chrome/browser/autofill/form_suggestion_view.h"
 #import "ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h"
 #import "ios/chrome/browser/passwords/password_generation_utils.h"
-#import "ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.h"
 #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
+#import "ios/chrome/browser/ui/util/keyboard_observer_helper.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
 #import "ios/web/public/url_scheme_util.h"
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn b/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn
index 3cbd60d..29014be 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn
+++ b/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn
@@ -82,8 +82,6 @@
     "credit_card.mm",
     "fallback_view_controller.h",
     "fallback_view_controller.mm",
-    "keyboard_observer_helper.h",
-    "keyboard_observer_helper.mm",
     "manual_fill_accessory_view_controller.h",
     "manual_fill_accessory_view_controller.mm",
     "manual_fill_address_cell.h",
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
index b8919c50..4ef192c 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
@@ -7,7 +7,7 @@
 #include "base/mac/foundation_util.h"
 #include "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
-#import "ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.h"
+#import "ios/chrome/browser/ui/util/keyboard_observer_helper.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/app/tab_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 4ac43485..113fb066 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -149,6 +149,7 @@
 #import "ios/chrome/browser/ui/toolbar_container/toolbar_container_coordinator.h"
 #import "ios/chrome/browser/ui/toolbar_container/toolbar_container_features.h"
 #include "ios/chrome/browser/ui/ui_feature_flags.h"
+#import "ios/chrome/browser/ui/util/keyboard_observer_helper.h"
 #import "ios/chrome/browser/ui/util/named_guide.h"
 #import "ios/chrome/browser/ui/util/named_guide_util.h"
 #import "ios/chrome/browser/ui/util/page_animation_util.h"
@@ -622,6 +623,9 @@
 // Whether the safe area insets should be used to adjust the viewport.
 @property(nonatomic, readonly) BOOL usesSafeInsetsForViewportAdjustments;
 
+// Whether the keyboard observer helper is viewed
+@property(nonatomic, strong) KeyboardObserverHelper* observer;
+
 // BVC initialization
 // ------------------
 // If the BVC is initialized with a valid browser state & tab model immediately,
@@ -817,6 +821,7 @@
 
     _footerFullscreenProgress = 1.0;
 
+    _observer = [[KeyboardObserverHelper alloc] init];
     if (model && browserState)
       [self updateWithTabModel:model browserState:browserState];
   }
@@ -1463,11 +1468,18 @@
   if (![self shouldRegisterKeyboardCommands]) {
     return nil;
   }
+
+  UIResponder* firstResponder = GetFirstResponder();
+
   return [self.keyCommandsProvider
       keyCommandsForConsumer:self
           baseViewController:self
                   dispatcher:self.dispatcher
-                 editingText:![self isFirstResponder]];
+                 editingText:[firstResponder
+                                 isKindOfClass:[UITextField class]] ||
+                             [firstResponder
+                                 isKindOfClass:[UITextView class]] ||
+                             [self.observer isKeyboardOnScreen]];
 }
 
 #pragma mark - UIResponder helpers
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
index d5186a2..26ead77 100644
--- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -258,6 +258,7 @@
     "//ios/chrome/browser/ui/tab_grid:egtest_support",
     "//ios/chrome/browser/ui/toolbar/buttons",
     "//ios/chrome/browser/ui/toolbar/public",
+    "//ios/chrome/test:test_support",
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/base:base",
     "//ios/chrome/test/earl_grey:test_support",
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
index 41b8ef7..425f9159 100644
--- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
+++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -47,6 +47,7 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
+#import "ios/chrome/test/scoped_eg_synchronization_disabler.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -643,9 +644,6 @@
 }
 
 - (void)testOpeningNewTab {
-  // TODO(crbug.com/933953): Re-enable this test when grey_tap() issue is fixed.
-  EARL_GREY_TEST_DISABLED(@"Disabled due to full-configs and slimnav failures");
-
   [ChromeEarlGreyUI openNewTab];
 
   // Check that the fake omnibox is here.
@@ -665,7 +663,14 @@
                             [NSString stringWithFormat:@"%i", 2])];
 
   // Test the same thing after opening a tab from the tab grid.
-  [[EarlGrey selectElementWithMatcher:tabGridMatcher] performAction:grey_tap()];
+  // TODO(crbug.com/933953) For an unknown reason synchronization doesn't work
+  // well with tapping on the tabgrid button, and instead triggers the long
+  // press gesture recognizer.  Disable this here so the test can be re-enabled.
+  {
+    ScopedSynchronizationDisabler disabler;
+    [[EarlGrey selectElementWithMatcher:tabGridMatcher]
+        performAction:[GREYActions actionForLongPressWithDuration:0.05]];
+  }
   [[EarlGrey selectElementWithMatcher:chrome_test_util::TabGridNewTabButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h b/ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h
index 907ffb2..bf5479d 100644
--- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h
+++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h
@@ -11,7 +11,7 @@
 @protocol InfobarBannerDelegate
 
 // Called when the InfobarBanner button was pressed.
-- (void)bannerInfobarButtonWasPressed:(UIViewController*)sender;
+- (void)bannerInfobarButtonWasPressed:(UIButton*)sender;
 
 // Asks the delegate to dismiss the InfobarBanner.
 - (void)dismissInfobarBanner:(UIViewController*)sender;
diff --git a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn
index 8364489..2d0231a4 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn
+++ b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn
@@ -21,5 +21,6 @@
     "//ios/chrome/browser/ui/infobars/banners",
     "//ios/chrome/browser/ui/infobars/modals",
     "//ios/chrome/browser/ui/infobars/presentation",
+    "//ios/chrome/browser/ui/table_view",
   ]
 }
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
index 09161e67..f989fc6 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
@@ -155,6 +155,11 @@
   }
 }
 
+- (void)modalInfobarButtonWasPressed:(UIButton*)sender {
+  // TODO(crbug.com/911864): NO-OP. There's still no defined design for a
+  // ConfirmInfobarModal.
+}
+
 #pragma mark - Private
 
 - (void)presentInfobarModalFrom:(UIViewController*)presentingViewController
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
index 8891767..0ca89764 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
@@ -12,8 +12,10 @@
 #import "ios/chrome/browser/ui/infobars/infobar_badge_ui_delegate.h"
 #import "ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h"
 #import "ios/chrome/browser/ui/infobars/modals/infobar_modal_view_controller.h"
+#import "ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h"
 #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.h"
 #import "ios/chrome/browser/ui/infobars/presentation/infobar_modal_transition_driver.h"
+#import "ios/chrome/browser/ui/table_view/table_view_navigation_controller.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -27,8 +29,9 @@
     IOSChromePasswordManagerInfoBarDelegate* passwordInfoBarDelegate;
 // InfobarBannerViewController owned by this Coordinator.
 @property(nonatomic, strong) InfobarBannerViewController* bannerViewController;
-// InfobarModalViewController owned by this Coordinator.
-@property(nonatomic, strong) InfobarModalViewController* modalViewController;
+// InfobarPasswordTableViewController owned by this Coordinator.
+@property(nonatomic, strong)
+    InfobarPasswordTableViewController* modalViewController;
 
 @end
 
@@ -112,7 +115,7 @@
 
 #pragma mark - InfobarBannerDelegate
 
-- (void)bannerInfobarButtonWasPressed:(id)sender {
+- (void)bannerInfobarButtonWasPressed:(UIButton*)sender {
   self.passwordInfoBarDelegate->Accept();
   [self.badgeDelegate infobarWasAccepted];
   [self dismissInfobarBanner:self.bannerViewController];
@@ -158,20 +161,29 @@
   }
 }
 
+- (void)modalInfobarButtonWasPressed:(UIButton*)sender {
+  self.passwordInfoBarDelegate->Accept();
+  [self.badgeDelegate infobarWasAccepted];
+  [self dismissInfobarModal:sender];
+}
+
 #pragma mark - Private
 
 - (void)presentInfobarModalFrom:(UIViewController*)presentingViewController
                          driver:(InfobarModalTransitionDriver*)driver {
-  self.modalViewController =
-      [[InfobarModalViewController alloc] initWithModalDelegate:self];
+  self.modalViewController = [[InfobarPasswordTableViewController alloc]
+      initWithTableViewStyle:UITableViewStylePlain
+                 appBarStyle:ChromeTableViewControllerStyleNoAppBar];
   self.modalViewController.title =
       base::SysUTF16ToNSString(self.passwordInfoBarDelegate->GetMessageText());
+  self.modalViewController.infobarModalDelegate = self;
 
-  UINavigationController* navController = [[UINavigationController alloc]
-      initWithRootViewController:self.modalViewController];
-  navController.transitioningDelegate = driver;
-  navController.modalPresentationStyle = UIModalPresentationCustom;
-  [presentingViewController presentViewController:navController
+  TableViewNavigationController* navigationController =
+      [[TableViewNavigationController alloc]
+          initWithTable:self.modalViewController];
+  navigationController.transitioningDelegate = driver;
+  navigationController.modalPresentationStyle = UIModalPresentationCustom;
+  [presentingViewController presentViewController:navigationController
                                          animated:YES
                                        completion:nil];
   [self.badgeDelegate infobarModalWasPresented];
diff --git a/ios/chrome/browser/ui/infobars/modals/BUILD.gn b/ios/chrome/browser/ui/infobars/modals/BUILD.gn
index 31837bc..6729466 100644
--- a/ios/chrome/browser/ui/infobars/modals/BUILD.gn
+++ b/ios/chrome/browser/ui/infobars/modals/BUILD.gn
@@ -8,5 +8,12 @@
     "infobar_modal_delegate.h",
     "infobar_modal_view_controller.h",
     "infobar_modal_view_controller.mm",
+    "infobar_password_table_view_controller.h",
+    "infobar_password_table_view_controller.mm",
+  ]
+  deps = [
+    "//base",
+    "//ios/chrome/browser/ui/table_view",
+    "//ios/chrome/browser/ui/table_view:styler",
   ]
 }
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h b/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h
index 503fff8..7185e032 100644
--- a/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h
+++ b/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h
@@ -13,6 +13,9 @@
 // Asks the delegate to dismiss the InfobarModal.
 - (void)dismissInfobarModal:(UIButton*)sender;
 
+// Called when the InfobarModal "Accept" button was pressed.
+- (void)modalInfobarButtonWasPressed:(UIButton*)sender;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_INFOBARS_MODALS_INFOBAR_MODAL_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h
new file mode 100644
index 0000000..775e0ae
--- /dev/null
+++ b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h
@@ -0,0 +1,21 @@
+// Copyright 2019 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 IOS_CHROME_BROWSER_UI_INFOBARS_MODALS_INFOBAR_PASSWORD_TABLE_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_INFOBARS_MODALS_INFOBAR_PASSWORD_TABLE_VIEW_CONTROLLER_H_
+
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h"
+
+@protocol InfobarModalDelegate;
+
+// InfobarPasswordTableViewController represents the content for the Passwords
+// InfobarModal.
+@interface InfobarPasswordTableViewController : ChromeTableViewController
+
+// InfobarModalDelegate for this ViewController.
+@property(strong, nonatomic) id<InfobarModalDelegate> infobarModalDelegate;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_INFOBARS_MODALS_INFOBAR_PASSWORD_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm
new file mode 100644
index 0000000..13d15dad
--- /dev/null
+++ b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm
@@ -0,0 +1,119 @@
+// Copyright 2019 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.
+
+#import "ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h"
+
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#import "ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h"
+#import "ios/chrome/browser/ui/table_view/cells/settings_detail_item.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.h"
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+typedef NS_ENUM(NSInteger, SectionIdentifier) {
+  SectionIdentifierContent = kSectionIdentifierEnumZero,
+};
+
+typedef NS_ENUM(NSInteger, ItemType) {
+  ItemTypeURL = kItemTypeEnumZero,
+  ItemTypeUsername,
+  ItemTypePassword,
+  ItemTypeSavePassword,
+};
+
+@implementation InfobarPasswordTableViewController
+
+#pragma mark - ViewController Lifecycle
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  self.view.backgroundColor = [UIColor whiteColor];
+  self.styler.cellBackgroundColor = [UIColor whiteColor];
+  self.tableView.scrollEnabled = NO;
+  self.tableView.sectionHeaderHeight = 0;
+  [self.tableView
+      setSeparatorInset:UIEdgeInsetsMake(0, kTableViewHorizontalSpacing, 0, 0)];
+
+  // Configure the NavigationBar.
+  UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc]
+      initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
+                           target:self.infobarModalDelegate
+                           action:@selector(dismissInfobarModal:)];
+  UIImage* settingsImage = [[UIImage imageNamed:@"infobar_settings_icon"]
+      imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+  UIBarButtonItem* settingsButton =
+      [[UIBarButtonItem alloc] initWithImage:settingsImage
+                                       style:UIBarButtonItemStylePlain
+                                      target:self
+                                      action:nil];
+  self.navigationItem.leftBarButtonItem = cancelButton;
+  self.navigationItem.rightBarButtonItem = settingsButton;
+  self.navigationController.navigationBar.prefersLargeTitles = NO;
+
+  [self loadModel];
+}
+
+#pragma mark - TableViewModel
+
+- (void)loadModel {
+  [super loadModel];
+
+  TableViewModel* model = self.tableViewModel;
+  [model addSectionWithIdentifier:SectionIdentifierContent];
+
+  SettingsDetailItem* URLDetailItem =
+      [[SettingsDetailItem alloc] initWithType:ItemTypeURL];
+  URLDetailItem.text = @"URL";
+  URLDetailItem.detailText = @"www.twitter.com";
+  [model addItem:URLDetailItem
+      toSectionWithIdentifier:SectionIdentifierContent];
+
+  SettingsDetailItem* usernameDetailItem =
+      [[SettingsDetailItem alloc] initWithType:ItemTypeUsername];
+  usernameDetailItem.text = @"Username";
+  usernameDetailItem.detailText = @"martijnb@google.com";
+  [model addItem:usernameDetailItem
+      toSectionWithIdentifier:SectionIdentifierContent];
+
+  SettingsDetailItem* passwordDetailItem =
+      [[SettingsDetailItem alloc] initWithType:ItemTypePassword];
+  passwordDetailItem.text = @"Password";
+  passwordDetailItem.detailText = @"********";
+  [model addItem:passwordDetailItem
+      toSectionWithIdentifier:SectionIdentifierContent];
+
+  TableViewTextButtonItem* savePasswordButtonItem =
+      [[TableViewTextButtonItem alloc] initWithType:ItemTypeSavePassword];
+  savePasswordButtonItem.buttonText = @"Save Password";
+  [model addItem:savePasswordButtonItem
+      toSectionWithIdentifier:SectionIdentifierContent];
+}
+
+#pragma mark - UITableViewDataSource
+
+- (UITableViewCell*)tableView:(UITableView*)tableView
+        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
+  UITableViewCell* cell = [super tableView:tableView
+                     cellForRowAtIndexPath:indexPath];
+  NSInteger itemTypeSelected =
+      [self.tableViewModel itemTypeForIndexPath:indexPath];
+
+  if (itemTypeSelected == ItemTypeSavePassword) {
+    TableViewTextButtonCell* tableViewTextButtonCell =
+        base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell);
+    [tableViewTextButtonCell.button
+               addTarget:self.infobarModalDelegate
+                  action:@selector(modalInfobarButtonWasPressed:)
+        forControlEvents:UIControlEventTouchUpInside];
+  }
+
+  return cell;
+}
+
+@end
diff --git a/ios/chrome/browser/ui/key_commands_provider.mm b/ios/chrome/browser/ui/key_commands_provider.mm
index f365fbe..8fca47b7 100644
--- a/ios/chrome/browser/ui/key_commands_provider.mm
+++ b/ios/chrome/browser/ui/key_commands_provider.mm
@@ -8,8 +8,10 @@
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
 #import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h"
+#import "ios/chrome/browser/ui/util/keyboard_observer_helper.h"
 #import "ios/chrome/browser/ui/util/named_guide.h"
 #include "ios/chrome/browser/ui/util/rtl_geometry.h"
+#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
@@ -20,12 +22,12 @@
 @implementation KeyCommandsProvider
 
 - (NSArray*)
-keyCommandsForConsumer:(id<KeyCommandsPlumbing>)consumer
-    baseViewController:(UIViewController*)baseViewController
-            dispatcher:
-                (id<ApplicationCommands, BrowserCommands, OmniboxFocuser>)
-                    dispatcher
-           editingText:(BOOL)editingText {
+    keyCommandsForConsumer:(id<KeyCommandsPlumbing>)consumer
+        baseViewController:(UIViewController*)baseViewController
+                dispatcher:
+                    (id<ApplicationCommands, BrowserCommands, OmniboxFocuser>)
+                        dispatcher
+               editingText:(BOOL)editingText {
   __weak id<KeyCommandsPlumbing> weakConsumer = consumer;
   __weak UIViewController* weakBaseViewController = baseViewController;
   __weak id<ApplicationCommands, BrowserCommands, OmniboxFocuser>
@@ -335,13 +337,12 @@
                           action:^{
                             [weakConsumer focusPreviousTab];
                           }],
-      [UIKeyCommand
-          cr_keyCommandWithInput:@"\t"
-                   modifierFlags:UIKeyModifierControl
-                           title:nil
-                          action:^{
-                            [weakConsumer focusNextTab];
-                          }],
+      [UIKeyCommand cr_keyCommandWithInput:@"\t"
+                             modifierFlags:UIKeyModifierControl
+                                     title:nil
+                                    action:^{
+                                      [weakConsumer focusNextTab];
+                                    }],
     ]];
   }
 
diff --git a/ios/chrome/browser/ui/translate/cells/translate_popup_menu_item.mm b/ios/chrome/browser/ui/translate/cells/translate_popup_menu_item.mm
index 1dc8c9b9..1535287 100644
--- a/ios/chrome/browser/ui/translate/cells/translate_popup_menu_item.mm
+++ b/ios/chrome/browser/ui/translate/cells/translate_popup_menu_item.mm
@@ -157,7 +157,9 @@
 
 - (void)prepareForReuse {
   [super prepareForReuse];
-  // Clear UIAccessibilityTraitSelected from the accessibility traits, if any.
+  // Hide the checkmark and clear UIAccessibilityTraitSelected from the
+  // accessibility traits, if applicable.
+  self.checkmarkView.hidden = YES;
   self.accessibilityTraits &= ~UIAccessibilityTraitSelected;
   self.selected = NO;
   [self setTitle:nil];
diff --git a/ios/chrome/browser/ui/translate/language_selection_coordinator.mm b/ios/chrome/browser/ui/translate/language_selection_coordinator.mm
index 8b413b0..320c9b3a 100644
--- a/ios/chrome/browser/ui/translate/language_selection_coordinator.mm
+++ b/ios/chrome/browser/ui/translate/language_selection_coordinator.mm
@@ -108,12 +108,12 @@
   [self.selectionDelegate
       languageSelectorSelectedLanguage:
           [self.selectionMediator languageCodeForLanguageAtIndex:index]];
-  [self.presenter dismissAnimated:YES];
+  [self.presenter dismissAnimated:NO];
 }
 
 - (void)languageSelectionCanceled {
   [self.selectionDelegate languageSelectorClosedWithoutSelection];
-  [self.presenter dismissAnimated:YES];
+  [self.presenter dismissAnimated:NO];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/util/BUILD.gn b/ios/chrome/browser/ui/util/BUILD.gn
index 0d59753..98a3656c 100644
--- a/ios/chrome/browser/ui/util/BUILD.gn
+++ b/ios/chrome/browser/ui/util/BUILD.gn
@@ -17,6 +17,8 @@
     "force_touch_long_press_gesture_recognizer.mm",
     "i18n_string.h",
     "i18n_string.mm",
+    "keyboard_observer_helper.h",
+    "keyboard_observer_helper.mm",
     "label_link_controller.h",
     "label_link_controller.mm",
     "label_observer.h",
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.h b/ios/chrome/browser/ui/util/keyboard_observer_helper.h
similarity index 78%
rename from ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.h
rename to ios/chrome/browser/ui/util/keyboard_observer_helper.h
index c9bad9def..53578e6 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.h
+++ b/ios/chrome/browser/ui/util/keyboard_observer_helper.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_KEYBOARD_OBSERVER_HELPER_H_
-#define IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_KEYBOARD_OBSERVER_HELPER_H_
+#ifndef IOS_CHROME_BROWSER_UI_UTIL_KEYBOARD_OBSERVER_HELPER_H_
+#define IOS_CHROME_BROWSER_UI_UTIL_KEYBOARD_OBSERVER_HELPER_H_
 
 #import <UIKit/UIKit.h>
 
@@ -29,9 +29,12 @@
 // Helper to observe the keyboard and report updates.
 @interface KeyboardObserverHelper : NSObject
 
+// Flag that indicates if the keyboard is on screen.
+@property(nonatomic, readonly, getter=isKeyboardOnScreen) BOOL keyboardOnScreen;
+
 // The consumer to inform of the keyboard state changes.
 @property(nonatomic, weak) id<KeyboardObserverHelperConsumer> consumer;
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_KEYBOARD_OBSERVER_HELPER_H_
+#endif  // IOS_CHROME_BROWSER_UI_UTIL_KEYBOARD_OBSERVER_HELPER_H_
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.mm b/ios/chrome/browser/ui/util/keyboard_observer_helper.mm
similarity index 95%
rename from ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.mm
rename to ios/chrome/browser/ui/util/keyboard_observer_helper.mm
index 6de288d..bbf637ac 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.mm
+++ b/ios/chrome/browser/ui/util/keyboard_observer_helper.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.h"
+#import "ios/chrome/browser/ui/util/keyboard_observer_helper.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -11,7 +11,8 @@
 @interface KeyboardObserverHelper ()
 
 // Flag that indicates if the keyboard is on screen.
-@property(nonatomic, getter=isKeyboardOnScreen) BOOL keyboardOnScreen;
+@property(nonatomic, readwrite, getter=isKeyboardOnScreen)
+    BOOL keyboardOnScreen;
 
 // Flag that indicates if the next keyboard did hide notification should be
 // ignored. This happens when the keyboard is on screen and the device rotates.
diff --git a/ios/showcase/omnibox_popup/BUILD.gn b/ios/showcase/omnibox_popup/BUILD.gn
index cfaf6be..cab3a87 100644
--- a/ios/showcase/omnibox_popup/BUILD.gn
+++ b/ios/showcase/omnibox_popup/BUILD.gn
@@ -10,9 +10,12 @@
     "sc_omnibox_popup_container_view_controller.mm",
     "sc_omnibox_popup_coordinator.h",
     "sc_omnibox_popup_coordinator.mm",
+    "sc_omnibox_popup_mediator.h",
+    "sc_omnibox_popup_mediator.mm",
   ]
   deps = [
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
+    "//ios/chrome/browser/ui/omnibox:omnibox_util",
     "//ios/chrome/browser/ui/omnibox/popup",
     "//ios/chrome/browser/ui/toolbar/buttons",
     "//ios/chrome/common/ui_util",
diff --git a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h
index b1a18e2..58ca099 100644
--- a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h
+++ b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h
@@ -8,8 +8,22 @@
 #import <UIKit/UIKit.h>
 
 #import "ios/chrome/browser/ui/omnibox/autocomplete_suggestion.h"
+#import "ios/chrome/browser/ui/omnibox/omnibox_util.h"
 
+// Fake class implementing AutocompleteSuggestion for Showcase.
 @interface FakeAutocompleteSuggestion : NSObject <AutocompleteSuggestion>
+
+@property(nonatomic) BOOL supportsDeletion;
+@property(nonatomic) BOOL hasAnswer;
+@property(nonatomic) BOOL isURL;
+@property(nonatomic) BOOL isAppendable;
+@property(nonatomic) BOOL isTabMatch;
+@property(nonatomic) NSAttributedString* text;
+@property(nonatomic) NSAttributedString* detailText;
+@property(nonatomic) NSInteger numberOfLines;
+@property(nonatomic) OmniboxSuggestionIconType iconType;
+@property(nonatomic) GURL imageURL;
+
 @end
 
 #endif  // IOS_SHOWCASE_OMNIBOX_POPUP_FAKE_AUTOCOMPLETE_SUGGESTION_H_
diff --git a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
index 4efb80429..2409c83 100644
--- a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
+++ b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
@@ -12,52 +12,25 @@
 
 @implementation FakeAutocompleteSuggestion
 
-- (BOOL)supportsDeletion {
-  return NO;
-}
-
-- (BOOL)hasAnswer {
-  return NO;
-}
-
-- (BOOL)isURL {
-  return YES;
-}
-
-- (BOOL)isAppendable {
-  return YES;
-}
-
-- (int)imageID {
-  return 0;
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _isURL = YES;
+    _text = [[NSAttributedString alloc] initWithString:@""];
+    _detailText = [[NSAttributedString alloc] initWithString:@""];
+    _numberOfLines = 1;
+    _iconType = DEFAULT_FAVICON;
+    _imageURL = GURL();
+  }
+  return self;
 }
 
 - (UIImage*)suggestionTypeIcon {
-  return nil;
-}
-
-- (BOOL)isTabMatch {
-  return NO;
-}
-
-- (NSAttributedString*)text {
-  return [[NSAttributedString alloc] initWithString:@"Test"];
-}
-
-- (NSAttributedString*)detailText {
-  return [[NSAttributedString alloc] initWithString:@"Test 2"];
-}
-
-- (NSInteger)numberOfLines {
-  return 1;
+  return GetOmniboxSuggestionIcon(self.iconType);
 }
 
 - (BOOL)hasImage {
-  return NO;
-}
-
-- (GURL)imageURL {
-  return GURL();
+  return self.imageURL.is_valid();
 }
 
 @end
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h b/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h
index 0fd0961..c9ffe64 100644
--- a/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h
+++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h
@@ -9,12 +9,22 @@
 
 @class OmniboxPopupViewController;
 
+// In the main app, the |OmniboxPopupViewController| view is contained inside
+// another view (see |OmniboxPopupPresenter|). This class mimics that for
+// Showcase.
 @interface SCOmniboxPopupContainerViewController : UIViewController
 
 @property(nonatomic, strong) OmniboxPopupViewController* popupViewController;
 
 - (instancetype)initWithPopupViewController:
-    (OmniboxPopupViewController*)popupViewController;
+    (OmniboxPopupViewController*)popupViewController NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+- (instancetype)initWithNibName:(NSString*)nibNameOrNil
+                         bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE;
+
+- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
 
 @end
 
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.mm b/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.mm
index 63c599d..dd3a103 100644
--- a/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.mm
+++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.mm
@@ -16,7 +16,7 @@
 
 - (instancetype)initWithPopupViewController:
     (OmniboxPopupViewController*)popupViewController {
-  self = [super init];
+  self = [super initWithNibName:nil bundle:nil];
   if (self) {
     _popupViewController = popupViewController;
   }
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.h b/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.h
index c087c7e..5eed7c8 100644
--- a/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.h
+++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.h
@@ -9,6 +9,7 @@
 
 #import "ios/showcase/common/navigation_coordinator.h"
 
+// Coordnator for the Omnibox Popup entry in Showcase.
 @interface SCOmniboxPopupCoordinator : NSObject <NavigationCoordinator>
 @end
 
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm b/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm
index 0634713..776db601 100644
--- a/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm
+++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm
@@ -7,8 +7,8 @@
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h"
 #import "ios/showcase/common/coordinator.h"
 #import "ios/showcase/common/protocol_alerter.h"
-#import "ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h"
 #import "ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h"
+#import "ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -19,6 +19,7 @@
 @property(nonatomic, strong) OmniboxPopupViewController* popupViewController;
 @property(nonatomic, strong)
     SCOmniboxPopupContainerViewController* containerViewController;
+@property(nonatomic, strong) SCOmniboxPopupMediator* mediator;
 
 @property(nonatomic, strong) ProtocolAlerter* alerter;
 
@@ -37,8 +38,10 @@
   self.popupViewController = [[OmniboxPopupViewController alloc] init];
   self.popupViewController.delegate =
       static_cast<id<AutocompleteResultConsumerDelegate>>(self.alerter);
-  [self.popupViewController updateMatches:[self autocompleteSuggestions]
-                            withAnimation:YES];
+
+  self.mediator = [[SCOmniboxPopupMediator alloc]
+      initWithConsumer:self.popupViewController];
+  [self.mediator updateMatches];
 
   self.containerViewController = [[SCOmniboxPopupContainerViewController alloc]
       initWithPopupViewController:self.popupViewController];
@@ -49,13 +52,4 @@
                                      animated:YES];
 }
 
-#pragma mark - Private
-
-- (NSArray<id<AutocompleteSuggestion>>*)autocompleteSuggestions {
-  return @[
-    [[FakeAutocompleteSuggestion alloc] init],
-    [[FakeAutocompleteSuggestion alloc] init]
-  ];
-}
-
 @end
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.h b/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.h
new file mode 100644
index 0000000..e0fd4f1
--- /dev/null
+++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.h
@@ -0,0 +1,25 @@
+// Copyright 2019 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 IOS_SHOWCASE_OMNIBOX_POPUP_SC_OMNIBOX_POPUP_MEDIATOR_H_
+#define IOS_SHOWCASE_OMNIBOX_POPUP_SC_OMNIBOX_POPUP_MEDIATOR_H_
+
+#include <UIKit/UIKit.h>
+
+@protocol AutocompleteResultConsumer;
+
+// Mediator for the omnibox popup entry in Showcase.
+@interface SCOmniboxPopupMediator : NSObject
+
+- (instancetype)initWithConsumer:(id<AutocompleteResultConsumer>)consumer
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+// Tell the consumer to update its matches with those provided by this provider.
+- (void)updateMatches;
+
+@end
+
+#endif  // IOS_SHOWCASE_OMNIBOX_POPUP_SC_OMNIBOX_POPUP_MEDIATOR_H_
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.mm b/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.mm
new file mode 100644
index 0000000..6c3f2e7
--- /dev/null
+++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.mm
@@ -0,0 +1,46 @@
+// Copyright 2019 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.
+
+#import "ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.h"
+
+#import "ios/chrome/browser/ui/omnibox/autocomplete_result_consumer.h"
+#import "ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface SCOmniboxPopupMediator ()
+
+@property(nonatomic, readonly, weak) id<AutocompleteResultConsumer> consumer;
+
+@end
+
+@implementation SCOmniboxPopupMediator
+
+- (instancetype)initWithConsumer:(id<AutocompleteResultConsumer>)consumer {
+  self = [super init];
+  if (self) {
+    _consumer = consumer;
+  }
+  return self;
+}
+
+- (void)updateMatches {
+  FakeAutocompleteSuggestion* suggestion1 =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion1.supportsDeletion = YES;
+  suggestion1.text = [[NSAttributedString alloc] initWithString:@"Match 1"];
+
+  FakeAutocompleteSuggestion* suggestion2 =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion2.supportsDeletion = YES;
+  suggestion2.text = [[NSAttributedString alloc] initWithString:@"Match 2"];
+  suggestion2.detailText =
+      [[NSAttributedString alloc] initWithString:@"Detail"];
+
+  [self.consumer updateMatches:@[ suggestion1, suggestion2 ] withAnimation:YES];
+}
+
+@end
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium
index b803bc5..24df9a2 100644
--- a/ios/third_party/material_components_ios/README.chromium
+++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@
 Name: Material Components for iOS
 URL: https://github.com/material-components/material-components-ios
 Version: 0
-Revision: 651b6470f437cdc51bb97f285b213d1520bc7201
+Revision: d4fdb374214cfe2010d167338affd3fa9e67263c
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/ios/third_party/webkit/BUILD.gn b/ios/third_party/webkit/BUILD.gn
index adda1074..b3ccc594 100644
--- a/ios/third_party/webkit/BUILD.gn
+++ b/ios/third_party/webkit/BUILD.gn
@@ -38,9 +38,17 @@
       "$target_out_dir/Debug-iphonesimulator/WebKitLegacy.framework/WebKitLegacy",
     ]
 
+    # TODO(crbug.com/934252): "-j 4" restricts xcodebuild to four simultaneous
+    # jobs. This is intended to prevent overloading the machine, because ninja
+    # will already be spawning a large number of jobs in parallel with
+    # xcodebuild, but it causes the webkit build to run very slowly. Find a way
+    # to increase the parallelism here.
     args = [
       "--output_dir",
       rebase_path("$target_out_dir"),
+      "-j",
+      "4",
+      "-quiet",
     ]
   }
 }
diff --git a/ios/third_party/webkit/build_webkit.py b/ios/third_party/webkit/build_webkit.py
index 11341290..183198e 100755
--- a/ios/third_party/webkit/build_webkit.py
+++ b/ios/third_party/webkit/build_webkit.py
@@ -3,33 +3,34 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import optparse
+import argparse
 import os
 import subprocess
 import sys
 
 def main():
-  usage = ('%prog [options]\n'
-           'Invokes build-webkit with the given options.')
-  parser = optparse.OptionParser(usage=usage)
-  parser.add_option('-o', '--output_dir',
+  description = 'Invokes build-webkit with the given options.'
+  parser = argparse.ArgumentParser(description=description)
+  parser.add_argument('--output_dir',
                     help='Output directory for build products.')
-  (opts, args) = parser.parse_args()
+  parser.add_argument('-j',
+                    help='Number of parallel jobs to run.')
+  (opts, extra_args) = parser.parse_known_args()
 
-  if not opts.output_dir:
-    print >>sys.stderr, '--output_dir is required.'
-    return 1
+  output_dir = opts.output_dir
+  if not output_dir:
+    # Use a default that matches what ninja uses.
+    output_dir = os.path.realpath(os.path.join(
+      os.path.dirname(__file__),
+      '../../..',
+      'out', 'Debug-iphonesimulator', 'obj', 'ios', 'third_party', 'webkit'));
 
-  # TODO(crbug.com/934252): "-jobs 2" is passed along to the underlying
-  # xcodebuild invocation and restricts xcodebuild to two simultaneous
-  # jobs. This is intended to prevent overloading the machine, because ninja
-  # will already be spawning a large number of jobs in parallel with xcodebuild,
-  # but it causes the webkit build to run very slowly. Find a way to increase
-  # the parallelism here.
-  command = ['src/Tools/Scripts/build-webkit', '--debug', '--ios-simulator',
-             '-quiet', '-jobs', '2']
+  command = ['src/Tools/Scripts/build-webkit', '--debug', '--ios-simulator']
+  if opts.j:
+    command.extend(['-jobs', opts.j])
+  command.extend(extra_args)
 
-  env = {'WEBKIT_OUTPUTDIR': opts.output_dir}
+  env = {'WEBKIT_OUTPUTDIR': output_dir}
   cwd = os.path.dirname(os.path.realpath(__file__))
   proc = subprocess.Popen(command, cwd=cwd, env=env)
   proc.communicate()
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h
index d0ec0ca..7ba69f0 100644
--- a/ios/web/web_state/ui/crw_web_controller.h
+++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -166,6 +166,7 @@
 
 // Loads |data| of type |MIMEType| and replaces last committed URL with the
 // given |URL|.
+// If a load is in progress, it will be stopped before the data is loaded.
 - (void)loadData:(NSData*)data
         MIMEType:(NSString*)MIMEType
           forURL:(const GURL&)URL;
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index a538c94..837cad0 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1353,6 +1353,7 @@
 - (void)loadData:(NSData*)data
         MIMEType:(NSString*)MIMEType
           forURL:(const GURL&)URL {
+  [self stopLoading];
   web::NavigationItemImpl* item =
       self.navigationManagerImpl->GetLastCommittedItemImpl();
   auto navigationContext = web::NavigationContextImpl::CreateNavigationContext(
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm
index 434fc67..6fee326 100644
--- a/ios/web/web_state/web_state_observer_inttest.mm
+++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -119,6 +119,42 @@
   EXPECT_EQ(url, item->GetURL());
 }
 
+// Verifies correctness of |NavigationContext| (|arg1|) for new page navigation
+// passed to |DidStartNavigation|. Stores |NavigationContext| in |context|
+// pointer. This action is used to verify one of multiple pending navigations.
+ACTION_P6(VerifyPageConcurrentlyStartedContext,
+          web_state,
+          context_url,
+          item_url,
+          transition,
+          context,
+          nav_id) {
+  *context = arg1;
+  ASSERT_TRUE(*context);
+  EXPECT_EQ(web_state, arg0);
+  EXPECT_EQ(web_state, (*context)->GetWebState());
+  *nav_id = (*context)->GetNavigationId();
+  EXPECT_NE(0, *nav_id);
+  EXPECT_EQ(context_url, (*context)->GetUrl());
+  EXPECT_TRUE((*context)->HasUserGesture());
+  ui::PageTransition actual_transition = (*context)->GetPageTransition();
+  EXPECT_TRUE(PageTransitionCoreTypeIs(transition, actual_transition))
+      << "Got unexpected transition: " << actual_transition;
+  EXPECT_FALSE((*context)->IsSameDocument());
+  EXPECT_FALSE((*context)->HasCommitted());
+  EXPECT_FALSE((*context)->IsDownload());
+  EXPECT_FALSE((*context)->IsPost());
+  EXPECT_FALSE((*context)->GetError());
+  EXPECT_FALSE((*context)->IsRendererInitiated());
+  ASSERT_FALSE((*context)->GetResponseHeaders());
+  ASSERT_TRUE(web_state->IsLoading());
+  // GetPendingItem() returns last pending item. Not item associated with
+  // the given navigation context.
+  NavigationManager* navigation_manager = web_state->GetNavigationManager();
+  NavigationItem* item = navigation_manager->GetPendingItem();
+  EXPECT_EQ(item_url, item->GetURL());
+}
+
 // Verifies correctness of |NavigationContext| (|arg1|) for data navigation
 // passed to |DidStartNavigation|. Stores |NavigationContext| in |context|
 // pointer.
@@ -217,11 +253,14 @@
   EXPECT_FALSE((*context)->IsPost());
   EXPECT_FALSE((*context)->GetError());
   EXPECT_FALSE((*context)->IsRendererInitiated());
-  ASSERT_TRUE((*context)->GetResponseHeaders());
-  std::string actual_mime_type;
-  (*context)->GetResponseHeaders()->GetMimeType(&actual_mime_type);
+  if (!url.SchemeIs(url::kAboutScheme)) {
+    ASSERT_TRUE((*context)->GetResponseHeaders());
+    std::string actual_mime_type;
+    (*context)->GetResponseHeaders()->GetMimeType(&actual_mime_type);
+    EXPECT_EQ(mime_type, actual_mime_type);
+    EXPECT_EQ(mime_type, actual_mime_type);
+  }
   ASSERT_TRUE(web_state->IsLoading());
-  EXPECT_EQ(mime_type, actual_mime_type);
   ASSERT_EQ(content_is_html, web_state->ContentIsHTML());
   NavigationManager* navigation_manager = web_state->GetNavigationManager();
   NavigationItem* item = navigation_manager->GetLastCommittedItem();
@@ -896,6 +935,69 @@
   ASSERT_TRUE(LoadUrl(url));
 }
 
+// Tests loading about://newtab and immediately loading another web page without
+// waiting until about://newtab navigation finishes.
+TEST_P(WebStateObserverTest, AboutNewTabNavigation) {
+  if (!web::features::StorePendingItemInContext()) {
+    return;
+  }
+
+  GURL first_url("about://newtab/");
+  const GURL second_url = test_server_->GetURL("/echoall");
+
+  // Perform about://newtab navigation and immediately perform the second
+  // navigation without waiting until the first navigation finishes.
+  NavigationContext* context = nullptr;
+  int32_t nav_id = 0;
+  EXPECT_CALL(observer_, DidStartLoading(web_state()));
+  EXPECT_CALL(observer_, DidStopLoading(web_state()));
+
+  EXPECT_CALL(observer_, DidStartLoading(web_state()));
+
+  WebStatePolicyDecider::RequestInfo expected_request_info(
+      ui::PageTransition::PAGE_TRANSITION_TYPED,
+      /*target_main_frame=*/true, /*has_user_gesture=*/false);
+  EXPECT_CALL(*decider_,
+              ShouldAllowRequest(_, RequestInfoMatch(expected_request_info)))
+      .WillOnce(Return(true));
+  EXPECT_CALL(observer_, DidStartNavigation(web_state(), _))
+      .WillOnce(VerifyPageConcurrentlyStartedContext(
+          web_state(), first_url, second_url,
+          ui::PageTransition::PAGE_TRANSITION_TYPED, &context, &nav_id));
+  EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
+      .WillOnce(VerifyNewPageFinishedContext(
+          web_state(), first_url, /*mime_type=*/std::string(),
+          /*content_is_html=*/false, &context, &nav_id));
+  EXPECT_CALL(observer_,
+              PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
+  EXPECT_CALL(*decider_,
+              ShouldAllowRequest(_, RequestInfoMatch(expected_request_info)))
+      .WillOnce(Return(true));
+  EXPECT_CALL(observer_, DidStartNavigation(web_state(), _))
+      .WillOnce(VerifyPageStartedContext(
+          web_state(), second_url, ui::PageTransition::PAGE_TRANSITION_TYPED,
+          &context, &nav_id));
+  EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true))
+      .WillOnce(Return(true));
+  EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
+      .WillOnce(VerifyNewPageFinishedContext(
+          web_state(), second_url, kExpectedMimeType, /*content_is_html=*/true,
+          &context, &nav_id));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()))
+      .WillOnce(VerifyTitle(second_url.GetContent()));
+  EXPECT_CALL(observer_, TitleWasSet(web_state()))
+      .WillOnce(VerifyTitle("EmbeddedTestServer - EchoAll"));
+  EXPECT_CALL(observer_, DidStopLoading(web_state()));
+  EXPECT_CALL(observer_,
+              PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS));
+
+  test::LoadUrl(web_state(), first_url);
+  test::LoadUrl(web_state(), second_url);
+  EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return !web_state()->IsLoading();
+  }));
+}
+
 // Tests that if web usage is already enabled, enabling it again would not cause
 // any page loads (related to restoring cached session). This is a regression
 // test for crbug.com/781916.
@@ -2094,7 +2196,7 @@
 
 // Tests stopping a navigation. Did FinishLoading and PageLoaded are never
 // called.
-TEST_P(WebStateObserverTest, ImmidiatelyStopNavigation) {
+TEST_P(WebStateObserverTest, ImmediatelyStopNavigation) {
   EXPECT_CALL(observer_, DidStartLoading(web_state()));
   EXPECT_CALL(observer_, DidStopLoading(web_state()));
   WebStatePolicyDecider::RequestInfo expected_request_info(
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 4880efb..9939587 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -312,6 +312,10 @@
 const base::Feature kUseSurfaceLayerForVideoPIP{
     "UseSurfaceLayerForVideoPIP", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enable VA-API hardware encode acceleration for VP8.
+const base::Feature kVaapiVP8Encoder{"VaapiVP8Encoder",
+                                     base::FEATURE_ENABLED_BY_DEFAULT};
+
 // Enable VA-API hardware encode acceleration for VP9.
 const base::Feature kVaapiVP9Encoder{"VaapiVP9Encoder",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 6b37b9c..8266279 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -135,6 +135,7 @@
 MEDIA_EXPORT extern const base::Feature kUseR16Texture;
 MEDIA_EXPORT extern const base::Feature kUseSurfaceLayerForVideo;
 MEDIA_EXPORT extern const base::Feature kUseSurfaceLayerForVideoPIP;
+MEDIA_EXPORT extern const base::Feature kVaapiVP8Encoder;
 MEDIA_EXPORT extern const base::Feature kVaapiVP9Encoder;
 MEDIA_EXPORT extern const base::Feature kVideoBlitColorAccuracy;
 
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn
index c60fa8a..a9b9bdd 100644
--- a/media/capture/BUILD.gn
+++ b/media/capture/BUILD.gn
@@ -167,7 +167,10 @@
       "video/mac/video_capture_device_mac.h",
       "video/mac/video_capture_device_mac.mm",
     ]
-    deps += [ "//third_party/decklink" ]
+    deps += [
+      "//services/video_capture/public/uma",
+      "//third_party/decklink",
+    ]
     libs = [
       "AVFoundation.framework",
       "CoreFoundation.framework",
diff --git a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h
index 492755d8..559907a 100644
--- a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h
+++ b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h
@@ -11,7 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "media/capture/video/chromeos/display_rotation_observer.h"
 #include "media/capture/video/video_capture_device.h"
 #include "media/capture/video/video_capture_device_descriptor.h"
diff --git a/media/capture/video/mac/DEPS b/media/capture/video/mac/DEPS
index 58a1003..577e795b 100644
--- a/media/capture/video/mac/DEPS
+++ b/media/capture/video/mac/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
   "+third_party/decklink",
+  "+services/video_capture/public/uma",
 ]
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
index fa4301ef..132a1c3d 100644
--- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
+++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -18,8 +18,10 @@
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "media/base/timestamp_constants.h"
+#include "media/capture/video/mac/video_capture_device_factory_mac.h"
 #include "media/capture/video/mac/video_capture_device_mac.h"
 #include "media/capture/video_capture_types.h"
+#include "services/video_capture/public/uma/video_capture_service_event.h"
 #include "ui/gfx/geometry/size.h"
 
 // Prefer MJPEG if frame width or height is larger than this.
@@ -86,16 +88,64 @@
 // investigating crbug/582931.
 void MaybeWriteUma(int number_of_devices, int number_of_suspended_devices) {
   std::string model = base::mac::GetModelIdentifier();
-  if (base::StartsWith(model, "MacBook",
-                       base::CompareCase::INSENSITIVE_ASCII)) {
-    UMA_HISTOGRAM_COUNTS_1M("Media.VideoCapture.MacBook.NumberOfDevices",
-                            number_of_devices + number_of_suspended_devices);
-    if (number_of_devices + number_of_suspended_devices == 0) {
-      UMA_HISTOGRAM_ENUMERATION(
-          "Media.VideoCapture.MacBook.HardwareVersionWhenNoCamera",
-          GetMacBookModel(model), MAX_MACBOOK_VERSION + 1);
+  if (!base::StartsWith(model, "MacBook",
+                        base::CompareCase::INSENSITIVE_ASCII)) {
+    return;
+  }
+  static int attempt_since_process_start_counter = 0;
+  static int device_count_at_last_attempt = 0;
+  static bool has_seen_zero_device_count = false;
+  const int attempt_count_since_process_start =
+      ++attempt_since_process_start_counter;
+  const int retry_count =
+      media::VideoCaptureDeviceFactoryMac::GetGetDeviceDescriptorsRetryCount();
+  const int device_count = number_of_devices + number_of_suspended_devices;
+  UMA_HISTOGRAM_COUNTS_1M("Media.VideoCapture.MacBook.NumberOfDevices",
+                          device_count);
+  if (device_count == 0) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "Media.VideoCapture.MacBook.HardwareVersionWhenNoCamera",
+        GetMacBookModel(model), MAX_MACBOOK_VERSION + 1);
+    if (!has_seen_zero_device_count) {
+      UMA_HISTOGRAM_COUNTS_1M(
+          "Media.VideoCapture.MacBook.AttemptCountWhenNoCamera",
+          attempt_count_since_process_start);
+      has_seen_zero_device_count = true;
     }
   }
+
+  if (attempt_count_since_process_start == 1) {
+    if (retry_count == 0) {
+      video_capture::uma::LogMacbookRetryGetDeviceInfosEvent(
+          device_count == 0
+              ? video_capture::uma::
+                    AVF_RECEIVED_ZERO_INFOS_FIRST_TRY_FIRST_ATTEMPT
+              : video_capture::uma::
+                    AVF_RECEIVED_NONZERO_INFOS_FIRST_TRY_FIRST_ATTEMPT);
+    } else {
+      video_capture::uma::LogMacbookRetryGetDeviceInfosEvent(
+          device_count == 0
+              ? video_capture::uma::AVF_RECEIVED_ZERO_INFOS_RETRY
+              : video_capture::uma::AVF_RECEIVED_NONZERO_INFOS_RETRY);
+    }
+    // attempt count > 1
+  } else if (retry_count == 0) {
+    video_capture::uma::LogMacbookRetryGetDeviceInfosEvent(
+        device_count == 0
+            ? video_capture::uma::
+                  AVF_RECEIVED_ZERO_INFOS_FIRST_TRY_NONFIRST_ATTEMPT
+            : video_capture::uma::
+                  AVF_RECEIVED_NONZERO_INFOS_FIRST_TRY_NONFIRST_ATTEMPT);
+  }
+  if (attempt_count_since_process_start > 1 &&
+      device_count != device_count_at_last_attempt) {
+    video_capture::uma::LogMacbookRetryGetDeviceInfosEvent(
+        device_count == 0
+            ? video_capture::uma::AVF_DEVICE_COUNT_CHANGED_FROM_POSITIVE_TO_ZERO
+            : video_capture::uma::
+                  AVF_DEVICE_COUNT_CHANGED_FROM_ZERO_TO_POSITIVE);
+  }
+  device_count_at_last_attempt = device_count;
 }
 
 // This function translates Mac Core Video pixel formats to Chromium pixel
diff --git a/media/capture/video/mac/video_capture_device_factory_mac.h b/media/capture/video/mac/video_capture_device_factory_mac.h
index ccf31dd..be8a3a9 100644
--- a/media/capture/video/mac/video_capture_device_factory_mac.h
+++ b/media/capture/video/mac/video_capture_device_factory_mac.h
@@ -19,6 +19,9 @@
   VideoCaptureDeviceFactoryMac();
   ~VideoCaptureDeviceFactoryMac() override;
 
+  static void SetGetDeviceDescriptorsRetryCount(int count);
+  static int GetGetDeviceDescriptorsRetryCount();
+
   std::unique_ptr<VideoCaptureDevice> CreateDevice(
       const VideoCaptureDeviceDescriptor& device_descriptor) override;
   void GetDeviceDescriptors(
diff --git a/media/capture/video/mac/video_capture_device_factory_mac.mm b/media/capture/video/mac/video_capture_device_factory_mac.mm
index 3005578..6ef3abb 100644
--- a/media/capture/video/mac/video_capture_device_factory_mac.mm
+++ b/media/capture/video/mac/video_capture_device_factory_mac.mm
@@ -37,6 +37,8 @@
 // uniqueId. At the moment these are just Blackmagic devices.
 const char* kBlacklistedCamerasIdSignature[] = {"-01FDA82C8A9C"};
 
+int32_t get_device_descriptors_retry_count = 0;
+
 }  // anonymous namespace
 
 namespace media {
@@ -64,6 +66,17 @@
 VideoCaptureDeviceFactoryMac::~VideoCaptureDeviceFactoryMac() {
 }
 
+// static
+void VideoCaptureDeviceFactoryMac::SetGetDeviceDescriptorsRetryCount(
+    int count) {
+  get_device_descriptors_retry_count = count;
+}
+
+// static
+int VideoCaptureDeviceFactoryMac::GetGetDeviceDescriptorsRetryCount() {
+  return get_device_descriptors_retry_count;
+}
+
 std::unique_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryMac::CreateDevice(
     const VideoCaptureDeviceDescriptor& descriptor) {
   DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index 3163164..ca983bb 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -48,7 +48,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "media/capture/video/chromeos/camera_buffer_factory.h"
 #include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
 #include "media/capture/video/chromeos/local_gpu_memory_buffer_manager.h"
diff --git a/media/capture/video/video_frame_receiver.h b/media/capture/video/video_frame_receiver.h
index baffd35..aaa69b788 100644
--- a/media/capture/video/video_frame_receiver.h
+++ b/media/capture/video/video_frame_receiver.h
@@ -13,7 +13,12 @@
 namespace media {
 
 // Callback interface for VideoCaptureDeviceClient to communicate with its
-// clients.
+// clients. On some platforms, VideoCaptureDeviceClient calls these methods from
+// OS or capture driver provided threads which do not have a task runner and
+// cannot be posted back to. The mostly equivalent interface
+// video_capture::mojom::Receiver cannot be used by VideoCaptureDeviceClient
+// directly, because creating a video_catpure::mojom::ScopedAccessPermissionPtr
+// for passing into OnFrameReadyInBuffer() requires a thread with a task runner.
 class CAPTURE_EXPORT VideoFrameReceiver {
  public:
   virtual ~VideoFrameReceiver() {}
@@ -46,9 +51,9 @@
   // while the receiver is still holding |buffer_read_permission| from a call to
   // OnFrameReadInBuffer() for the same buffer. In that case, it means that the
   // caller is asking the VideoFrameReceiver to release the read permission and
-  // buffer handle at its earliest convenience.
-  // After this call, a producer may immediately reuse the retired |buffer_id|
-  // with a new buffer via a call to OnNewBufferHandle().
+  // buffer handle at its earliest convenience. After this call, a producer may
+  // immediately reuse the retired |buffer_id| with a new buffer via a call to
+  // OnNewBuffer().
   virtual void OnBufferRetired(int buffer_id) = 0;
 
   virtual void OnError(VideoCaptureError error) = 0;
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc
index 21f1b71..673eeb54 100644
--- a/media/capture/video/win/video_capture_device_factory_win.cc
+++ b/media/capture/video/win/video_capture_device_factory_win.cc
@@ -87,7 +87,10 @@
     // Sensoray 2253
     "1943:2253",
     // Dell E5440
-    "0c45:64d0", "0c45:64d2"};
+    "0c45:64d0", "0c45:64d2",
+    // Lenovo Thinkpad Model 20CG0006FMZ front and rear cameras, see
+    // also https://crbug.com/924528
+    "04ca:7047", "04ca:7048"};
 
 const std::pair<VideoCaptureApi, std::vector<std::pair<GUID, GUID>>>
     kMfAttributes[] = {{VideoCaptureApi::WIN_MEDIA_FOUNDATION,
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index 3ad73ffd..e178115 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -178,6 +178,13 @@
     }
   }
 
+  // TODO(posciak): Remove once VP8 encoding is to be enabled by default.
+  if (mode == VaapiWrapper::CodecMode::kEncode &&
+      va_profile == VAProfileVP8Version0_3 &&
+      !base::FeatureList::IsEnabled(kVaapiVP8Encoder)) {
+    return true;
+  }
+
   // TODO(crbug.com/811912): Remove once VP9 encoding is to be enabled by
   // default.
   if (mode == VaapiWrapper::CodecMode::kEncode &&
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
index b60b9260..906eae0 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -431,7 +431,7 @@
       {{alloc_params(method.param_struct, "params", "message", desc)|
           indent(4)}}
       // A null |impl| means no implementation was bound.
-      assert(impl);
+      DCHECK(impl);
       impl->{{method.name}}({{pass_params(method.parameters)}});
       return true;
 {%-     else %}
@@ -494,7 +494,7 @@
               message->has_flag(mojo::Message::kFlagIsSync),
               std::move(responder));
       // A null |impl| means no implementation was bound.
-      assert(impl);
+      DCHECK(impl);
       impl->{{method.name}}(
 {%- if method.parameters -%}{{pass_params(method.parameters)}}, {% endif -%}std::move(callback));
       return true;
diff --git a/net/base/escape.cc b/net/base/escape.cc
index 103e6f4..b37078cb 100644
--- a/net/base/escape.cc
+++ b/net/base/escape.cc
@@ -395,6 +395,11 @@
     {0x00000000L, 0x00000020L, 0x00000000L, 0x00000000L, 0xffffffffL,
      0xffffffffL, 0xffffffffL, 0xffffffffL}};
 
+// non-7bit
+static const Charmap kNonASCIICharmap = {{0x00000000L, 0x00000000L, 0x00000000L,
+                                          0x00000000L, 0xffffffffL, 0xffffffffL,
+                                          0xffffffffL, 0xffffffffL}};
+
 // Everything except alphanumerics, the reserved characters(;/?:@&=+$,) and
 // !'()*-._~#[]
 static const Charmap kExternalHandlerCharmap = {{
@@ -430,6 +435,10 @@
   return Escape(input, kNonASCIICharmapAndPercent, false);
 }
 
+std::string EscapeNonASCII(base::StringPiece input) {
+  return Escape(input, kNonASCIICharmap, false);
+}
+
 std::string EscapeExternalHandlerValue(base::StringPiece text) {
   return Escape(text, kExternalHandlerCharmap, false, true);
 }
diff --git a/net/base/escape.h b/net/base/escape.h
index 7a98ff8d..8e86e61f 100644
--- a/net/base/escape.h
+++ b/net/base/escape.h
@@ -50,6 +50,11 @@
 // Escapes all non-ASCII input, as well as escaping % to %25.
 NET_EXPORT std::string EscapeNonASCIIAndPercent(base::StringPiece input);
 
+// Escapes all non-ASCII input. Note this function leaves % unescaped, which
+// means the unescaping the resulting string will not give back the original
+// input.
+NET_EXPORT std::string EscapeNonASCII(base::StringPiece input);
+
 // Escapes characters in text suitable for use as an external protocol handler
 // command.
 // We %XX everything except alphanumerics and -_.!~*'() and the restricted
diff --git a/net/base/escape_unittest.cc b/net/base/escape_unittest.cc
index 422604e..f70f7cd 100644
--- a/net/base/escape_unittest.cc
+++ b/net/base/escape_unittest.cc
@@ -522,5 +522,10 @@
   EXPECT_FALSE(ContainsEncodedBytes("caf%C3%A9", {'\xe9'}));
 }
 
+TEST(EscapeTest, EscapeNonASCII) {
+  EXPECT_EQ("abc\n%2580%80", EscapeNonASCIIAndPercent("abc\n%80\x80"));
+  EXPECT_EQ("abc\n%80%80", EscapeNonASCII("abc\n%80\x80"));
+}
+
 }  // namespace
 }  // namespace net
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h
index ab03531..454b438 100644
--- a/net/cookies/canonical_cookie.h
+++ b/net/cookies/canonical_cookie.h
@@ -67,7 +67,10 @@
     EXCLUDE_OVERWRITE_SECURE,
     EXCLUDE_OVERWRITE_HTTP_ONLY,
     EXCLUDE_INVALID_DOMAIN,
-    EXCLUDE_INVALID_PREFIX
+    EXCLUDE_INVALID_PREFIX,
+
+    // Please keep last
+    EXCLUDE_UNKNOWN_ERROR
   };
 
   // Creates a new |CanonicalCookie| from the |cookie_line| and the
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc
index 8be8918..02af9b87 100644
--- a/net/dns/dns_transaction.cc
+++ b/net/dns/dns_transaction.cc
@@ -179,6 +179,8 @@
   int result_;
 
   const unsigned server_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(DnsAttempt);
 };
 
 class DnsUDPAttempt : public DnsAttempt {
@@ -403,12 +405,6 @@
   // DnsAttempt overrides.
 
   int Start(CompletionOnceCallback callback) override {
-    if (DNSDomainToString(query_->qname()).compare(request_->url().host()) ==
-        0) {
-      // Fast failing looking up a server with itself.
-      return ERR_DNS_HTTP_FAILED;
-    }
-
     callback_ = std::move(callback);
     request_->Start();
     return ERR_IO_PENDING;
@@ -1049,11 +1045,6 @@
         url_request_context_, request_priority_));
     ++doh_attempts_;
     ++attempts_count_;
-    // Check that we're not using the DoH server to resolve itself.
-    if (DNSDomainToString(qnames_.front()) == gurl_without_parameters.host()) {
-      static_cast<DnsHTTPAttempt*>(attempts_.back().get())->Cancel();
-      return AttemptResult(ERR_CONNECTION_REFUSED, attempts_.back().get());
-    }
     int rv = attempts_.back()->Start(
         base::Bind(&DnsTransactionImpl::OnAttemptComplete,
                    base::Unretained(this), attempt_number));
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index e20b7857..9fd28aa 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -2001,12 +2001,14 @@
   EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
 }
 
-TEST_F(DnsTransactionTest, HttpsCantLookupDohServers) {
-  ConfigDohServers(true /* clear_udp */, true /* use_post */, 2);
-  TransactionHelper helper0(kMockHostname, kT0Qtype, ERR_CONNECTION_REFUSED,
+TEST_F(DnsTransactionTest, CanLookupDohServerName) {
+  config_.search.push_back("http");
+  ConfigDohServers(true /* clear_udp */, true /* use_post */);
+  AddQueryAndErrorResponse(0, kMockHostname, dns_protocol::kTypeA,
+                           ERR_NAME_NOT_RESOLVED, SYNCHRONOUS,
+                           Transport::HTTPS);
+  TransactionHelper helper0("mock", dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED,
                             true /* expected_secure */);
-  transaction_ids_.push_back(0);
-  transaction_ids_.push_back(1);
   EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get()));
 }
 
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc
index e541ca8..c2c0f4b8 100644
--- a/net/dns/host_resolver_manager.cc
+++ b/net/dns/host_resolver_manager.cc
@@ -973,13 +973,24 @@
   std::unique_ptr<DnsTransaction> CreateTransaction(
       DnsQueryType dns_query_type) {
     DCHECK_NE(DnsQueryType::UNSPECIFIED, dns_query_type);
+    SecureDnsMode secure_dns_mode = SecureDnsMode::AUTOMATIC;
+    // Downgrade to OFF mode if the query name for this attempt matches one of
+    // the DoH server names. This is needed to prevent infinite recursion.
+    DCHECK(client_->GetConfig());
+    for (auto& doh_server : client_->GetConfig()->dns_over_https_servers) {
+      if (key_.hostname.compare(GURL(GetURLFromTemplateWithoutParameters(
+                                         doh_server.server_template))
+                                    .host()) == 0) {
+        secure_dns_mode = SecureDnsMode::OFF;
+      }
+    }
     std::unique_ptr<DnsTransaction> trans =
         client_->GetTransactionFactory()->CreateTransaction(
             key_.hostname, DnsQueryTypeToQtype(dns_query_type),
             base::BindOnce(&DnsTask::OnTransactionComplete,
                            base::Unretained(this), tick_clock_->NowTicks(),
                            dns_query_type),
-            net_log_, SecureDnsMode::AUTOMATIC);
+            net_log_, secure_dns_mode);
     trans->SetRequestContext(delegate_->url_request_context());
     trans->SetRequestPriority(delegate_->priority());
     return trans;
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc
index 70f8a6d6..f08806c6 100644
--- a/net/dns/host_resolver_manager_unittest.cc
+++ b/net/dns/host_resolver_manager_unittest.cc
@@ -4664,6 +4664,29 @@
   EXPECT_FALSE(ResolveLocalHostname("foo.localhoste", &addresses));
 }
 
+TEST_F(HostResolverManagerDnsTest, ResolveDnsOverHttpsServerName) {
+  MockDnsClientRuleList rules;
+  rules.emplace_back(
+      "dns.example2.com", dns_protocol::kTypeA, SecureDnsMode::OFF,
+      MockDnsClientRule::Result(MockDnsClientRule::OK), false /* delay */);
+  rules.emplace_back(
+      "dns.example2.com", dns_protocol::kTypeAAAA, SecureDnsMode::OFF,
+      MockDnsClientRule::Result(MockDnsClientRule::OK), false /* delay */);
+  CreateResolver();
+  UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+  DnsConfigOverrides overrides;
+  overrides.dns_over_https_servers.emplace({DnsConfig::DnsOverHttpsServerConfig(
+      "https://dns.example.com/", true /*  use_post */)});
+  overrides.dns_over_https_servers.emplace({DnsConfig::DnsOverHttpsServerConfig(
+      "https://dns.example2.com/dns-query{?dns}", false /* use_post */)});
+  resolver_->SetDnsConfigOverrides(overrides);
+
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair("dns.example2.com", 80), NetLogWithSource(), base::nullopt));
+  ASSERT_THAT(response.result_error(), IsOk());
+}
+
 TEST_F(HostResolverManagerDnsTest, AddDnsOverHttpsServerAfterConfig) {
   resolver_ = nullptr;
   test::ScopedMockNetworkChangeNotifier notifier;
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc
index f457e187..670935c 100644
--- a/net/http/http_response_headers.cc
+++ b/net/http/http_response_headers.cc
@@ -925,9 +925,12 @@
                                         parsed_[i].value_end);
     // Escape any non-ASCII characters to preserve them.  The server should
     // only be returning ASCII here, but for compat we need to do this.
-    *location = base::IsStringASCII(location_strpiece)
-                    ? location_strpiece.as_string()
-                    : EscapeNonASCIIAndPercent(location_strpiece);
+    //
+    // The URL parser escapes things internally, but it expect the bytes to be
+    // valid UTF-8, so encoding errors turn into replacement characters before
+    // escaping. Escaping here preserves the bytes as-is. See
+    // https://crbug.com/942073#c14.
+    *location = EscapeNonASCII(location_strpiece);
   }
 
   return true;
diff --git a/net/server/http_server.cc b/net/server/http_server.cc
index cf711625c..0b77834 100644
--- a/net/server/http_server.cc
+++ b/net/server/http_server.cc
@@ -81,7 +81,7 @@
 
 void HttpServer::SendOverWebSocket(
     int connection_id,
-    const std::string& data,
+    base::StringPiece data,
     NetworkTrafficAnnotationTag traffic_annotation) {
   HttpConnection* connection = FindConnection(connection_id);
   if (connection == nullptr)
diff --git a/net/server/http_server.h b/net/server/http_server.h
index 8115016..edf90e2e 100644
--- a/net/server/http_server.h
+++ b/net/server/http_server.h
@@ -14,6 +14,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/strings/string_piece.h"
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
@@ -56,7 +57,7 @@
                        const HttpServerRequestInfo& request,
                        NetworkTrafficAnnotationTag traffic_annotation);
   void SendOverWebSocket(int connection_id,
-                         const std::string& data,
+                         base::StringPiece data,
                          NetworkTrafficAnnotationTag traffic_annotation);
   // Sends the provided data directly to the given connection. No validation is
   // performed that data constitutes a valid HTTP response. A valid HTTP
diff --git a/net/server/web_socket.cc b/net/server/web_socket.cc
index c3b7cf5..dc3ca0b 100644
--- a/net/server/web_socket.cc
+++ b/net/server/web_socket.cc
@@ -124,7 +124,7 @@
   return result;
 }
 
-void WebSocket::Send(const std::string& message,
+void WebSocket::Send(base::StringPiece message,
                      const NetworkTrafficAnnotationTag traffic_annotation) {
   if (closed_)
     return;
diff --git a/net/server/web_socket.h b/net/server/web_socket.h
index 6d57a7d..6752b74 100644
--- a/net/server/web_socket.h
+++ b/net/server/web_socket.h
@@ -33,7 +33,7 @@
   void Accept(const HttpServerRequestInfo& request,
               const NetworkTrafficAnnotationTag traffic_annotation);
   ParseResult Read(std::string* message);
-  void Send(const std::string& message,
+  void Send(base::StringPiece message,
             const NetworkTrafficAnnotationTag traffic_annotation);
   ~WebSocket();
 
diff --git a/net/server/web_socket_encoder.cc b/net/server/web_socket_encoder.cc
index bec3c83..772cf7d 100644
--- a/net/server/web_socket_encoder.cc
+++ b/net/server/web_socket_encoder.cc
@@ -140,7 +140,7 @@
   return closed ? WebSocket::FRAME_CLOSE : WebSocket::FRAME_OK;
 }
 
-void EncodeFrameHybi17(const std::string& message,
+void EncodeFrameHybi17(base::StringPiece message,
                        int masking_key,
                        bool compressed,
                        std::string* output) {
@@ -301,7 +301,7 @@
   return result;
 }
 
-void WebSocketEncoder::EncodeFrame(const std::string& frame,
+void WebSocketEncoder::EncodeFrame(base::StringPiece frame,
                                    int masking_key,
                                    std::string* output) {
   std::string compressed;
@@ -333,8 +333,7 @@
   return true;
 }
 
-bool WebSocketEncoder::Deflate(const std::string& message,
-                               std::string* output) {
+bool WebSocketEncoder::Deflate(base::StringPiece message, std::string* output) {
   if (!deflater_)
     return false;
   if (!deflater_->AddBytes(message.data(), message.length())) {
diff --git a/net/server/web_socket_encoder.h b/net/server/web_socket_encoder.h
index af81228..de6bea7 100644
--- a/net/server/web_socket_encoder.h
+++ b/net/server/web_socket_encoder.h
@@ -38,7 +38,7 @@
   WebSocket::ParseResult DecodeFrame(const base::StringPiece& frame,
                                      int* bytes_consumed,
                                      std::string* output);
-  void EncodeFrame(const std::string& frame,
+  void EncodeFrame(base::StringPiece frame,
                    int masking_key,
                    std::string* output);
 
@@ -55,7 +55,7 @@
                    std::unique_ptr<WebSocketInflater> inflater);
 
   bool Inflate(std::string* message);
-  bool Deflate(const std::string& message, std::string* output);
+  bool Deflate(base::StringPiece message, std::string* output);
 
   Type type_;
   std::unique_ptr<WebSocketDeflater> deflater_;
diff --git a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
index 6d5c3e34..d69ea2d 100644
--- a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
+++ b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
@@ -283,15 +283,15 @@
      * Sets a redirect.
      *
      * @param requestPath The path to respond to.
-     * @param targetPath The path to redirect to.
+     * @param targetLocation The path (or absolute URL) to redirect to.
      * @return The full URL including the path that should be requested to get the expected
      *         response.
      */
-    public String setRedirect(String requestPath, String targetPath) {
+    public String setRedirect(String requestPath, String targetLocation) {
         List<Pair<String, String>> responseHeaders = new ArrayList<Pair<String, String>>();
-        responseHeaders.add(Pair.create("Location", targetPath));
+        responseHeaders.add(Pair.create("Location", targetLocation));
 
-        return setResponseInternal(requestPath, ApiCompatibilityUtils.getBytesUtf8(targetPath),
+        return setResponseInternal(requestPath, ApiCompatibilityUtils.getBytesUtf8(targetLocation),
                 responseHeaders, null, RESPONSE_STATUS_MOVED_TEMPORARILY);
     }
 
diff --git a/net/test/python_utils.cc b/net/test/python_utils.cc
index e4110c1..37efd035 100644
--- a/net/test/python_utils.cc
+++ b/net/test/python_utils.cc
@@ -11,51 +11,42 @@
 #include "base/environment.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/process/launch.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/foundation_util.h"
 #endif
 
-const char kPythonPathEnv[] = "PYTHONPATH";
-const char kVPythonClearPathEnv[] = "VPYTHON_CLEAR_PYTHONPATH";
+namespace {
+const base::FilePath::CharType kPythonPathEnv[] =
+    FILE_PATH_LITERAL("PYTHONPATH");
+const base::FilePath::CharType kVPythonClearPathEnv[] =
+    FILE_PATH_LITERAL("VPYTHON_CLEAR_PYTHONPATH");
+}  // namespace
 
-void ClearPythonPath() {
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
-  env->UnSetVar(kPythonPathEnv);
+void SetPythonPathInEnvironment(const std::vector<base::FilePath>& python_path,
+                                base::EnvironmentMap* map) {
+  base::NativeEnvironmentString path_str;
+  for (const auto& path : python_path) {
+    if (!path_str.empty()) {
+#if defined(OS_WIN)
+      path_str.push_back(';');
+#else
+      path_str.push_back(':');
+#endif
+    }
+    path_str += path.value();
+  }
+
+  (*map)[kPythonPathEnv] = path_str;
 
   // vpython has instructions on BuildBot (not swarming or LUCI) to clear
   // PYTHONPATH on invocation. Since we are clearing and manipulating it
   // ourselves, we don't want vpython to throw out our hard work.
-  env->UnSetVar(kVPythonClearPathEnv);
-}
-
-void AppendToPythonPath(const base::FilePath& dir) {
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
-  std::string old_path;
-  std::string dir_path;
-#if defined(OS_WIN)
-  dir_path = base::UTF16ToUTF8(dir.value());
-#elif defined(OS_POSIX)
-  dir_path = dir.value();
-#endif
-  if (!env->GetVar(kPythonPathEnv, &old_path)) {
-    env->SetVar(kPythonPathEnv, dir_path.c_str());
-  } else if (old_path.find(dir_path) == std::string::npos) {
-    std::string new_path(old_path);
-#if defined(OS_WIN)
-    new_path.append(";");
-#elif defined(OS_POSIX)
-    new_path.append(":");
-#endif
-    new_path.append(dir_path.c_str());
-    env->SetVar(kPythonPathEnv, new_path);
-  }
+  (*map)[kVPythonClearPathEnv] = base::NativeEnvironmentString();
 }
 
 bool GetPyProtoPath(base::FilePath* dir) {
diff --git a/net/test/python_utils.h b/net/test/python_utils.h
index aba4add..1154e66 100644
--- a/net/test/python_utils.h
+++ b/net/test/python_utils.h
@@ -5,21 +5,19 @@
 #ifndef NET_TEST_PYTHON_UTILS_H_
 #define NET_TEST_PYTHON_UTILS_H_
 
+#include <vector>
+
 #include "base/compiler_specific.h"
+#include "base/environment.h"
 
 namespace base {
 class CommandLine;
 class FilePath;
 }
 
-// This is the python path variable name.
-extern const char kPythonPathEnv[];
-
-// Clears the python path, this is useful for test hermeticity.
-void ClearPythonPath();
-
-// Appends the dir to python path environment variable.
-void AppendToPythonPath(const base::FilePath& dir);
+// Modifies |map| to use the specified Python path.
+void SetPythonPathInEnvironment(const std::vector<base::FilePath>& python_path,
+                                base::EnvironmentMap* map);
 
 // Return the location of the compiler-generated python protobuf.
 bool GetPyProtoPath(base::FilePath* dir);
diff --git a/net/test/python_utils_unittest.cc b/net/test/python_utils_unittest.cc
index ec89b62..d4abcd9 100644
--- a/net/test/python_utils_unittest.cc
+++ b/net/test/python_utils_unittest.cc
@@ -15,43 +15,19 @@
 #include "base/strings/stringprintf.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-TEST(PythonUtils, Clear) {
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
-  env->SetVar(kPythonPathEnv, "foo");
-  EXPECT_TRUE(env->HasVar(kPythonPathEnv));
-
-  ClearPythonPath();
-  EXPECT_FALSE(env->HasVar(kPythonPathEnv));
-}
-
-TEST(PythonUtils, Append) {
-  const base::FilePath::CharType kAppendDir1[] =
-      FILE_PATH_LITERAL("test/path_append1");
-  const base::FilePath::CharType kAppendDir2[] =
-      FILE_PATH_LITERAL("test/path_append2");
-
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
-
-  std::string python_path;
-  base::FilePath append_path1(kAppendDir1);
-  base::FilePath append_path2(kAppendDir2);
-
-  // Get a clean start
-  env->UnSetVar(kPythonPathEnv);
-
-  // Append the path
-  AppendToPythonPath(append_path1);
-  env->GetVar(kPythonPathEnv, &python_path);
-  ASSERT_EQ(python_path, "test/path_append1");
-
-  // Append the safe path again, nothing changes
-  AppendToPythonPath(append_path2);
-  env->GetVar(kPythonPathEnv, &python_path);
+TEST(PythonUtils, SetPythonPathInEnvironment) {
+  base::EnvironmentMap env;
+  SetPythonPathInEnvironment({base::FilePath(FILE_PATH_LITERAL("test/path1")),
+                              base::FilePath(FILE_PATH_LITERAL("test/path2"))},
+                             &env);
 #if defined(OS_WIN)
-  ASSERT_EQ(std::string("test/path_append1;test/path_append2"), python_path);
-#elif defined(OS_POSIX)
-  ASSERT_EQ(std::string("test/path_append1:test/path_append2"), python_path);
+  EXPECT_EQ(L"test/path1;test/path2", env[L"PYTHONPATH"]);
+#else
+  EXPECT_EQ("test/path1:test/path2", env["PYTHONPATH"]);
 #endif
+  EXPECT_NE(env.end(), env.find(FILE_PATH_LITERAL("VPYTHON_CLEAR_PYTHONPATH")));
+  EXPECT_EQ(base::NativeEnvironmentString(),
+            env[FILE_PATH_LITERAL("VPYTHON_CLEAR_PYTHONPATH")]);
 }
 
 TEST(PythonUtils, PythonRunTime) {
diff --git a/net/test/spawned_test_server/local_test_server.cc b/net/test/spawned_test_server/local_test_server.cc
index c430773..fca9136d 100644
--- a/net/test/spawned_test_server/local_test_server.cc
+++ b/net/test/spawned_test_server/local_test_server.cc
@@ -101,12 +101,13 @@
     return false;
   }
 
-  if (!SetPythonPath()) {
-    LOG(ERROR) << "Could not set Python path.";
+  base::Optional<std::vector<base::FilePath>> python_path = GetPythonPath();
+  if (!python_path) {
+    LOG(ERROR) << "Could not get Python path.";
     return false;
   }
 
-  if (!LaunchPython(testserver_path)) {
+  if (!LaunchPython(testserver_path, *python_path)) {
     LOG(ERROR) << "Could not launch Python with path " << testserver_path;
     return false;
   }
@@ -165,30 +166,30 @@
   return true;
 }
 
-bool LocalTestServer::SetPythonPath() const {
-  ClearPythonPath();
-
+base::Optional<std::vector<base::FilePath>> LocalTestServer::GetPythonPath()
+    const {
   base::FilePath third_party_dir;
   if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &third_party_dir)) {
     LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT";
-    return false;
+    return base::nullopt;
   }
   third_party_dir = third_party_dir.AppendASCII("third_party");
 
-  AppendToPythonPath(third_party_dir.AppendASCII("tlslite"));
-  AppendToPythonPath(
-      third_party_dir.AppendASCII("pywebsocket").AppendASCII("src"));
+  std::vector<base::FilePath> ret = {
+      third_party_dir.AppendASCII("tlslite"),
+      third_party_dir.AppendASCII("pywebsocket").AppendASCII("src"),
+  };
 
   // Locate the Python code generated by the protocol buffers compiler.
   base::FilePath pyproto_dir;
-  if (!GetPyProtoPath(&pyproto_dir)) {
+  if (GetPyProtoPath(&pyproto_dir)) {
+    ret.push_back(pyproto_dir);
+  } else {
     LOG(WARNING) << "Cannot find pyproto dir for generated code. "
                  << "Testserver features that rely on it will not work";
-    return true;
   }
-  AppendToPythonPath(pyproto_dir);
 
-  return true;
+  return ret;
 }
 
 bool LocalTestServer::AddCommandLineArguments(
diff --git a/net/test/spawned_test_server/local_test_server.h b/net/test/spawned_test_server/local_test_server.h
index adc13f1..81489c9 100644
--- a/net/test/spawned_test_server/local_test_server.h
+++ b/net/test/spawned_test_server/local_test_server.h
@@ -6,10 +6,12 @@
 #define NET_TEST_SPAWNED_TEST_SERVER_LOCAL_TEST_SERVER_H_
 
 #include <string>
+#include <vector>
 
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/process/process.h"
 #include "net/test/spawned_test_server/base_test_server.h"
 
@@ -46,8 +48,8 @@
   // Stop the server started by Start().
   bool Stop();
 
-  // Modify PYTHONPATH to contain libraries we need.
-  virtual bool SetPythonPath() const WARN_UNUSED_RESULT;
+  // Returns the directories to use as the PYTHONPATH, or nullopt on error.
+  virtual base::Optional<std::vector<base::FilePath>> GetPythonPath() const;
 
   // Returns true if the base::FilePath for the testserver python script is
   // successfully stored  in |*testserver_path|.
@@ -66,8 +68,12 @@
  private:
   bool Init(const base::FilePath& document_root);
 
-  // Launches the Python test server. Returns true on success.
-  bool LaunchPython(const base::FilePath& testserver_path) WARN_UNUSED_RESULT;
+  // Launches the Python test server. Returns true on success. |testserver_path|
+  // is the path to the test server script. |python_path| is the list of
+  // directories to use as the PYTHONPATH environment variable.
+  bool LaunchPython(const base::FilePath& testserver_path,
+                    const std::vector<base::FilePath>& python_path)
+      WARN_UNUSED_RESULT;
 
   // Waits for the server to start. Returns true on success.
   bool WaitToStart() WARN_UNUSED_RESULT;
diff --git a/net/test/spawned_test_server/local_test_server_posix.cc b/net/test/spawned_test_server/local_test_server_posix.cc
index 64ba2c8c..06c2fe28 100644
--- a/net/test/spawned_test_server/local_test_server_posix.cc
+++ b/net/test/spawned_test_server/local_test_server_posix.cc
@@ -103,11 +103,9 @@
 
 namespace net {
 
-bool LocalTestServer::LaunchPython(const base::FilePath& testserver_path) {
-  // Log is useful in the event you want to run a nearby script (e.g. a test) in
-  // the same environment as the TestServer.
-  VLOG(1) << "LaunchPython called with PYTHONPATH = " << getenv(kPythonPathEnv);
-
+bool LocalTestServer::LaunchPython(
+    const base::FilePath& testserver_path,
+    const std::vector<base::FilePath>& python_path) {
   base::CommandLine python_command(base::CommandLine::NO_PROGRAM);
   if (!GetPythonCommand(&python_command))
     return false;
@@ -137,6 +135,12 @@
 
   // Launch a new testserver process.
   base::LaunchOptions options;
+  SetPythonPathInEnvironment(python_path, &options.environment);
+
+  // Log is useful in the event you want to run a nearby script (e.g. a test) in
+  // the same environment as the TestServer.
+  VLOG(1) << "LaunchPython called with PYTHONPATH = "
+          << options.environment["PYTHONPATH"];
 
   // Set CWD to source root.
   if (!base::PathService::Get(base::DIR_SOURCE_ROOT,
diff --git a/net/test/spawned_test_server/local_test_server_win.cc b/net/test/spawned_test_server/local_test_server_win.cc
index e6fcbf7..e5c1fa60 100644
--- a/net/test/spawned_test_server/local_test_server_win.cc
+++ b/net/test/spawned_test_server/local_test_server_win.cc
@@ -87,7 +87,9 @@
 
 namespace net {
 
-bool LocalTestServer::LaunchPython(const base::FilePath& testserver_path) {
+bool LocalTestServer::LaunchPython(
+    const base::FilePath& testserver_path,
+    const std::vector<base::FilePath>& python_path) {
   base::CommandLine python_command(base::CommandLine::NO_PROGRAM);
   if (!GetPythonCommand(&python_command))
     return false;
@@ -128,6 +130,7 @@
       base::NumberToString(reinterpret_cast<uintptr_t>(child_write)));
 
   base::LaunchOptions launch_options;
+  SetPythonPathInEnvironment(python_path, &launch_options.environment);
 
   // Set CWD to source root.
   if (!base::PathService::Get(base::DIR_SOURCE_ROOT,
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 5d0d73f..14f4d89 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -832,13 +832,13 @@
       OnCallToDelegate(NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED);
       allowed_unsafe_redirect_url_ = GURL();
       // The NetworkDelegate must watch for OnRequestDestroyed and not modify
-      // any of the arguments or invoke the callback after it's called. Not
-      // using a WeakPtr here because it's not enough, the consumer has to watch
-      // for destruction regardless, due to the pointer parameters.
+      // any of the arguments after it's called.
+      // TODO(mattm): change the API to remove the out-params and take the
+      // results as params of the callback.
       int error = network_delegate()->NotifyHeadersReceived(
           request_,
           base::BindOnce(&URLRequestHttpJob::OnHeadersReceivedCallback,
-                         base::Unretained(this)),
+                         weak_factory_.GetWeakPtr()),
           headers.get(), &override_response_headers_,
           &allowed_unsafe_redirect_url_);
       if (error != OK) {
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index c71e8ad..6133fc4 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -53,6 +53,7 @@
 #include "net/base/chunked_upload_data_stream.h"
 #include "net/base/directory_listing.h"
 #include "net/base/elements_upload_data_stream.h"
+#include "net/base/escape.h"
 #include "net/base/layered_network_delegate.h"
 #include "net/base/load_flags.h"
 #include "net/base/load_timing_info.h"
@@ -5519,6 +5520,37 @@
   EXPECT_EQ(destination_url, req->url_chain()[2]);
 }
 
+// This is a regression test for https://crbug.com/942073.
+TEST_F(URLRequestTestHTTP, RedirectEscaping) {
+  ASSERT_TRUE(http_test_server()->Start());
+
+  // Assemble the destination URL as a string so it is not escaped by GURL.
+  GURL destination_base = http_test_server()->GetURL("/defaultresponse");
+  // Add a URL fragment of U+2603 unescaped, U+2603 escaped, and then a UTF-8
+  // encoding error.
+  std::string destination_url =
+      destination_base.spec() + "#\xE2\x98\x83_%E2%98%83_\xE0\xE0";
+  // Redirect resolution should percent-escape bytes and preserve the UTF-8
+  // error at the end.
+  std::string destination_escaped =
+      destination_base.spec() + "#%E2%98%83_%E2%98%83_%E0%E0";
+  GURL original_url = http_test_server()->GetURL(
+      "/server-redirect?" + EscapeQueryParamValue(destination_url, false));
+  TestDelegate d;
+  std::unique_ptr<URLRequest> req(default_context().CreateRequest(
+      original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
+  req->Start();
+  d.RunUntilComplete();
+
+  EXPECT_EQ(1, d.response_started_count());
+  EXPECT_EQ(1, d.received_redirect_count());
+  EXPECT_EQ(destination_escaped, req->url().spec());
+  EXPECT_EQ(original_url, req->original_url());
+  ASSERT_EQ(2U, req->url_chain().size());
+  EXPECT_EQ(original_url, req->url_chain()[0]);
+  EXPECT_EQ(destination_escaped, req->url_chain()[1].spec());
+}
+
 // First and second pieces of information logged by delegates to URLRequests.
 const char kFirstDelegateInfo[] = "Wonderful delegate";
 const char kSecondDelegateInfo[] = "Exciting delegate";
diff --git a/sandbox/linux/services/namespace_sandbox.cc b/sandbox/linux/services/namespace_sandbox.cc
index eb91e525..2a1814b 100644
--- a/sandbox/linux/services/namespace_sandbox.cc
+++ b/sandbox/linux/services/namespace_sandbox.cc
@@ -200,7 +200,7 @@
       std::make_pair(CLONE_NEWNET, kSandboxNETNSEnvironmentVarName),
   };
 
-  base::EnvironmentMap* environ = &launch_options_copy.environ;
+  base::EnvironmentMap* environ = &launch_options_copy.environment;
   for (const auto& entry : clone_flag_environ) {
     const int flag = entry.first;
     const char* environ_name = entry.second;
diff --git a/sandbox/linux/suid/client/setuid_sandbox_host.cc b/sandbox/linux/suid/client/setuid_sandbox_host.cc
index 7a103bf..a277ffa 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_host.cc
+++ b/sandbox/linux/suid/client/setuid_sandbox_host.cc
@@ -170,7 +170,7 @@
 
   // Launching a setuid binary requires PR_SET_NO_NEW_PRIVS to not be used.
   options->allow_new_privs = true;
-  UnsetExpectedEnvironmentVariables(&options->environ);
+  UnsetExpectedEnvironmentVariables(&options->environment);
 
   // Set dummy_fd to the reading end of a closed pipe.
   int pipe_fds[2];
diff --git a/services/device/battery/battery_status_manager_chromeos.cc b/services/device/battery/battery_status_manager_chromeos.cc
index d38aee27..3bd55f37 100644
--- a/services/device/battery/battery_status_manager_chromeos.cc
+++ b/services/device/battery/battery_status_manager_chromeos.cc
@@ -9,8 +9,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager_client.h"
 
 namespace device {
 
diff --git a/services/device/generic_sensor/platform_sensor_reader_linux.cc b/services/device/generic_sensor/platform_sensor_reader_linux.cc
index 285d182c..d1ddd0e 100644
--- a/services/device/generic_sensor/platform_sensor_reader_linux.cc
+++ b/services/device/generic_sensor/platform_sensor_reader_linux.cc
@@ -10,6 +10,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/threading/thread_checker.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/timer/timer.h"
 #include "services/device/generic_sensor/linux/sensor_data_linux.h"
@@ -52,6 +53,10 @@
   // Repeating timer for data polling.
   base::RepeatingTimer timer_;
 
+  // In builds with DCHECK enabled, checks that methods of this class are
+  // called on the right thread.
+  THREAD_CHECKER(thread_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(PollingSensorReader);
 };
 
@@ -63,7 +68,9 @@
       sensor_file_paths_(sensor_device->device_reading_files),
       scaling_value_(sensor_device->device_scaling_value),
       offset_value_(sensor_device->device_offset_value),
-      apply_scaling_func_(sensor_device->apply_scaling_func) {}
+      apply_scaling_func_(sensor_device->apply_scaling_func) {
+  DETACH_FROM_THREAD(thread_checker_);
+}
 
 PollingSensorReader::~PollingSensorReader() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -146,15 +153,11 @@
     : sensor_(sensor),
       task_runner_(std::move(task_runner)),
       is_reading_active_(false) {
-  DETACH_FROM_THREAD(thread_checker_);
 }
 
-SensorReader::~SensorReader() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-}
+SensorReader::~SensorReader() = default;
 
 void SensorReader::NotifyReadError() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   if (is_reading_active_) {
     task_runner_->PostTask(
         FROM_HERE,
diff --git a/services/device/generic_sensor/platform_sensor_reader_linux.h b/services/device/generic_sensor/platform_sensor_reader_linux.h
index c944efa..aed51dd4 100644
--- a/services/device/generic_sensor/platform_sensor_reader_linux.h
+++ b/services/device/generic_sensor/platform_sensor_reader_linux.h
@@ -8,7 +8,6 @@
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -49,10 +48,6 @@
   // Notifies |sensor_| about an error.
   void NotifyReadError();
 
-  // In builds with DCHECK enabled checks that methods of this
-  // and derived classes are called on a right thread.
-  THREAD_CHECKER(thread_checker_);
-
   // A sensor that this reader is owned by and notifies about errors and
   // readings to.
   base::WeakPtr<PlatformSensorLinux> sensor_;
diff --git a/services/device/wake_lock/power_save_blocker/power_save_blocker_chromeos.cc b/services/device/wake_lock/power_save_blocker/power_save_blocker_chromeos.cc
index 870c176..53d33b22 100644
--- a/services/device/wake_lock/power_save_blocker/power_save_blocker_chromeos.cc
+++ b/services/device/wake_lock/power_save_blocker/power_save_blocker_chromeos.cc
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner.h"
-#include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 
 namespace device {
 
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc
index b99b658..4b7ae63 100644
--- a/services/identity/public/cpp/identity_manager_unittest.cc
+++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -290,6 +290,11 @@
     account_fetcher_.Shutdown();
   }
 
+  void SetUp() override {
+    primary_account_id_ =
+        identity_manager_->PickAccountIdForAccount(kTestGaiaId, kTestEmail);
+  }
+
   IdentityManager* identity_manager() { return identity_manager_.get(); }
   TestIdentityManagerObserver* identity_manager_observer() {
     return identity_manager_observer_.get();
@@ -408,6 +413,8 @@
     consumer->OnOAuthMultiloginFinished(result);
   }
 
+  std::string primary_account_id() { return primary_account_id_; }
+
   TestSigninClient* signin_client() { return &signin_client_; }
 
   network::TestURLLoaderFactory* test_url_loader_factory() {
@@ -428,6 +435,7 @@
   std::unique_ptr<TestIdentityManagerObserver> identity_manager_observer_;
   std::unique_ptr<TestIdentityManagerDiagnosticsObserver>
       identity_manager_diagnostics_observer_;
+  std::string primary_account_id_;
 
   DISALLOW_COPY_AND_ASSIGN(IdentityManagerTest);
 };
@@ -536,8 +544,6 @@
   // Should not have any refresh tokens at initialization.
   EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
 
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
   // Add a refresh token for the primary account and check that it shows up in
   // GetAccountsWithRefreshTokens().
   SetRefreshTokenForPrimaryAccount(identity_manager());
@@ -546,7 +552,7 @@
       identity_manager()->GetAccountsWithRefreshTokens();
 
   EXPECT_EQ(1u, accounts_after_update.size());
-  EXPECT_EQ(accounts_after_update[0].account_id, account_id);
+  EXPECT_EQ(accounts_after_update[0].account_id, primary_account_id());
   EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId);
   EXPECT_EQ(accounts_after_update[0].email, kTestEmail);
 
@@ -557,7 +563,7 @@
       identity_manager()->GetAccountsWithRefreshTokens();
 
   EXPECT_EQ(1u, accounts_after_second_update.size());
-  EXPECT_EQ(accounts_after_second_update[0].account_id, account_id);
+  EXPECT_EQ(accounts_after_second_update[0].account_id, primary_account_id());
   EXPECT_EQ(accounts_after_second_update[0].gaia, kTestGaiaId);
   EXPECT_EQ(accounts_after_second_update[0].email, kTestEmail);
 
@@ -605,8 +611,6 @@
 TEST_F(IdentityManagerTest, GetAccountsReflectsNonemptyInitialState) {
   EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
 
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
   // Add a refresh token for the primary account and sanity-check that it shows
   // up in GetAccountsWithRefreshTokens().
   SetRefreshTokenForPrimaryAccount(identity_manager());
@@ -615,7 +619,7 @@
       identity_manager()->GetAccountsWithRefreshTokens();
 
   EXPECT_EQ(1u, accounts_after_update.size());
-  EXPECT_EQ(accounts_after_update[0].account_id, account_id);
+  EXPECT_EQ(accounts_after_update[0].account_id, primary_account_id());
   EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId);
   EXPECT_EQ(accounts_after_update[0].email, kTestEmail);
 
@@ -626,7 +630,7 @@
   std::vector<AccountInfo> accounts_after_recreation =
       identity_manager()->GetAccountsWithRefreshTokens();
   EXPECT_EQ(1u, accounts_after_recreation.size());
-  EXPECT_EQ(accounts_after_recreation[0].account_id, account_id);
+  EXPECT_EQ(accounts_after_recreation[0].account_id, primary_account_id());
   EXPECT_EQ(accounts_after_recreation[0].gaia, kTestGaiaId);
   EXPECT_EQ(accounts_after_recreation[0].email, kTestEmail);
 }
@@ -803,8 +807,6 @@
 
   // Add a refresh token for the primary account and check that it
   // also shows up in GetAccountsWithRefreshTokens().
-  std::string primary_account_id =
-      signin_manager()->GetAuthenticatedAccountId();
   SetRefreshTokenForPrimaryAccount(identity_manager());
 
   std::vector<AccountInfo> accounts_after_second_update =
@@ -854,8 +856,6 @@
 
   // Add a refresh token for the primary account and check that it
   // *does* impact the stsate of HasPrimaryAccountWithRefreshToken().
-  std::string primary_account_id =
-      signin_manager()->GetAuthenticatedAccountId();
   SetRefreshTokenForPrimaryAccount(identity_manager());
 
   EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
@@ -1086,14 +1086,13 @@
   std::string access_token = "access_token";
 
   signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-  token_service()->UpdateCredentials(account_id, "refresh_token");
+  token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
 
   base::RunLoop run_loop;
   token_service()->set_on_access_token_invalidated_info(
-      account_id, scopes, access_token, run_loop.QuitClosure());
+      primary_account_id(), scopes, access_token, run_loop.QuitClosure());
 
-  identity_manager()->RemoveAccessTokenFromCache(account_id, scopes,
+  identity_manager()->RemoveAccessTokenFromCache(primary_account_id(), scopes,
                                                  access_token);
 
   run_loop.Run();
@@ -1101,7 +1100,7 @@
   // RemoveAccessTokenFromCache should lead to OnAccessTokenRemovedFromCache
   // from IdentityManager::DiagnosticsObserver.
   EXPECT_EQ(
-      account_id,
+      primary_account_id(),
       identity_manager_diagnostics_observer()->token_remover_account_id());
   EXPECT_EQ(scopes,
             identity_manager_diagnostics_observer()->token_remover_scopes());
@@ -1125,8 +1124,7 @@
       ->set_on_access_token_requested_callback(run_loop.QuitClosure());
 
   signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-  token_service()->UpdateCredentials(account_id, "refresh_token");
+  token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
 
   std::set<std::string> scopes{"scope"};
   AccessTokenFetcher::TokenCallback callback = base::BindOnce(
@@ -1140,8 +1138,8 @@
           &test_url_loader_factory));
   std::unique_ptr<AccessTokenFetcher> token_fetcher =
       identity_manager()->CreateAccessTokenFetcherForAccount(
-          account_id, kTestConsumerId, test_shared_url_loader_factory, scopes,
-          std::move(callback), AccessTokenFetcher::Mode::kImmediate);
+          primary_account_id(), kTestConsumerId, test_shared_url_loader_factory,
+          scopes, std::move(callback), AccessTokenFetcher::Mode::kImmediate);
 
   run_loop.Run();
 
@@ -1155,7 +1153,7 @@
 
   // The account ID and consumer's name should match the data passed as well.
   EXPECT_EQ(
-      account_id,
+      primary_account_id(),
       identity_manager_diagnostics_observer()->token_requestor_account_id());
   EXPECT_EQ(
       kTestConsumerId,
@@ -1164,7 +1162,7 @@
   // Cancel the pending request in preparation to check that creating an
   // AccessTokenFetcher without a custom factory works as expected as well.
   token_service()->IssueErrorForAllPendingRequestsForAccount(
-      account_id,
+      primary_account_id(),
       GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
 
   // Now add a second account and request an access token for it to test
@@ -1212,8 +1210,7 @@
       ->set_on_access_token_requested_callback(run_loop.QuitClosure());
 
   signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-  token_service()->UpdateCredentials(account_id, "refresh_token");
+  token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
 
   std::set<std::string> scopes{"scope"};
   AccessTokenFetcher::TokenCallback callback = base::BindOnce(
@@ -1226,7 +1223,7 @@
   run_loop.Run();
 
   EXPECT_EQ(
-      account_id,
+      primary_account_id(),
       identity_manager_diagnostics_observer()->token_requestor_account_id());
   EXPECT_EQ(
       kTestConsumerId,
@@ -1265,8 +1262,7 @@
       ->set_on_access_token_request_completed_callback(run_loop.QuitClosure());
 
   signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-  token_service()->UpdateCredentials(account_id, "refresh_token");
+  token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
   token_service()->set_auto_post_fetch_response_on_message_loop(true);
 
   std::set<std::string> scopes{"scope"};
@@ -1281,8 +1277,9 @@
   run_loop.Run();
 
   EXPECT_TRUE(token_fetcher);
-  EXPECT_EQ(account_id, identity_manager_diagnostics_observer()
-                            ->on_access_token_request_completed_account_id());
+  EXPECT_EQ(primary_account_id(),
+            identity_manager_diagnostics_observer()
+                ->on_access_token_request_completed_account_id());
   EXPECT_EQ(kTestConsumerId,
             identity_manager_diagnostics_observer()
                 ->on_access_token_request_completed_consumer_id());
@@ -1412,8 +1409,6 @@
 
 TEST_F(IdentityManagerTest,
        CallbackSentOnPrimaryAccountRefreshTokenUpdateWithValidToken) {
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
   SetRefreshTokenForPrimaryAccount(identity_manager());
 
   CoreAccountInfo account_info =
@@ -1424,8 +1419,6 @@
 
 TEST_F(IdentityManagerTest,
        CallbackSentOnPrimaryAccountRefreshTokenUpdateWithInvalidToken) {
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
   SetInvalidRefreshTokenForPrimaryAccount(identity_manager());
 
   CoreAccountInfo account_info =
@@ -1435,14 +1428,12 @@
 }
 
 TEST_F(IdentityManagerTest, CallbackSentOnPrimaryAccountRefreshTokenRemoval) {
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
   SetRefreshTokenForPrimaryAccount(identity_manager());
 
   RemoveRefreshTokenForPrimaryAccount(identity_manager());
 
   EXPECT_EQ(
-      account_id,
+      primary_account_id(),
       identity_manager_observer()->AccountIdFromRefreshTokenRemovedCallback());
 }
 
@@ -1563,8 +1554,6 @@
 TEST_F(
     IdentityManagerTest,
     IdentityManagerGivesConsistentValuesFromTokenServiceObserverNotificationOfTokenUpdate) {
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
   base::RunLoop run_loop;
   TestTokenServiceObserver token_service_observer(token_service());
   token_service_observer.set_on_refresh_token_available_callback(
@@ -1583,15 +1572,13 @@
   // IdentityManager should have already received the event and forwarded it on
   // to its own observers. This is checked internally by
   // TestTokenServiceObserver.
-  token_service()->UpdateCredentials(account_id, "refresh_token");
+  token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
   run_loop.Run();
 }
 
 TEST_F(
     IdentityManagerTest,
     IdentityManagerGivesConsistentValuesFromTokenServiceObserverNotificationOfTokenRemoval) {
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
   base::RunLoop run_loop;
   TestTokenServiceObserver token_service_observer(token_service());
   token_service_observer.set_on_refresh_token_available_callback(
@@ -1605,7 +1592,7 @@
   RecreateIdentityManager();
   token_service_observer.set_identity_manager(identity_manager());
 
-  token_service()->UpdateCredentials(account_id, "refresh_token");
+  token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
   run_loop.Run();
 
   // When the observer receives the callback directly from the token service,
@@ -1615,13 +1602,11 @@
   base::RunLoop run_loop2;
   token_service_observer.set_on_refresh_token_revoked_callback(
       run_loop2.QuitClosure());
-  token_service()->RevokeCredentials(account_id);
+  token_service()->RevokeCredentials(primary_account_id());
   run_loop2.Run();
 }
 
 TEST_F(IdentityManagerTest, IdentityManagerGetsTokensLoadedEvent) {
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
   base::RunLoop run_loop;
   identity_manager_observer()->SetOnRefreshTokensLoadedCallback(
       run_loop.QuitClosure());
@@ -2140,13 +2125,12 @@
 TEST_F(IdentityManagerTest,
        BatchChangeObserversAreNotifiedOnCredentialsUpdate) {
   signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-  token_service()->UpdateCredentials(account_id, "refresh_token");
+  token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
 
   EXPECT_EQ(1ul, identity_manager_observer()->BatchChangeRecords().size());
   EXPECT_EQ(1ul,
             identity_manager_observer()->BatchChangeRecords().at(0).size());
-  EXPECT_EQ(account_id,
+  EXPECT_EQ(primary_account_id(),
             identity_manager_observer()->BatchChangeRecords().at(0).at(0));
 }
 
diff --git a/services/media_session/audio_focus_manager.cc b/services/media_session/audio_focus_manager.cc
index d5a095b..befbd65 100644
--- a/services/media_session/audio_focus_manager.cc
+++ b/services/media_session/audio_focus_manager.cc
@@ -149,7 +149,7 @@
   void BindToController(mojom::MediaControllerRequest request) {
     if (!controller_) {
       controller_ = std::make_unique<MediaController>();
-      controller_->SetMediaSession(session_.get());
+      controller_->SetMediaSession(session_.get(), id());
     }
 
     controller_->BindToInterface(std::move(request));
@@ -453,18 +453,11 @@
     break;
   }
 
-  if (!active_media_controller_.SetMediaSession(active ? active->session()
-                                                       : nullptr)) {
-    return;
+  if (active) {
+    active_media_controller_.SetMediaSession(active->session(), active->id());
+  } else {
+    active_media_controller_.ClearMediaSession();
   }
-
-  mojom::AudioFocusRequestStatePtr state =
-      active ? active->ToAudioFocusRequestState() : nullptr;
-
-  // Notify observers that the active media session changed.
-  observers_.ForAllPtrs([&state](mojom::AudioFocusObserver* observer) {
-    observer->OnActiveSessionChanged(state.Clone());
-  });
 }
 
 AudioFocusManager::AudioFocusManager()
diff --git a/services/media_session/audio_focus_manager_unittest.cc b/services/media_session/audio_focus_manager_unittest.cc
index 8e471f9..1231095 100644
--- a/services/media_session/audio_focus_manager_unittest.cc
+++ b/services/media_session/audio_focus_manager_unittest.cc
@@ -1035,61 +1035,6 @@
   }
 }
 
-TEST_P(AudioFocusManagerTest, ObserverActiveSessionChanged) {
-  test::MockMediaSession media_session_1;
-  test::MockMediaSession media_session_2;
-  media_session_1.SetIsControllable(true);
-
-  {
-    std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
-
-    RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
-    EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
-              GetState(&media_session_1));
-
-    EXPECT_EQ(media_session_1.request_id(),
-              observer->active_session()->request_id);
-  }
-
-  {
-    std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
-
-    RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
-    EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
-              GetState(&media_session_2));
-
-    EXPECT_NE(
-        test::TestAudioFocusObserver::NotificationType::kActiveSessionChanged,
-        observer->notifications().back());
-    EXPECT_TRUE(observer->active_session().is_null());
-  }
-
-  {
-    std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
-    media_session_2.AbandonAudioFocusFromClient();
-
-    EXPECT_NE(
-        test::TestAudioFocusObserver::NotificationType::kActiveSessionChanged,
-        observer->notifications().back());
-    EXPECT_TRUE(observer->active_session().is_null());
-  }
-
-  {
-    std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver();
-    media_session_1.AbandonAudioFocusFromClient();
-
-    // TODO(https://crbug.com/916177): This should wait on a more precise
-    // condition than RunLoop idling, but it's not clear exactly what that
-    // should be.
-    base::RunLoop().RunUntilIdle();
-
-    EXPECT_EQ(
-        test::TestAudioFocusObserver::NotificationType::kActiveSessionChanged,
-        observer->notifications().back());
-    EXPECT_TRUE(observer->active_session().is_null());
-  }
-}
-
 TEST_P(AudioFocusManagerTest, AudioFocusGrouping_LayeredFocus) {
   test::MockMediaSession media_session_1;
   test::MockMediaSession media_session_2;
diff --git a/services/media_session/media_controller.cc b/services/media_session/media_controller.cc
index 06af9f9..41dd934 100644
--- a/services/media_session/media_controller.cc
+++ b/services/media_session/media_controller.cc
@@ -129,6 +129,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Flush the new observer with the current state.
+  observer->MediaSessionChanged(request_id_);
   observer->MediaSessionInfoChanged(session_info_.Clone());
   observer->MediaSessionMetadataChanged(session_metadata_);
   observer->MediaSessionActionsChanged(session_actions_);
@@ -233,40 +234,54 @@
       it == session_images_.end() ? std::vector<MediaImage>() : it->second));
 }
 
-bool MediaController::SetMediaSession(mojom::MediaSession* session) {
+void MediaController::SetMediaSession(
+    mojom::MediaSession* session,
+    const base::UnguessableToken& request_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  bool changed = session != session_;
+  DCHECK(session);
+  DCHECK(request_id);
 
-  if (changed) {
-    session_binding_.Close();
-    session_info_.reset();
-    session_metadata_.reset();
-    session_actions_.clear();
-    session_images_.clear();
+  if (session_ == session)
+    return;
 
-    if (session) {
-      // Add |this| as an observer for |session|.
-      mojom::MediaSessionObserverPtr observer;
-      session_binding_.Bind(mojo::MakeRequest(&observer));
-      session->AddObserver(std::move(observer));
-    } else {
-      // If we are no longer bound to a session we should flush the observers
-      // with empty data.
-      observers_.ForAllPtrs([](mojom::MediaControllerObserver* observer) {
-        observer->MediaSessionInfoChanged(nullptr);
-        observer->MediaSessionMetadataChanged(base::nullopt);
-        observer->MediaSessionActionsChanged(
-            std::vector<mojom::MediaSessionAction>());
-      });
-
-      for (auto& holder : image_observers_)
-        holder->ClearImage();
-    }
-  }
+  Reset();
 
   session_ = session;
-  return changed;
+  request_id_ = request_id;
+
+  // We should always notify the observers that the media session has changed.
+  observers_.ForAllPtrs(
+      [&request_id](mojom::MediaControllerObserver* observer) {
+        observer->MediaSessionChanged(request_id);
+      });
+
+  // Add |this| as an observer for |session|.
+  mojom::MediaSessionObserverPtr observer;
+  session_binding_.Bind(mojo::MakeRequest(&observer));
+  session->AddObserver(std::move(observer));
+}
+
+void MediaController::ClearMediaSession() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!session_)
+    return;
+
+  Reset();
+
+  // If we are no longer bound to a session we should flush the observers
+  // with empty data.
+  observers_.ForAllPtrs([](mojom::MediaControllerObserver* observer) {
+    observer->MediaSessionChanged(base::nullopt);
+    observer->MediaSessionInfoChanged(nullptr);
+    observer->MediaSessionMetadataChanged(base::nullopt);
+    observer->MediaSessionActionsChanged(
+        std::vector<mojom::MediaSessionAction>());
+  });
+
+  for (auto& holder : image_observers_)
+    holder->ClearImage();
 }
 
 void MediaController::BindToInterface(mojom::MediaControllerRequest request) {
@@ -283,4 +298,14 @@
                 [](const auto& holder) { return !holder->is_valid(); });
 }
 
+void MediaController::Reset() {
+  session_ = nullptr;
+  request_id_.reset();
+  session_binding_.Close();
+  session_info_.reset();
+  session_metadata_.reset();
+  session_actions_.clear();
+  session_images_.clear();
+}
+
 }  // namespace media_session
diff --git a/services/media_session/media_controller.h b/services/media_session/media_controller.h
index 45e2604..be3b284 100644
--- a/services/media_session/media_controller.h
+++ b/services/media_session/media_controller.h
@@ -19,6 +19,10 @@
 #include "services/media_session/public/mojom/media_controller.mojom.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
 
+namespace base {
+class UnguessableToken;
+}  // namespace base
+
 namespace media_session {
 
 // MediaController provides a control surface over Mojo for controlling a
@@ -56,9 +60,9 @@
       const base::flat_map<mojom::MediaSessionImageType,
                            std::vector<MediaImage>>& images) override;
 
-  // Sets the media session that the controller should be bound to. If the
-  // session is already bound to the same session then we will return false.
-  bool SetMediaSession(mojom::MediaSession* session);
+  void SetMediaSession(mojom::MediaSession* session,
+                       const base::UnguessableToken& request_id);
+  void ClearMediaSession();
 
   void BindToInterface(mojom::MediaControllerRequest request);
   void FlushForTesting();
@@ -71,6 +75,8 @@
   // Removes unbound or faulty image observers.
   void CleanupImageObservers();
 
+  void Reset();
+
   // Holds mojo bindings for mojom::MediaController.
   mojo::BindingSet<mojom::MediaController> bindings_;
 
@@ -100,6 +106,9 @@
   // Manages individual image observers.
   std::vector<std::unique_ptr<ImageObserverHolder>> image_observers_;
 
+  // The request id for the bound media session.
+  base::Optional<base::UnguessableToken> request_id_;
+
   // Protects |session_| as it is not thread safe.
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/services/media_session/media_controller_unittest.cc b/services/media_session/media_controller_unittest.cc
index ace124e..ae247b8 100644
--- a/services/media_session/media_controller_unittest.cc
+++ b/services/media_session/media_controller_unittest.cc
@@ -1091,4 +1091,71 @@
   }
 }
 
+TEST_F(MediaControllerTest, ActiveController_Observer_SessionChanged) {
+  test::MockMediaSession media_session_1;
+  test::MockMediaSession media_session_2;
+
+  media_session_1.SetIsControllable(true);
+  media_session_2.SetIsControllable(true);
+
+  {
+    test::TestMediaControllerObserver observer(controller());
+    observer.WaitForSession(base::nullopt);
+  }
+
+  {
+    test::MockMediaSessionMojoObserver observer(media_session_1);
+    RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
+    observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
+  }
+
+  {
+    test::TestMediaControllerObserver observer(controller());
+    observer.WaitForSession(media_session_1.request_id());
+  }
+
+  {
+    test::TestMediaControllerObserver observer(controller());
+    RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGain);
+    observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
+  }
+
+  {
+    test::TestMediaControllerObserver observer(controller());
+    observer.WaitForSession(media_session_2.request_id());
+  }
+
+  {
+    test::TestMediaControllerObserver observer(controller());
+    media_session_2.AbandonAudioFocusFromClient();
+    observer.WaitForSession(media_session_1.request_id());
+  }
+
+  {
+    test::TestMediaControllerObserver observer(controller());
+    media_session_1.SetIsControllable(false);
+    observer.WaitForSession(base::nullopt);
+  }
+}
+
+TEST_F(MediaControllerTest, BoundController_Observer_SessionChanged) {
+  test::MockMediaSession media_session;
+
+  {
+    test::MockMediaSessionMojoObserver observer(media_session);
+    RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
+    observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
+  }
+
+  mojom::MediaControllerPtr controller;
+  manager()->CreateMediaControllerForSession(mojo::MakeRequest(&controller),
+                                             media_session.request_id());
+  manager().FlushForTesting();
+
+  {
+    test::TestMediaControllerObserver observer(controller);
+    observer.WaitForSession(media_session.request_id());
+  }
+}
+
 }  // namespace media_session
diff --git a/services/media_session/public/cpp/test/audio_focus_test_util.cc b/services/media_session/public/cpp/test/audio_focus_test_util.cc
index 855dafe6..e519363 100644
--- a/services/media_session/public/cpp/test/audio_focus_test_util.cc
+++ b/services/media_session/public/cpp/test/audio_focus_test_util.cc
@@ -41,12 +41,6 @@
     run_loop_.Quit();
 }
 
-void TestAudioFocusObserver::OnActiveSessionChanged(
-    media_session::mojom::AudioFocusRequestStatePtr session) {
-  active_session_ = std::move(session);
-  notifications_.push_back(NotificationType::kActiveSessionChanged);
-}
-
 void TestAudioFocusObserver::WaitForGainedEvent() {
   if (!focus_gained_session_.is_null())
     return;
diff --git a/services/media_session/public/cpp/test/audio_focus_test_util.h b/services/media_session/public/cpp/test/audio_focus_test_util.h
index 2d9f752..7944478 100644
--- a/services/media_session/public/cpp/test/audio_focus_test_util.h
+++ b/services/media_session/public/cpp/test/audio_focus_test_util.h
@@ -26,8 +26,6 @@
       media_session::mojom::AudioFocusRequestStatePtr session) override;
   void OnFocusLost(
       media_session::mojom::AudioFocusRequestStatePtr session) override;
-  void OnActiveSessionChanged(
-      media_session::mojom::AudioFocusRequestStatePtr session) override;
 
   void WaitForGainedEvent();
   void WaitForLostEvent();
@@ -44,16 +42,10 @@
     return focus_lost_session_;
   }
 
-  const media_session::mojom::AudioFocusRequestStatePtr& active_session()
-      const {
-    return active_session_;
-  }
-
   // These store the order of notifications that were received by the observer.
   enum class NotificationType {
     kFocusGained,
     kFocusLost,
-    kActiveSessionChanged,
   };
   const std::vector<NotificationType>& notifications() const {
     return notifications_;
@@ -65,7 +57,6 @@
   // These store the values we received.
   media_session::mojom::AudioFocusRequestStatePtr focus_gained_session_;
   media_session::mojom::AudioFocusRequestStatePtr focus_lost_session_;
-  media_session::mojom::AudioFocusRequestStatePtr active_session_;
 
   // If either of these are true we will quit the run loop if we observe a gain
   // or lost event.
diff --git a/services/media_session/public/cpp/test/test_media_controller.cc b/services/media_session/public/cpp/test/test_media_controller.cc
index 64723a4..f964563 100644
--- a/services/media_session/public/cpp/test/test_media_controller.cc
+++ b/services/media_session/public/cpp/test/test_media_controller.cc
@@ -100,6 +100,17 @@
   }
 }
 
+void TestMediaControllerObserver::MediaSessionChanged(
+    const base::Optional<base::UnguessableToken>& request_id) {
+  session_request_id_ = request_id;
+
+  if (expected_request_id_.has_value() &&
+      expected_request_id_ == session_request_id_) {
+    run_loop_->Quit();
+    expected_request_id_.reset();
+  }
+}
+
 void TestMediaControllerObserver::WaitForState(
     mojom::MediaSessionInfo::SessionState wanted_state) {
   if (session_info_ && session_info()->state == wanted_state)
@@ -156,6 +167,15 @@
   StartWaiting();
 }
 
+void TestMediaControllerObserver::WaitForSession(
+    const base::Optional<base::UnguessableToken>& request_id) {
+  if (session_request_id_.has_value() && session_request_id_ == request_id)
+    return;
+
+  expected_request_id_ = request_id;
+  StartWaiting();
+}
+
 void TestMediaControllerObserver::StartWaiting() {
   DCHECK(!run_loop_);
 
diff --git a/services/media_session/public/cpp/test/test_media_controller.h b/services/media_session/public/cpp/test/test_media_controller.h
index 2037b867..67b39a46 100644
--- a/services/media_session/public/cpp/test/test_media_controller.h
+++ b/services/media_session/public/cpp/test/test_media_controller.h
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/component_export.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
@@ -61,6 +62,8 @@
       const base::Optional<MediaMetadata>& metadata) override;
   void MediaSessionActionsChanged(
       const std::vector<mojom::MediaSessionAction>& actions) override;
+  void MediaSessionChanged(
+      const base::Optional<base::UnguessableToken>& request_id) override;
 
   void WaitForState(mojom::MediaSessionInfo::SessionState wanted_state);
   void WaitForPlaybackState(mojom::MediaPlaybackState wanted_state);
@@ -73,6 +76,8 @@
   void WaitForExpectedActions(
       const std::set<mojom::MediaSessionAction>& actions);
 
+  void WaitForSession(const base::Optional<base::UnguessableToken>& request_id);
+
   const mojom::MediaSessionInfoPtr& session_info() const {
     return *session_info_;
   }
@@ -92,6 +97,7 @@
   base::Optional<mojom::MediaSessionInfoPtr> session_info_;
   base::Optional<base::Optional<MediaMetadata>> session_metadata_;
   base::Optional<std::set<mojom::MediaSessionAction>> session_actions_;
+  base::Optional<base::Optional<base::UnguessableToken>> session_request_id_;
 
   base::Optional<MediaMetadata> expected_metadata_;
   base::Optional<std::set<mojom::MediaSessionAction>> expected_actions_;
@@ -101,6 +107,8 @@
   base::Optional<mojom::MediaSessionInfo::SessionState> wanted_state_;
   base::Optional<mojom::MediaPlaybackState> wanted_playback_state_;
 
+  base::Optional<base::Optional<base::UnguessableToken>> expected_request_id_;
+
   std::unique_ptr<base::RunLoop> run_loop_;
 
   mojo::Binding<mojom::MediaControllerObserver> binding_;
diff --git a/services/media_session/public/mojom/audio_focus.mojom b/services/media_session/public/mojom/audio_focus.mojom
index 6bbfa078..472c179 100644
--- a/services/media_session/public/mojom/audio_focus.mojom
+++ b/services/media_session/public/mojom/audio_focus.mojom
@@ -70,12 +70,6 @@
 
   // The given |session| lost audio focus.
   OnFocusLost(AudioFocusRequestState state);
-
-  // The currently active session changed. The active session is the top most
-  // session that is not temporary. This is the session that will be associated
-  // with the MediaController interface. If all the media sessions have ended
-  // then |session| will be null.
-  OnActiveSessionChanged(AudioFocusRequestState? session);
 };
 
 // Controls audio focus for an associated request.
diff --git a/services/media_session/public/mojom/media_controller.mojom b/services/media_session/public/mojom/media_controller.mojom
index 1795f69..3efbd33 100644
--- a/services/media_session/public/mojom/media_controller.mojom
+++ b/services/media_session/public/mojom/media_controller.mojom
@@ -82,6 +82,10 @@
   // Called when the bound media session action list has changed. This tells
   // the observer which actions can be used to control the session.
   MediaSessionActionsChanged(array<MediaSessionAction> action);
+
+  // Called when the bound media session changes. This tells the observer the
+  // |request_id| of the new session of null if it is not bound to a session.
+  MediaSessionChanged(mojo_base.mojom.UnguessableToken? request_id);
 };
 
 // The observer for observing when images associated with a media controller
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 02b87cb..172e1a7 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -19,6 +19,8 @@
 #include "base/location.h"
 #include "base/metrics/field_trial.h"
 #include "base/optional.h"
+#include "base/power_monitor/power_monitor.h"
+#include "base/power_monitor/power_monitor_source.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/strcat.h"
@@ -4422,6 +4424,254 @@
   }
 }
 
+class HangingTestURLLoaderHeaderClient
+    : public mojom::TrustedURLLoaderHeaderClient {
+ public:
+  class TestHeaderClient : public mojom::TrustedHeaderClient {
+   public:
+    TestHeaderClient() : binding_(this) {}
+
+    // network::mojom::TrustedHeaderClient:
+    void OnBeforeSendHeaders(const net::HttpRequestHeaders& headers,
+                             OnBeforeSendHeadersCallback callback) override {
+      auto new_headers = headers;
+      new_headers.SetHeader("foo", "bar");
+      std::move(callback).Run(net::OK, new_headers);
+    }
+
+    void OnHeadersReceived(const std::string& headers,
+                           OnHeadersReceivedCallback callback) override {
+      saved_received_headers_ = headers;
+      saved_on_headers_received_callback_ = std::move(callback);
+      on_headers_received_loop_.Quit();
+    }
+
+    void CallOnHeadersReceivedCallback() {
+      auto new_headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+          saved_received_headers_);
+      new_headers->AddHeader("baz: qux");
+      std::move(saved_on_headers_received_callback_)
+          .Run(net::OK, new_headers->raw_headers(), GURL());
+    }
+
+    void WaitForOnHeadersReceived() { on_headers_received_loop_.Run(); }
+
+    void Bind(network::mojom::TrustedHeaderClientRequest request) {
+      binding_.Bind(std::move(request));
+    }
+
+   private:
+    base::RunLoop on_headers_received_loop_;
+    std::string saved_received_headers_;
+    OnHeadersReceivedCallback saved_on_headers_received_callback_;
+    mojo::Binding<mojom::TrustedHeaderClient> binding_;
+
+    DISALLOW_COPY_AND_ASSIGN(TestHeaderClient);
+  };
+
+  HangingTestURLLoaderHeaderClient(
+      mojom::TrustedURLLoaderHeaderClientRequest request)
+      : binding_(this, std::move(request)) {}
+
+  // network::mojom::TrustedURLLoaderHeaderClient:
+  void OnLoaderCreated(
+      int32_t request_id,
+      network::mojom::TrustedHeaderClientRequest request) override {
+    header_client_.Bind(std::move(request));
+  }
+
+  void CallOnHeadersReceivedCallback() {
+    header_client_.CallOnHeadersReceivedCallback();
+  }
+
+  void WaitForOnHeadersReceived() { header_client_.WaitForOnHeadersReceived(); }
+
+ private:
+  TestHeaderClient header_client_;
+  mojo::Binding<mojom::TrustedURLLoaderHeaderClient> binding_;
+
+  DISALLOW_COPY_AND_ASSIGN(HangingTestURLLoaderHeaderClient);
+};
+
+// Test waiting on the OnHeadersReceived event, then proceeding to call the
+// OnHeadersReceivedCallback asynchronously. This mostly just verifies that
+// HangingTestURLLoaderHeaderClient works.
+TEST_F(NetworkContextTest, HangingHeaderClientModifiesHeadersAsynchronously) {
+  net::EmbeddedTestServer test_server;
+  net::test_server::RegisterDefaultHandlers(&test_server);
+  ASSERT_TRUE(test_server.Start());
+
+  std::unique_ptr<NetworkContext> network_context =
+      CreateContextWithParams(CreateContextParams());
+
+  ResourceRequest request;
+  request.url = test_server.GetURL("/echoheader?foo");
+
+  mojom::URLLoaderFactoryPtr loader_factory;
+  mojom::URLLoaderFactoryParamsPtr params =
+      mojom::URLLoaderFactoryParams::New();
+  params->process_id = mojom::kBrowserProcessId;
+  params->is_corb_enabled = false;
+  HangingTestURLLoaderHeaderClient header_client(
+      mojo::MakeRequest(&params->header_client));
+  network_context->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory),
+                                          std::move(params));
+
+  mojom::URLLoaderPtr loader;
+  TestURLLoaderClient client;
+  loader_factory->CreateLoaderAndStart(
+      mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */,
+      mojom::kURLLoadOptionUseHeaderClient, request,
+      client.CreateInterfacePtr(),
+      net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+
+  header_client.WaitForOnHeadersReceived();
+
+  header_client.CallOnHeadersReceivedCallback();
+
+  client.RunUntilComplete();
+
+  EXPECT_EQ(client.completion_status().error_code, net::OK);
+  // Make sure request header was modified. The value will be in the body
+  // since we used the /echoheader endpoint.
+  std::string response;
+  EXPECT_TRUE(
+      mojo::BlockingCopyToString(client.response_body_release(), &response));
+  EXPECT_EQ(response, "bar");
+
+  // Make sure response header was modified.
+  EXPECT_TRUE(client.response_head().headers->HasHeaderValue("baz", "qux"));
+}
+
+// Test destroying the mojom::URLLoader after the OnHeadersReceived event and
+// then calling the OnHeadersReceivedCallback.
+TEST_F(NetworkContextTest, HangingHeaderClientAbortedRequest) {
+  net::EmbeddedTestServer test_server;
+  net::test_server::RegisterDefaultHandlers(&test_server);
+  ASSERT_TRUE(test_server.Start());
+
+  std::unique_ptr<NetworkContext> network_context =
+      CreateContextWithParams(CreateContextParams());
+
+  ResourceRequest request;
+  request.url = test_server.GetURL("/echoheader?foo");
+
+  mojom::URLLoaderFactoryPtr loader_factory;
+  mojom::URLLoaderFactoryParamsPtr params =
+      mojom::URLLoaderFactoryParams::New();
+  params->process_id = mojom::kBrowserProcessId;
+  params->is_corb_enabled = false;
+  HangingTestURLLoaderHeaderClient header_client(
+      mojo::MakeRequest(&params->header_client));
+  network_context->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory),
+                                          std::move(params));
+
+  mojom::URLLoaderPtr loader;
+  TestURLLoaderClient client;
+  loader_factory->CreateLoaderAndStart(
+      mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */,
+      mojom::kURLLoadOptionUseHeaderClient, request,
+      client.CreateInterfacePtr(),
+      net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+
+  header_client.WaitForOnHeadersReceived();
+
+  loader.reset();
+
+  // Ensure the loader is destroyed before the callback is run.
+  base::RunLoop().RunUntilIdle();
+
+  header_client.CallOnHeadersReceivedCallback();
+
+  client.RunUntilComplete();
+
+  EXPECT_EQ(client.completion_status().error_code, net::ERR_FAILED);
+}
+
+// Test power monitor source that can simulate entering suspend mode. Can't use
+// the one in base/ because it insists on bringing its own MessageLoop.
+class TestPowerMonitorSource : public base::PowerMonitorSource {
+ public:
+  TestPowerMonitorSource() = default;
+  ~TestPowerMonitorSource() override = default;
+
+  void Shutdown() override {}
+
+  void Suspend() { ProcessPowerEvent(SUSPEND_EVENT); }
+
+  void Resume() { ProcessPowerEvent(RESUME_EVENT); }
+
+  bool IsOnBatteryPowerImpl() override { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestPowerMonitorSource);
+};
+
+// If the OnHeadersReceivedCallback is called immediately after a Suspend event
+// (|runloop_after_suspend|==false), the URLRequest will not have been destroyed
+// yet, but the URLRequestHttpJob will have destroyed the transaction_. This
+// test ensures that URLRequestHttpJob does not attempt to dereference the
+// transaction_.
+//
+// If a Suspend event occurs and the message loop is allowed to run afterwards
+// (|runloop_after_suspend|==true), the URLLoader and URLRequest will be
+// destroyed. Attempting to call the OnHeadersReceivedCallback should do nothing
+// as URLLoader bound it to a weakptr.
+TEST_F(NetworkContextTest, HangingHeaderClientSuspendThenCallback) {
+  net::EmbeddedTestServer test_server;
+  net::test_server::RegisterDefaultHandlers(&test_server);
+  ASSERT_TRUE(test_server.Start());
+
+  for (bool runloop_after_suspend : {false, true}) {
+    SCOPED_TRACE(testing::Message()
+                 << "runloop_after_suspend=" << runloop_after_suspend);
+
+    std::unique_ptr<TestPowerMonitorSource> power_monitor_source =
+        std::make_unique<TestPowerMonitorSource>();
+    TestPowerMonitorSource* unowned_power_monitor_source =
+        power_monitor_source.get();
+    base::PowerMonitor power_monitor(std::move(power_monitor_source));
+
+    std::unique_ptr<NetworkContext> network_context =
+        CreateContextWithParams(CreateContextParams());
+
+    ResourceRequest request;
+    request.url = test_server.GetURL("/echoheader?foo");
+
+    mojom::URLLoaderFactoryPtr loader_factory;
+    mojom::URLLoaderFactoryParamsPtr params =
+        mojom::URLLoaderFactoryParams::New();
+    params->process_id = mojom::kBrowserProcessId;
+    params->is_corb_enabled = false;
+    HangingTestURLLoaderHeaderClient header_client(
+        mojo::MakeRequest(&params->header_client));
+    network_context->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory),
+                                            std::move(params));
+
+    mojom::URLLoaderPtr loader;
+    TestURLLoaderClient client;
+    loader_factory->CreateLoaderAndStart(
+        mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */,
+        mojom::kURLLoadOptionUseHeaderClient, request,
+        client.CreateInterfacePtr(),
+        net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+
+    header_client.WaitForOnHeadersReceived();
+
+    unowned_power_monitor_source->Suspend();
+    if (runloop_after_suspend)
+      base::RunLoop().RunUntilIdle();
+
+    header_client.CallOnHeadersReceivedCallback();
+
+    client.RunUntilComplete();
+
+    EXPECT_EQ(client.completion_status().error_code, net::ERR_ABORTED);
+
+    unowned_power_monitor_source->Resume();
+  }
+}
+
 // Custom proxy does not apply to localhost, so resolve kMockHost to localhost,
 // and use that instead.
 class NetworkContextMockHostTest : public NetworkContextTest {
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn
index 1c9d3708..702e927f 100644
--- a/services/network/public/cpp/BUILD.gn
+++ b/services/network/public/cpp/BUILD.gn
@@ -179,6 +179,7 @@
   testonly = true
 
   sources = [
+    "cookie_manager_mojom_traits_unittest.cc",
     "cors/cors_unittest.cc",
     "cors/origin_access_entry_unittest.cc",
     "cors/origin_access_list_unittest.cc",
diff --git a/services/network/public/cpp/cookie_manager.typemap b/services/network/public/cpp/cookie_manager.typemap
index c176706..7f56a8a5 100644
--- a/services/network/public/cpp/cookie_manager.typemap
+++ b/services/network/public/cpp/cookie_manager.typemap
@@ -19,4 +19,6 @@
   "network.mojom.CookieSameSiteFilter=net::CookieOptions::SameSiteCookieContext",
   "network.mojom.CookieOptions=net::CookieOptions",
   "network.mojom.CanonicalCookie=net::CanonicalCookie",
+  "network.mojom.CookieInclusionStatus=net::CanonicalCookie::CookieInclusionStatus",
+  "network.mojom.CookieWithStatus=net::CookieWithStatus",
 ]
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits.cc b/services/network/public/cpp/cookie_manager_mojom_traits.cc
index 7ecc3dac..5efac7b 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits.cc
+++ b/services/network/public/cpp/cookie_manager_mojom_traits.cc
@@ -72,6 +72,119 @@
   return false;
 }
 
+network::mojom::CookieInclusionStatus
+EnumTraits<network::mojom::CookieInclusionStatus,
+           net::CanonicalCookie::CookieInclusionStatus>::
+    ToMojom(net::CanonicalCookie::CookieInclusionStatus input) {
+  switch (input) {
+    case net::CanonicalCookie::CookieInclusionStatus::INCLUDE:
+      return network::mojom::CookieInclusionStatus::INCLUDE;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_HTTP_ONLY;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_SECURE_ONLY;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES;
+
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE;
+    case net::CanonicalCookie::CookieInclusionStatus::
+        EXCLUDE_NONCOOKIEABLE_SCHEME:
+      return network::mojom::CookieInclusionStatus::
+          EXCLUDE_NONCOOKIEABLE_SCHEME;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE;
+    case net::CanonicalCookie::CookieInclusionStatus::
+        EXCLUDE_OVERWRITE_HTTP_ONLY:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN;
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX;
+
+    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR:
+      return network::mojom::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR;
+  }
+  NOTREACHED();
+  return network::mojom::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR;
+}
+
+bool EnumTraits<network::mojom::CookieInclusionStatus,
+                net::CanonicalCookie::CookieInclusionStatus>::
+    FromMojom(network::mojom::CookieInclusionStatus input,
+              net::CanonicalCookie::CookieInclusionStatus* output) {
+  switch (input) {
+    case network::mojom::CookieInclusionStatus::INCLUDE:
+      *output = net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_HTTP_ONLY:
+      *output = net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_SECURE_ONLY:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME:
+      *output = net::CanonicalCookie::CookieInclusionStatus::
+          EXCLUDE_NONCOOKIEABLE_SCHEME;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY:
+      *output = net::CanonicalCookie::CookieInclusionStatus::
+          EXCLUDE_OVERWRITE_HTTP_ONLY;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX;
+      return true;
+    case network::mojom::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR:
+      *output =
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR;
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
 network::mojom::CookieSameSiteFilter
 EnumTraits<network::mojom::CookieSameSiteFilter,
            net::CookieOptions::SameSiteCookieContext>::
@@ -130,6 +243,12 @@
   if (optional_server_time) {
     cookie_options->set_server_time(*optional_server_time);
   }
+
+  if (mojo_options.return_excluded_cookies())
+    cookie_options->set_return_excluded_cookies();
+  else
+    cookie_options->unset_return_excluded_cookies();
+
   return true;
 }
 
@@ -179,4 +298,20 @@
   return out->IsCanonical();
 }
 
+bool StructTraits<
+    network::mojom::CookieWithStatusDataView,
+    net::CookieWithStatus>::Read(network::mojom::CookieWithStatusDataView c,
+                                 net::CookieWithStatus* out) {
+  net::CanonicalCookie cookie;
+  net::CanonicalCookie::CookieInclusionStatus status;
+  if (!c.ReadCookie(&cookie))
+    return false;
+  if (!c.ReadStatus(&status))
+    return false;
+
+  *out = {cookie, status};
+
+  return true;
+}
+
 }  // namespace mojo
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits.h b/services/network/public/cpp/cookie_manager_mojom_traits.h
index dac85818..52c80598 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits.h
+++ b/services/network/public/cpp/cookie_manager_mojom_traits.h
@@ -29,6 +29,15 @@
 };
 
 template <>
+struct EnumTraits<network::mojom::CookieInclusionStatus,
+                  net::CanonicalCookie::CookieInclusionStatus> {
+  static network::mojom::CookieInclusionStatus ToMojom(
+      net::CanonicalCookie::CookieInclusionStatus input);
+  static bool FromMojom(network::mojom::CookieInclusionStatus input,
+                        net::CanonicalCookie::CookieInclusionStatus* output);
+};
+
+template <>
 struct EnumTraits<network::mojom::CookieSameSiteFilter,
                   net::CookieOptions::SameSiteCookieContext> {
   static network::mojom::CookieSameSiteFilter ToMojom(
@@ -55,6 +64,9 @@
       return base::nullopt;
     return base::Optional<base::Time>(o.server_time());
   }
+  static bool return_excluded_cookies(const net::CookieOptions& o) {
+    return o.return_excluded_cookies();
+  }
 
   static bool Read(network::mojom::CookieOptionsDataView mojo_options,
                    net::CookieOptions* cookie_options);
@@ -97,6 +109,20 @@
                    net::CanonicalCookie* out);
 };
 
+template <>
+struct StructTraits<network::mojom::CookieWithStatusDataView,
+                    net::CookieWithStatus> {
+  static const net::CanonicalCookie& cookie(const net::CookieWithStatus& c) {
+    return c.cookie;
+  }
+  static const net::CanonicalCookie::CookieInclusionStatus& status(
+      const net::CookieWithStatus& c) {
+    return c.status;
+  }
+  static bool Read(network::mojom::CookieWithStatusDataView cookie,
+                   net::CookieWithStatus* out);
+};
+
 }  // namespace mojo
 
 #endif  // SERVICES_NETWORK_PUBLIC_CPP_COOKIE_MANAGER_MOJOM_TRAITS_H_
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc b/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
new file mode 100644
index 0000000..68a67ce
--- /dev/null
+++ b/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
@@ -0,0 +1,116 @@
+// Copyright 2018 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 "services/network/public/cpp/cookie_manager_mojom_traits.h"
+
+#include <vector>
+
+#include "base/test/gtest_util.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "services/network/public/cpp/cookie_manager_mojom_traits.h"
+#include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace network {
+namespace {
+
+TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) {
+  std::vector<net::CanonicalCookie::CookieInclusionStatus> statuses = {
+      net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR,
+  };
+
+  for (auto status : statuses) {
+    int32_t serialized = -1;
+    using CookieInclusionStatusSerializer =
+        mojo::internal::Serializer<mojom::CookieInclusionStatus,
+                                   net::CanonicalCookie::CookieInclusionStatus>;
+    CookieInclusionStatusSerializer::Serialize(status, &serialized);
+    EXPECT_EQ(static_cast<int>(status), serialized);
+    net::CanonicalCookie::CookieInclusionStatus deserialized;
+    CookieInclusionStatusSerializer::Deserialize(serialized, &deserialized);
+    EXPECT_EQ(serialized, static_cast<int>(deserialized));
+  }
+}
+
+TEST(CookieManagerTraitsTest, Roundtrips_CanonicalCookie) {
+  net::CanonicalCookie original(
+      "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false,
+      false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW);
+
+  net::CanonicalCookie copied;
+
+  EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
+      &original, &copied));
+
+  EXPECT_EQ(original.Name(), copied.Name());
+  EXPECT_EQ(original.Value(), copied.Value());
+  EXPECT_EQ(original.Domain(), copied.Domain());
+  EXPECT_EQ(original.Path(), copied.Path());
+  EXPECT_EQ(original.CreationDate(), copied.CreationDate());
+  EXPECT_EQ(original.LastAccessDate(), copied.LastAccessDate());
+  EXPECT_EQ(original.ExpiryDate(), copied.ExpiryDate());
+  EXPECT_EQ(original.IsSecure(), copied.IsSecure());
+  EXPECT_EQ(original.IsHttpOnly(), copied.IsHttpOnly());
+  EXPECT_EQ(original.SameSite(), copied.SameSite());
+  EXPECT_EQ(original.Priority(), copied.Priority());
+
+  // Serializer returns false if cookie is non-canonical.
+  // Example is non-canonical because of newline in name.
+
+  original = net::CanonicalCookie("A\n", "B", "x.y", "/path", base::Time(),
+                                  base::Time(), base::Time(), false, false,
+                                  net::CookieSameSite::NO_RESTRICTION,
+                                  net::COOKIE_PRIORITY_LOW);
+
+  EXPECT_FALSE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
+      &original, &copied));
+}
+
+TEST(CookieManagerTraitsTest, Roundtrips_CookieWithStatus) {
+  net::CanonicalCookie original_cookie(
+      "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false,
+      false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW);
+
+  net::CookieWithStatus original = {
+      original_cookie, net::CanonicalCookie::CookieInclusionStatus::INCLUDE};
+
+  net::CookieWithStatus copied;
+
+  EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieWithStatus>(
+      &original, &copied));
+
+  EXPECT_EQ(original.cookie.Name(), copied.cookie.Name());
+  EXPECT_EQ(original.cookie.Value(), copied.cookie.Value());
+  EXPECT_EQ(original.cookie.Domain(), copied.cookie.Domain());
+  EXPECT_EQ(original.cookie.Path(), copied.cookie.Path());
+  EXPECT_EQ(original.cookie.CreationDate(), copied.cookie.CreationDate());
+  EXPECT_EQ(original.cookie.LastAccessDate(), copied.cookie.LastAccessDate());
+  EXPECT_EQ(original.cookie.ExpiryDate(), copied.cookie.ExpiryDate());
+  EXPECT_EQ(original.cookie.IsSecure(), copied.cookie.IsSecure());
+  EXPECT_EQ(original.cookie.IsHttpOnly(), copied.cookie.IsHttpOnly());
+  EXPECT_EQ(original.cookie.SameSite(), copied.cookie.SameSite());
+  EXPECT_EQ(original.cookie.Priority(), copied.cookie.Priority());
+  EXPECT_EQ(original.status, copied.status);
+}
+
+// TODO: Add tests for CookiePriority, CookieSameSite, CookieSameSiteFilter, &
+// CookieOptions
+
+}  // namespace
+}  // namespace network
diff --git a/services/network/public/mojom/cookie_manager.mojom b/services/network/public/mojom/cookie_manager.mojom
index 9afd983..0d127eae 100644
--- a/services/network/public/mojom/cookie_manager.mojom
+++ b/services/network/public/mojom/cookie_manager.mojom
@@ -55,6 +55,7 @@
   // TODO(rdsmith): Remove this element from the mojo structure?  It's only
   // used in the underlying net:: structure in CanonicalCookie::Create().
   mojo_base.mojom.Time? server_time;
+  bool return_excluded_cookies = false;
 };
 
 // See net/cookies/canonical_cookie.{h,cc} for documentation.
@@ -73,6 +74,34 @@
   CookiePriority priority = MEDIUM;
 };
 
+// Keep values here in sync with net::CanonicalCookie::CookieInclusionStatus.
+enum CookieInclusionStatus {
+  INCLUDE,
+  EXCLUDE_HTTP_ONLY,
+  EXCLUDE_SECURE_ONLY,
+  EXCLUDE_DOMAIN_MISMATCH,
+  EXCLUDE_NOT_ON_PATH,
+  EXCLUDE_SAMESITE_STRICT,
+  EXCLUDE_SAMESITE_LAX,
+  EXCLUDE_USER_PREFERENCES,
+
+  // Statuses specific to setting cookies
+  EXCLUDE_FAILURE_TO_STORE,
+  EXCLUDE_NONCOOKIEABLE_SCHEME,
+  EXCLUDE_OVERWRITE_SECURE,
+  EXCLUDE_OVERWRITE_HTTP_ONLY,
+  EXCLUDE_INVALID_DOMAIN,
+  EXCLUDE_INVALID_PREFIX,
+
+  // Please keep last
+  EXCLUDE_UNKNOWN_ERROR
+};
+
+struct CookieWithStatus {
+  CanonicalCookie cookie;
+  CookieInclusionStatus status;
+};
+
 // Keep values here in sync with net::CookieStore::ChangeCause.
 // (Not typemapped to avoid forcing clients to know about net::CookieStore.)
 enum CookieChangeCause {
diff --git a/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc b/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
index 2e23798..53ea196a 100644
--- a/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
+++ b/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
@@ -150,7 +150,7 @@
 
   if (type_ == service_manager::SANDBOX_TYPE_NO_SANDBOX) {
     options->spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_JOB;
-    options->clear_environ = false;
+    options->clear_environment = false;
     return;
   }
 
@@ -162,7 +162,7 @@
 
   // Clear environmental variables to better isolate the child from
   // this process.
-  options->clear_environ = true;
+  options->clear_environment = true;
 
   // Don't clone anything by default.
   options->spawn_flags = 0;
diff --git a/services/shape_detection/barcode_detection_impl_mac_unittest.mm b/services/shape_detection/barcode_detection_impl_mac_unittest.mm
index 9420444d..762662c 100644
--- a/services/shape_detection/barcode_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/barcode_detection_impl_mac_unittest.mm
@@ -47,8 +47,10 @@
 std::unique_ptr<mojom::BarcodeDetection> CreateBarcodeDetectorImplMacVision(
     mojom::BarcodeDetectorOptionsPtr options) {
   if (@available(macOS 10.13, *)) {
-    return std::make_unique<BarcodeDetectionImplMacVision>(
-        mojom::BarcodeDetectorOptions::New());
+    if (!BarcodeDetectionImplMacVision::IsBlockedMacOSVersion()) {
+      return std::make_unique<BarcodeDetectionImplMacVision>(
+          mojom::BarcodeDetectorOptions::New());
+    }
   }
   return nullptr;
 }
diff --git a/services/shape_detection/barcode_detection_impl_mac_vision.h b/services/shape_detection/barcode_detection_impl_mac_vision.h
index 3867926..beed4e5 100644
--- a/services/shape_detection/barcode_detection_impl_mac_vision.h
+++ b/services/shape_detection/barcode_detection_impl_mac_vision.h
@@ -26,6 +26,8 @@
 class API_AVAILABLE(macos(10.13)) BarcodeDetectionImplMacVision
     : public mojom::BarcodeDetection {
  public:
+  static bool IsBlockedMacOSVersion();
+
   explicit BarcodeDetectionImplMacVision(
       mojom::BarcodeDetectorOptionsPtr options);
   ~BarcodeDetectionImplMacVision() override;
diff --git a/services/shape_detection/barcode_detection_impl_mac_vision.mm b/services/shape_detection/barcode_detection_impl_mac_vision.mm
index d6c5f68..fcedfec 100644
--- a/services/shape_detection/barcode_detection_impl_mac_vision.mm
+++ b/services/shape_detection/barcode_detection_impl_mac_vision.mm
@@ -45,6 +45,15 @@
 
 }  // unnamed namespace
 
+// static
+bool BarcodeDetectionImplMacVision::IsBlockedMacOSVersion() {
+  static NSOperatingSystemVersion version =
+      [[NSProcessInfo processInfo] operatingSystemVersion];
+  DCHECK_EQ(version.majorVersion, 10);
+  // Vision Framework doesn't work properly on 10.14.{0,1,2}: crbug.com/921968.
+  return version.minorVersion == 14 && version.patchVersion < 3;
+}
+
 BarcodeDetectionImplMacVision::BarcodeDetectionImplMacVision(
     mojom::BarcodeDetectorOptionsPtr options)
     : weak_factory_(this) {
diff --git a/services/shape_detection/barcode_detection_provider_mac.mm b/services/shape_detection/barcode_detection_provider_mac.mm
index d57e702..f0a7a39 100644
--- a/services/shape_detection/barcode_detection_provider_mac.mm
+++ b/services/shape_detection/barcode_detection_provider_mac.mm
@@ -28,15 +28,16 @@
 void BarcodeDetectionProviderMac::CreateBarcodeDetection(
     mojom::BarcodeDetectionRequest request,
     mojom::BarcodeDetectorOptionsPtr options) {
-  // Vision Framework needs at least MAC OS X 10.13. Stay vigilant: past OS
-  // upgrades (e.g. to 10.14, see crbug.com/921968) have broken it.
+  // Vision Framework needs at least MAC OS X 10.13.
   if (@available(macOS 10.13, *)) {
-    auto impl =
-        std::make_unique<BarcodeDetectionImplMacVision>(std::move(options));
-    auto* impl_ptr = impl.get();
-    impl_ptr->SetBinding(
-        mojo::MakeStrongBinding(std::move(impl), std::move(request)));
-    return;
+    if (!BarcodeDetectionImplMacVision::IsBlockedMacOSVersion()) {
+      auto impl =
+          std::make_unique<BarcodeDetectionImplMacVision>(std::move(options));
+      auto* impl_ptr = impl.get();
+      impl_ptr->SetBinding(
+          mojo::MakeStrongBinding(std::move(impl), std::move(request)));
+      return;
+    }
   }
 
   // CIDetector barcode detection needs at least MAC OS X 10.10.
@@ -50,15 +51,17 @@
     EnumerateSupportedFormatsCallback callback) {
   // Vision Framework needs at least MAC OS X 10.13.
   if (@available(macOS 10.13, *)) {
-    // Vision recognizes more barcode symbologies than Core Image Framework.
-    std::move(callback).Run(
-        {mojom::BarcodeFormat::AZTEC, mojom::BarcodeFormat::CODE_128,
-         mojom::BarcodeFormat::CODE_39, mojom::BarcodeFormat::CODE_93,
-         mojom::BarcodeFormat::DATA_MATRIX, mojom::BarcodeFormat::EAN_13,
-         mojom::BarcodeFormat::EAN_8, mojom::BarcodeFormat::ITF,
-         mojom::BarcodeFormat::PDF417, mojom::BarcodeFormat::QR_CODE,
-         mojom::BarcodeFormat::UPC_E});
-    return;
+    if (!BarcodeDetectionImplMacVision::IsBlockedMacOSVersion()) {
+      // Vision recognizes more barcode symbologies than Core Image Framework.
+      std::move(callback).Run(
+          {mojom::BarcodeFormat::AZTEC, mojom::BarcodeFormat::CODE_128,
+           mojom::BarcodeFormat::CODE_39, mojom::BarcodeFormat::CODE_93,
+           mojom::BarcodeFormat::DATA_MATRIX, mojom::BarcodeFormat::EAN_13,
+           mojom::BarcodeFormat::EAN_8, mojom::BarcodeFormat::ITF,
+           mojom::BarcodeFormat::PDF417, mojom::BarcodeFormat::QR_CODE,
+           mojom::BarcodeFormat::UPC_E});
+      return;
+    }
   }
 
   // Barcode detection needs at least MAC OS X 10.10.
diff --git a/services/shape_detection/barcode_detection_provider_mac_unittest.mm b/services/shape_detection/barcode_detection_provider_mac_unittest.mm
index 0c2d710..ad85660 100644
--- a/services/shape_detection/barcode_detection_provider_mac_unittest.mm
+++ b/services/shape_detection/barcode_detection_provider_mac_unittest.mm
@@ -12,6 +12,7 @@
 #include "base/callback_forward.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "services/shape_detection/barcode_detection_impl_mac_vision.h"
 #include "services/shape_detection/barcode_detection_provider_mac.h"
 #include "services/shape_detection/public/mojom/barcodedetection_provider.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -59,12 +60,14 @@
   void SetUp() override {
     bool is_vision_available = false;
     if (@available(macOS 10.13, *)) {
-      is_vision_available = true;
+      if (!BarcodeDetectionImplMacVision::IsBlockedMacOSVersion()) {
+        is_vision_available = true;
 
-      // Only load Vision if we're testing it.
-      if (GetParam().test_vision_api) {
-        vision_framework_ = dlopen(
-            "/System/Library/Frameworks/Vision.framework/Vision", RTLD_LAZY);
+        // Only load Vision if we're testing it.
+        if (GetParam().test_vision_api) {
+          vision_framework_ = dlopen(
+              "/System/Library/Frameworks/Vision.framework/Vision", RTLD_LAZY);
+        }
       }
     }
     valid_combination_ = is_vision_available == GetParam().test_vision_api;
diff --git a/services/tracing/public/cpp/tracing_features.cc b/services/tracing/public/cpp/tracing_features.cc
index 08887d9..d94c5d6 100644
--- a/services/tracing/public/cpp/tracing_features.cc
+++ b/services/tracing/public/cpp/tracing_features.cc
@@ -34,9 +34,17 @@
 namespace tracing {
 
 bool TracingUsesPerfettoBackend() {
+  // This is checked early at startup, so feature list may not be initialized.
+  // So, for startup tracing cases there is no way to control the backend using
+  // feature list.
+  // TODO(oysteine): Fix this to return true when perfetto is enabled by
+  // default.
+  if (base::FeatureList::GetInstance() &&
+      base::FeatureList::IsEnabled(features::kTracingPerfettoBackend)) {
+    return true;
+  }
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
-             switches::kEnablePerfetto) ||
-         base::FeatureList::IsEnabled(features::kTracingPerfettoBackend);
+      switches::kEnablePerfetto);
 }
 
 }  // namespace tracing
diff --git a/services/video_capture/device_factory_provider_impl.cc b/services/video_capture/device_factory_provider_impl.cc
index cbb9cfb..0cf03c03 100644
--- a/services/video_capture/device_factory_provider_impl.cc
+++ b/services/video_capture/device_factory_provider_impl.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/task/post_task.h"
+#include "build/build_config.h"
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
 #include "media/capture/video/create_video_capture_device_factory.h"
 #include "media/capture/video/fake_video_capture_device_factory.h"
@@ -19,6 +20,10 @@
 #include "services/video_capture/virtual_device_enabled_device_factory.h"
 #include "services/ws/public/cpp/gpu/gpu.h"
 
+#if defined(OS_MACOSX)
+#include "media/capture/video/mac/video_capture_device_factory_mac.h"
+#endif
+
 namespace video_capture {
 
 // Intended usage of this class is to instantiate on any sequence, and then
@@ -125,6 +130,12 @@
     std::move(request_service_quit_asap_cb_).Run();
 }
 
+void DeviceFactoryProviderImpl::SetRetryCount(int32_t count) {
+#if defined(OS_MACOSX)
+  media::VideoCaptureDeviceFactoryMac::SetGetDeviceDescriptorsRetryCount(count);
+#endif
+}
+
 void DeviceFactoryProviderImpl::LazyInitializeGpuDependenciesContext() {
   if (!gpu_dependencies_context_)
     gpu_dependencies_context_ = std::make_unique<GpuDependenciesContext>();
diff --git a/services/video_capture/device_factory_provider_impl.h b/services/video_capture/device_factory_provider_impl.h
index 5000a6a0..64d42126 100644
--- a/services/video_capture/device_factory_provider_impl.h
+++ b/services/video_capture/device_factory_provider_impl.h
@@ -43,6 +43,7 @@
   void ConnectToVideoSourceProvider(
       mojom::VideoSourceProviderRequest request) override;
   void ShutdownServiceAsap() override;
+  void SetRetryCount(int32_t count) override;
 
 #if defined(OS_CHROMEOS)
   void BindCrosImageCaptureRequest(
diff --git a/services/video_capture/public/cpp/mock_device_factory_provider.h b/services/video_capture/public/cpp/mock_device_factory_provider.h
index d9dfe83..45c1e01 100644
--- a/services/video_capture/public/cpp/mock_device_factory_provider.h
+++ b/services/video_capture/public/cpp/mock_device_factory_provider.h
@@ -34,6 +34,7 @@
   MOCK_METHOD1(DoConnectToVideoSourceProvider,
                void(video_capture::mojom::VideoSourceProviderRequest& request));
   MOCK_METHOD0(ShutdownServiceAsap, void());
+  MOCK_METHOD1(SetRetryCount, void(int32_t));
 };
 
 }  // namespace video_capture
diff --git a/services/video_capture/public/mojom/device_factory_provider.mojom b/services/video_capture/public/mojom/device_factory_provider.mojom
index 01b68f8..f350cce 100644
--- a/services/video_capture/public/mojom/device_factory_provider.mojom
+++ b/services/video_capture/public/mojom/device_factory_provider.mojom
@@ -35,4 +35,8 @@
   // Lets the service to close all connections and ask the service_manager to be
   // shut down.
   ShutdownServiceAsap();
+
+  // Sets a retry count that is used by the service for logging UMA events in
+  // the context of investigation for https://crbug.com/643068.
+  SetRetryCount(int32 count);
 };
diff --git a/services/video_capture/public/mojom/receiver.mojom b/services/video_capture/public/mojom/receiver.mojom
index 676a80a..2160cc7 100644
--- a/services/video_capture/public/mojom/receiver.mojom
+++ b/services/video_capture/public/mojom/receiver.mojom
@@ -7,18 +7,48 @@
 import "media/capture/mojom/video_capture_types.mojom";
 import "services/video_capture/public/mojom/scoped_access_permission.mojom";
 
-// Callback interface for receiving data and messages from a started
-// video_capture.mojom.Device.
+// Callback interface for receiving data and messages from a
+// video_capture.mojom.Device or
+// video_capture.mojom.PushVideoStreamSubscription.
 interface Receiver {
+  // Indicates that the producer is going to subsequently use the provided
+  // buffer as one of possibly many for frame delivery via
+  // OnFrameReadyInBuffer(). Note, that a call to this method does not mean that
+  // the caller allows the receiver to read from or write to the buffer just
+  // yet. Temporary permission to read will be given with subsequent calls to
+  // OnFrameReadyInBuffer().
   OnNewBuffer(int32 buffer_id, media.mojom.VideoBufferHandle buffer_handle);
+
+  // Indicates that a new frame is ready for consumption in the buffer with id
+  // |buffer_id| and allows it to read the data from the buffer. The producer
+  // guarantees that the buffer and its contents stay alive and unchanged until
+  // VideoFrameReceiver releases the given |access_permission|.
   OnFrameReadyInBuffer(int32 buffer_id, int32 frame_feedback_id,
                        ScopedAccessPermission access_permission,
                        media.mojom.VideoFrameInfo frame_info);
+
+  // Indicates that the producer is no longer going to use the buffer with id
+  // |buffer_id| for frame delivery. This may be called even while the receiver
+  // is still holding |access_permission| from a call to OnFrameReadInBuffer()
+  // for the same buffer. In that case, it means that the caller is asking the
+  // VideoFrameReceiver to release the read permission and buffer handle at its
+  //  earliest convenience. After this call, a producer may immediately reuse
+  // the retired |buffer_id| with a new buffer via a call to OnNewBuffer().
   OnBufferRetired(int32 buffer_id);
+
+  // Indicates that an error occurred on the producer side.
   OnError(media.mojom.VideoCaptureError error);
+
   OnFrameDropped(media.mojom.VideoCaptureFrameDropReason reason);
   OnLog(string message);
+
+  // Indicates that the producer side has started successfully. The producer
+  // guarantees that this is called before any call to OnFrameReadyInBuffer().
   OnStarted();
+
   OnStartedUsingGpuDecode();
+
+  // Indicates that the producer side has stopped and is not going to make any
+  // further calls to this Receiver.
   OnStopped();
 };
diff --git a/services/video_capture/public/uma/video_capture_service_event.cc b/services/video_capture/public/uma/video_capture_service_event.cc
index f8ab7e80..1498d9e 100644
--- a/services/video_capture/public/uma/video_capture_service_event.cc
+++ b/services/video_capture/public/uma/video_capture_service_event.cc
@@ -56,5 +56,14 @@
   DVLOG(4) << "Logged DurationUntilReconnectAfterCapture";
 }
 
+#if defined(OS_MACOSX)
+void LogMacbookRetryGetDeviceInfosEvent(MacbookRetryGetDeviceInfosEvent event) {
+  UMA_HISTOGRAM_ENUMERATION(
+      "Media.VideoCapture.MacBook.RetryGetDeviceInfosEvent", event,
+      NUM_RETRY_GET_DEVICE_INFOS_EVENT);
+  DVLOG(4) << "Logged MacbookRetryGetDeviceInfosEvent " << event;
+}
+#endif
+
 }  // namespace uma
 }  // namespace video_capture
diff --git a/services/video_capture/public/uma/video_capture_service_event.h b/services/video_capture/public/uma/video_capture_service_event.h
index 5f5dcc0..963a1ea 100644
--- a/services/video_capture/public/uma/video_capture_service_event.h
+++ b/services/video_capture/public/uma/video_capture_service_event.h
@@ -6,6 +6,7 @@
 #define SERVICES_VIDEO_CAPTURE_VIDEO_CAPTURE_SERVICE_EVENT_H_
 
 #include "base/time/time.h"
+#include "build/build_config.h"
 
 namespace video_capture {
 namespace uma {
@@ -28,6 +29,25 @@
   NUM_VIDEO_CAPTURE_SERVICE_EVENT
 };
 
+#if defined(OS_MACOSX)
+enum MacbookRetryGetDeviceInfosEvent {
+  PROVIDER_RECEIVED_ZERO_INFOS_STOPPING_SERVICE = 0,
+  PROVIDER_SERVICE_STOPPED_ISSUING_RETRY = 1,
+  PROVIDER_RECEIVED_ZERO_INFOS_FROM_RETRY_GIVING_UP = 2,
+  PROVIDER_RECEIVED_NONZERO_INFOS_FROM_RETRY = 3,
+  PROVIDER_NOT_ATTEMPTING_RETRY_BECAUSE_ALREADY_PENDING = 4,
+  AVF_RECEIVED_ZERO_INFOS_FIRST_TRY_FIRST_ATTEMPT = 5,
+  AVF_RECEIVED_NONZERO_INFOS_FIRST_TRY_FIRST_ATTEMPT = 6,
+  AVF_RECEIVED_ZERO_INFOS_FIRST_TRY_NONFIRST_ATTEMPT = 7,
+  AVF_RECEIVED_NONZERO_INFOS_FIRST_TRY_NONFIRST_ATTEMPT = 8,
+  AVF_RECEIVED_ZERO_INFOS_RETRY = 9,
+  AVF_RECEIVED_NONZERO_INFOS_RETRY = 10,
+  AVF_DEVICE_COUNT_CHANGED_FROM_ZERO_TO_POSITIVE = 11,
+  AVF_DEVICE_COUNT_CHANGED_FROM_POSITIVE_TO_ZERO = 12,
+  NUM_RETRY_GET_DEVICE_INFOS_EVENT
+};
+#endif
+
 void LogVideoCaptureServiceEvent(VideoCaptureServiceEvent event);
 
 void LogDurationFromLastConnectToClosingConnectionAfterEnumerationOnly(
@@ -38,6 +58,10 @@
 void LogDurationUntilReconnectAfterEnumerationOnly(base::TimeDelta duration);
 void LogDurationUntilReconnectAfterCapture(base::TimeDelta duration);
 
+#if defined(OS_MACOSX)
+void LogMacbookRetryGetDeviceInfosEvent(MacbookRetryGetDeviceInfosEvent event);
+#endif
+
 }  // namespace uma
 }  // namespace video_capture
 
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 6fe5c8f4..49ba297 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -5876,30 +5876,35 @@
     ],
     "gtest_tests": [
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "accessibility_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "angle_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "app_list_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "app_shell_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -5909,6 +5914,7 @@
         "args": [
           "--disable-features=SingleProcessMash"
         ],
+        "isolate_coverage_data": true,
         "name": "non_single_process_mash_ash_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -5916,42 +5922,49 @@
         "test": "ash_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "aura_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "base_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "blink_common_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "blink_fuzzer_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "blink_heap_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "blink_platform_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "name": "webkit_unit_tests",
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -5959,18 +5972,21 @@
         "test": "blink_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "boringssl_crypto_tests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "boringssl_ssl_tests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 10
@@ -5984,6 +6000,7 @@
           "--override-use-software-gl-for-tests",
           "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.mash.browser_tests.filter"
         ],
+        "isolate_coverage_data": true,
         "name": "mash_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -5996,6 +6013,7 @@
           "--disable-features=SingleProcessMash",
           "--override-use-software-gl-for-tests"
         ],
+        "isolate_coverage_data": true,
         "name": "non_single_process_mash_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6007,6 +6025,7 @@
         "args": [
           "--enable-features=VizDisplayCompositor"
         ],
+        "isolate_coverage_data": true,
         "name": "viz_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6019,6 +6038,7 @@
           "--disable-features=WebUIPolymer2",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer1_browser_tests.filter"
         ],
+        "isolate_coverage_data": true,
         "name": "webui_polymer1_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6027,6 +6047,7 @@
         "test": "browser_tests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -6036,66 +6057,77 @@
         "args": [
           "--gtest_filter=-*UsingRealWebcam*"
         ],
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "capture_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "cast_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "cc_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "chrome_app_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "chromedriver_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "chromeos_components_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "chromeos_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "components_browsertests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "components_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "compositor_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 6
@@ -6107,6 +6139,7 @@
           "--disable-features=SingleProcessMash",
           "--override-use-software-gl-for-tests"
         ],
+        "isolate_coverage_data": true,
         "name": "non_single_process_mash_content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6119,6 +6152,7 @@
           "--enable-perfetto",
           "--gtest_filter=TracingControllerTest.*"
         ],
+        "isolate_coverage_data": true,
         "name": "perfetto_content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -6129,6 +6163,7 @@
         "args": [
           "--enable-features=VizDisplayCompositor"
         ],
+        "isolate_coverage_data": true,
         "name": "viz_content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6137,6 +6172,7 @@
         "test": "content_browsertests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -6146,6 +6182,7 @@
         "args": [
           "--disable-features=SingleProcessMash"
         ],
+        "isolate_coverage_data": true,
         "name": "non_single_process_mash_content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -6156,6 +6193,7 @@
         "args": [
           "--enable-features=VizDisplayCompositor"
         ],
+        "isolate_coverage_data": true,
         "name": "viz_content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -6163,36 +6201,42 @@
         "test": "content_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "crypto_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "dbus_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "device_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "display_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "events_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -6202,6 +6246,7 @@
         "args": [
           "--disable-features=SingleProcessMash"
         ],
+        "isolate_coverage_data": true,
         "name": "non_single_process_mash_exo_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -6209,60 +6254,70 @@
         "test": "exo_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "extensions_browsertests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "extensions_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "filesystem_service_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "gcm_unit_tests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "gfx_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "gin_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "gl_unittests_ozone"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "google_apis_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "gpu_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 3
@@ -6273,6 +6328,7 @@
         "args": [
           "--disable-features=SingleProcessMash"
         ],
+        "isolate_coverage_data": true,
         "name": "non_single_process_mash_interactive_ui_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6285,6 +6341,7 @@
           "--disable-features=WebUIPolymer2",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer1_interactive_ui_tests.filter"
         ],
+        "isolate_coverage_data": true,
         "name": "webui_polymer1_interactive_ui_tests",
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -6292,102 +6349,119 @@
         "test": "interactive_ui_tests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ipc_tests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "jingle_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "keyboard_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "latency_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "leveldb_service_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "libjingle_xmpp_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "media_blink_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "media_service_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "media_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "message_center_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "midi_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "mojo_core_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "mojo_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "nacl_helper_nonsfi_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "nacl_loader_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "native_theme_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -6397,126 +6471,147 @@
         "args": [
           "--ozone-platform=headless"
         ],
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ozone_gl_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ozone_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ozone_x11_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "pdf_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ppapi_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "printing_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "remoting_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "sandbox_linux_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "service_manager_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "services_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "shell_dialogs_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "skia_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "snapshot_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "sql_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "storage_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "sync_integration_tests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "traffic_annotation_auditor_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ui_base_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ui_chromeos_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ui_touch_selection_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -6526,6 +6621,7 @@
         "args": [
           "--disable-features=SingleProcessMash"
         ],
+        "isolate_coverage_data": true,
         "name": "non_single_process_mash_unit_tests",
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -6533,6 +6629,7 @@
         "test": "unit_tests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -6540,36 +6637,42 @@
       },
       {
         "experiment_percentage": 100,
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "usage_time_limit_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "views_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "viz_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "wayland_client_perftests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "wm_unittests"
       },
       {
+        "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
         },
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index eea14d007..171429d 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -288,6 +288,33 @@
           "--browser=release",
           "--passthrough",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl2_conformance_d3d11_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-24.20.100.6286",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false,
+          "shards": 20
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -799,33 +826,6 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating",
-          "--webgl-conformance-version=2.0.1",
-          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl2_conformance_d3d11_validating_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-24.21.14.1195",
-              "os": "Windows-10",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "idempotent": false,
-          "shards": 20
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=release",
-          "--passthrough",
-          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -895,7 +895,7 @@
             }
           ],
           "idempotent": false,
-          "shards": 6
+          "shards": 2
         }
       },
       {
@@ -945,7 +945,7 @@
             }
           ],
           "idempotent": false,
-          "shards": 6
+          "shards": 2
         }
       },
       {
@@ -972,6 +972,31 @@
           "idempotent": false,
           "shards": 2
         }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-24.21.14.1195",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false,
+          "shards": 2
+        }
       }
     ]
   },
@@ -17813,7 +17838,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "name": "webgl_conformance_d3d11_validating_tests",
@@ -17896,7 +17921,7 @@
             }
           ],
           "idempotent": false,
-          "shards": 6
+          "shards": 2
         },
         "trigger_script": {
           "args": [
@@ -17941,6 +17966,40 @@
           ],
           "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py"
         }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl_conformance_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-24.21.14.1195",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false,
+          "shards": 2
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-trigger-configs",
+            "[{\"gpu\": \"10de:1cb3-24.21.14.1195\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]",
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py"
+        }
       }
     ]
   },
@@ -18487,7 +18546,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "name": "webgl_conformance_d3d11_validating_tests",
@@ -18552,7 +18611,7 @@
             }
           ],
           "idempotent": false,
-          "shards": 6
+          "shards": 2
         }
       },
       {
@@ -19228,6 +19287,34 @@
           "--browser=release",
           "--passthrough",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl2_conformance_d3d11_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-24.20.100.6286",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "shards": 20
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -20005,6 +20092,33 @@
           "--browser=release",
           "--passthrough",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "name": "webgl2_conformance_d3d11_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-24.20.100.6286",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false,
+          "shards": 20
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -21068,42 +21182,6 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating",
-          "--webgl-conformance-version=2.0.1",
-          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl2_conformance_d3d11_validating_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-24.21.14.1195",
-              "os": "Windows-10",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "idempotent": false,
-          "shards": 20
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-trigger-configs",
-            "[{\"gpu\": \"10de:1cb3-24.21.14.1195\", \"os\": \"Windows-10\", \"pool\": \"Chrome-GPU\"}]",
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py"
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=release",
-          "--passthrough",
-          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -21176,7 +21254,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "name": "webgl_conformance_d3d11_validating_tests",
@@ -21259,7 +21337,7 @@
             }
           ],
           "idempotent": false,
-          "shards": 6
+          "shards": 2
         },
         "trigger_script": {
           "args": [
@@ -21727,10 +21805,10 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9 --use-cmd-decoder=passthrough"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_d3d11_validating_tests",
+        "name": "webgl_conformance_d3d9_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -21753,10 +21831,10 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9 --use-cmd-decoder=passthrough"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_d3d9_passthrough_tests",
+        "name": "webgl_conformance_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -22335,7 +22413,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "name": "webgl_conformance_d3d11_validating_tests",
@@ -22403,7 +22481,7 @@
           ],
           "expiration": 21600,
           "idempotent": false,
-          "shards": 6
+          "shards": 2
         }
       },
       {
@@ -23018,32 +23096,6 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_d3d11_validating_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "1002:6613",
-              "os": "Windows-2008ServerR2-SP1",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "expiration": 21600,
-          "idempotent": false,
-          "shards": 2
-        }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=release",
-          "--passthrough",
-          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9 --use-cmd-decoder=passthrough"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -23086,7 +23138,7 @@
           ],
           "expiration": 21600,
           "idempotent": false,
-          "shards": 6
+          "shards": 2
         }
       },
       {
@@ -23961,7 +24013,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "name": "webgl_conformance_d3d11_validating_tests",
@@ -24047,7 +24099,7 @@
           ],
           "expiration": 21600,
           "idempotent": false,
-          "shards": 6
+          "shards": 2
         },
         "trigger_script": {
           "args": [
@@ -24995,7 +25047,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "name": "webgl_conformance_d3d11_validating_tests",
@@ -25081,7 +25133,7 @@
           ],
           "expiration": 21600,
           "idempotent": false,
-          "shards": 6
+          "shards": 2
         },
         "trigger_script": {
           "args": [
diff --git a/testing/buildbot/filters/mojo.fyi.network_webview_CTS_test.filter b/testing/buildbot/filters/mojo.fyi.network_webview_CTS_test.filter
index d27c318a..901451c 100644
--- a/testing/buildbot/filters/mojo.fyi.network_webview_CTS_test.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_webview_CTS_test.filter
@@ -12,9 +12,6 @@
 
 # Tests that fail with NetworkService feature enabled. https://crbug.com/923938
 
-# https://crbug.com/937388
--android.webkit.cts.WebViewClientTest.testOnReceivedError
-
 # https://crbug.com/937417
 -android.webkit.cts.WebViewClientTest.testShouldOverrideUrlLoading
 
diff --git a/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter b/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter
index 0eb8c8f7..506ebb08 100644
--- a/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter
@@ -24,6 +24,10 @@
 -org.chromium.android_webview.test.CookieManagerTest.testCookieForWebSocketHandshake_firstParty_disabled
 -org.chromium.android_webview.test.CookieManagerTest.testCookieForWebSocketHandshake_thirdParty_disabled
 
+# https://crbug.com/941337
+-org.chromium.android_webview.test.CookieManagerTest.testThirdPartyCookie_redirectFromThirdToFirst
+-org.chromium.android_webview.test.CookieManagerTest.testThirdPartyCookie_redirectFromFirstPartyToThird
+
 # https://crbug.com/893580
 -org.chromium.android_webview.test.LoadDataWithBaseUrlTest.testLoadDataWithBaseUrlAccessingFile
 
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index b3d3a078..bbe9599 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3213,11 +3213,7 @@
     },
 
     'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests': {
-      'webgl_conformance_d3d11_validating': {
-        'telemetry_test_name': 'webgl_conformance',
-        'args': [
-          '--extra-browser-args=--use-angle=d3d11 --use-cmd-decoder=validating',
-        ],
+      'webgl_conformance': {
         'swarming': {
           'shards': 2,
         },
@@ -3261,27 +3257,6 @@
       },
     },
 
-    'gpu_fyi_and_optional_win_intel_specific_gpu_telemetry_tests': {
-      'webgl_conformance_d3d9_passthrough': {
-        'telemetry_test_name': 'webgl_conformance',
-        'args': [
-          '--extra-browser-args=--use-angle=d3d9 --use-cmd-decoder=passthrough',
-        ],
-        'swarming': {
-          'shards': 2,
-        },
-      },
-      'webgl_conformance_vulkan_passthrough': {
-        'telemetry_test_name': 'webgl_conformance',
-        'args': [
-          '--extra-browser-args=--use-angle=vulkan --use-cmd-decoder=passthrough',
-        ],
-        'swarming': {
-          'shards': 2,
-        },
-      },
-    },
-
     'gpu_fyi_and_optional_win_specific_gtests': {
       'angle_gles1_conformance_tests': {
         'args': ['--use-gpu-in-tests']
@@ -3347,6 +3322,25 @@
       },
     },
 
+    'gpu_fyi_only_win_intel_specific_telemetry_tests': {
+      'webgl2_conformance_d3d11_validating_tests': {
+        'args': [
+          '--webgl-conformance-version=2.0.1',
+          # The current working directory when run via isolate is
+          # out/Debug or out/Release. Reference this file relatively to
+          # it.
+          '--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json',
+          '--extra-browser-args=--use-angle=d3d11 --use-cmd-decoder=validating',
+        ],
+        'telemetry_test_name': 'webgl_conformance',
+        'swarming': {
+          # These tests currently take about an hour and fifteen minutes
+          # to run. Split them into roughly 5-minute shards.
+          'shards': 20,
+        },
+      },
+    },
+
     'gpu_fyi_only_win_linux_intel_nvidia_specific_telemetry_tests': {
       'webgl2_conformance_gl_passthrough_tests': {
         'telemetry_test_name': 'webgl_conformance',
@@ -3366,25 +3360,6 @@
       },
     },
 
-    'gpu_fyi_only_win_nvidia_release_specific_telemetry_tests': {
-      'webgl2_conformance_d3d11_validating_tests': {
-        'args': [
-          '--webgl-conformance-version=2.0.1',
-          # The current working directory when run via isolate is
-          # out/Debug or out/Release. Reference this file relatively to
-          # it.
-          '--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json',
-          '--extra-browser-args=--use-angle=d3d11 --use-cmd-decoder=validating',
-        ],
-        'telemetry_test_name': 'webgl_conformance',
-        'swarming': {
-          # These tests currently take about an hour and fifteen minutes
-          # to run. Split them into roughly 5-minute shards.
-          'shards': 20,
-        },
-      },
-    },
-
     'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests': {
       'webgl2_conformance_tests': {
         'telemetry_test_name': 'webgl_conformance',
@@ -3473,14 +3448,6 @@
       }
     },
 
-    'gpu_optional_and_angle_win_intel_specific_gpu_telemetry_tests': {
-      'webgl_conformance': {
-        'swarming': {
-          'shards': 2,
-        },
-      },
-    },
-
     'gpu_telemetry_tests': {
       'context_lost': {},
       'depth_capture': {},
@@ -3587,7 +3554,7 @@
           '--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=validating',
         ],
         'swarming': {
-          'shards': 6,
+          'shards': 2,
         },
       },
     },
@@ -3599,7 +3566,7 @@
           '--extra-browser-args=--use-gl=angle --use-angle=d3d9 --use-cmd-decoder=validating',
         ],
         'swarming': {
-          'shards': 6,
+          'shards': 2,
         },
       },
     },
@@ -4747,18 +4714,17 @@
 
     'gpu_angle_win_intel_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_fyi_and_optional_win_intel_specific_gpu_telemetry_tests',
+      'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests',
       'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests',
+      'gpu_fyi_only_win_intel_specific_telemetry_tests',
       'gpu_fyi_only_win_linux_intel_nvidia_specific_telemetry_tests',
       'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests',
-      'gpu_optional_and_angle_win_intel_specific_gpu_telemetry_tests',
     ],
 
     'gpu_angle_win_nvidia_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
       'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests',
       'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests',
-      'gpu_fyi_only_win_nvidia_release_specific_telemetry_tests',
       'gpu_fyi_only_win_linux_intel_nvidia_specific_telemetry_tests',
       'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests',
       'gpu_webgl_conformance_d3d11_validating_tests',
@@ -4891,6 +4857,7 @@
       'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests',
       'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests',
       'gpu_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_validating_tests',
       'gpu_webgl_conformance_d3d9_validating_tests',
     ],
 
@@ -4921,6 +4888,7 @@
       'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests',
       'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests',
       'gpu_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_validating_tests',
       'gpu_webgl_conformance_d3d9_validating_tests',
     ],
 
@@ -4940,8 +4908,9 @@
 
     'gpu_fyi_win_intel_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_fyi_and_optional_win_intel_specific_gpu_telemetry_tests',
+      'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests',
       'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests',
+      'gpu_fyi_only_win_intel_specific_telemetry_tests',
       'gpu_fyi_only_win_linux_intel_nvidia_specific_telemetry_tests',
       'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests',
       'gpu_telemetry_tests',
@@ -4962,10 +4931,10 @@
       'gpu_common_and_optional_telemetry_tests',
       'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests',
       'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests',
-      'gpu_fyi_only_win_nvidia_release_specific_telemetry_tests',
       'gpu_fyi_only_win_linux_intel_nvidia_specific_telemetry_tests',
       'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests',
       'gpu_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_validating_tests',
       'gpu_webgl_conformance_d3d9_validating_tests',
     ],
 
@@ -4977,11 +4946,10 @@
 
     'gpu_optional_win_intel_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_fyi_and_optional_win_intel_specific_gpu_telemetry_tests',
+      'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests',
       'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests',
       'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests',
       'gpu_win_intel_specific_telemetry_tests',
-      'gpu_optional_and_angle_win_intel_specific_gpu_telemetry_tests',
     ],
 
     'gpu_optional_win_telemetry_tests': [
@@ -4989,6 +4957,7 @@
       'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests',
       'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests',
       'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_validating_tests',
       'gpu_webgl_conformance_d3d9_validating_tests',
     ],
 
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index c3eec97..4087e13 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -1507,6 +1507,9 @@
         },
       },
       'linux-chromeos-code-coverage': {
+        'mixins': [
+            'code-coverage',
+        ],
         'additional_compile_targets': [
           'gn_all',
         ],
diff --git a/third_party/blink/renderer/bindings/bindings.gni b/third_party/blink/renderer/bindings/bindings.gni
index 9eb65cc..0da42a9 100644
--- a/third_party/blink/renderer/bindings/bindings.gni
+++ b/third_party/blink/renderer/bindings/bindings.gni
@@ -56,6 +56,8 @@
                     "core/v8/local_window_proxy.cc",
                     "core/v8/local_window_proxy.h",
                     "core/v8/maplike.h",
+                    "core/v8/module_record.cc",
+                    "core/v8/module_record.h",
                     "core/v8/native_value_traits.h",
                     "core/v8/native_value_traits_impl.h",
                     "core/v8/referrer_script_info.cc",
@@ -83,8 +85,6 @@
                     "core/v8/script_function.h",
                     "core/v8/script_iterator.cc",
                     "core/v8/script_iterator.h",
-                    "core/v8/script_module.cc",
-                    "core/v8/script_module.h",
                     "core/v8/script_promise.cc",
                     "core/v8/script_promise.h",
                     "core/v8/script_promise_property.h",
@@ -191,10 +191,10 @@
           "core/v8/dom_wrapper_world_test.cc",
           "core/v8/initialize_v8_extras_binding_test.cc",
           "core/v8/idl_types_test.cc",
+          "core/v8/module_record_test.cc",
           "core/v8/native_value_traits_impl_test.cc",
           "core/v8/native_value_traits_test.cc",
           "core/v8/referrer_script_info_test.cc",
-          "core/v8/script_module_test.cc",
           "core/v8/script_promise_property_test.cc",
           "core/v8/script_promise_resolver_test.cc",
           "core/v8/script_promise_test.cc",
diff --git a/third_party/blink/renderer/bindings/core/v8/script_module.cc b/third_party/blink/renderer/bindings/core/v8/module_record.cc
similarity index 84%
rename from third_party/blink/renderer/bindings/core/v8/script_module.cc
rename to third_party/blink/renderer/bindings/core/v8/module_record.cc
index d24e43e5..5ecdb23 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_module.cc
+++ b/third_party/blink/renderer/bindings/core/v8/module_record.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 
 #include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
-#include "third_party/blink/renderer/core/script/script_module_resolver.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
@@ -17,7 +17,7 @@
 
 namespace blink {
 
-ScriptModuleProduceCacheData::ScriptModuleProduceCacheData(
+ModuleRecordProduceCacheData::ModuleRecordProduceCacheData(
     v8::Isolate* isolate,
     SingleCachedMetadataHandler* cache_handler,
     V8CodeCache::ProduceCacheOptions produce_cache_options,
@@ -36,14 +36,14 @@
   }
 }
 
-void ScriptModuleProduceCacheData::Trace(blink::Visitor* visitor) {
+void ModuleRecordProduceCacheData::Trace(blink::Visitor* visitor) {
   visitor->Trace(cache_handler_);
   visitor->Trace(unbound_script_.UnsafeCast<v8::Value>());
 }
 
-ScriptModule::ScriptModule() = default;
+ModuleRecord::ModuleRecord() = default;
 
-ScriptModule::ScriptModule(v8::Isolate* isolate,
+ModuleRecord::ModuleRecord(v8::Isolate* isolate,
                            v8::Local<v8::Module> module,
                            const KURL& source_url)
     : module_(SharedPersistent<v8::Module>::Create(module, isolate)),
@@ -52,9 +52,9 @@
   DCHECK(!module_->IsEmpty());
 }
 
-ScriptModule::~ScriptModule() = default;
+ModuleRecord::~ModuleRecord() = default;
 
-ScriptModule ScriptModule::Compile(
+ModuleRecord ModuleRecord::Compile(
     v8::Isolate* isolate,
     const String& source,
     const KURL& source_url,
@@ -65,7 +65,7 @@
     V8CacheOptions v8_cache_options,
     SingleCachedMetadataHandler* cache_handler,
     ScriptSourceLocationType source_location_type,
-    ScriptModuleProduceCacheData** out_produce_cache_data) {
+    ModuleRecordProduceCacheData** out_produce_cache_data) {
   v8::TryCatch try_catch(isolate);
   v8::Local<v8::Module> module;
 
@@ -90,20 +90,20 @@
            .ToLocal(&module)) {
     DCHECK(try_catch.HasCaught());
     exception_state.RethrowV8Exception(try_catch.Exception());
-    return ScriptModule();
+    return ModuleRecord();
   }
   DCHECK(!try_catch.HasCaught());
 
   if (out_produce_cache_data) {
     *out_produce_cache_data =
-        MakeGarbageCollected<ScriptModuleProduceCacheData>(
+        MakeGarbageCollected<ModuleRecordProduceCacheData>(
             isolate, cache_handler, produce_cache_options, module);
   }
 
-  return ScriptModule(isolate, module, source_url);
+  return ModuleRecord(isolate, module, source_url);
 }
 
-ScriptValue ScriptModule::Instantiate(ScriptState* script_state) {
+ScriptValue ModuleRecord::Instantiate(ScriptState* script_state) {
   v8::Isolate* isolate = script_state->GetIsolate();
   v8::TryCatch try_catch(isolate);
   try_catch.SetVerbose(true);
@@ -123,7 +123,7 @@
   return ScriptValue();
 }
 
-ScriptValue ScriptModule::Evaluate(ScriptState* script_state) const {
+ScriptValue ModuleRecord::Evaluate(ScriptState* script_state) const {
   v8::Isolate* isolate = script_state->GetIsolate();
 
   // Isolate exceptions that occur when executing the code. These exceptions
@@ -146,12 +146,12 @@
   return ScriptValue();
 }
 
-void ScriptModule::ReportException(ScriptState* script_state,
+void ModuleRecord::ReportException(ScriptState* script_state,
                                    v8::Local<v8::Value> exception) {
   V8ScriptRunner::ReportException(script_state->GetIsolate(), exception);
 }
 
-Vector<String> ScriptModule::ModuleRequests(ScriptState* script_state) {
+Vector<String> ModuleRecord::ModuleRequests(ScriptState* script_state) {
   if (IsNull())
     return Vector<String>();
 
@@ -168,7 +168,7 @@
   return ret;
 }
 
-Vector<TextPosition> ScriptModule::ModuleRequestPositions(
+Vector<TextPosition> ModuleRecord::ModuleRequestPositions(
     ScriptState* script_state) {
   if (IsNull())
     return Vector<TextPosition>();
@@ -186,13 +186,13 @@
   return ret;
 }
 
-v8::Local<v8::Value> ScriptModule::V8Namespace(v8::Isolate* isolate) {
+v8::Local<v8::Value> ModuleRecord::V8Namespace(v8::Isolate* isolate) {
   DCHECK(!IsNull());
   v8::Local<v8::Module> module = module_->NewLocal(isolate);
   return module->GetModuleNamespace();
 }
 
-v8::MaybeLocal<v8::Module> ScriptModule::ResolveModuleCallback(
+v8::MaybeLocal<v8::Module> ModuleRecord::ResolveModuleCallback(
     v8::Local<v8::Context> context,
     v8::Local<v8::String> specifier,
     v8::Local<v8::Module> referrer) {
@@ -201,10 +201,10 @@
   DCHECK(modulator);
 
   // TODO(shivanisha): Can a valid source url be passed to the constructor.
-  ScriptModule referrer_record(isolate, referrer, KURL());
+  ModuleRecord referrer_record(isolate, referrer, KURL());
   ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
-                                 "ScriptModule", "resolveModuleCallback");
-  ScriptModule resolved = modulator->GetScriptModuleResolver()->Resolve(
+                                 "ModuleRecord", "resolveModuleCallback");
+  ModuleRecord resolved = modulator->GetModuleRecordResolver()->Resolve(
       ToCoreStringWithNullCheck(specifier), referrer_record, exception_state);
   DCHECK(!resolved.IsNull());
   DCHECK(!exception_state.HadException());
diff --git a/third_party/blink/renderer/bindings/core/v8/script_module.h b/third_party/blink/renderer/bindings/core/v8/module_record.h
similarity index 68%
rename from third_party/blink/renderer/bindings/core/v8/script_module.h
rename to third_party/blink/renderer/bindings/core/v8/module_record.h
index d11e0d6..24caed4 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_module.h
+++ b/third_party/blink/renderer/bindings/core/v8/module_record.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_MODULE_H_
-#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_MODULE_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_MODULE_RECORD_H_
+#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_MODULE_RECORD_H_
 
 #include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
@@ -25,12 +25,12 @@
 class ScriptState;
 class ScriptValue;
 
-// ScriptModuleProduceCacheData is a parameter object for
-// ScriptModule::ProduceCache().
-class CORE_EXPORT ScriptModuleProduceCacheData final
-    : public GarbageCollectedFinalized<ScriptModuleProduceCacheData> {
+// ModuleRecordProduceCacheData is a parameter object for
+// ModuleRecord::ProduceCache().
+class CORE_EXPORT ModuleRecordProduceCacheData final
+    : public GarbageCollectedFinalized<ModuleRecordProduceCacheData> {
  public:
-  ScriptModuleProduceCacheData(v8::Isolate*,
+  ModuleRecordProduceCacheData(v8::Isolate*,
                                SingleCachedMetadataHandler*,
                                V8CodeCache::ProduceCacheOptions,
                                v8::Local<v8::Module>);
@@ -55,18 +55,18 @@
   TraceWrapperV8Reference<v8::UnboundModuleScript> unbound_script_;
 };
 
-// ScriptModule wraps a handle to a v8::Module for use in core.
+// ModuleRecord wraps a handle to a v8::Module for use in core.
 //
-// Using ScriptModules needs a ScriptState and its scope to operate in. You
-// should always provide the same ScriptState and not try to reuse ScriptModules
+// Using ModuleRecords needs a ScriptState and its scope to operate in. You
+// should always provide the same ScriptState and not try to reuse ModuleRecords
 // across different contexts.
-// Currently all ScriptModule users can easily access its context Modulator, so
+// Currently all ModuleRecord users can easily access its context Modulator, so
 // we use it to fill ScriptState in.
-class CORE_EXPORT ScriptModule final {
+class CORE_EXPORT ModuleRecord final {
   DISALLOW_NEW();
 
  public:
-  static ScriptModule Compile(
+  static ModuleRecord Compile(
       v8::Isolate*,
       const String& source,
       const KURL& source_url,
@@ -78,13 +78,13 @@
       SingleCachedMetadataHandler* = nullptr,
       ScriptSourceLocationType source_location_type =
           ScriptSourceLocationType::kInternal,
-      ScriptModuleProduceCacheData** out_produce_cache_data = nullptr);
+      ModuleRecordProduceCacheData** out_produce_cache_data = nullptr);
 
   // TODO(kouhei): Remove copy ctor
-  ScriptModule();
-  ~ScriptModule();
+  ModuleRecord();
+  ~ModuleRecord();
 
-  ScriptModule(v8::Isolate*, v8::Local<v8::Module>, const KURL&);
+  ModuleRecord(v8::Isolate*, v8::Local<v8::Module>, const KURL&);
 
   // Returns exception, if any.
   ScriptValue Instantiate(ScriptState*);
@@ -96,8 +96,8 @@
   Vector<String> ModuleRequests(ScriptState*);
   Vector<TextPosition> ModuleRequestPositions(ScriptState*);
 
-  inline bool operator==(const blink::ScriptModule& other) const;
-  bool operator!=(const blink::ScriptModule& other) const {
+  inline bool operator==(const blink::ModuleRecord& other) const;
+  bool operator!=(const blink::ModuleRecord& other) const {
     return !(*this == other);
   }
 
@@ -107,7 +107,7 @@
 
  private:
   // ModuleScript instances store their record as
-  // TraceWrapperV8Reference<v8::Module>, and reconstructs ScriptModule from it.
+  // TraceWrapperV8Reference<v8::Module>, and reconstructs ModuleRecord from it.
   friend class ModuleScript;
 
   v8::Local<v8::Module> NewLocal(v8::Isolate* isolate) {
@@ -123,20 +123,20 @@
   unsigned identity_hash_ = 0;
   String source_url_;
 
-  friend struct ScriptModuleHash;
-  friend struct WTF::HashTraits<blink::ScriptModule>;
+  friend struct ModuleRecordHash;
+  friend struct WTF::HashTraits<blink::ModuleRecord>;
 };
 
-struct ScriptModuleHash {
-  STATIC_ONLY(ScriptModuleHash);
+struct ModuleRecordHash {
+  STATIC_ONLY(ModuleRecordHash);
 
  public:
-  static unsigned GetHash(const blink::ScriptModule& key) {
+  static unsigned GetHash(const blink::ModuleRecord& key) {
     return key.identity_hash_;
   }
 
-  static bool Equal(const blink::ScriptModule& a,
-                    const blink::ScriptModule& b) {
+  static bool Equal(const blink::ModuleRecord& a,
+                    const blink::ModuleRecord& b) {
     return a == b;
   }
 
@@ -148,19 +148,19 @@
 namespace WTF {
 
 template <>
-struct DefaultHash<blink::ScriptModule> {
-  using Hash = blink::ScriptModuleHash;
+struct DefaultHash<blink::ModuleRecord> {
+  using Hash = blink::ModuleRecordHash;
 };
 
 template <>
-struct HashTraits<blink::ScriptModule>
-    : public SimpleClassHashTraits<blink::ScriptModule> {
-  static bool IsDeletedValue(const blink::ScriptModule& value) {
+struct HashTraits<blink::ModuleRecord>
+    : public SimpleClassHashTraits<blink::ModuleRecord> {
+  static bool IsDeletedValue(const blink::ModuleRecord& value) {
     return HashTraits<scoped_refptr<blink::SharedPersistent<v8::Module>>>::
         IsDeletedValue(value.module_);
   }
 
-  static void ConstructDeletedValue(blink::ScriptModule& slot,
+  static void ConstructDeletedValue(blink::ModuleRecord& slot,
                                     bool zero_value) {
     HashTraits<scoped_refptr<blink::SharedPersistent<v8::Module>>>::
         ConstructDeletedValue(slot.module_, zero_value);
@@ -171,13 +171,13 @@
 
 namespace blink {
 
-inline bool ScriptModule::operator==(const ScriptModule& other) const {
-  if (HashTraits<ScriptModule>::IsDeletedValue(*this) &&
-      HashTraits<ScriptModule>::IsDeletedValue(other))
+inline bool ModuleRecord::operator==(const ModuleRecord& other) const {
+  if (HashTraits<ModuleRecord>::IsDeletedValue(*this) &&
+      HashTraits<ModuleRecord>::IsDeletedValue(other))
     return true;
 
-  if (HashTraits<ScriptModule>::IsDeletedValue(*this) ||
-      HashTraits<ScriptModule>::IsDeletedValue(other))
+  if (HashTraits<ModuleRecord>::IsDeletedValue(*this) ||
+      HashTraits<ModuleRecord>::IsDeletedValue(other))
     return false;
 
   blink::SharedPersistent<v8::Module>* left = module_.get();
@@ -191,4 +191,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_MODULE_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_MODULE_RECORD_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/script_module_test.cc b/third_party/blink/renderer/bindings/core/v8/module_record_test.cc
similarity index 71%
rename from third_party/blink/renderer/bindings/core/v8/script_module_test.cc
rename to third_party/blink/renderer/bindings/core/v8/module_record_test.cc
index d07b2dba..096585e8 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_module_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/module_record_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -11,7 +11,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/script/script_module_resolver.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver.h"
 #include "third_party/blink/renderer/core/testing/dummy_modulator.h"
 #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
 #include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
@@ -21,107 +21,107 @@
 
 namespace {
 
-class TestScriptModuleResolver final : public ScriptModuleResolver {
+class TestModuleRecordResolver final : public ModuleRecordResolver {
  public:
-  TestScriptModuleResolver() = default;
-  ~TestScriptModuleResolver() override = default;
+  TestModuleRecordResolver() = default;
+  ~TestModuleRecordResolver() override = default;
 
   size_t ResolveCount() const { return specifiers_.size(); }
   const Vector<String>& Specifiers() const { return specifiers_; }
-  void PushScriptModule(ScriptModule script_module) {
-    script_modules_.push_back(script_module);
+  void PushModuleRecord(ModuleRecord module_record) {
+    module_records_.push_back(module_record);
   }
 
  private:
-  // Implements ScriptModuleResolver:
+  // Implements ModuleRecordResolver:
 
   void RegisterModuleScript(const ModuleScript*) override { NOTREACHED(); }
   void UnregisterModuleScript(const ModuleScript*) override { NOTREACHED(); }
-  const ModuleScript* GetHostDefined(const ScriptModule&) const override {
+  const ModuleScript* GetHostDefined(const ModuleRecord&) const override {
     NOTREACHED();
     return nullptr;
   }
 
-  ScriptModule Resolve(const String& specifier,
-                       const ScriptModule&,
+  ModuleRecord Resolve(const String& specifier,
+                       const ModuleRecord&,
                        ExceptionState&) override {
     specifiers_.push_back(specifier);
-    return script_modules_.TakeFirst();
+    return module_records_.TakeFirst();
   }
 
   Vector<String> specifiers_;
-  Deque<ScriptModule> script_modules_;
+  Deque<ModuleRecord> module_records_;
 };
 
-class ScriptModuleTestModulator final : public DummyModulator {
+class ModuleRecordTestModulator final : public DummyModulator {
  public:
-  ScriptModuleTestModulator();
-  ~ScriptModuleTestModulator() override = default;
+  ModuleRecordTestModulator();
+  ~ModuleRecordTestModulator() override = default;
 
   void Trace(blink::Visitor*) override;
 
-  TestScriptModuleResolver* GetTestScriptModuleResolver() {
+  TestModuleRecordResolver* GetTestModuleRecordResolver() {
     return resolver_.Get();
   }
 
  private:
   // Implements Modulator:
 
-  ScriptModuleResolver* GetScriptModuleResolver() override {
+  ModuleRecordResolver* GetModuleRecordResolver() override {
     return resolver_.Get();
   }
 
-  Member<TestScriptModuleResolver> resolver_;
+  Member<TestModuleRecordResolver> resolver_;
 };
 
-ScriptModuleTestModulator::ScriptModuleTestModulator()
-    : resolver_(MakeGarbageCollected<TestScriptModuleResolver>()) {}
+ModuleRecordTestModulator::ModuleRecordTestModulator()
+    : resolver_(MakeGarbageCollected<TestModuleRecordResolver>()) {}
 
-void ScriptModuleTestModulator::Trace(blink::Visitor* visitor) {
+void ModuleRecordTestModulator::Trace(blink::Visitor* visitor) {
   visitor->Trace(resolver_);
   DummyModulator::Trace(visitor);
 }
 
-TEST(ScriptModuleTest, compileSuccess) {
+TEST(ModuleRecordTest, compileSuccess) {
   V8TestingScope scope;
   const KURL js_url("https://example.com/foo.js");
-  ScriptModule module = ScriptModule::Compile(
+  ModuleRecord module = ModuleRecord::Compile(
       scope.GetIsolate(), "export const a = 42;", js_url, js_url,
       ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module.IsNull());
 }
 
-TEST(ScriptModuleTest, compileFail) {
+TEST(ModuleRecordTest, compileFail) {
   V8TestingScope scope;
   const KURL js_url("https://example.com/foo.js");
-  ScriptModule module = ScriptModule::Compile(
+  ModuleRecord module = ModuleRecord::Compile(
       scope.GetIsolate(), "123 = 456", js_url, js_url, ScriptFetchOptions(),
       TextPosition::MinimumPosition(), scope.GetExceptionState());
   ASSERT_TRUE(module.IsNull());
   EXPECT_TRUE(scope.GetExceptionState().HadException());
 }
 
-TEST(ScriptModuleTest, equalAndHash) {
+TEST(ModuleRecordTest, equalAndHash) {
   V8TestingScope scope;
   const KURL js_url_a("https://example.com/a.js");
   const KURL js_url_b("https://example.com/b.js");
 
-  ScriptModule module_null;
-  ScriptModule module_a = ScriptModule::Compile(
+  ModuleRecord module_null;
+  ModuleRecord module_a = ModuleRecord::Compile(
       scope.GetIsolate(), "export const a = 'a';", js_url_a, js_url_a,
       ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module_a.IsNull());
-  ScriptModule module_b = ScriptModule::Compile(
+  ModuleRecord module_b = ModuleRecord::Compile(
       scope.GetIsolate(), "export const b = 'b';", js_url_b, js_url_b,
       ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module_b.IsNull());
-  Vector<char> module_deleted_buffer(sizeof(ScriptModule));
-  ScriptModule& module_deleted =
-      *reinterpret_cast<ScriptModule*>(module_deleted_buffer.data());
-  HashTraits<ScriptModule>::ConstructDeletedValue(module_deleted, true);
+  Vector<char> module_deleted_buffer(sizeof(ModuleRecord));
+  ModuleRecord& module_deleted =
+      *reinterpret_cast<ModuleRecord*>(module_deleted_buffer.data());
+  HashTraits<ModuleRecord>::ConstructDeletedValue(module_deleted, true);
 
   EXPECT_EQ(module_null, module_null);
   EXPECT_EQ(module_a, module_a);
@@ -144,18 +144,18 @@
   EXPECT_NE(module_deleted, module_a);
   EXPECT_NE(module_deleted, module_b);
 
-  EXPECT_NE(DefaultHash<ScriptModule>::Hash::GetHash(module_a),
-            DefaultHash<ScriptModule>::Hash::GetHash(module_b));
-  EXPECT_NE(DefaultHash<ScriptModule>::Hash::GetHash(module_null),
-            DefaultHash<ScriptModule>::Hash::GetHash(module_a));
-  EXPECT_NE(DefaultHash<ScriptModule>::Hash::GetHash(module_null),
-            DefaultHash<ScriptModule>::Hash::GetHash(module_b));
+  EXPECT_NE(DefaultHash<ModuleRecord>::Hash::GetHash(module_a),
+            DefaultHash<ModuleRecord>::Hash::GetHash(module_b));
+  EXPECT_NE(DefaultHash<ModuleRecord>::Hash::GetHash(module_null),
+            DefaultHash<ModuleRecord>::Hash::GetHash(module_a));
+  EXPECT_NE(DefaultHash<ModuleRecord>::Hash::GetHash(module_null),
+            DefaultHash<ModuleRecord>::Hash::GetHash(module_b));
 }
 
-TEST(ScriptModuleTest, moduleRequests) {
+TEST(ModuleRecordTest, moduleRequests) {
   V8TestingScope scope;
   const KURL js_url("https://example.com/foo.js");
-  ScriptModule module = ScriptModule::Compile(
+  ModuleRecord module = ModuleRecord::Compile(
       scope.GetIsolate(), "import 'a'; import 'b'; export const c = 'c';",
       js_url, js_url, ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
@@ -165,16 +165,16 @@
   EXPECT_THAT(requests, testing::ContainerEq<Vector<String>>({"a", "b"}));
 }
 
-TEST(ScriptModuleTest, instantiateNoDeps) {
+TEST(ModuleRecordTest, instantiateNoDeps) {
   V8TestingScope scope;
 
-  auto* modulator = MakeGarbageCollected<ScriptModuleTestModulator>();
-  auto* resolver = modulator->GetTestScriptModuleResolver();
+  auto* modulator = MakeGarbageCollected<ModuleRecordTestModulator>();
+  auto* resolver = modulator->GetTestModuleRecordResolver();
 
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
   const KURL js_url("https://example.com/foo.js");
-  ScriptModule module = ScriptModule::Compile(
+  ModuleRecord module = ModuleRecord::Compile(
       scope.GetIsolate(), "export const a = 42;", js_url, js_url,
       ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
@@ -185,32 +185,32 @@
   EXPECT_EQ(0u, resolver->ResolveCount());
 }
 
-TEST(ScriptModuleTest, instantiateWithDeps) {
+TEST(ModuleRecordTest, instantiateWithDeps) {
   V8TestingScope scope;
 
-  auto* modulator = MakeGarbageCollected<ScriptModuleTestModulator>();
-  auto* resolver = modulator->GetTestScriptModuleResolver();
+  auto* modulator = MakeGarbageCollected<ModuleRecordTestModulator>();
+  auto* resolver = modulator->GetTestModuleRecordResolver();
 
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
   const KURL js_url_a("https://example.com/a.js");
-  ScriptModule module_a = ScriptModule::Compile(
+  ModuleRecord module_a = ModuleRecord::Compile(
       scope.GetIsolate(), "export const a = 'a';", js_url_a, js_url_a,
       ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module_a.IsNull());
-  resolver->PushScriptModule(module_a);
+  resolver->PushModuleRecord(module_a);
 
   const KURL js_url_b("https://example.com/b.js");
-  ScriptModule module_b = ScriptModule::Compile(
+  ModuleRecord module_b = ModuleRecord::Compile(
       scope.GetIsolate(), "export const b = 'b';", js_url_b, js_url_b,
       ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module_b.IsNull());
-  resolver->PushScriptModule(module_b);
+  resolver->PushModuleRecord(module_b);
 
   const KURL js_url_c("https://example.com/c.js");
-  ScriptModule module = ScriptModule::Compile(
+  ModuleRecord module = ModuleRecord::Compile(
       scope.GetIsolate(), "import 'a'; import 'b'; export const c = 123;",
       js_url_c, js_url_c, ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
@@ -223,16 +223,16 @@
   EXPECT_EQ("b", resolver->Specifiers()[1]);
 }
 
-TEST(ScriptModuleTest, EvaluationErrrorIsRemembered) {
+TEST(ModuleRecordTest, EvaluationErrrorIsRemembered) {
   V8TestingScope scope;
 
-  auto* modulator = MakeGarbageCollected<ScriptModuleTestModulator>();
-  auto* resolver = modulator->GetTestScriptModuleResolver();
+  auto* modulator = MakeGarbageCollected<ModuleRecordTestModulator>();
+  auto* resolver = modulator->GetTestModuleRecordResolver();
 
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
   const KURL js_url_f("https://example.com/failure.js");
-  ScriptModule module_failure = ScriptModule::Compile(
+  ModuleRecord module_failure = ModuleRecord::Compile(
       scope.GetIsolate(), "nonexistent_function()", js_url_f, js_url_f,
       ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
@@ -242,10 +242,10 @@
       module_failure.Evaluate(scope.GetScriptState());
   EXPECT_FALSE(evaluation_error.IsEmpty());
 
-  resolver->PushScriptModule(module_failure);
+  resolver->PushModuleRecord(module_failure);
 
   const KURL js_url_c("https://example.com/c.js");
-  ScriptModule module = ScriptModule::Compile(
+  ModuleRecord module = ModuleRecord::Compile(
       scope.GetIsolate(), "import 'failure'; export const c = 123;", js_url_c,
       js_url_c, ScriptFetchOptions(), TextPosition::MinimumPosition(),
       scope.GetExceptionState());
@@ -260,14 +260,14 @@
   EXPECT_EQ("failure", resolver->Specifiers()[0]);
 }
 
-TEST(ScriptModuleTest, Evaluate) {
+TEST(ModuleRecordTest, Evaluate) {
   V8TestingScope scope;
 
-  auto* modulator = MakeGarbageCollected<ScriptModuleTestModulator>();
+  auto* modulator = MakeGarbageCollected<ModuleRecordTestModulator>();
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
   const KURL js_url("https://example.com/foo.js");
-  ScriptModule module = ScriptModule::Compile(
+  ModuleRecord module = ModuleRecord::Compile(
       scope.GetIsolate(), "export const a = 42; window.foo = 'bar';", js_url,
       js_url, ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
@@ -294,14 +294,14 @@
   EXPECT_EQ(42.0, exported_value->NumberValue(scope.GetContext()).ToChecked());
 }
 
-TEST(ScriptModuleTest, EvaluateCaptureError) {
+TEST(ModuleRecordTest, EvaluateCaptureError) {
   V8TestingScope scope;
 
-  auto* modulator = MakeGarbageCollected<ScriptModuleTestModulator>();
+  auto* modulator = MakeGarbageCollected<ModuleRecordTestModulator>();
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
   const KURL js_url("https://example.com/foo.js");
-  ScriptModule module = ScriptModule::Compile(
+  ModuleRecord module = ModuleRecord::Compile(
       scope.GetIsolate(), "throw 'bar';", js_url, js_url, ScriptFetchOptions(),
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module.IsNull());
diff --git a/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc b/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
index 2c848e5..7c596897 100644
--- a/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
@@ -312,8 +312,8 @@
 bool V0CustomElementConstructorBuilder::DidRegisterDefinition() const {
   DCHECK(!constructor_.IsEmpty());
 
-  return callbacks_->SetBinding(
-      V0CustomElementBinding::Create(script_state_->GetIsolate(), prototype_));
+  return callbacks_->SetBinding(std::make_unique<V0CustomElementBinding>(
+      script_state_->GetIsolate(), prototype_));
 }
 
 ScriptValue V0CustomElementConstructorBuilder::BindingsReturnValue() const {
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
index 4f261839..519b6ee7 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
@@ -7,8 +7,8 @@
 #include "base/optional.h"
 #include "build/build_config.h"
 #include "third_party/blink/public/web/web_settings.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_initializer.h"
@@ -271,7 +271,7 @@
 }
 
 void V8CodeCache::ProduceCache(v8::Isolate* isolate,
-                               ScriptModuleProduceCacheData* produce_cache_data,
+                               ModuleRecordProduceCacheData* produce_cache_data,
                                size_t source_text_length,
                                const KURL& source_url,
                                const TextPosition& source_start_position) {
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h
index 312e594..b85bdba 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h
+++ b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h
@@ -27,7 +27,7 @@
 class KURL;
 class SingleCachedMetadataHandler;
 class ScriptSourceCode;
-class ScriptModuleProduceCacheData;
+class ModuleRecordProduceCacheData;
 
 class CORE_EXPORT V8CodeCache final {
   STATIC_ONLY(V8CodeCache);
@@ -72,7 +72,7 @@
                            const ScriptSourceCode&,
                            ProduceCacheOptions);
   static void ProduceCache(v8::Isolate*,
-                           ScriptModuleProduceCacheData*,
+                           ModuleRecordProduceCacheData*,
                            size_t source_text_length,
                            const KURL& source_url,
                            const WTF::TextPosition& source_start_position);
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
index 2f5645b..f27b98774 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -599,7 +599,7 @@
 
   // TODO(shivanisha): Can a valid source url be passed to the constructor.
   ModuleImportMeta host_meta = modulator->HostGetImportMetaProperties(
-      ScriptModule(isolate, module, KURL()));
+      ModuleRecord(isolate, module, KURL()));
 
   // 3. Return <<Record { [[Key]]: "url", [[Value]]: urlString }>>. [spec text]
   v8::Local<v8::String> url_key = V8String(isolate, "url");
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
index 507303a..5e3f7d59 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
+++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
@@ -95,7 +95,7 @@
                                                   v8::Local<v8::Module>,
                                                   v8::Local<v8::Context>);
 
-  // Only to be used from ScriptModule::ReportException().
+  // Only to be used from ModuleRecord::ReportException().
   static void ReportExceptionForModule(v8::Isolate*,
                                        v8::Local<v8::Value> exception,
                                        const String& file_name,
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
index 8ba3c6ca..c603dc9 100644
--- a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
+++ b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
@@ -179,8 +179,7 @@
                                          const String& key_path) {
   WebData web_data(SharedBuffer::AdoptVector(wire_bytes));
   scoped_refptr<SharedBuffer> data(web_data);
-  std::unique_ptr<IDBValue> value =
-      IDBValue::Create(data, Vector<WebBlobInfo>());
+  auto value = std::make_unique<IDBValue>(data, Vector<WebBlobInfo>());
   value->SetInjectedPrimaryKey(IDBKey::CreateNumber(primary_key),
                                IDBKeyPath(key_path));
 
diff --git a/third_party/blink/renderer/bindings/scripts/v8_types.py b/third_party/blink/renderer/bindings/scripts/v8_types.py
index 40b0331..5b572099 100644
--- a/third_party/blink/renderer/bindings/scripts/v8_types.py
+++ b/third_party/blink/renderer/bindings/scripts/v8_types.py
@@ -1052,7 +1052,7 @@
     """Converts an expression that is a valid C++ literal for this type."""
     # FIXME: add validation that idl_type and idl_literal are compatible
     if idl_type.base_type in ('any', 'object') and idl_literal.is_null:
-        return 'ScriptValue()'
+        return 'ScriptValue::CreateNull(script_state)'
     literal_value = str(idl_literal)
     if idl_type.base_type in ('octet', 'unsigned short', 'unsigned long'):
         return literal_value + 'u'
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 06b1c1d0..0c43794 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -2172,8 +2172,8 @@
     "script/layered_api_test.cc",
     "script/mock_script_element_base.h",
     "script/module_map_test.cc",
+    "script/module_record_resolver_impl_test.cc",
     "script/module_script_test.cc",
-    "script/script_module_resolver_impl_test.cc",
     "script/script_runner_test.cc",
     "scroll/scrollable_area_test.cc",
     "scroll/scrollbar_theme_overlay_test.cc",
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.cc b/third_party/blink/renderer/core/animation/compositor_animations.cc
index 45d30eb9..8b99c1a8a 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -160,15 +160,14 @@
     case CSSPropertyTransform:
       return CompositorElementIdNamespace::kPrimaryTransform;
     case CSSPropertyFilter:
-    case CSSPropertyBackdropFilter: {
+    case CSSPropertyBackdropFilter:
       return CompositorElementIdNamespace::kEffectFilter;
-      case CSSPropertyVariable:
-        return CompositorElementIdNamespace::kPrimary;
-      default:
-        NOTREACHED();
-    }
+    case CSSPropertyVariable:
       return CompositorElementIdNamespace::kPrimary;
+    default:
+      NOTREACHED();
   }
+  return CompositorElementIdNamespace::kPrimary;
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/core/clipboard/data_object_item.cc b/third_party/blink/renderer/core/clipboard/data_object_item.cc
index 64f74d6..8bc02b9 100644
--- a/third_party/blink/renderer/core/clipboard/data_object_item.cc
+++ b/third_party/blink/renderer/core/clipboard/data_object_item.cc
@@ -139,7 +139,7 @@
         mojom::ClipboardBuffer::kStandard);
     std::vector<unsigned char> png_data;
     if (gfx::PNGCodec::FastEncodeBGRASkBitmap(image, false, &png_data)) {
-      std::unique_ptr<BlobData> data = BlobData::Create();
+      auto data = std::make_unique<BlobData>();
       data->SetContentType(kMimeTypeImagePng);
       data->AppendBytes(png_data.data(), png_data.size());
       const uint64_t length = data->length();
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc
index e84723a..ac511a03 100644
--- a/third_party/blink/renderer/core/css/media_values.cc
+++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -180,6 +180,8 @@
     LocalFrame* frame) {
   DCHECK(frame);
   DCHECK(frame->GetSettings());
+  if (frame->GetSettings()->ForceDarkModeEnabled())
+    return PreferredColorScheme::kNoPreference;
   return frame->GetSettings()->GetPreferredColorScheme();
 }
 
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc
index 2c04450e..0e600004 100644
--- a/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -1510,6 +1510,31 @@
                 GetCSSPropertyColor()));
 }
 
+TEST_F(StyleEngineTest, MediaQueriesChangeColorSchemeForcedDarkMode) {
+  RuntimeEnabledFeatures::SetMediaQueryPrefersColorSchemeEnabled(true);
+
+  GetDocument().GetSettings()->SetForceDarkModeEnabled(true);
+  GetDocument().GetSettings()->SetPreferredColorScheme(
+      PreferredColorScheme::kDark);
+
+  GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+    <style>
+      @media (prefers-color-scheme: no-preference) {
+        body { color: green }
+      }
+      @media (prefers-color-scheme: dark) {
+        body { color: red }
+      }
+    </style>
+    <body></body>
+  )HTML");
+
+  UpdateAllLifecyclePhases();
+  EXPECT_EQ(MakeRGB(0, 128, 0),
+            GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+                GetCSSPropertyColor()));
+}
+
 TEST_F(StyleEngineTest, MediaQueriesChangePrefersReducedMotion) {
   GetDocument().body()->SetInnerHTMLFromString(R"HTML(
     <style>
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 951ab6f..4083996 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -603,7 +603,8 @@
 
   LayoutRect bounds = BoundingBoxForScrollIntoView();
   GetLayoutObject()->ScrollRectToVisible(
-      bounds, {align_x, align_y, kProgrammaticScroll, false, behavior});
+      bounds, {align_x, align_y, kProgrammaticScroll,
+               /*make_visible_in_visual_viewport=*/true, behavior});
 
   GetDocument().SetSequentialFocusNavigationStartingPoint(this);
 }
@@ -617,14 +618,12 @@
   LayoutRect bounds = BoundingBoxForScrollIntoView();
   if (center_if_needed) {
     GetLayoutObject()->ScrollRectToVisible(
-        bounds,
-        {ScrollAlignment::kAlignCenterIfNeeded,
-         ScrollAlignment::kAlignCenterIfNeeded, kProgrammaticScroll, false});
+        bounds, {ScrollAlignment::kAlignCenterIfNeeded,
+                 ScrollAlignment::kAlignCenterIfNeeded});
   } else {
     GetLayoutObject()->ScrollRectToVisible(
-        bounds,
-        {ScrollAlignment::kAlignToEdgeIfNeeded,
-         ScrollAlignment::kAlignToEdgeIfNeeded, kProgrammaticScroll, false});
+        bounds, {ScrollAlignment::kAlignToEdgeIfNeeded,
+                 ScrollAlignment::kAlignToEdgeIfNeeded});
   }
 }
 
diff --git a/third_party/blink/renderer/core/exported/web_blob.cc b/third_party/blink/renderer/core/exported/web_blob.cc
index 4f2f06f..c62ae5c 100644
--- a/third_party/blink/renderer/core/exported/web_blob.cc
+++ b/third_party/blink/renderer/core/exported/web_blob.cc
@@ -47,7 +47,7 @@
 }
 
 WebBlob WebBlob::CreateFromFile(const WebString& path, uint64_t size) {
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->AppendFile(path, 0, size, InvalidFileTime());
   return Blob::Create(BlobDataHandle::Create(std::move(blob_data), size));
 }
diff --git a/third_party/blink/renderer/core/fetch/body.cc b/third_party/blink/renderer/core/fetch/body.cc
index dcda9967f..b40289f 100644
--- a/third_party/blink/renderer/core/fetch/body.cc
+++ b/third_party/blink/renderer/core/fetch/body.cc
@@ -206,7 +206,7 @@
       return ScriptPromise();
     }
   } else {
-    std::unique_ptr<BlobData> blob_data = BlobData::Create();
+    auto blob_data = std::make_unique<BlobData>();
     blob_data->SetContentType(MimeType());
     resolver->Resolve(
         Blob::Create(BlobDataHandle::Create(std::move(blob_data), 0)));
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc b/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
index c06daa5..6f6fd9e 100644
--- a/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
+++ b/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
@@ -208,7 +208,7 @@
 
 TEST_F(BodyStreamBufferTest, DrainAsBlobDataHandle) {
   V8TestingScope scope;
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendText("hello", false);
   auto size = data->length();
   scoped_refptr<BlobDataHandle> blob_data_handle =
diff --git a/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc b/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc
index df34021..eee1df3e 100644
--- a/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc
+++ b/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc
@@ -351,7 +351,7 @@
 
 TEST_F(BytesConsumerTeeTest, BlobHandle) {
   scoped_refptr<BlobDataHandle> blob_data_handle =
-      BlobDataHandle::Create(BlobData::Create(), 12345);
+      BlobDataHandle::Create(std::make_unique<BlobData>(), 12345);
   BytesConsumer* src =
       MakeGarbageCollected<FakeBlobBytesConsumer>(blob_data_handle);
 
@@ -373,7 +373,7 @@
 
 TEST_F(BytesConsumerTeeTest, BlobHandleWithInvalidSize) {
   scoped_refptr<BlobDataHandle> blob_data_handle = BlobDataHandle::Create(
-      BlobData::Create(), std::numeric_limits<uint64_t>::max());
+      std::make_unique<BlobData>(), std::numeric_limits<uint64_t>::max());
   BytesConsumer* src =
       MakeGarbageCollected<FakeBlobBytesConsumer>(blob_data_handle);
 
diff --git a/third_party/blink/renderer/core/fetch/fetch_data_loader.cc b/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
index 802fc6a..e144222 100644
--- a/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
@@ -48,7 +48,7 @@
       if (blob_handle->GetType() != mime_type_) {
         // A new Blob is created to override the Blob's type.
         auto blob_size = blob_handle->size();
-        auto blob_data = BlobData::Create();
+        auto blob_data = std::make_unique<BlobData>();
         blob_data->SetContentType(mime_type_);
         blob_data->AppendBlob(std::move(blob_handle), 0, blob_size);
         client_->DidFetchDataLoadedBlobHandle(
@@ -59,7 +59,7 @@
       return;
     }
 
-    blob_data_ = BlobData::Create();
+    blob_data_ = std::make_unique<BlobData>();
     blob_data_->SetContentType(mime_type_);
     consumer_->SetClient(this);
     OnStateChange();
@@ -355,7 +355,7 @@
       if (disposition_type != "form-data" || name_.IsNull())
         return false;
       if (!filename_.IsNull()) {
-        blob_data_ = BlobData::Create();
+        blob_data_ = std::make_unique<BlobData>();
         const AtomicString& content_type =
             header_fields.Get(http_names::kContentType);
         blob_data_->SetContentType(content_type.IsNull() ? "text/plain"
diff --git a/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc b/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc
index a6354e568..f82ac7b 100644
--- a/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc
@@ -183,7 +183,7 @@
 
 TEST(FetchDataLoaderTest,
      LoadAsBlobViaDrainAsBlobDataHandleWithSameContentType) {
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->AppendBytes(kQuickBrownFox,
                          kQuickBrownFoxLengthWithTerminatingNull);
   blob_data->SetContentType("text/test");
@@ -225,7 +225,7 @@
 
 TEST(FetchDataLoaderTest,
      LoadAsBlobViaDrainAsBlobDataHandleWithDifferentContentType) {
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->AppendBytes(kQuickBrownFox,
                          kQuickBrownFoxLengthWithTerminatingNull);
   blob_data->SetContentType("text/different");
diff --git a/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc b/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
index 2b2883d..7ede271 100644
--- a/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
+++ b/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
@@ -92,7 +92,7 @@
     Vector<char> data;
     form_data_->Flatten(data);
     form_data_ = nullptr;
-    std::unique_ptr<BlobData> blob_data = BlobData::Create();
+    auto blob_data = std::make_unique<BlobData>();
     blob_data->AppendBytes(data.data(), data.size());
     auto length = blob_data->length();
     state_ = PublicState::kClosed;
@@ -399,7 +399,7 @@
       return;
     }
 
-    std::unique_ptr<BlobData> blob_data = BlobData::Create();
+    auto blob_data = std::make_unique<BlobData>();
     for (const auto& element : form_data_->Elements()) {
       switch (element.type_) {
         case FormDataElement::kData:
diff --git a/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc b/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc
index 9f5f55a4..48c99d97 100644
--- a/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc
+++ b/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc
@@ -74,7 +74,7 @@
 
   data->AppendData("foo", 3);
   data->AppendFileRange("/foo/bar/baz", 3, 4, 5);
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->AppendText("hello", false);
   auto size = blob_data->length();
   scoped_refptr<BlobDataHandle> blob_data_handle =
diff --git a/third_party/blink/renderer/core/fileapi/blob.cc b/third_party/blink/renderer/core/fileapi/blob.cc
index aa868b2..513c4c9 100644
--- a/third_party/blink/renderer/core/fileapi/blob.cc
+++ b/third_party/blink/renderer/core/fileapi/blob.cc
@@ -93,7 +93,7 @@
   if (normalize_line_endings_to_native)
     UseCounter::Count(context, WebFeature::kFileAPINativeLineEndings);
 
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->SetContentType(NormalizeType(options->type()));
 
   PopulateBlobData(blob_data.get(), blob_parts,
@@ -109,7 +109,7 @@
                    const String& content_type) {
   DCHECK(data);
 
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->SetContentType(content_type);
   blob_data->AppendBytes(data, size);
   uint64_t blob_size = blob_data->length();
@@ -176,7 +176,7 @@
   ClampSliceOffsets(size, start, end);
 
   uint64_t length = end - start;
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->SetContentType(NormalizeType(content_type));
   blob_data->AppendBlob(blob_data_handle_, start, length);
   return Blob::Create(BlobDataHandle::Create(std::move(blob_data), length));
diff --git a/third_party/blink/renderer/core/fileapi/file.cc b/third_party/blink/renderer/core/fileapi/file.cc
index db25563..3003a2a 100644
--- a/third_party/blink/renderer/core/fileapi/file.cc
+++ b/third_party/blink/renderer/core/fileapi/file.cc
@@ -72,7 +72,7 @@
     const String& path,
     File::ContentTypeLookupPolicy policy) {
   if (path.IsEmpty()) {
-    std::unique_ptr<BlobData> blob_data = BlobData::Create();
+    auto blob_data = std::make_unique<BlobData>();
     blob_data->SetContentType("application/octet-stream");
     return blob_data;
   }
@@ -96,7 +96,7 @@
     blob_data = BlobData::CreateForFileWithUnknownSize(
         metadata.platform_path, metadata.modification_time / kMsPerSecond);
   } else {
-    blob_data = BlobData::Create();
+    blob_data = std::make_unique<BlobData>();
     blob_data->AppendFile(metadata.platform_path, 0, metadata.length,
                           metadata.modification_time / kMsPerSecond);
   }
@@ -113,7 +113,7 @@
     blob_data = BlobData::CreateForFileSystemURLWithUnknownSize(
         file_system_url, metadata.modification_time / kMsPerSecond);
   } else {
-    blob_data = BlobData::Create();
+    blob_data = std::make_unique<BlobData>();
     blob_data->AppendFileSystemURL(file_system_url, 0, metadata.length,
                                    metadata.modification_time / kMsPerSecond);
   }
@@ -141,7 +141,7 @@
   if (normalize_line_endings_to_native)
     UseCounter::Count(context, WebFeature::kFileAPINativeLineEndings);
 
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->SetContentType(NormalizeType(options->type()));
   PopulateBlobData(blob_data.get(), file_bits,
                    normalize_line_endings_to_native);
@@ -358,7 +358,7 @@
   ClampSliceOffsets(size, start, end);
 
   uint64_t length = end - start;
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->SetContentType(NormalizeType(content_type));
   DCHECK(!path_.IsEmpty());
   blob_data->AppendFile(path_, start, length,
diff --git a/third_party/blink/renderer/core/frame/root_frame_viewport.cc b/third_party/blink/renderer/core/frame/root_frame_viewport.cc
index b58470f..a1866e9 100644
--- a/third_party/blink/renderer/core/frame/root_frame_viewport.cc
+++ b/third_party/blink/renderer/core/frame/root_frame_viewport.cc
@@ -181,15 +181,14 @@
 LayoutRect RootFrameViewport::VisibleScrollSnapportRect(
     IncludeScrollbarsInRect scrollbar_inclusion) const {
   // The effective viewport is the intersection of the visual viewport with the
-  // layout viewport. However, we don't use visibleContentRect directly since it
-  // floors the scroll offset. Instead, we use ScrollAnimatorBase::currentOffset
-  // and construct a LayoutRect from that.
+  // layout viewport.
   LayoutRect frame_rect_in_content = LayoutRect(
-      FloatPoint(LayoutViewport().GetScrollAnimator().CurrentOffset()),
+      FloatPoint(LayoutViewport().GetScrollOffset()),
       FloatSize(
           LayoutViewport().VisibleContentRect(scrollbar_inclusion).Size()));
   LayoutRect visual_rect_in_content = LayoutRect(
-      FloatPoint(ScrollOffsetFromScrollAnimators()),
+      FloatPoint(LayoutViewport().GetScrollOffset() +
+                 VisualViewport().GetScrollAnimator().CurrentOffset()),
       FloatSize(
           VisualViewport().VisibleContentRect(scrollbar_inclusion).Size()));
 
diff --git a/third_party/blink/renderer/core/layout/custom/layout_worklet_test.cc b/third_party/blink/renderer/core/layout/custom/layout_worklet_test.cc
index 528773e1..6e933760 100644
--- a/third_party/blink/renderer/core/layout/custom/layout_worklet_test.cc
+++ b/third_party/blink/renderer/core/layout/custom/layout_worklet_test.cc
@@ -6,7 +6,7 @@
 
 #include <memory>
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -47,7 +47,7 @@
     ScriptState::Scope scope(script_state);
 
     KURL js_url("https://example.com/worklet.js");
-    ScriptModule module = ScriptModule::Compile(
+    ModuleRecord module = ModuleRecord::Compile(
         script_state->GetIsolate(), source_code, js_url, js_url,
         ScriptFetchOptions(), TextPosition::MinimumPosition(),
         ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 094796c..cf877fff 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -397,10 +397,12 @@
     ResourceRequest& request,
     const FetchInitiatorInfo& initiator_info,
     WebScopedVirtualTimePauser& virtual_time_pauser,
-    RedirectType redirect_type,
     ResourceType resource_type) {
   // TODO(yhirano): Clarify which statements are actually needed when
-  // |redirect_type| is |kForRedirect|.
+  // this is called during redirect.
+  const bool for_redirect =
+      (request.GetRedirectStatus() ==
+       ResourceRequest::RedirectStatus::kFollowedRedirect);
 
   SetFirstPartyCookie(request);
   request.SetTopFrameOrigin(GetTopFrameOrigin());
@@ -412,8 +414,7 @@
     return;
   GetLocalFrameClient()->DispatchWillSendRequest(request);
   FrameScheduler* frame_scheduler = GetFrame()->GetFrameScheduler();
-  if (redirect_type == FetchContext::RedirectType::kNotForRedirect &&
-      frame_scheduler) {
+  if (!for_redirect && frame_scheduler) {
     virtual_time_pauser = frame_scheduler->CreateWebScopedVirtualTimePauser(
         request.Url().GetString(),
         WebScopedVirtualTimePauser::VirtualTaskDuration::kNonInstant);
@@ -430,8 +431,7 @@
   }
 
   // If it's not for redirect, hook up ApplicationCache here too.
-  if (redirect_type == FetchContext::RedirectType::kNotForRedirect &&
-      GetDocumentLoader() && !GetDocumentLoader()->Archive() &&
+  if (!for_redirect && GetDocumentLoader() && !GetDocumentLoader()->Archive() &&
       request.Url().IsValid()) {
     GetDocumentLoader()->GetApplicationCacheHost()->WillStartLoading(request);
   }
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h
index 206c9cb..7691be2 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -89,7 +89,6 @@
   void PrepareRequest(ResourceRequest&,
                       const FetchInitiatorInfo&,
                       WebScopedVirtualTimePauser&,
-                      RedirectType,
                       ResourceType) override;
   void DispatchWillSendRequest(
       unsigned long identifier,
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
index 8e47d82f..81bf36b 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -1246,9 +1246,8 @@
 
   ResourceRequest request(KURL("https://localhost/"));
   WebScopedVirtualTimePauser virtual_time_pauser;
-  GetFetchContext()->PrepareRequest(
-      request, FetchInitiatorInfo(), virtual_time_pauser,
-      FetchContext::RedirectType::kNotForRedirect, ResourceType::kRaw);
+  GetFetchContext()->PrepareRequest(request, FetchInitiatorInfo(),
+                                    virtual_time_pauser, ResourceType::kRaw);
 
   EXPECT_EQ("hi", request.HttpHeaderField(http_names::kUserAgent));
 }
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
index ba3b722..ff5d470 100644
--- a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
@@ -88,7 +88,7 @@
       requests_.emplace_back(request, TextPosition::MinimumPosition());
     }
   }
-  Vector<ModuleRequest> ModuleRequestsFromScriptModule(ScriptModule) override {
+  Vector<ModuleRequest> ModuleRequestsFromModuleRecord(ModuleRecord) override {
     return requests_;
   }
 
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc
index 861deb6..6eda5c9 100644
--- a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc
@@ -4,7 +4,7 @@
 
 #include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h"
 
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h"
 #include "third_party/blink/renderer/core/script/layered_api.h"
@@ -308,7 +308,7 @@
   }
 
   // [FD] Step 2. Let record be module script's record.
-  ScriptModule record = module_script->Record();
+  ModuleRecord record = module_script->Record();
 
   // [FD] Step 1. If module script's record is null, then asynchronously
   // complete this algorithm with module script and abort these steps.
@@ -338,7 +338,7 @@
 
   // [FD] Step 5. For each string requested of record.[[RequestedModules]],
   Vector<Modulator::ModuleRequest> module_requests =
-      modulator_->ModuleRequestsFromScriptModule(record);
+      modulator_->ModuleRequestsFromModuleRecord(record);
   for (const auto& module_request : module_requests) {
     // [FD] Step 5.1. Let url be the result of resolving a module specifier
     // given module script and requested.
@@ -450,7 +450,7 @@
 #endif
 
     // [FDaI] Step 6.1. Let record be result's record.
-    ScriptModule record = result_->Record();
+    ModuleRecord record = result_->Record();
 
     // [FDaI] Step 6.2. Perform record.Instantiate().
     AdvanceState(State::kInstantiating);
@@ -501,14 +501,14 @@
 
   // [FFPE] Step 4. If moduleScript's record is null, then return moduleScript's
   // parse error.
-  ScriptModule record = module_script->Record();
+  ModuleRecord record = module_script->Record();
   if (record.IsNull())
     return module_script->CreateParseError();
 
   // [FFPE] Step 5. Let childSpecifiers be the value of moduleScript's record's
   // [[RequestedModules]] internal slot.
   Vector<Modulator::ModuleRequest> child_specifiers =
-      modulator_->ModuleRequestsFromScriptModule(record);
+      modulator_->ModuleRequestsFromModuleRecord(record);
 
   for (const auto& module_request : child_specifiers) {
     // [FFPE] Step 6. Let childURLs be the list obtained by calling resolve a
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
index 70a58eb..cc804d25 100644
--- a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
@@ -8,7 +8,7 @@
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
@@ -83,13 +83,13 @@
     }
     source_text.Append("export default 'grapes';");
 
-    ScriptModule script_module = ScriptModule::Compile(
+    ModuleRecord module_record = ModuleRecord::Compile(
         script_state_->GetIsolate(), source_text.ToString(), url, url,
         ScriptFetchOptions(), TextPosition::MinimumPosition(),
         ASSERT_NO_EXCEPTION);
-    auto* module_script = ModuleScript::CreateForTest(this, script_module, url);
+    auto* module_script = ModuleScript::CreateForTest(this, module_record, url);
     auto result_request = dependency_module_requests_map_.insert(
-        script_module, dependency_module_requests);
+        module_record, dependency_module_requests);
     EXPECT_TRUE(result_request.is_new_entry);
     auto result_map = module_map_.insert(url, module_script);
     EXPECT_TRUE(result_map.is_new_entry);
@@ -147,7 +147,7 @@
     return it->value;
   }
 
-  ScriptValue InstantiateModule(ScriptModule record) override {
+  ScriptValue InstantiateModule(ModuleRecord record) override {
     if (instantiate_should_fail_) {
       ScriptState::Scope scope(script_state_);
       v8::Local<v8::Value> error = V8ThrowException::CreateError(
@@ -158,12 +158,12 @@
     return ScriptValue();
   }
 
-  Vector<ModuleRequest> ModuleRequestsFromScriptModule(
-      ScriptModule script_module) override {
-    if (script_module.IsNull())
+  Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
+      ModuleRecord module_record) override {
+    if (module_record.IsNull())
       return Vector<ModuleRequest>();
 
-    const auto& it = dependency_module_requests_map_.find(script_module);
+    const auto& it = dependency_module_requests_map_.find(module_record);
     if (it == dependency_module_requests_map_.end())
       return Vector<ModuleRequest>();
 
@@ -172,9 +172,9 @@
 
   Member<ScriptState> script_state_;
   HeapHashMap<KURL, Member<SingleModuleClient>> pending_clients_;
-  HashMap<ScriptModule, Vector<ModuleRequest>> dependency_module_requests_map_;
+  HashMap<ModuleRecord, Vector<ModuleRequest>> dependency_module_requests_map_;
   HeapHashMap<KURL, Member<ModuleScript>> module_map_;
-  HashSet<ScriptModule> instantiated_records_;
+  HashSet<ModuleRecord> instantiated_records_;
   bool instantiate_should_fail_ = false;
 };
 
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
index e36a198e..ce66580 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -192,7 +192,6 @@
     ResourceRequest& request,
     const FetchInitiatorInfo& initiator_info,
     WebScopedVirtualTimePauser&,
-    RedirectType redirect_type,
     ResourceType resource_type) {
   String user_agent = global_scope_->UserAgent();
   probe::ApplyUserAgentOverride(Probe(), &user_agent);
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/third_party/blink/renderer/core/loader/worker_fetch_context.h
index 2939779..0e340ab 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -75,7 +75,6 @@
   void PrepareRequest(ResourceRequest&,
                       const FetchInitiatorInfo&,
                       WebScopedVirtualTimePauser&,
-                      RedirectType,
                       ResourceType) override;
   void AddAdditionalRequestHeaders(ResourceRequest&) override;
   void DispatchWillSendRequest(unsigned long,
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index 8fd0c1f..fa617ec95 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -271,6 +271,12 @@
       if (paint_phase != PaintPhase::kFloat) {
         if (physical_box_fragment.IsBlockFlow()) {
           PaintBlockFlowContents(paint_info, paint_offset);
+        } else if (ShouldPaintDescendantOutlines(paint_info.phase)) {
+          // TODO(kojii): |PaintInlineChildrenOutlines()| should do the work
+          // instead. Legacy does so, and is more efficient. But NG outline
+          // logic currently depends on |PaintInlineChildren()|.
+          PaintInlineChildren(box_fragment_.Children(),
+                              paint_info.ForDescendants(), paint_offset);
         } else {
           PaintInlineChildren(box_fragment_.Children(), paint_info,
                               paint_offset);
@@ -350,25 +356,6 @@
   }
 }
 
-void NGBoxFragmentPainter::PaintInlineChild(const NGPaintFragment& child,
-                                            const PaintInfo& paint_info,
-                                            const LayoutPoint& paint_offset) {
-  // Atomic-inline children should be painted by PaintAtomicInlineChild.
-  DCHECK(!child.PhysicalFragment().IsAtomicInline());
-
-  const NGPhysicalFragment& fragment = child.PhysicalFragment();
-  PaintInfo descendants_info = paint_info.ForDescendants();
-  if (fragment.Type() == NGPhysicalFragment::kFragmentText) {
-    PaintTextChild(child, descendants_info, paint_offset);
-  } else if (fragment.Type() == NGPhysicalFragment::kFragmentBox) {
-    if (child.HasSelfPaintingLayer())
-      return;
-    NGInlineBoxFragmentPainter(child).Paint(descendants_info, paint_offset);
-  } else {
-    NOTREACHED();
-  }
-}
-
 void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info) {
   for (const NGPaintFragment* child : box_fragment_.Children()) {
     const NGPhysicalFragment& fragment = child->PhysicalFragment();
@@ -739,8 +726,7 @@
   if (!line_boxes.size())
     return;
 
-  const bool is_horizontal =
-      IsHorizontalWritingMode(box_fragment_.Style().GetWritingMode());
+  const bool is_horizontal = box_fragment_.Style().IsHorizontalWritingMode();
 
   for (const NGPaintFragment* line : line_boxes) {
     const NGPhysicalFragment& child_fragment = line->PhysicalFragment();
@@ -784,13 +770,35 @@
     NGPaintFragment::ChildList inline_children,
     const PaintInfo& paint_info,
     const LayoutPoint& paint_offset) {
+  // TODO(kojii): kOutline should go |PaintInlineChildrenOutlines()|, which is
+  // more efficien. This DCHECK can then match to |InlineFlowBoxPainter::Paint|.
+  DCHECK_NE(paint_info.phase, PaintPhase::kDescendantOutlinesOnly);
+
   for (const NGPaintFragment* child : inline_children) {
-    if (child->PhysicalFragment().IsFloating())
+    const NGPhysicalFragment& child_fragment = child->PhysicalFragment();
+    if (child_fragment.IsFloating())
       continue;
-    if (child->PhysicalFragment().IsAtomicInline()) {
-      PaintAtomicInlineChild(*child, paint_info);
+
+    // Skip if this child does not intersect with CullRect.
+    if (!paint_info.GetCullRect().Intersects(
+            child->InkOverflow().ToLayoutRect(),
+            paint_offset + child->Offset().ToLayoutPoint()) &&
+        // Don't skip empty size text in order to paint selection for <br>.
+        !(child_fragment.IsText() && child_fragment.Size().IsEmpty()))
+      continue;
+
+    if (child_fragment.Type() == NGPhysicalFragment::kFragmentText) {
+      DCHECK(!child_fragment.HasSelfPaintingLayer());
+      PaintTextChild(*child, paint_info, paint_offset);
+    } else if (child_fragment.Type() == NGPhysicalFragment::kFragmentBox) {
+      if (child_fragment.HasSelfPaintingLayer())
+        continue;
+      if (child_fragment.IsAtomicInline())
+        PaintAtomicInlineChild(*child, paint_info);
+      else
+        NGInlineBoxFragmentPainter(*child).Paint(paint_info, paint_offset);
     } else {
-      PaintInlineChild(*child, paint_info, paint_offset);
+      NOTREACHED();
     }
   }
 }
@@ -831,20 +839,8 @@
       paint_info.phase != PaintPhase::kMask)
     return;
 
-  // Note: To paint selection for <br>, we don't check intersection with
-  // fragment paint rect and cull rect since computing selection rect is
-  // expensive.
   const NGPhysicalTextFragment& text_fragment =
       ToNGPhysicalTextFragment(paint_fragment.PhysicalFragment());
-  if (!text_fragment.Size().IsEmpty()) {
-    LayoutRect physical_visual_overflow =
-        text_fragment.SelfInkOverflow().ToLayoutRect();
-    physical_visual_overflow.MoveBy(paint_fragment.Offset().ToLayoutPoint());
-    physical_visual_overflow.MoveBy(paint_offset);
-    if (!paint_info.GetCullRect().Intersects(physical_visual_overflow))
-      return;
-  }
-
   NodeHolder node_holder;
   if (auto* node = text_fragment.GetNode()) {
     if (node->GetLayoutObject()->IsText())
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
index 37627ac..be471245 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -89,9 +89,6 @@
                                               const PaintInfo&);
   void PaintBlockFlowContents(const PaintInfo&,
                               const LayoutPoint& paint_offset);
-  void PaintInlineChild(const NGPaintFragment&,
-                        const PaintInfo&,
-                        const LayoutPoint& paint_offset);
   void PaintAtomicInlineChild(const NGPaintFragment&, const PaintInfo&);
   void PaintTextChild(const NGPaintFragment&,
                       const PaintInfo&,
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
index 5ba5b20..8bd46e5 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -330,7 +330,7 @@
         std::max(property_changed, property_tree_builder->UpdateForChildren());
 
     // Save clip_changed flag in |context| so that all descendants will see it
-    // even if we don't creae tree_builder_context.
+    // even if we don't create tree_builder_context.
     if (context.tree_builder_context->clip_changed)
       context.clip_changed = true;
 
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
index 0ade5c5..3f91aba 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
@@ -45,7 +45,8 @@
           inside_blocking_touch_event_handler(
               parent_context.inside_blocking_touch_event_handler),
           effective_whitelisted_touch_action_changed(
-              parent_context.effective_whitelisted_touch_action_changed) {
+              parent_context.effective_whitelisted_touch_action_changed),
+          clip_changed(parent_context.clip_changed) {
       if (needs_tree_builder_context || DCHECK_IS_ON()) {
         DCHECK(parent_context.tree_builder_context);
         tree_builder_context.emplace(*parent_context.tree_builder_context);
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc
index f4085af..0575c7e1 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc
@@ -230,7 +230,7 @@
       .clip { overflow: hidden }
     </style>
     <div id='parent' style='transform: translateZ(0); width: 100px;
-      height: 100px; trans'>
+      height: 100px;'>
       <div id='child' style='overflow: hidden; z-index: 0;
           position: absolute; width: 50px; height: 50px'>
         content
@@ -253,6 +253,32 @@
   EXPECT_TRUE(child_paint_layer->NeedsRepaint());
 }
 
+TEST_P(PrePaintTreeWalkTest, ClipChangeRepaintsDescendants) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #parent { height: 75px; position: relative; width: 100px; }
+      #child { overflow: hidden; width: 10%; height: 100%; position: relative; }
+      #greatgrandchild {
+        width: 5px; height: 5px; z-index: 100; position: relative;
+      }
+    </style>
+    <div id='parent' style='height: 100px;'>
+      <div id='child'>
+        <div id='grandchild'>
+          <div id='greatgrandchild'></div>
+        </div>
+      </div>
+    </div>
+  )HTML");
+
+  GetDocument().getElementById("parent")->removeAttribute("style");
+  GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
+
+  auto* greatgrandchild = GetLayoutObjectByElementId("greatgrandchild");
+  auto* paint_layer = ToLayoutBoxModelObject(greatgrandchild)->Layer();
+  EXPECT_TRUE(paint_layer->NeedsRepaint());
+}
+
 TEST_P(PrePaintTreeWalkTest, VisualRectClipForceSubtree) {
   SetBodyInnerHTML(R"HTML(
     <style>
diff --git a/third_party/blink/renderer/core/script/BUILD.gn b/third_party/blink/renderer/core/script/BUILD.gn
index 2ac894f..062d17f 100644
--- a/third_party/blink/renderer/core/script/BUILD.gn
+++ b/third_party/blink/renderer/core/script/BUILD.gn
@@ -39,6 +39,9 @@
     "module_map.h",
     "module_pending_script.cc",
     "module_pending_script.h",
+    "module_record_resolver.h",
+    "module_record_resolver_impl.cc",
+    "module_record_resolver_impl.h",
     "module_script.cc",
     "module_script.h",
     "parsed_specifier.cc",
@@ -50,9 +53,6 @@
     "script_element_base.h",
     "script_loader.cc",
     "script_loader.h",
-    "script_module_resolver.h",
-    "script_module_resolver_impl.cc",
-    "script_module_resolver_impl.h",
     "script_runner.cc",
     "script_runner.h",
     "script_scheduling_type.h",
diff --git a/third_party/blink/renderer/core/script/dynamic_module_resolver.cc b/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
index 2311307..52d715c 100644
--- a/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
+++ b/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
@@ -116,9 +116,9 @@
   // step="2.2">Let moduleRecord be !
   // HostResolveImportedModule(referencingScriptOrModule, specifier).</spec>
   //
-  // Note: We skip invocation of ScriptModuleResolver here. The
+  // Note: We skip invocation of ModuleRecordResolver here. The
   // result of HostResolveImportedModule is guaranteed to be |module_script|.
-  ScriptModule record = module_script->Record();
+  ModuleRecord record = module_script->Record();
   DCHECK(!record.IsNull());
 
   // <spec
diff --git a/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc b/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
index 0f3c85f..c67641c 100644
--- a/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
+++ b/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
@@ -56,7 +56,7 @@
   ModuleScript* GetFetchedModuleScript(const KURL& url) final {
     EXPECT_EQ(TestReferrerURL(), url);
     ModuleScript* module_script =
-        ModuleScript::CreateForTest(this, ScriptModule(), url);
+        ModuleScript::CreateForTest(this, ModuleRecord(), url);
     return module_script;
   }
 
@@ -225,7 +225,7 @@
   v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
   EXPECT_FALSE(capture->WasCalled());
 
-  ScriptModule record = ScriptModule::Compile(
+  ModuleRecord record = ModuleRecord::Compile(
       scope.GetIsolate(), "export const foo = 'hello';", TestReferrerURL(),
       TestReferrerURL(), ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
@@ -317,7 +317,7 @@
 
   EXPECT_FALSE(capture->WasCalled());
 
-  ScriptModule record = ScriptModule::Compile(
+  ModuleRecord record = ModuleRecord::Compile(
       scope.GetIsolate(), "throw Error('bar')", TestReferrerURL(),
       TestReferrerURL(), ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
@@ -357,7 +357,7 @@
   v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
   EXPECT_FALSE(capture->WasCalled());
 
-  ScriptModule record = ScriptModule::Compile(
+  ModuleRecord record = ModuleRecord::Compile(
       scope.GetIsolate(), "export const foo = 'hello';", TestDependencyURL(),
       TestDependencyURL(), ScriptFetchOptions(),
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/core/script/modulator.h b/third_party/blink/renderer/core/script/modulator.h
index 05d01b3..350858d 100644
--- a/third_party/blink/renderer/core/script/modulator.h
+++ b/third_party/blink/renderer/core/script/modulator.h
@@ -8,8 +8,8 @@
 #include "base/single_thread_task_runner.h"
 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
 #include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/script/layered_api_module.h"
@@ -31,7 +31,7 @@
 class ImportMap;
 class ReferrerScriptInfo;
 class ResourceFetcher;
-class ScriptModuleResolver;
+class ModuleRecordResolver;
 class ScriptPromiseResolver;
 class ScriptState;
 class ScriptValue;
@@ -110,7 +110,7 @@
   void Trace(blink::Visitor* visitor) override {}
   const char* NameInHeapSnapshot() const override { return "Modulator"; }
 
-  virtual ScriptModuleResolver* GetScriptModuleResolver() = 0;
+  virtual ModuleRecordResolver* GetModuleRecordResolver() = 0;
   virtual base::SingleThreadTaskRunner* TaskRunner() = 0;
 
   virtual ScriptState* GetScriptState() = 0;
@@ -180,11 +180,11 @@
   virtual void ClearIsAcquiringImportMaps() = 0;
 
   // https://html.spec.whatwg.org/C/#hostgetimportmetaproperties
-  virtual ModuleImportMeta HostGetImportMetaProperties(ScriptModule) const = 0;
+  virtual ModuleImportMeta HostGetImportMetaProperties(ModuleRecord) const = 0;
 
   virtual bool HasValidContext() = 0;
 
-  virtual ScriptValue InstantiateModule(ScriptModule) = 0;
+  virtual ScriptValue InstantiateModule(ModuleRecord) = 0;
 
   struct ModuleRequest {
     String specifier;
@@ -192,8 +192,8 @@
     ModuleRequest(const String& specifier, const TextPosition& position)
         : specifier(specifier), position(position) {}
   };
-  virtual Vector<ModuleRequest> ModuleRequestsFromScriptModule(
-      ScriptModule) = 0;
+  virtual Vector<ModuleRequest> ModuleRequestsFromModuleRecord(
+      ModuleRecord) = 0;
 
   enum class CaptureEvalErrorFlag : bool { kReport, kCapture };
 
diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.cc b/third_party/blink/renderer/core/script/modulator_impl_base.cc
index 8b20ac1..a27c3184 100644
--- a/third_party/blink/renderer/core/script/modulator_impl_base.cc
+++ b/third_party/blink/renderer/core/script/modulator_impl_base.cc
@@ -15,9 +15,9 @@
 #include "third_party/blink/renderer/core/script/dynamic_module_resolver.h"
 #include "third_party/blink/renderer/core/script/import_map.h"
 #include "third_party/blink/renderer/core/script/module_map.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver_impl.h"
 #include "third_party/blink/renderer/core/script/module_script.h"
 #include "third_party/blink/renderer/core/script/parsed_specifier.h"
-#include "third_party/blink/renderer/core/script/script_module_resolver_impl.h"
 #include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
 
 namespace blink {
@@ -32,7 +32,7 @@
                        ->GetTaskRunner(TaskType::kNetworking)),
       map_(ModuleMap::Create(this)),
       tree_linker_registry_(ModuleTreeLinkerRegistry::Create()),
-      script_module_resolver_(ScriptModuleResolverImpl::Create(
+      module_record_resolver_(ModuleRecordResolverImpl::Create(
           this,
           ExecutionContext::From(script_state_))),
       dynamic_module_resolver_(DynamicModuleResolver::Create(this)) {
@@ -260,10 +260,10 @@
 
 // <specdef href="https://html.spec.whatwg.org/C/#hostgetimportmetaproperties">
 ModuleImportMeta ModulatorImplBase::HostGetImportMetaProperties(
-    ScriptModule record) const {
+    ModuleRecord record) const {
   // <spec step="1">Let module script be moduleRecord.[[HostDefined]].</spec>
   const ModuleScript* module_script =
-      script_module_resolver_->GetHostDefined(record);
+      module_record_resolver_->GetHostDefined(record);
   DCHECK(module_script);
 
   // <spec step="2">Let urlString be module script's base URL,
@@ -275,20 +275,20 @@
   return ModuleImportMeta(url_string);
 }
 
-ScriptValue ModulatorImplBase::InstantiateModule(ScriptModule script_module) {
+ScriptValue ModulatorImplBase::InstantiateModule(ModuleRecord module_record) {
   UseCounter::Count(GetExecutionContext(),
                     WebFeature::kInstantiateModuleScript);
 
   ScriptState::Scope scope(script_state_);
-  return script_module.Instantiate(script_state_);
+  return module_record.Instantiate(script_state_);
 }
 
 Vector<Modulator::ModuleRequest>
-ModulatorImplBase::ModuleRequestsFromScriptModule(ScriptModule script_module) {
+ModulatorImplBase::ModuleRequestsFromModuleRecord(ModuleRecord module_record) {
   ScriptState::Scope scope(script_state_);
-  Vector<String> specifiers = script_module.ModuleRequests(script_state_);
+  Vector<String> specifiers = module_record.ModuleRequests(script_state_);
   Vector<TextPosition> positions =
-      script_module.ModuleRequestPositions(script_state_);
+      module_record.ModuleRequestPositions(script_state_);
   DCHECK_EQ(specifiers.size(), positions.size());
   Vector<ModuleRequest> requests;
   requests.ReserveInitialCapacity(specifiers.size());
@@ -316,13 +316,13 @@
 
   discovered_set->insert(module_script);
 
-  ScriptModule record = module_script->Record();
+  ModuleRecord record = module_script->Record();
   DCHECK(!record.IsNull());
 
   module_script->ProduceCache();
 
   Vector<Modulator::ModuleRequest> child_specifiers =
-      ModuleRequestsFromScriptModule(record);
+      ModuleRequestsFromModuleRecord(record);
 
   for (const auto& module_request : child_specifiers) {
     KURL child_url =
@@ -359,7 +359,7 @@
 
   // <spec step="4">Prepare to run script given settings.</spec>
   //
-  // This is placed here to also cover ScriptModule::ReportException().
+  // This is placed here to also cover ModuleRecord::ReportException().
   ScriptState::Scope scope(script_state_);
 
   // <spec step="5">Let evaluationStatus be null.</spec>
@@ -376,7 +376,7 @@
     // <spec step="7">Otherwise:</spec>
 
     // <spec step="7.1">Let record be script's record.</spec>
-    const ScriptModule& record = module_script->Record();
+    const ModuleRecord& record = module_script->Record();
     CHECK(!record.IsNull());
 
     // <spec step="7.2">Set evaluationStatus to record.Evaluate(). ...</spec>
@@ -405,7 +405,7 @@
 
     // <spec step="8.2">Otherwise, report the exception given by
     // evaluationStatus.[[Value]] for script.</spec>
-    ScriptModule::ReportException(script_state_, error.V8Value());
+    ModuleRecord::ReportException(script_state_, error.V8Value());
   }
 
   // <spec step="9">Clean up after running script with settings.</spec>
@@ -418,7 +418,7 @@
   visitor->Trace(script_state_);
   visitor->Trace(map_);
   visitor->Trace(tree_linker_registry_);
-  visitor->Trace(script_module_resolver_);
+  visitor->Trace(module_record_resolver_);
   visitor->Trace(dynamic_module_resolver_);
   visitor->Trace(import_map_);
 
diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.h b/third_party/blink/renderer/core/script/modulator_impl_base.h
index cf9455e0..9bb58adb 100644
--- a/third_party/blink/renderer/core/script/modulator_impl_base.h
+++ b/third_party/blink/renderer/core/script/modulator_impl_base.h
@@ -6,7 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULATOR_IMPL_BASE_H_
 
 #include "base/single_thread_task_runner.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
@@ -46,8 +46,8 @@
   bool BuiltInModuleEnabled(blink::layered_api::Module) const override;
   void BuiltInModuleUseCount(blink::layered_api::Module) const override;
 
-  ScriptModuleResolver* GetScriptModuleResolver() override {
-    return script_module_resolver_.Get();
+  ModuleRecordResolver* GetModuleRecordResolver() override {
+    return module_record_resolver_.Get();
   }
   base::SingleThreadTaskRunner* TaskRunner() override {
     return task_runner_.get();
@@ -81,9 +81,9 @@
   void RegisterImportMap(const ImportMap*) final;
   bool IsAcquiringImportMaps() const final { return acquiring_import_maps_; }
   void ClearIsAcquiringImportMaps() final { acquiring_import_maps_ = false; }
-  ModuleImportMeta HostGetImportMetaProperties(ScriptModule) const override;
-  ScriptValue InstantiateModule(ScriptModule) override;
-  Vector<ModuleRequest> ModuleRequestsFromScriptModule(ScriptModule) override;
+  ModuleImportMeta HostGetImportMetaProperties(ModuleRecord) const override;
+  ScriptValue InstantiateModule(ModuleRecord) override;
+  Vector<ModuleRequest> ModuleRequestsFromModuleRecord(ModuleRecord) override;
   ScriptValue ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) override;
 
   // Populates |reason| and returns true if the dynamic import is disallowed on
@@ -101,7 +101,7 @@
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   TraceWrapperMember<ModuleMap> map_;
   TraceWrapperMember<ModuleTreeLinkerRegistry> tree_linker_registry_;
-  Member<ScriptModuleResolver> script_module_resolver_;
+  Member<ModuleRecordResolver> module_record_resolver_;
   Member<DynamicModuleResolver> dynamic_module_resolver_;
 
   Member<const ImportMap> import_map_;
diff --git a/third_party/blink/renderer/core/script/module_map.cc b/third_party/blink/renderer/core/script/module_map.cc
index 7e0f3e5..84b7fbc8 100644
--- a/third_party/blink/renderer/core/script/module_map.cc
+++ b/third_party/blink/renderer/core/script/module_map.cc
@@ -35,7 +35,7 @@
   // Notify fetched |m_moduleScript| to the client asynchronously.
   void AddClient(SingleModuleClient*);
 
-  // This is only to be used from ScriptModuleResolver implementations.
+  // This is only to be used from ModuleRecordResolver implementations.
   ModuleScript* GetModuleScript() const;
 
  private:
diff --git a/third_party/blink/renderer/core/script/module_map_test.cc b/third_party/blink/renderer/core/script/module_map_test.cc
index a03685e..db9b447 100644
--- a/third_party/blink/renderer/core/script/module_map_test.cc
+++ b/third_party/blink/renderer/core/script/module_map_test.cc
@@ -12,8 +12,8 @@
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_loader_client.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver.h"
 #include "third_party/blink/renderer/core/script/module_script.h"
-#include "third_party/blink/renderer/core/script/script_module_resolver.h"
 #include "third_party/blink/renderer/core/testing/dummy_modulator.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
@@ -48,9 +48,9 @@
   Member<ModuleScript> module_script_;
 };
 
-class TestScriptModuleResolver final : public ScriptModuleResolver {
+class TestModuleRecordResolver final : public ModuleRecordResolver {
  public:
-  TestScriptModuleResolver() {}
+  TestModuleRecordResolver() {}
 
   int RegisterModuleScriptCallCount() const {
     return register_module_script_call_count_;
@@ -64,16 +64,16 @@
     FAIL() << "UnregisterModuleScript shouldn't be called in ModuleMapTest";
   }
 
-  const ModuleScript* GetHostDefined(const ScriptModule&) const override {
+  const ModuleScript* GetHostDefined(const ModuleRecord&) const override {
     NOTREACHED();
     return nullptr;
   }
 
-  ScriptModule Resolve(const String& specifier,
-                       const ScriptModule& referrer,
+  ModuleRecord Resolve(const String& specifier,
+                       const ModuleRecord& referrer,
                        ExceptionState&) override {
     NOTREACHED();
-    return ScriptModule();
+    return ModuleRecord();
   }
 
  private:
@@ -89,14 +89,14 @@
 
   void Trace(blink::Visitor*) override;
 
-  TestScriptModuleResolver* GetTestScriptModuleResolver() {
+  TestModuleRecordResolver* GetTestModuleRecordResolver() {
     return resolver_.Get();
   }
   void ResolveFetches();
 
  private:
   // Implements Modulator:
-  ScriptModuleResolver* GetScriptModuleResolver() override {
+  ModuleRecordResolver* GetModuleRecordResolver() override {
     return resolver_.Get();
   }
   ScriptState* GetScriptState() override { return script_state_; }
@@ -136,7 +136,7 @@
     return MakeGarbageCollected<TestModuleScriptFetcher>(this);
   }
 
-  Vector<ModuleRequest> ModuleRequestsFromScriptModule(ScriptModule) override {
+  Vector<ModuleRequest> ModuleRequestsFromModuleRecord(ModuleRecord) override {
     return Vector<ModuleRequest>();
   }
 
@@ -161,12 +161,12 @@
   HeapVector<Member<TestRequest>> test_requests_;
 
   Member<ScriptState> script_state_;
-  Member<TestScriptModuleResolver> resolver_;
+  Member<TestModuleRecordResolver> resolver_;
 };
 
 ModuleMapTestModulator::ModuleMapTestModulator(ScriptState* script_state)
     : script_state_(script_state),
-      resolver_(MakeGarbageCollected<TestScriptModuleResolver>()) {}
+      resolver_(MakeGarbageCollected<TestModuleRecordResolver>()) {}
 
 void ModuleMapTestModulator::Trace(blink::Visitor* visitor) {
   visitor->Trace(test_requests_);
@@ -225,7 +225,7 @@
   platform->RunUntilIdle();
 
   EXPECT_EQ(Modulator()
-                ->GetTestScriptModuleResolver()
+                ->GetTestModuleRecordResolver()
                 ->RegisterModuleScriptCallCount(),
             1);
   EXPECT_TRUE(client->WasNotifyFinished());
@@ -244,7 +244,7 @@
   platform->RunUntilIdle();
 
   EXPECT_EQ(Modulator()
-                ->GetTestScriptModuleResolver()
+                ->GetTestModuleRecordResolver()
                 ->RegisterModuleScriptCallCount(),
             1)
       << "registerModuleScript sholudn't be called in secondary request.";
@@ -283,7 +283,7 @@
   platform->RunUntilIdle();
 
   EXPECT_EQ(Modulator()
-                ->GetTestScriptModuleResolver()
+                ->GetTestModuleRecordResolver()
                 ->RegisterModuleScriptCallCount(),
             1);
 
diff --git a/third_party/blink/renderer/core/script/module_record_resolver.h b/third_party/blink/renderer/core/script/module_record_resolver.h
new file mode 100644
index 0000000..fb075478
--- /dev/null
+++ b/third_party/blink/renderer/core/script/module_record_resolver.h
@@ -0,0 +1,52 @@
+// 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_BLINK_RENDERER_CORE_SCRIPT_MODULE_RECORD_RESOLVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULE_RECORD_RESOLVER_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ModuleRecord;
+class ModuleScript;
+
+// The ModuleRecordResolver interface is used from V8 module bindings
+// when it need the ModuleRecord's descendants.
+//
+// When a module writes import 'x', the module is called the referrer, 'x' is
+// the specifier, and the module identified by 'x' is the descendant.
+// ModuleRecordResolver, given a referrer and specifier, can look up the
+// descendant.
+class CORE_EXPORT ModuleRecordResolver
+    : public GarbageCollectedFinalized<ModuleRecordResolver> {
+ public:
+  virtual ~ModuleRecordResolver() = default;
+  virtual void Trace(blink::Visitor* visitor) {}
+
+  // Notifies the ModuleRecordResolver that a ModuleScript exists.
+  // This hook gives a chance for the resolver impl to populate module record
+  // identifier -> ModuleScript mapping entry.
+  virtual void RegisterModuleScript(const ModuleScript*) = 0;
+
+  // Notifies the ModuleRecordResolver to clear its ModuleScript mapping.
+  virtual void UnregisterModuleScript(const ModuleScript*) = 0;
+
+  // Corresponds to the spec concept "[[HostDefined]]".
+  virtual const ModuleScript* GetHostDefined(const ModuleRecord&) const = 0;
+
+  // Implements "Runtime Semantics: HostResolveImportedModule"
+  // https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule
+  // This returns a null ModuleRecord when an exception is thrown.
+  virtual ModuleRecord Resolve(const String& specifier,
+                               const ModuleRecord& referrer,
+                               ExceptionState&) = 0;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULE_RECORD_RESOLVER_H_
diff --git a/third_party/blink/renderer/core/script/script_module_resolver_impl.cc b/third_party/blink/renderer/core/script/module_record_resolver_impl.cc
similarity index 76%
rename from third_party/blink/renderer/core/script/script_module_resolver_impl.cc
rename to third_party/blink/renderer/core/script/module_record_resolver_impl.cc
index a31ef938..212ee50d 100644
--- a/third_party/blink/renderer/core/script/script_module_resolver_impl.cc
+++ b/third_party/blink/renderer/core/script/module_record_resolver_impl.cc
@@ -2,23 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/script/script_module_resolver_impl.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver_impl.h"
 
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
 #include "third_party/blink/renderer/core/script/module_script.h"
 
 namespace blink {
 
-void ScriptModuleResolverImpl::RegisterModuleScript(
+void ModuleRecordResolverImpl::RegisterModuleScript(
     const ModuleScript* module_script) {
   DCHECK(module_script);
   if (module_script->Record().IsNull())
     return;
 
-  DVLOG(1) << "ScriptModuleResolverImpl::RegisterModuleScript(url="
+  DVLOG(1) << "ModuleRecordResolverImpl::RegisterModuleScript(url="
            << module_script->BaseURL().GetString()
-           << ", hash=" << ScriptModuleHash::GetHash(module_script->Record())
+           << ", hash=" << ModuleRecordHash::GetHash(module_script->Record())
            << ")";
 
   auto result =
@@ -26,22 +26,22 @@
   DCHECK(result.is_new_entry);
 }
 
-void ScriptModuleResolverImpl::UnregisterModuleScript(
+void ModuleRecordResolverImpl::UnregisterModuleScript(
     const ModuleScript* module_script) {
   DCHECK(module_script);
   if (module_script->Record().IsNull())
     return;
 
-  DVLOG(1) << "ScriptModuleResolverImpl::UnregisterModuleScript(url="
+  DVLOG(1) << "ModuleRecordResolverImpl::UnregisterModuleScript(url="
            << module_script->BaseURL().GetString()
-           << ", hash=" << ScriptModuleHash::GetHash(module_script->Record())
+           << ", hash=" << ModuleRecordHash::GetHash(module_script->Record())
            << ")";
 
   record_to_module_script_map_.erase(module_script->Record());
 }
 
-const ModuleScript* ScriptModuleResolverImpl::GetHostDefined(
-    const ScriptModule& record) const {
+const ModuleScript* ModuleRecordResolverImpl::GetHostDefined(
+    const ModuleRecord& record) const {
   const auto it = record_to_module_script_map_.find(record);
   CHECK_NE(it, record_to_module_script_map_.end())
       << "Failed to find ModuleScript corresponding to the "
@@ -52,12 +52,12 @@
 
 // <specdef
 // href="https://html.spec.whatwg.org/C/#hostresolveimportedmodule(referencingscriptormodule,-specifier)">
-ScriptModule ScriptModuleResolverImpl::Resolve(
+ModuleRecord ModuleRecordResolverImpl::Resolve(
     const String& specifier,
-    const ScriptModule& referrer,
+    const ModuleRecord& referrer,
     ExceptionState& exception_state) {
-  DVLOG(1) << "ScriptModuleResolverImpl::resolve(specifier=\"" << specifier
-           << ", referrer.hash=" << ScriptModuleHash::GetHash(referrer) << ")";
+  DVLOG(1) << "ModuleRecordResolverImpl::resolve(specifier=\"" << specifier
+           << ", referrer.hash=" << ModuleRecordHash::GetHash(referrer) << ")";
 
   // <spec step="1">Let referencing script be
   // referencingScriptOrModule.[[HostDefined]].</spec>
@@ -93,14 +93,14 @@
   return module_script->Record();
 }
 
-void ScriptModuleResolverImpl::ContextDestroyed(ExecutionContext*) {
+void ModuleRecordResolverImpl::ContextDestroyed(ExecutionContext*) {
   // crbug.com/725816 : What we should really do is to make the map key
   // weak reference to v8::Module.
   record_to_module_script_map_.clear();
 }
 
-void ScriptModuleResolverImpl::Trace(blink::Visitor* visitor) {
-  ScriptModuleResolver::Trace(visitor);
+void ModuleRecordResolverImpl::Trace(blink::Visitor* visitor) {
+  ModuleRecordResolver::Trace(visitor);
   ContextLifecycleObserver::Trace(visitor);
   visitor->Trace(record_to_module_script_map_);
   visitor->Trace(modulator_);
diff --git a/third_party/blink/renderer/core/script/script_module_resolver_impl.h b/third_party/blink/renderer/core/script/module_record_resolver_impl.h
similarity index 63%
rename from third_party/blink/renderer/core/script/script_module_resolver_impl.h
rename to third_party/blink/renderer/core/script/module_record_resolver_impl.h
index 6a22cd6..29c35df 100644
--- a/third_party/blink/renderer/core/script/script_module_resolver_impl.h
+++ b/third_party/blink/renderer/core/script/module_record_resolver_impl.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_MODULE_RESOLVER_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_MODULE_RESOLVER_IMPL_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULE_RECORD_RESOLVER_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULE_RECORD_RESOLVER_IMPL_H_
 
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/script/script_module_resolver.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -17,54 +17,54 @@
 
 class Modulator;
 class ModuleScript;
-class ScriptModule;
+class ModuleRecord;
 
-// The ScriptModuleResolverImpl implements ScriptModuleResolver interface
+// The ModuleRecordResolverImpl implements ModuleRecordResolver interface
 // and implements "HostResolveImportedModule" HTML spec algorithm to bridge
 // ModuleMap (via Modulator) and V8 bindings.
-class CORE_EXPORT ScriptModuleResolverImpl final
-    : public ScriptModuleResolver,
+class CORE_EXPORT ModuleRecordResolverImpl final
+    : public ModuleRecordResolver,
       public ContextLifecycleObserver {
  public:
-  static ScriptModuleResolverImpl* Create(Modulator* modulator,
+  static ModuleRecordResolverImpl* Create(Modulator* modulator,
                                           ExecutionContext* execution_context) {
-    return MakeGarbageCollected<ScriptModuleResolverImpl>(modulator,
+    return MakeGarbageCollected<ModuleRecordResolverImpl>(modulator,
                                                           execution_context);
   }
 
-  explicit ScriptModuleResolverImpl(Modulator* modulator,
+  explicit ModuleRecordResolverImpl(Modulator* modulator,
                                     ExecutionContext* execution_context)
       : ContextLifecycleObserver(execution_context), modulator_(modulator) {}
 
   void Trace(blink::Visitor*) override;
-  USING_GARBAGE_COLLECTED_MIXIN(ScriptModuleResolverImpl);
+  USING_GARBAGE_COLLECTED_MIXIN(ModuleRecordResolverImpl);
 
  private:
-  // Implements ScriptModuleResolver:
+  // Implements ModuleRecordResolver:
 
   void RegisterModuleScript(const ModuleScript*) final;
   void UnregisterModuleScript(const ModuleScript*) final;
-  const ModuleScript* GetHostDefined(const ScriptModule&) const final;
+  const ModuleScript* GetHostDefined(const ModuleRecord&) const final;
 
   // Implements "Runtime Semantics: HostResolveImportedModule" per HTML spec.
   // https://html.spec.whatwg.org/C/#hostresolveimportedmodule(referencingscriptormodule,-specifier))
-  ScriptModule Resolve(const String& specifier,
-                       const ScriptModule& referrer,
+  ModuleRecord Resolve(const String& specifier,
+                       const ModuleRecord& referrer,
                        ExceptionState&) final;
 
   // Implements ContextLifecycleObserver:
   void ContextDestroyed(ExecutionContext*) final;
 
   // Corresponds to the spec concept "referencingModule.[[HostDefined]]".
-  // crbug.com/725816 : ScriptModule contains strong ref to v8::Module thus we
-  // should not use ScriptModule as the map key. We currently rely on Detach()
+  // crbug.com/725816 : ModuleRecord contains strong ref to v8::Module thus we
+  // should not use ModuleRecord as the map key. We currently rely on Detach()
   // to clear the refs, but we should implement a key type which keeps a
   // weak-ref to v8::Module.
-  HeapHashMap<ScriptModule, Member<const ModuleScript>>
+  HeapHashMap<ModuleRecord, Member<const ModuleScript>>
       record_to_module_script_map_;
   Member<Modulator> modulator_;
 };
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_MODULE_RESOLVER_IMPL_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULE_RECORD_RESOLVER_IMPL_H_
diff --git a/third_party/blink/renderer/core/script/script_module_resolver_impl_test.cc b/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
similarity index 83%
rename from third_party/blink/renderer/core/script/script_module_resolver_impl_test.cc
rename to third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
index 5cc43ce7..b3ccf3d 100644
--- a/third_party/blink/renderer/core/script/script_module_resolver_impl_test.cc
+++ b/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/script/script_module_resolver_impl.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver_impl.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/platform.h"
@@ -20,10 +20,10 @@
 
 namespace {
 
-class ScriptModuleResolverImplTestModulator final : public DummyModulator {
+class ModuleRecordResolverImplTestModulator final : public DummyModulator {
  public:
-  ScriptModuleResolverImplTestModulator() {}
-  ~ScriptModuleResolverImplTestModulator() override {}
+  ModuleRecordResolverImplTestModulator() {}
+  ~ModuleRecordResolverImplTestModulator() override {}
 
   void Trace(blink::Visitor*) override;
 
@@ -57,13 +57,13 @@
   Member<ModuleScript> module_script_;
 };
 
-void ScriptModuleResolverImplTestModulator::Trace(blink::Visitor* visitor) {
+void ModuleRecordResolverImplTestModulator::Trace(blink::Visitor* visitor) {
   visitor->Trace(script_state_);
   visitor->Trace(module_script_);
   DummyModulator::Trace(visitor);
 }
 
-ModuleScript* ScriptModuleResolverImplTestModulator::GetFetchedModuleScript(
+ModuleScript* ModuleRecordResolverImplTestModulator::GetFetchedModuleScript(
     const KURL& url) {
   get_fetched_module_script_called_++;
   fetched_url_ = url;
@@ -73,7 +73,7 @@
 ModuleScript* CreateReferrerModuleScript(Modulator* modulator,
                                          V8TestingScope& scope) {
   KURL js_url("https://example.com/referrer.js");
-  ScriptModule referrer_record = ScriptModule::Compile(
+  ModuleRecord referrer_record = ModuleRecord::Compile(
       scope.GetIsolate(), "import './target.js'; export const a = 42;", js_url,
       js_url, ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
@@ -87,7 +87,7 @@
                                        V8TestingScope& scope,
                                        bool has_parse_error = false) {
   KURL js_url("https://example.com/target.js");
-  ScriptModule record = ScriptModule::Compile(
+  ModuleRecord record = ModuleRecord::Compile(
       scope.GetIsolate(), "export const pi = 3.14;", js_url, js_url,
       ScriptFetchOptions(), TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
@@ -104,28 +104,28 @@
 
 }  // namespace
 
-class ScriptModuleResolverImplTest : public testing::Test {
+class ModuleRecordResolverImplTest : public testing::Test {
  public:
   void SetUp() override;
 
-  ScriptModuleResolverImplTestModulator* Modulator() {
+  ModuleRecordResolverImplTestModulator* Modulator() {
     return modulator_.Get();
   }
 
  protected:
   ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
       platform_;
-  Persistent<ScriptModuleResolverImplTestModulator> modulator_;
+  Persistent<ModuleRecordResolverImplTestModulator> modulator_;
 };
 
-void ScriptModuleResolverImplTest::SetUp() {
+void ModuleRecordResolverImplTest::SetUp() {
   platform_->AdvanceClockSeconds(1.);  // For non-zero DocumentParserTimings
-  modulator_ = MakeGarbageCollected<ScriptModuleResolverImplTestModulator>();
+  modulator_ = MakeGarbageCollected<ModuleRecordResolverImplTestModulator>();
 }
 
-TEST_F(ScriptModuleResolverImplTest, RegisterResolveSuccess) {
+TEST_F(ModuleRecordResolverImplTest, RegisterResolveSuccess) {
   V8TestingScope scope;
-  ScriptModuleResolver* resolver = ScriptModuleResolverImpl::Create(
+  ModuleRecordResolver* resolver = ModuleRecordResolverImpl::Create(
       Modulator(), scope.GetExecutionContext());
   Modulator()->SetScriptState(scope.GetScriptState());
 
@@ -137,7 +137,7 @@
       CreateTargetModuleScript(modulator_, scope);
   Modulator()->SetModuleScript(target_module_script);
 
-  ScriptModule resolved =
+  ModuleRecord resolved =
       resolver->Resolve("./target.js", referrer_module_script->Record(),
                         scope.GetExceptionState());
   EXPECT_FALSE(scope.GetExceptionState().HadException());
diff --git a/third_party/blink/renderer/core/script/module_script.cc b/third_party/blink/renderer/core/script/module_script.cc
index 0dc607c..9d68d53 100644
--- a/third_party/blink/renderer/core/script/module_script.cc
+++ b/third_party/blink/renderer/core/script/module_script.cc
@@ -5,7 +5,7 @@
 #include "third_party/blink/renderer/core/script/module_script.h"
 
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/core/script/script_module_resolver.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "v8/include/v8.h"
 
@@ -42,9 +42,9 @@
   ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
                                  "ModuleScript", "Create");
 
-  ScriptModuleProduceCacheData* produce_cache_data = nullptr;
+  ModuleRecordProduceCacheData* produce_cache_data = nullptr;
 
-  ScriptModule result = ScriptModule::Compile(
+  ModuleRecord result = ModuleRecord::Compile(
       isolate, source_text.ToString(), source_url, base_url, options,
       start_position, exception_state, modulator->GetV8CacheOptions(),
       cache_handler, source_location_type, &produce_cache_data);
@@ -75,7 +75,7 @@
   // <spec step="9">For each string requested of
   // result.[[RequestedModules]]:</spec>
   for (const auto& requested :
-       modulator->ModuleRequestsFromScriptModule(result)) {
+       modulator->ModuleRequestsFromModuleRecord(result)) {
     // <spec step="9.1">Let url be the result of resolving a module specifier
     // given script's base URL and requested.</spec>
     //
@@ -103,7 +103,7 @@
 }
 
 ModuleScript* ModuleScript::CreateForTest(Modulator* modulator,
-                                          ScriptModule record,
+                                          ModuleRecord record,
                                           const KURL& base_url,
                                           const ScriptFetchOptions& options) {
   ParkableString dummy_source_text(String("").ReleaseImpl());
@@ -117,12 +117,12 @@
 ModuleScript* ModuleScript::CreateInternal(
     const ParkableString& source_text,
     Modulator* modulator,
-    ScriptModule result,
+    ModuleRecord result,
     const KURL& source_url,
     const KURL& base_url,
     const ScriptFetchOptions& options,
     const TextPosition& start_position,
-    ScriptModuleProduceCacheData* produce_cache_data) {
+    ModuleRecordProduceCacheData* produce_cache_data) {
   // <spec step="6">Set script's parse error and error to rethrow to
   // null.</spec>
   //
@@ -139,19 +139,19 @@
 
   // Step 7, a part of ParseModule(): Passing script as the last parameter
   // here ensures result.[[HostDefined]] will be script.
-  modulator->GetScriptModuleResolver()->RegisterModuleScript(module_script);
+  modulator->GetModuleRecordResolver()->RegisterModuleScript(module_script);
 
   return module_script;
 }
 
 ModuleScript::ModuleScript(Modulator* settings_object,
-                           ScriptModule record,
+                           ModuleRecord record,
                            const KURL& source_url,
                            const KURL& base_url,
                            const ScriptFetchOptions& fetch_options,
                            const ParkableString& source_text,
                            const TextPosition& start_position,
-                           ScriptModuleProduceCacheData* produce_cache_data)
+                           ModuleRecordProduceCacheData* produce_cache_data)
     : Script(fetch_options, base_url),
       settings_object_(settings_object),
       source_text_(source_text),
@@ -170,13 +170,13 @@
   record_.Set(isolate, record.NewLocal(isolate));
 }
 
-ScriptModule ModuleScript::Record() const {
+ModuleRecord ModuleScript::Record() const {
   if (record_.IsEmpty())
-    return ScriptModule();
+    return ModuleRecord();
 
   v8::Isolate* isolate = settings_object_->GetScriptState()->GetIsolate();
   v8::HandleScope scope(isolate);
-  return ScriptModule(isolate, record_.NewLocal(isolate), source_url_);
+  return ModuleRecord(isolate, record_.NewLocal(isolate), source_url_);
 }
 
 bool ModuleScript::HasEmptyRecord() const {
diff --git a/third_party/blink/renderer/core/script/module_script.h b/third_party/blink/renderer/core/script/module_script.h
index 3d6d0d37..151e712 100644
--- a/third_party/blink/renderer/core/script/module_script.h
+++ b/third_party/blink/renderer/core/script/module_script.h
@@ -5,7 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULE_SCRIPT_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULE_SCRIPT_H_
 
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
@@ -38,25 +38,25 @@
       const ScriptFetchOptions&,
       const TextPosition& start_position = TextPosition::MinimumPosition());
 
-  // Mostly corresponds to Create() but accepts ScriptModule as the argument
-  // and allows null ScriptModule.
+  // Mostly corresponds to Create() but accepts ModuleRecord as the argument
+  // and allows null ModuleRecord.
   static ModuleScript* CreateForTest(
       Modulator*,
-      ScriptModule,
+      ModuleRecord,
       const KURL& base_url,
       const ScriptFetchOptions& = ScriptFetchOptions());
 
   ModuleScript(Modulator* settings_object,
-               ScriptModule record,
+               ModuleRecord record,
                const KURL& source_url,
                const KURL& base_url,
                const ScriptFetchOptions&,
                const ParkableString& source_text,
                const TextPosition& start_position,
-               ScriptModuleProduceCacheData*);
+               ModuleRecordProduceCacheData*);
   ~ModuleScript() override = default;
 
-  ScriptModule Record() const;
+  ModuleRecord Record() const;
   bool HasEmptyRecord() const;
 
   // Note: ParseError-related methods should only be used from ModuleTreeLinker
@@ -87,12 +87,12 @@
  private:
   static ModuleScript* CreateInternal(const ParkableString& source_text,
                                       Modulator*,
-                                      ScriptModule,
+                                      ModuleRecord,
                                       const KURL& source_url,
                                       const KURL& base_url,
                                       const ScriptFetchOptions&,
                                       const TextPosition&,
-                                      ScriptModuleProduceCacheData*);
+                                      ModuleRecordProduceCacheData*);
 
   mojom::ScriptType GetScriptType() const override {
     return mojom::ScriptType::kModule;
@@ -164,13 +164,13 @@
   // - CompileModule() and ProduceCache() should be called at different
   //   timings, and
   // - There are no persistent object that can hold this in
-  //   bindings/core/v8 side. ScriptModule should be short-lived and is
+  //   bindings/core/v8 side. ModuleRecord should be short-lived and is
   //   constructed every time in ModuleScript::Record().
   //
   // Cleared once ProduceCache() is called, to avoid
   // calling V8CodeCache::ProduceCache() multiple times, as a ModuleScript
   // can appear multiple times in multiple module graphs.
-  Member<ScriptModuleProduceCacheData> produce_cache_data_;
+  Member<ModuleRecordProduceCacheData> produce_cache_data_;
 };
 
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const ModuleScript&);
diff --git a/third_party/blink/renderer/core/script/module_script_test.cc b/third_party/blink/renderer/core/script/module_script_test.cc
index 81bcca55..86fc9a2 100644
--- a/third_party/blink/renderer/core/script/module_script_test.cc
+++ b/third_party/blink/renderer/core/script/module_script_test.cc
@@ -30,7 +30,7 @@
       : script_state_(script_state) {}
   ~ModuleScriptTestModulator() override = default;
 
-  Vector<ModuleRequest> ModuleRequestsFromScriptModule(ScriptModule) override {
+  Vector<ModuleRequest> ModuleRequestsFromModuleRecord(ModuleRecord) override {
     return Vector<ModuleRequest>();
   }
 
diff --git a/third_party/blink/renderer/core/script/script_module_resolver.h b/third_party/blink/renderer/core/script/script_module_resolver.h
deleted file mode 100644
index ddc63864..0000000
--- a/third_party/blink/renderer/core/script/script_module_resolver.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_MODULE_RESOLVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_MODULE_RESOLVER_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class ScriptModule;
-class ModuleScript;
-
-// The ScriptModuleResolver interface is used from V8 module bindings
-// when it need the ScriptModule's descendants.
-//
-// When a module writes import 'x', the module is called the referrer, 'x' is
-// the specifier, and the module identified by 'x' is the descendant.
-// ScriptModuleResolver, given a referrer and specifier, can look up the
-// descendant.
-class CORE_EXPORT ScriptModuleResolver
-    : public GarbageCollectedFinalized<ScriptModuleResolver> {
- public:
-  virtual ~ScriptModuleResolver() = default;
-  virtual void Trace(blink::Visitor* visitor) {}
-
-  // Notifies the ScriptModuleResolver that a ModuleScript exists.
-  // This hook gives a chance for the resolver impl to populate module record
-  // identifier -> ModuleScript mapping entry.
-  virtual void RegisterModuleScript(const ModuleScript*) = 0;
-
-  // Notifies the ScriptModuleResolver to clear its ModuleScript mapping.
-  virtual void UnregisterModuleScript(const ModuleScript*) = 0;
-
-  // Corresponds to the spec concept "[[HostDefined]]".
-  virtual const ModuleScript* GetHostDefined(const ScriptModule&) const = 0;
-
-  // Implements "Runtime Semantics: HostResolveImportedModule"
-  // https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule
-  // This returns a null ScriptModule when an exception is thrown.
-  virtual ScriptModule Resolve(const String& specifier,
-                               const ScriptModule& referrer,
-                               ExceptionState&) = 0;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_MODULE_RESOLVER_H_
diff --git a/third_party/blink/renderer/core/testing/dummy_modulator.cc b/third_party/blink/renderer/core/testing/dummy_modulator.cc
index ef3144f..5a4d3f4 100644
--- a/third_party/blink/renderer/core/testing/dummy_modulator.cc
+++ b/third_party/blink/renderer/core/testing/dummy_modulator.cc
@@ -5,38 +5,38 @@
 #include "third_party/blink/renderer/core/testing/dummy_modulator.h"
 
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/core/script/script_module_resolver.h"
+#include "third_party/blink/renderer/core/script/module_record_resolver.h"
 
 namespace blink {
 
 namespace {
 
-class EmptyScriptModuleResolver final : public ScriptModuleResolver {
+class EmptyModuleRecordResolver final : public ModuleRecordResolver {
  public:
-  EmptyScriptModuleResolver() = default;
+  EmptyModuleRecordResolver() = default;
 
   // We ignore {Unr,R}egisterModuleScript() calls caused by
   // ModuleScript::CreateForTest().
   void RegisterModuleScript(const ModuleScript*) override {}
   void UnregisterModuleScript(const ModuleScript*) override {}
 
-  const ModuleScript* GetHostDefined(const ScriptModule&) const override {
+  const ModuleScript* GetHostDefined(const ModuleRecord&) const override {
     NOTREACHED();
     return nullptr;
   }
 
-  ScriptModule Resolve(const String& specifier,
-                       const ScriptModule& referrer,
+  ModuleRecord Resolve(const String& specifier,
+                       const ModuleRecord& referrer,
                        ExceptionState&) override {
     NOTREACHED();
-    return ScriptModule();
+    return ModuleRecord();
   }
 };
 
 }  // namespace
 
 DummyModulator::DummyModulator()
-    : resolver_(MakeGarbageCollected<EmptyScriptModuleResolver>()) {}
+    : resolver_(MakeGarbageCollected<EmptyModuleRecordResolver>()) {}
 
 DummyModulator::~DummyModulator() = default;
 
@@ -68,7 +68,7 @@
 
 void DummyModulator::BuiltInModuleUseCount(blink::layered_api::Module) const {}
 
-ScriptModuleResolver* DummyModulator::GetScriptModuleResolver() {
+ModuleRecordResolver* DummyModulator::GetModuleRecordResolver() {
   return resolver_.Get();
 }
 
@@ -138,18 +138,18 @@
 }
 
 ModuleImportMeta DummyModulator::HostGetImportMetaProperties(
-    ScriptModule) const {
+    ModuleRecord) const {
   NOTREACHED();
   return ModuleImportMeta(String());
 }
 
-ScriptValue DummyModulator::InstantiateModule(ScriptModule) {
+ScriptValue DummyModulator::InstantiateModule(ModuleRecord) {
   NOTREACHED();
   return ScriptValue();
 }
 
-Vector<Modulator::ModuleRequest> DummyModulator::ModuleRequestsFromScriptModule(
-    ScriptModule) {
+Vector<Modulator::ModuleRequest> DummyModulator::ModuleRequestsFromModuleRecord(
+    ModuleRecord) {
   NOTREACHED();
   return Vector<ModuleRequest>();
 }
diff --git a/third_party/blink/renderer/core/testing/dummy_modulator.h b/third_party/blink/renderer/core/testing/dummy_modulator.h
index 01c1e51..9959681 100644
--- a/third_party/blink/renderer/core/testing/dummy_modulator.h
+++ b/third_party/blink/renderer/core/testing/dummy_modulator.h
@@ -6,13 +6,13 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_DUMMY_MODULATOR_H_
 
 #include "base/single_thread_task_runner.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
 
-class ScriptModuleResolver;
+class ModuleRecordResolver;
 
 // DummyModulator provides empty Modulator interface implementation w/
 // NOTREACHED().
@@ -29,7 +29,7 @@
   ~DummyModulator() override;
   void Trace(blink::Visitor*) override;
 
-  ScriptModuleResolver* GetScriptModuleResolver() override;
+  ModuleRecordResolver* GetModuleRecordResolver() override;
   base::SingleThreadTaskRunner* TaskRunner() override;
   ScriptState* GetScriptState() override;
   V8CacheOptions GetV8CacheOptions() const override;
@@ -64,14 +64,14 @@
   void RegisterImportMap(const ImportMap*) override;
   bool IsAcquiringImportMaps() const override;
   void ClearIsAcquiringImportMaps() override;
-  ModuleImportMeta HostGetImportMetaProperties(ScriptModule) const override;
-  ScriptValue InstantiateModule(ScriptModule) override;
-  Vector<ModuleRequest> ModuleRequestsFromScriptModule(ScriptModule) override;
+  ModuleImportMeta HostGetImportMetaProperties(ModuleRecord) const override;
+  ScriptValue InstantiateModule(ModuleRecord) override;
+  Vector<ModuleRequest> ModuleRequestsFromModuleRecord(ModuleRecord) override;
   ScriptValue ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) override;
   ModuleScriptFetcher* CreateModuleScriptFetcher(
       ModuleScriptCustomFetchType) override;
 
-  Member<ScriptModuleResolver> resolver_;
+  Member<ModuleRecordResolver> resolver_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
index d2934fc3..7c7ff2b 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -411,7 +411,7 @@
     return nullptr;
 
   if (!response_blob_) {
-    std::unique_ptr<BlobData> blob_data = BlobData::Create();
+    auto blob_data = std::make_unique<BlobData>();
     blob_data->SetContentType(FinalResponseMIMETypeWithFallback().LowerASCII());
     size_t size = 0;
     if (binary_response_builder_ && binary_response_builder_->size()) {
@@ -1968,7 +1968,7 @@
     String mime_type = FinalResponseMIMETypeWithFallback().LowerASCII();
     if (blob->GetType() != mime_type) {
       auto blob_size = blob->size();
-      auto blob_data = BlobData::Create();
+      auto blob_data = std::make_unique<BlobData>();
       blob_data->SetContentType(mime_type);
       blob_data->AppendBlob(std::move(blob), 0, blob_size);
       response_blob_ =
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
index 3be5809..0ca7bae 100644
--- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
@@ -8,7 +8,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
@@ -436,7 +436,7 @@
         global_scope->ScriptController()->GetScriptState();
     EXPECT_TRUE(script_state);
     const KURL js_url("https://example.com/worklet.js");
-    ScriptModule module = ScriptModule::Compile(
+    ModuleRecord module = ModuleRecord::Compile(
         script_state->GetIsolate(), source_code, js_url, js_url,
         ScriptFetchOptions(), TextPosition::MinimumPosition(),
         ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
index 3e7893e..5bd4ad8 100644
--- a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
+++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -745,10 +745,8 @@
   // timeline becomes newly inactive. See https://crbug.com/906050.
   last_current_time_ = current_time;
   if (!was_active && is_active) {
-    input_state->Add(
-        {id_,
-         std::string(animator_name_.Ascii().data(), animator_name_.length()),
-         current_time_ms, CloneOptions(), effects_.size()});
+    input_state->Add({id_, std::string(animator_name_.Utf8().data()),
+                      current_time_ms, CloneOptions(), effects_.size()});
   } else if (was_active && is_active) {
     // Skip if the input time is not changed.
     if (did_time_change)
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
index 314e12d9..21a9ebe 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -441,7 +441,7 @@
     batch_operation->request = std::move(fetch_api_request_);
     batch_operation->response = std::move(fetch_api_response_);
 
-    std::unique_ptr<BlobData> blob_data = BlobData::Create();
+    auto blob_data = std::make_unique<BlobData>();
     blob_data->SetContentType(mime_type_);
     blob_data->AppendBytes(array_buffer->Data(), array_buffer->ByteLength());
     batch_operation->response->blob = BlobDataHandle::Create(
@@ -453,7 +453,7 @@
       if (cached_metadata) {
         const Vector<uint8_t>& serialized_data =
             cached_metadata->SerializedData();
-        std::unique_ptr<BlobData> side_data_blob_data = BlobData::Create();
+        auto side_data_blob_data = std::make_unique<BlobData>();
         side_data_blob_data->AppendBytes(serialized_data.data(),
                                          serialized_data.size());
 
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
index 7a335f2e..334abf1cf 100644
--- a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
+++ b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
@@ -363,7 +363,7 @@
       success_callback_(success_callback) {}
 
 void FileWriterCallbacks::DidCreateFileWriter(const KURL& path,
-                                              long long length) {
+                                              int64_t length) {
   if (!success_callback_)
     return;
   file_writer_->Initialize(path, length);
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h
index 6ac6a351..9e43fec3 100644
--- a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h
+++ b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h
@@ -386,7 +386,7 @@
                       ExecutionContext*);
 
   // Called when an AsyncFileWrter has been created successfully.
-  void DidCreateFileWriter(const KURL& path, long long length);
+  void DidCreateFileWriter(const KURL& path, int64_t length);
 
   // Called when a request operation has failed.
   void DidFail(base::File::Error error);
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc b/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc
index 3901303..1ded9d9 100644
--- a/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc
+++ b/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc
@@ -577,7 +577,7 @@
     FileMetadata file_metadata = FileMetadata::From(file_info);
     file_metadata.platform_path = FilePathToWebString(platform_path);
 
-    std::unique_ptr<BlobData> blob_data = BlobData::Create();
+    auto blob_data = std::make_unique<BlobData>();
     blob_data->AppendFile(file_metadata.platform_path, 0, file_metadata.length,
                           InvalidFileTime());
     scoped_refptr<BlobDataHandle> snapshot_blob =
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
index ec0725a..c50291e8 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
@@ -58,7 +58,7 @@
   V8TestingScope scope;
   scope.GetDocument().SetSecurityOrigin(
       SecurityOrigin::Create(KURL("https://example.com")));
-  std::unique_ptr<MockWebIDBFactory> web_factory = MockWebIDBFactory::Create();
+  auto web_factory = std::make_unique<MockWebIDBFactory>();
   std::unique_ptr<WebIDBCallbacks> callbacks;
   web_factory->SetCallbacksPointer(&callbacks);
   IDBFactory* factory = IDBFactory::CreateForTest(std::move(web_factory));
@@ -91,7 +91,7 @@
   V8TestingScope scope;
   scope.GetDocument().SetSecurityOrigin(
       SecurityOrigin::Create(KURL("https://example.com")));
-  std::unique_ptr<MockWebIDBFactory> web_factory = MockWebIDBFactory::Create();
+  auto web_factory = std::make_unique<MockWebIDBFactory>();
   std::unique_ptr<WebIDBCallbacks> callbacks;
   web_factory->SetCallbacksPointer(&callbacks);
   IDBFactory* factory = IDBFactory::CreateForTest(std::move(web_factory));
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
index fee49ea..7ec33b59 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -573,8 +573,8 @@
   if (base::FeatureList::IsEnabled(kIndexedDBLargeValueWrapping))
     value_wrapper.WrapIfBiggerThan(IDBValueWrapper::kWrapThreshold);
 
-  std::unique_ptr<IDBValue> idb_value = IDBValue::Create(
-      value_wrapper.TakeWireBytes(), value_wrapper.TakeBlobInfo());
+  auto idb_value = std::make_unique<IDBValue>(value_wrapper.TakeWireBytes(),
+                                              value_wrapper.TakeBlobInfo());
 
   request->transit_blob_handles() = value_wrapper.TakeBlobDataHandles();
   BackendDB()->Put(
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request.cc b/third_party/blink/renderer/modules/indexeddb/idb_request.cc
index 513aa1c..5b036954 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request.cc
@@ -204,8 +204,7 @@
 
 std::unique_ptr<WebIDBCallbacks> IDBRequest::CreateWebCallbacks() {
   DCHECK(!web_callbacks_);
-  std::unique_ptr<WebIDBCallbacks> callbacks =
-      WebIDBCallbacksImpl::Create(this);
+  auto callbacks = std::make_unique<WebIDBCallbacksImpl>(this);
   web_callbacks_ = callbacks.get();
   return callbacks;
 }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc
index 48948d7f..2844e3f 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc
@@ -239,7 +239,7 @@
 
 TEST_F(IDBRequestTest, EventsAfterEarlyDeathStop) {
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
 
@@ -260,7 +260,7 @@
 
 TEST_F(IDBRequestTest, EventsAfterDoneStop) {
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
 
@@ -280,7 +280,7 @@
 
 TEST_F(IDBRequestTest, EventsAfterEarlyDeathStopWithQueuedResult) {
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
 
@@ -303,7 +303,7 @@
 
 TEST_F(IDBRequestTest, EventsAfterEarlyDeathStopWithTwoQueuedResults) {
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_test_helper.cc b/third_party/blink/renderer/modules/indexeddb/idb_test_helper.cc
index 4b16746..9345b90 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_test_helper.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_test_helper.cc
@@ -26,8 +26,8 @@
   scoped_refptr<SharedBuffer> idb_value_buffer = SharedBuffer::Create();
   idb_value_buffer->Append(reinterpret_cast<const char*>(ssv_wire_bytes.data()),
                            ssv_wire_bytes.size());
-  std::unique_ptr<IDBValue> idb_value =
-      IDBValue::Create(std::move(idb_value_buffer), Vector<WebBlobInfo>());
+  auto idb_value = std::make_unique<IDBValue>(std::move(idb_value_buffer),
+                                              Vector<WebBlobInfo>());
   idb_value->SetInjectedPrimaryKey(IDBKey::CreateNumber(42.0),
                                    IDBKeyPath(String("primaryKey")));
   idb_value->SetIsolate(isolate);
@@ -54,8 +54,8 @@
   Vector<WebBlobInfo> blob_infos = wrapper.TakeBlobInfo();
   scoped_refptr<SharedBuffer> wrapped_marker_buffer = wrapper.TakeWireBytes();
 
-  std::unique_ptr<IDBValue> idb_value =
-      IDBValue::Create(std::move(wrapped_marker_buffer), std::move(blob_infos));
+  auto idb_value = std::make_unique<IDBValue>(std::move(wrapped_marker_buffer),
+                                              std::move(blob_infos));
   idb_value->SetInjectedPrimaryKey(IDBKey::CreateNumber(42.0),
                                    IDBKeyPath(String("primaryKey")));
   idb_value->SetIsolate(isolate);
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc
index 889759b1..19034e8 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc
@@ -116,7 +116,7 @@
 
 TEST_F(IDBTransactionTest, ContextDestroyedEarlyDeath) {
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
 
@@ -152,7 +152,7 @@
 
 TEST_F(IDBTransactionTest, ContextDestroyedAfterDone) {
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
 
@@ -194,7 +194,7 @@
 
 TEST_F(IDBTransactionTest, ContextDestroyedWithQueuedResult) {
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
 
@@ -233,7 +233,7 @@
 
 TEST_F(IDBTransactionTest, ContextDestroyedWithTwoQueuedResults) {
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
 
@@ -279,7 +279,7 @@
   // This test covers the conditions of https://crbug.com/733642
 
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
 
@@ -323,7 +323,7 @@
 
 TEST_F(IDBTransactionTest, TransactionFinish) {
   V8TestingScope scope;
-  std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
+  auto backend = std::make_unique<MockWebIDBDatabase>();
   EXPECT_CALL(*backend, Commit(kTransactionId, 0)).Times(1);
   EXPECT_CALL(*backend, Close()).Times(1);
   BuildTransaction(scope, std::move(backend));
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value.cc b/third_party/blink/renderer/modules/indexeddb/idb_value.cc
index 74a851e..026313c 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_value.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_value.cc
@@ -26,11 +26,6 @@
     isolate_->AdjustAmountOfExternalAllocatedMemory(-external_allocated_size_);
 }
 
-std::unique_ptr<IDBValue> IDBValue::Create(scoped_refptr<SharedBuffer> data,
-                                           Vector<WebBlobInfo> blob_info) {
-  return base::WrapUnique(new IDBValue(std::move(data), std::move(blob_info)));
-}
-
 scoped_refptr<SerializedScriptValue> IDBValue::CreateSerializedValue() const {
   return SerializedScriptValue::Create(data_);
 }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value.h b/third_party/blink/renderer/modules/indexeddb/idb_value.h
index f5ffd05..c70e8c2 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_value.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_value.h
@@ -36,9 +36,7 @@
 // the values before returning them to the user.
 class MODULES_EXPORT IDBValue final {
  public:
-  static std::unique_ptr<IDBValue> Create(scoped_refptr<SharedBuffer>,
-                                          Vector<WebBlobInfo>);
-
+  IDBValue(scoped_refptr<SharedBuffer>, Vector<WebBlobInfo>);
   ~IDBValue();
 
   size_t DataSize() const { return data_ ? data_->size() : 0; }
@@ -85,8 +83,6 @@
 
   friend class IDBValueUnwrapper;
 
-  IDBValue(scoped_refptr<SharedBuffer>, Vector<WebBlobInfo>);
-
   // Keep this private to prevent new refs because we manually bookkeep the
   // memory to V8.
   scoped_refptr<SharedBuffer> data_;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.cc b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.cc
index 5ab0aac..74b7c5a 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.cc
@@ -143,7 +143,7 @@
 
   // TODO(pwnall): The MIME type should probably be an atomic string.
   String mime_type(kWrapMimeType);
-  std::unique_ptr<BlobData> wrapper_blob_data = BlobData::Create();
+  auto wrapper_blob_data = std::make_unique<BlobData>();
   wrapper_blob_data->SetContentType(String(kWrapMimeType));
   wrapper_blob_data->AppendBytes(wire_data_.data(), wire_data_size);
   scoped_refptr<BlobDataHandle> wrapper_handle =
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping_test.cc
index 46fe6cc..04d80067 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping_test.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping_test.cc
@@ -491,8 +491,8 @@
   ASSERT_TRUE(wrapped_marker_buffer->GetBytes(wrapped_marker_bytes.data(),
                                               wrapped_marker_bytes.size()));
 
-  std::unique_ptr<IDBValue> wrapped_value =
-      IDBValue::Create(std::move(wrapped_marker_buffer), std::move(blob_infos));
+  auto wrapped_value = std::make_unique<IDBValue>(
+      std::move(wrapped_marker_buffer), std::move(blob_infos));
   wrapped_value->SetIsolate(scope.GetIsolate());
   EXPECT_TRUE(IDBValueUnwrapper::IsWrapped(wrapped_value.get()));
 
@@ -501,9 +501,9 @@
   // return false.
   ASSERT_LT(3U, wrapped_marker_bytes.size());
   for (wtf_size_t i = 0; i < 3; ++i) {
-    std::unique_ptr<IDBValue> mutant_value =
-        IDBValue::Create(SharedBuffer::Create(wrapped_marker_bytes.data(), i),
-                         std::move(blob_infos));
+    auto mutant_value = std::make_unique<IDBValue>(
+        SharedBuffer::Create(wrapped_marker_bytes.data(), i),
+        std::move(blob_infos));
     mutant_value->SetIsolate(scope.GetIsolate());
 
     EXPECT_FALSE(IDBValueUnwrapper::IsWrapped(mutant_value.get()));
@@ -516,10 +516,10 @@
     for (int j = 0; j < 8; ++j) {
       char mask = 1 << j;
       wrapped_marker_bytes[i] ^= mask;
-      std::unique_ptr<IDBValue> mutant_value =
-          IDBValue::Create(SharedBuffer::Create(wrapped_marker_bytes.data(),
-                                                wrapped_marker_bytes.size()),
-                           std::move(blob_infos));
+      auto mutant_value = std::make_unique<IDBValue>(
+          SharedBuffer::Create(wrapped_marker_bytes.data(),
+                               wrapped_marker_bytes.size()),
+          std::move(blob_infos));
       mutant_value->SetIsolate(scope.GetIsolate());
       EXPECT_FALSE(IDBValueUnwrapper::IsWrapped(mutant_value.get()));
 
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
index 4e253d1..b0ede2f 100644
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
+++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
@@ -227,8 +227,8 @@
     return false;
 
   if (value_bits.IsEmpty()) {
-    *out = blink::IDBValue::Create(scoped_refptr<blink::SharedBuffer>(),
-                                   Vector<blink::WebBlobInfo>());
+    *out = std::make_unique<blink::IDBValue>(
+        scoped_refptr<blink::SharedBuffer>(), Vector<blink::WebBlobInfo>());
     return true;
   }
 
@@ -254,8 +254,8 @@
     }
   }
 
-  *out = blink::IDBValue::Create(std::move(value_buffer),
-                                 std::move(value_blob_info));
+  *out = std::make_unique<blink::IDBValue>(std::move(value_buffer),
+                                           std::move(value_blob_info));
   return true;
 }
 
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits_test.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits_test.cc
index 98b29dd..7f7a02b 100644
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits_test.cc
+++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits_test.cc
@@ -67,8 +67,8 @@
   ASSERT_EQ(input_vector.size(), test_data_size);
 
   // Create IDBValue mojom message.
-  std::unique_ptr<IDBValue> input =
-      IDBValue::Create(std::move(input_data), Vector<WebBlobInfo>());
+  auto input =
+      std::make_unique<IDBValue>(std::move(input_data), Vector<WebBlobInfo>());
   mojo::Message mojo_message =
       mojom::blink::IDBValue::SerializeAsMessage(&input);
 
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc
index a73dcb5..22aa44a 100644
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc
+++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc
@@ -50,8 +50,8 @@
     if (observation->value.has_value())
       value = std::move(observation->value.value());
     if (!value || value->Data()->IsEmpty()) {
-      value = IDBValue::Create(scoped_refptr<SharedBuffer>(),
-                               Vector<WebBlobInfo>());
+      value = std::make_unique<IDBValue>(scoped_refptr<SharedBuffer>(),
+                                         Vector<WebBlobInfo>());
     }
     observations.emplace_back(
         IDBObservation::Create(observation->object_store_id, observation->type,
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc
index 3b66f4b..bf95b302 100644
--- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc
+++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc
@@ -14,8 +14,4 @@
 
 MockWebIDBDatabase::~MockWebIDBDatabase() = default;
 
-std::unique_ptr<MockWebIDBDatabase> MockWebIDBDatabase::Create() {
-  return base::WrapUnique(new MockWebIDBDatabase());
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
index 835bd82..fde619c 100644
--- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
+++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
@@ -15,10 +15,9 @@
 
 class MockWebIDBDatabase : public testing::StrictMock<WebIDBDatabase> {
  public:
+  MockWebIDBDatabase();
   ~MockWebIDBDatabase() override;
 
-  static std::unique_ptr<MockWebIDBDatabase> Create();
-
   MOCK_METHOD5(CreateObjectStore,
                void(int64_t transaction_id,
                     int64_t object_store_id,
@@ -135,9 +134,6 @@
                void(int64_t transaction_id,
                     int64_t object_store_id,
                     WebIDBCallbacks*));
-
- private:
-  MockWebIDBDatabase();
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.cc b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.cc
index a1ce311..c24498e 100644
--- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.cc
+++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.cc
@@ -15,10 +15,6 @@
 
 MockWebIDBFactory::~MockWebIDBFactory() = default;
 
-std::unique_ptr<MockWebIDBFactory> MockWebIDBFactory::Create() {
-  return base::WrapUnique(new MockWebIDBFactory());
-}
-
 void MockWebIDBFactory::GetDatabaseInfo(
     std::unique_ptr<WebIDBCallbacks> callbacks) {
   *callbacks_ptr_ = std::move(callbacks);
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h
index a577ac43..557edc5 100644
--- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h
+++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h
@@ -21,10 +21,9 @@
 
 class MockWebIDBFactory : public testing::StrictMock<blink::WebIDBFactory> {
  public:
+  MockWebIDBFactory();
   ~MockWebIDBFactory() override;
 
-  static std::unique_ptr<MockWebIDBFactory> Create();
-
   void GetDatabaseInfo(std::unique_ptr<WebIDBCallbacks>);
   MOCK_METHOD1(GetDatabaseNames, void(std::unique_ptr<WebIDBCallbacks>));
   MOCK_METHOD5(Open,
@@ -41,7 +40,6 @@
   void SetCallbacksPointer(std::unique_ptr<WebIDBCallbacks>* callbacks);
 
  private:
-  MockWebIDBFactory();
   std::unique_ptr<WebIDBCallbacks>* callbacks_ptr_;
 };
 
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
index 78cebd1..58dab1cf 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
@@ -53,8 +53,8 @@
 std::unique_ptr<IDBValue> ConvertReturnValue(
     const mojom::blink::IDBReturnValuePtr& input) {
   if (!input) {
-    return IDBValue::Create(scoped_refptr<SharedBuffer>(),
-                            Vector<WebBlobInfo>());
+    return std::make_unique<IDBValue>(scoped_refptr<SharedBuffer>(),
+                                      Vector<WebBlobInfo>());
   }
 
   std::unique_ptr<IDBValue> output = std::move(input->value);
@@ -64,12 +64,6 @@
 
 }  // namespace
 
-// static
-std::unique_ptr<WebIDBCallbacksImpl> WebIDBCallbacksImpl::Create(
-    IDBRequest* request) {
-  return base::WrapUnique(new WebIDBCallbacksImpl(request));
-}
-
 WebIDBCallbacksImpl::WebIDBCallbacksImpl(IDBRequest* request)
     : request_(request) {
   task_runner_ =
@@ -149,8 +143,8 @@
   if (optional_value.has_value()) {
     value = std::move(optional_value.value());
   } else {
-    value =
-        IDBValue::Create(scoped_refptr<SharedBuffer>(), Vector<WebBlobInfo>());
+    value = std::make_unique<IDBValue>(scoped_refptr<SharedBuffer>(),
+                                       Vector<WebBlobInfo>());
   }
   DCHECK(value);
 
@@ -262,8 +256,8 @@
   if (optional_value.has_value()) {
     value = std::move(optional_value.value());
   } else {
-    value =
-        IDBValue::Create(scoped_refptr<SharedBuffer>(), Vector<WebBlobInfo>());
+    value = std::make_unique<IDBValue>(scoped_refptr<SharedBuffer>(),
+                                       Vector<WebBlobInfo>());
   }
   DCHECK(value);
   value->SetIsolate(request_->GetIsolate());
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
index cc8dc62..981f9e2 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
@@ -54,8 +54,7 @@
   // cases.
   enum : int64_t { kNoTransaction = -1 };
 
-  static std::unique_ptr<WebIDBCallbacksImpl> Create(IDBRequest*);
-
+  explicit WebIDBCallbacksImpl(IDBRequest*);
   ~WebIDBCallbacksImpl() override;
 
   void SetState(base::WeakPtr<WebIDBCursorImpl> cursor,
@@ -94,8 +93,6 @@
   void DetachRequestFromCallback() override;
 
  private:
-  explicit WebIDBCallbacksImpl(IDBRequest*);
-
   void Detach();
   void DetachCallbackFromRequest();
 
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
index 13599d7..4184553 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
@@ -180,8 +180,8 @@
         blob_info.emplace_back(WebBlobInfo::BlobForTesting(
             WebString("blobuuid"), "text/plain", 123));
       }
-      values.emplace_back(IDBValue::Create(scoped_refptr<SharedBuffer>(),
-                                           std::move(blob_info)));
+      values.emplace_back(std::make_unique<IDBValue>(
+          scoped_refptr<SharedBuffer>(), std::move(blob_info)));
     }
     cursor_->SetPrefetchData(std::move(keys), std::move(primary_keys),
                              std::move(values));
@@ -252,8 +252,8 @@
       blob_info.emplace_back(WebBlobInfo::BlobForTesting(WebString("blobuuid"),
                                                          "text/plain", 123));
     }
-    values.emplace_back(
-        IDBValue::Create(scoped_refptr<SharedBuffer>(), std::move(blob_info)));
+    values.emplace_back(std::make_unique<IDBValue>(
+        scoped_refptr<SharedBuffer>(), std::move(blob_info)));
   }
   cursor_->SetPrefetchData(std::move(keys), std::move(primary_keys),
                            std::move(values));
@@ -337,8 +337,8 @@
   Vector<std::unique_ptr<IDBKey>> primary_keys(prefetch_count);
   Vector<std::unique_ptr<IDBValue>> values;
   for (int i = 0; i < prefetch_count; ++i) {
-    values.emplace_back(
-        IDBValue::Create(scoped_refptr<SharedBuffer>(), Vector<WebBlobInfo>()));
+    values.emplace_back(std::make_unique<IDBValue>(
+        scoped_refptr<SharedBuffer>(), Vector<WebBlobInfo>()));
   }
   cursor_->SetPrefetchData(std::move(keys), std::move(primary_keys),
                            std::move(values));
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc
index 4b27268c..0bd8f206 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc
@@ -34,7 +34,7 @@
   const scoped_refptr<SharedBuffer> value_data =
       SharedBuffer::Create(&data.front(), data.size());
   const Vector<WebBlobInfo> blob_info;
-  std::unique_ptr<IDBValue> value = IDBValue::Create(value_data, blob_info);
+  auto value = std::make_unique<IDBValue>(value_data, blob_info);
   std::unique_ptr<IDBKey> key = IDBKey::CreateNumber(0);
   const int64_t transaction_id = 1;
   const int64_t object_store_id = 2;
@@ -62,7 +62,7 @@
   const scoped_refptr<SharedBuffer> value_data =
       SharedBuffer::Create(&data.front(), data.size());
   const Vector<WebBlobInfo> blob_info;
-  std::unique_ptr<IDBValue> value = IDBValue::Create(value_data, blob_info);
+  auto value = std::make_unique<IDBValue>(value_data, blob_info);
   const int64_t transaction_id = 1;
   const int64_t object_store_id = 2;
   StrictMock<MockWebIDBCallbacks> callbacks;
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc
index 248de8f..1e709cd 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc
@@ -101,13 +101,13 @@
     return;
 
   opaque_ = true;
+  removeAttribute("class");
 
   if (is_displayed_) {
     // Make sure we are listening for the 'transitionend' event.
     EnsureTransitionEventListener();
 
     SetIsWanted(true);
-    removeAttribute("class");
     DidBecomeVisible();
   }
 }
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
index 0fa418d..1e6d9d4 100644
--- a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
@@ -334,7 +334,7 @@
   }
 
   if (!blob_data_) {
-    blob_data_ = BlobData::Create();
+    blob_data_ = std::make_unique<BlobData>();
     blob_data_->SetContentType(mime_type_);
   }
   if (data)
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_client.h b/third_party/blink/renderer/modules/mediastream/user_media_client.h
index c828ebb..4b6675a 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_client.h
+++ b/third_party/blink/renderer/modules/mediastream/user_media_client.h
@@ -51,9 +51,7 @@
   USING_FAST_MALLOC(UserMediaClient);
 
  public:
-  static std::unique_ptr<UserMediaClient> Create(WebUserMediaClient* client) {
-    return base::WrapUnique(new UserMediaClient(client));
-  }
+  explicit UserMediaClient(WebUserMediaClient*);
 
   void RequestUserMedia(UserMediaRequest*);
   void CancelUserMediaRequest(UserMediaRequest*);
@@ -62,8 +60,6 @@
   bool IsCapturing();
 
  private:
-  explicit UserMediaClient(WebUserMediaClient*);
-
   WebUserMediaClient* client_;
 };
 
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc
index ac53f40..95fb51f 100644
--- a/third_party/blink/renderer/modules/modules_initializer.cc
+++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -172,7 +172,8 @@
   WebLocalFrameClient* client = web_frame->Client();
   DCHECK(client);
   ProvidePushControllerTo(frame, client->PushClient());
-  ProvideUserMediaTo(frame, UserMediaClient::Create(client->UserMediaClient()));
+  ProvideUserMediaTo(
+      frame, std::make_unique<UserMediaClient>(client->UserMediaClient()));
   ProvideIndexedDBClientTo(frame, IndexedDBClient::Create(frame));
   ProvideLocalFileSystemTo(frame, LocalFileSystemClient::Create());
   NavigatorContentUtils::ProvideTo(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index 8a841ca..41d9e55 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -2007,8 +2007,9 @@
     ScriptPromiseResolver* resolver =
         ScriptPromiseResolver::Create(script_state);
     ScriptPromise promise = resolver->Promise();
-    peer_handler_->GetStats(WebRTCStatsReportCallbackResolver::Create(resolver),
-                            GetRTCStatsFilter(script_state));
+    peer_handler_->GetStats(
+        std::make_unique<WebRTCStatsReportCallbackResolver>(resolver),
+        GetRTCStatsFilter(script_state));
 
     return promise;
   }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
index 3a965db..0e22b56 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
@@ -84,8 +84,9 @@
 ScriptPromise RTCRtpReceiver::getStats(ScriptState* script_state) {
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   ScriptPromise promise = resolver->Promise();
-  receiver_->GetStats(WebRTCStatsReportCallbackResolver::Create(resolver),
-                      GetRTCStatsFilter(script_state));
+  receiver_->GetStats(
+      std::make_unique<WebRTCStatsReportCallbackResolver>(resolver),
+      GetRTCStatsFilter(script_state));
   return promise;
 }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
index 2d258c86..4cdc907 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -454,8 +454,9 @@
 ScriptPromise RTCRtpSender::getStats(ScriptState* script_state) {
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   ScriptPromise promise = resolver->Promise();
-  sender_->GetStats(WebRTCStatsReportCallbackResolver::Create(resolver),
-                    GetRTCStatsFilter(script_state));
+  sender_->GetStats(
+      std::make_unique<WebRTCStatsReportCallbackResolver>(resolver),
+      GetRTCStatsFilter(script_state));
   return promise;
 }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.cc b/third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.cc
index e2b8613..d2a2a529 100644
--- a/third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.cc
+++ b/third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.cc
@@ -4,13 +4,6 @@
 
 namespace blink {
 
-// static
-std::unique_ptr<WebRTCStatsReportCallback>
-WebRTCStatsReportCallbackResolver::Create(ScriptPromiseResolver* resolver) {
-  return std::unique_ptr<WebRTCStatsReportCallback>(
-      new WebRTCStatsReportCallbackResolver(resolver));
-}
-
 WebRTCStatsReportCallbackResolver::WebRTCStatsReportCallbackResolver(
     ScriptPromiseResolver* resolver)
     : resolver_(resolver) {}
diff --git a/third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.h b/third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.h
index 2ad1403..2228bcc 100644
--- a/third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.h
+++ b/third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.h
@@ -16,13 +16,10 @@
 class WebRTCStatsReportCallbackResolver : public WebRTCStatsReportCallback {
  public:
   // Takes ownership of |resolver|.
-  static std::unique_ptr<WebRTCStatsReportCallback> Create(
-      ScriptPromiseResolver*);
+  explicit WebRTCStatsReportCallbackResolver(ScriptPromiseResolver*);
   ~WebRTCStatsReportCallbackResolver() override;
 
  private:
-  explicit WebRTCStatsReportCallbackResolver(ScriptPromiseResolver*);
-
   void OnStatsDelivered(std::unique_ptr<WebRTCStatsReport>) override;
 
   Persistent<ScriptPromiseResolver> resolver_;
diff --git a/third_party/blink/renderer/modules/presentation/presentation_connection.cc b/third_party/blink/renderer/modules/presentation/presentation_connection.cc
index f1570cc..f286ef7 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_connection.cc
+++ b/third_party/blink/renderer/modules/presentation/presentation_connection.cc
@@ -552,7 +552,7 @@
 
   switch (binary_type_) {
     case kBinaryTypeBlob: {
-      std::unique_ptr<BlobData> blob_data = BlobData::Create();
+      auto blob_data = std::make_unique<BlobData>();
       blob_data->AppendBytes(data, length);
       Blob* blob =
           Blob::Create(BlobDataHandle::Create(std::move(blob_data), length));
diff --git a/third_party/blink/renderer/modules/push_messaging/push_message_data.cc b/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
index b7609dc..ec7a9e58 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
+++ b/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
@@ -63,7 +63,7 @@
 }
 
 Blob* PushMessageData::blob() const {
-  std::unique_ptr<BlobData> blob_data = BlobData::Create();
+  auto blob_data = std::make_unique<BlobData>();
   blob_data->AppendBytes(data_.data(), data_.size());
 
   // Note that the content type of the Blob object is deliberately not being
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc b/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
index 5ee60afe..50fb3b6f2 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
@@ -218,7 +218,7 @@
       return;
     }
 
-    auto script_data = RawScriptData::Create(
+    auto script_data = std::make_unique<RawScriptData>(
         script_info->encoding, receivers->body()->TakeChunks(),
         receivers->meta_data()->TakeChunks());
     for (const auto& entry : script_info->headers)
diff --git a/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.cc b/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.cc
index 4d0db13..fdb883d0 100644
--- a/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.cc
+++ b/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.cc
@@ -8,15 +8,6 @@
 
 namespace blink {
 
-// static
-std::unique_ptr<ThreadSafeScriptContainer::RawScriptData>
-ThreadSafeScriptContainer::RawScriptData::Create(const String& encoding,
-                                                 Vector<BytesChunk> script_text,
-                                                 Vector<BytesChunk> meta_data) {
-  return base::WrapUnique(new RawScriptData(encoding, std::move(script_text),
-                                            std::move(meta_data)));
-}
-
 ThreadSafeScriptContainer::RawScriptData::RawScriptData(
     const String& encoding,
     Vector<BytesChunk> script_text,
diff --git a/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h b/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h
index 22069d93..00a9e857 100644
--- a/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h
+++ b/third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h
@@ -47,10 +47,9 @@
     USING_FAST_MALLOC(RawScriptData);
 
    public:
-    static std::unique_ptr<RawScriptData> Create(const String& encoding,
-                                                 Vector<BytesChunk> script_text,
-                                                 Vector<BytesChunk> meta_data);
-
+    RawScriptData(const String& encoding,
+                  Vector<BytesChunk> script_text,
+                  Vector<BytesChunk> meta_data);
     ~RawScriptData();
 
     void AddHeader(const String& key, const String& value);
@@ -69,9 +68,6 @@
     }
 
    private:
-    RawScriptData(const String& encoding,
-                  Vector<BytesChunk> script_text,
-                  Vector<BytesChunk> meta_data);
     String encoding_;
     Vector<BytesChunk> script_text_;
     Vector<BytesChunk> meta_data_;
diff --git a/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc b/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc
index d321c13..0e23e13 100644
--- a/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc
+++ b/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc
@@ -46,10 +46,11 @@
             [](scoped_refptr<ThreadSafeScriptContainer> container,
                ThreadSafeScriptContainer::RawScriptData** out_data,
                base::WaitableEvent* waiter) {
-              auto data = ThreadSafeScriptContainer::RawScriptData::Create(
-                  String::FromUTF8("utf-8") /* encoding */,
-                  Vector<Vector<char>>() /* script_text */,
-                  Vector<Vector<char>>() /* meta_data */);
+              auto data =
+                  std::make_unique<ThreadSafeScriptContainer::RawScriptData>(
+                      String::FromUTF8("utf-8") /* encoding */,
+                      Vector<Vector<char>>() /* script_text */,
+                      Vector<Vector<char>>() /* meta_data */);
               *out_data = data.get();
               container->AddOnIOThread(KURL(kKeyUrl), std::move(data));
               waiter->Signal();
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
index 079090e..1c39df0 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
@@ -10,7 +10,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
@@ -138,7 +138,7 @@
         global_scope->ScriptController()->GetScriptState();
     EXPECT_TRUE(script_state);
     KURL js_url("https://example.com/worklet.js");
-    ScriptModule module = ScriptModule::Compile(
+    ModuleRecord module = ModuleRecord::Compile(
         script_state->GetIsolate(), source_code, js_url, js_url,
         ScriptFetchOptions(), TextPosition::MinimumPosition(),
         ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
index aebb00fa..6df31520 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
@@ -9,7 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
@@ -88,7 +88,7 @@
     EXPECT_TRUE(script_state);
     ScriptState::Scope scope(script_state);
     KURL js_url("https://example.com/worklet.js");
-    ScriptModule module = ScriptModule::Compile(
+    ModuleRecord module = ModuleRecord::Compile(
         script_state->GetIsolate(), "var counter = 0; ++counter;", js_url,
         js_url, ScriptFetchOptions(), TextPosition::MinimumPosition(),
         ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc b/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc
index 8cd20acd..f49c4d5 100644
--- a/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc
@@ -85,7 +85,7 @@
   if (IsInitialized())
     return;
 
-  stereo_panner_ = StereoPanner::Create(Context()->sampleRate());
+  stereo_panner_ = std::make_unique<StereoPanner>(Context()->sampleRate());
 
   AudioHandler::Initialize();
 }
diff --git a/third_party/blink/renderer/modules/webdatabase/change_version_wrapper.cc b/third_party/blink/renderer/modules/webdatabase/change_version_wrapper.cc
index 44d8ee42..9898834 100644
--- a/third_party/blink/renderer/modules/webdatabase/change_version_wrapper.cc
+++ b/third_party/blink/renderer/modules/webdatabase/change_version_wrapper.cc
@@ -55,9 +55,10 @@
   }
 
   if (actual_version != old_version_) {
-    sql_error_ = SQLErrorData::Create(SQLError::kVersionErr,
-                                      "current version of the database and "
-                                      "`oldVersion` argument do not match");
+    sql_error_ =
+        std::make_unique<SQLErrorData>(SQLError::kVersionErr,
+                                       "current version of the database and "
+                                       "`oldVersion` argument do not match");
     return false;
   }
 
diff --git a/third_party/blink/renderer/modules/webdatabase/database.cc b/third_party/blink/renderer/modules/webdatabase/database.cc
index b5a1235..a0897dc 100644
--- a/third_party/blink/renderer/modules/webdatabase/database.cc
+++ b/third_party/blink/renderer/modules/webdatabase/database.cc
@@ -288,7 +288,7 @@
 
   DatabaseTracker::Tracker().PrepareToOpenDatabase(this);
   bool success = false;
-  std::unique_ptr<DatabaseOpenTask> task = DatabaseOpenTask::Create(
+  auto task = std::make_unique<DatabaseOpenTask>(
       this, set_version_in_new_database, &event, error, error_message, success);
   GetDatabaseContext()->GetDatabaseThread()->ScheduleTask(std::move(task));
   event.Wait();
@@ -377,8 +377,7 @@
     transaction = transaction_queue_.TakeFirst();
 
   if (transaction && GetDatabaseContext()->DatabaseThreadAvailable()) {
-    std::unique_ptr<DatabaseTransactionTask> task =
-        DatabaseTransactionTask::Create(transaction);
+    auto task = std::make_unique<DatabaseTransactionTask>(transaction);
     STORAGE_DVLOG(1) << "Scheduling DatabaseTransactionTask " << task.get()
                      << " for transaction " << task->Transaction();
     transaction_in_progress_ = true;
@@ -392,8 +391,7 @@
   if (!GetDatabaseContext()->DatabaseThreadAvailable())
     return;
 
-  std::unique_ptr<DatabaseTransactionTask> task =
-      DatabaseTransactionTask::Create(transaction);
+  auto task = std::make_unique<DatabaseTransactionTask>(transaction);
   STORAGE_DVLOG(1) << "Scheduling DatabaseTransactionTask " << task.get()
                    << " for the transaction step";
   GetDatabaseContext()->GetDatabaseThread()->ScheduleTask(std::move(task));
@@ -776,7 +774,7 @@
   if (GetDatabaseContext()->DatabaseThreadAvailable() && Opened()) {
     LogErrorMessage("forcibly closing database");
     GetDatabaseContext()->GetDatabaseThread()->ScheduleTask(
-        DatabaseCloseTask::Create(this, nullptr));
+        std::make_unique<DatabaseCloseTask>(this, nullptr));
   }
 }
 
@@ -851,8 +849,8 @@
     DCHECK_EQ(transaction_error_callback, original_error_callback);
 #endif
     if (transaction_error_callback) {
-      std::unique_ptr<SQLErrorData> error = SQLErrorData::Create(
-          SQLError::kUnknownErr, "database has been closed");
+      auto error = std::make_unique<SQLErrorData>(SQLError::kUnknownErr,
+                                                  "database has been closed");
       GetDatabaseTaskRunner()->PostTask(
           FROM_HERE, WTF::Bind(&CallTransactionErrorCallback,
                                WrapPersistent(transaction_error_callback),
@@ -908,8 +906,7 @@
   if (!GetDatabaseContext()->DatabaseThreadAvailable())
     return result;
 
-  std::unique_ptr<DatabaseTableNamesTask> task =
-      DatabaseTableNamesTask::Create(this, &event, result);
+  auto task = std::make_unique<DatabaseTableNamesTask>(this, &event, result);
   GetDatabaseContext()->GetDatabaseThread()->ScheduleTask(std::move(task));
   event.Wait();
 
diff --git a/third_party/blink/renderer/modules/webdatabase/database_task.h b/third_party/blink/renderer/modules/webdatabase/database_task.h
index 6339445..31db2441 100644
--- a/third_party/blink/renderer/modules/webdatabase/database_task.h
+++ b/third_party/blink/renderer/modules/webdatabase/database_task.h
@@ -75,19 +75,6 @@
 
 class Database::DatabaseOpenTask final : public DatabaseTask {
  public:
-  static std::unique_ptr<DatabaseOpenTask> Create(
-      Database* db,
-      bool set_version_in_new_database,
-      base::WaitableEvent* complete_event,
-      DatabaseError& error,
-      String& error_message,
-      bool& success) {
-    return base::WrapUnique(
-        new DatabaseOpenTask(db, set_version_in_new_database, complete_event,
-                             error, error_message, success));
-  }
-
- private:
   DatabaseOpenTask(Database*,
                    bool set_version_in_new_database,
                    base::WaitableEvent*,
@@ -95,6 +82,7 @@
                    String& error_message,
                    bool& success);
 
+ private:
   void DoPerformTask() override;
 #if DCHECK_IS_ON()
   const char* DebugTaskName() const override;
@@ -108,15 +96,9 @@
 
 class Database::DatabaseCloseTask final : public DatabaseTask {
  public:
-  static std::unique_ptr<DatabaseCloseTask> Create(
-      Database* db,
-      base::WaitableEvent* synchronizer) {
-    return base::WrapUnique(new DatabaseCloseTask(db, synchronizer));
-  }
-
- private:
   DatabaseCloseTask(Database*, base::WaitableEvent*);
 
+ private:
   void DoPerformTask() override;
 #if DCHECK_IS_ON()
   const char* DebugTaskName() const override;
@@ -125,19 +107,13 @@
 
 class Database::DatabaseTransactionTask final : public DatabaseTask {
  public:
-  ~DatabaseTransactionTask() override;
-
   // Transaction task is never synchronous, so no 'synchronizer' parameter.
-  static std::unique_ptr<DatabaseTransactionTask> Create(
-      SQLTransactionBackend* transaction) {
-    return base::WrapUnique(new DatabaseTransactionTask(transaction));
-  }
+  explicit DatabaseTransactionTask(SQLTransactionBackend*);
+  ~DatabaseTransactionTask() override;
 
   SQLTransactionBackend* Transaction() const { return transaction_.Get(); }
 
  private:
-  explicit DatabaseTransactionTask(SQLTransactionBackend*);
-
   void DoPerformTask() override;
   void TaskCancelled() override;
 #if DCHECK_IS_ON()
@@ -149,19 +125,11 @@
 
 class Database::DatabaseTableNamesTask final : public DatabaseTask {
  public:
-  static std::unique_ptr<DatabaseTableNamesTask> Create(
-      Database* db,
-      base::WaitableEvent* synchronizer,
-      Vector<String>& names) {
-    return base::WrapUnique(
-        new DatabaseTableNamesTask(db, synchronizer, names));
-  }
-
- private:
   DatabaseTableNamesTask(Database*,
                          base::WaitableEvent*,
                          Vector<String>& names);
 
+ private:
   void DoPerformTask() override;
 #if DCHECK_IS_ON()
   const char* DebugTaskName() const override;
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_error.h b/third_party/blink/renderer/modules/webdatabase/sql_error.h
index afcd120..0cf5de3 100644
--- a/third_party/blink/renderer/modules/webdatabase/sql_error.h
+++ b/third_party/blink/renderer/modules/webdatabase/sql_error.h
@@ -42,21 +42,16 @@
 
  public:
   static std::unique_ptr<SQLErrorData> Create(unsigned code,
-                                              const String& message) {
-    return base::WrapUnique(new SQLErrorData(code, message));
-  }
-
-  static std::unique_ptr<SQLErrorData> Create(unsigned code,
                                               const char* message,
                                               int sqlite_code,
                                               const char* sqlite_message) {
-    return Create(code, String::Format("%s (%d %s)", message, sqlite_code,
-                                       sqlite_message));
+    return std::make_unique<SQLErrorData>(
+        code,
+        String::Format("%s (%d %s)", message, sqlite_code, sqlite_message));
   }
 
-  static std::unique_ptr<SQLErrorData> Create(const SQLErrorData& data) {
-    return Create(data.Code(), data.Message());
-  }
+  SQLErrorData(unsigned code, const String& message)
+      : code_(code), message_(message.IsolatedCopy()) {}
 
   SQLErrorData(const SQLErrorData& data)
       : code_(data.code_), message_(data.message_.IsolatedCopy()) {}
@@ -65,9 +60,6 @@
   String Message() const { return message_.IsolatedCopy(); }
 
  private:
-  SQLErrorData(unsigned code, const String& message)
-      : code_(code), message_(message.IsolatedCopy()) {}
-
   unsigned code_;
   String message_;
 };
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.cc b/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.cc
index e331be9..2e9d147 100644
--- a/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.cc
+++ b/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.cc
@@ -166,7 +166,7 @@
   if (statement.BindParameterCount() != arguments_.size()) {
     STORAGE_DVLOG(1)
         << "Bind parameter count doesn't match number of question marks";
-    error_ = SQLErrorData::Create(
+    error_ = std::make_unique<SQLErrorData>(
         SQLError::kSyntaxErr,
         "number of '?'s in statement string does not match argument count");
     return false;
@@ -249,7 +249,7 @@
 void SQLStatementBackend::SetVersionMismatchedError(Database* database) {
   DCHECK(!error_);
   DCHECK(!result_set_->IsValid());
-  error_ = SQLErrorData::Create(
+  error_ = std::make_unique<SQLErrorData>(
       SQLError::kVersionErr,
       "current version of the database and `oldVersion` argument do not match");
 }
@@ -257,10 +257,11 @@
 void SQLStatementBackend::SetFailureDueToQuota(Database* database) {
   DCHECK(!error_);
   DCHECK(!result_set_->IsValid());
-  error_ = SQLErrorData::Create(SQLError::kQuotaErr,
-                                "there was not enough remaining storage "
-                                "space, or the storage quota was reached and "
-                                "the user declined to allow more space");
+  error_ = std::make_unique<SQLErrorData>(
+      SQLError::kQuotaErr,
+      "there was not enough remaining storage "
+      "space, or the storage quota was reached and "
+      "the user declined to allow more space");
 }
 
 void SQLStatementBackend::ClearFailureDueToQuota() {
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc b/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
index a5ba0fe5..5bccafb6 100644
--- a/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
+++ b/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
@@ -199,7 +199,7 @@
   // jump to the error callback.
   SQLTransactionState next_state = SQLTransactionState::kRunStatements;
   if (should_deliver_error_callback) {
-    transaction_error_ = SQLErrorData::Create(
+    transaction_error_ = std::make_unique<SQLErrorData>(
         SQLError::kUnknownErr,
         "the SQLTransactionCallback was null or threw an exception");
     next_state = SQLTransactionState::kDeliverTransactionErrorCallback;
@@ -219,7 +219,8 @@
     // a lock.
     if (!transaction_error_) {
       DCHECK(backend_->TransactionError());
-      transaction_error_ = SQLErrorData::Create(*backend_->TransactionError());
+      transaction_error_ =
+          std::make_unique<SQLErrorData>(*backend_->TransactionError());
     }
     DCHECK(transaction_error_);
     error_callback->OnError(SQLError::Create(*transaction_error_));
@@ -248,10 +249,10 @@
   execute_sql_allowed_ = false;
 
   if (result) {
-    transaction_error_ =
-        SQLErrorData::Create(SQLError::kUnknownErr,
-                             "the statement callback raised an exception or "
-                             "statement error callback did not return false");
+    transaction_error_ = std::make_unique<SQLErrorData>(
+        SQLError::kUnknownErr,
+        "the statement callback raised an exception or "
+        "statement error callback did not return false");
     return NextStateForTransactionError();
   }
   return SQLTransactionState::kRunStatements;
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc b/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc
index fbd78bc..8ec97828 100644
--- a/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc
+++ b/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc
@@ -654,9 +654,10 @@
     sqlite_transaction_.reset();
     database_->EnableAuthorizer();
     if (wrapper_->SqlError()) {
-      transaction_error_ = SQLErrorData::Create(*wrapper_->SqlError());
+      transaction_error_ =
+          std::make_unique<SQLErrorData>(*wrapper_->SqlError());
     } else {
-      transaction_error_ = SQLErrorData::Create(
+      transaction_error_ = std::make_unique<SQLErrorData>(
           SQLError::kUnknownErr,
           "unknown error occurred during transaction preflight");
     }
@@ -772,9 +773,9 @@
 
   if (current_statement_backend_->SqlError()) {
     transaction_error_ =
-        SQLErrorData::Create(*current_statement_backend_->SqlError());
+        std::make_unique<SQLErrorData>(*current_statement_backend_->SqlError());
   } else {
-    transaction_error_ = SQLErrorData::Create(
+    transaction_error_ = std::make_unique<SQLErrorData>(
         SQLError::kDatabaseErr, "the statement failed to execute");
   }
   return NextStateForTransactionError();
@@ -787,9 +788,10 @@
   // they fail.
   if (wrapper_ && !wrapper_->PerformPostflight(this)) {
     if (wrapper_->SqlError()) {
-      transaction_error_ = SQLErrorData::Create(*wrapper_->SqlError());
+      transaction_error_ =
+          std::make_unique<SQLErrorData>(*wrapper_->SqlError());
     } else {
-      transaction_error_ = SQLErrorData::Create(
+      transaction_error_ = std::make_unique<SQLErrorData>(
           SQLError::kUnknownErr,
           "unknown error occurred during transaction postflight");
     }
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket.cc b/third_party/blink/renderer/modules/websockets/dom_websocket.cc
index 26b90ef..3fcdd14 100644
--- a/third_party/blink/renderer/modules/websockets/dom_websocket.cc
+++ b/third_party/blink/renderer/modules/websockets/dom_websocket.cc
@@ -746,7 +746,7 @@
       size_t size = binary_data->size();
       scoped_refptr<RawData> raw_data = RawData::Create();
       binary_data->swap(*raw_data->MutableData());
-      std::unique_ptr<BlobData> blob_data = BlobData::Create();
+      auto blob_data = std::make_unique<BlobData>();
       blob_data->AppendData(std::move(raw_data));
       Blob* blob =
           Blob::Create(BlobDataHandle::Create(std::move(blob_data), size));
diff --git a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
index c20ccc7f..650d0f6 100644
--- a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
+++ b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
@@ -8,7 +8,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
+#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
@@ -75,7 +75,7 @@
     EXPECT_TRUE(script_state);
     ScriptState::Scope scope(script_state);
     const KURL js_url("https://example.com/foo.js");
-    ScriptModule module = ScriptModule::Compile(
+    ModuleRecord module = ModuleRecord::Compile(
         script_state->GetIsolate(), "var counter = 0; ++counter;", js_url,
         js_url, ScriptFetchOptions(), TextPosition::MinimumPosition(),
         ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/platform/animation/compositor_animation.cc b/third_party/blink/renderer/platform/animation/compositor_animation.cc
index c1dc980..5d8c808 100644
--- a/third_party/blink/renderer/platform/animation/compositor_animation.cc
+++ b/third_party/blink/renderer/platform/animation/compositor_animation.cc
@@ -26,8 +26,8 @@
     std::unique_ptr<CompositorScrollTimeline> scroll_timeline,
     std::unique_ptr<cc::AnimationOptions> options) {
   return std::make_unique<CompositorAnimation>(cc::WorkletAnimation::Create(
-      worklet_animation_id, std::string(name.Ascii().data(), name.length()),
-      playback_rate, std::move(scroll_timeline), std::move(options)));
+      worklet_animation_id, std::string(name.Utf8().data()), playback_rate,
+      std::move(scroll_timeline), std::move(options)));
 }
 
 CompositorAnimation::CompositorAnimation(
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database.cc b/third_party/blink/renderer/platform/audio/hrtf_database.cc
index 89f88a5..41f3687f 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_database.cc
+++ b/third_party/blink/renderer/platform/audio/hrtf_database.cc
@@ -45,10 +45,6 @@
 const unsigned HRTFDatabase::kNumberOfTotalElevations =
     kNumberOfRawElevations * kInterpolationFactor;
 
-std::unique_ptr<HRTFDatabase> HRTFDatabase::Create(float sample_rate) {
-  return base::WrapUnique(new HRTFDatabase(sample_rate));
-}
-
 HRTFDatabase::HRTFDatabase(float sample_rate)
     : elevations_(kNumberOfTotalElevations), sample_rate_(sample_rate) {
   unsigned elevation_index = 0;
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database.h b/third_party/blink/renderer/platform/audio/hrtf_database.h
index 708fab1..0a7a6b2 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_database.h
+++ b/third_party/blink/renderer/platform/audio/hrtf_database.h
@@ -46,7 +46,7 @@
   USING_FAST_MALLOC(HRTFDatabase);
 
  public:
-  static std::unique_ptr<HRTFDatabase> Create(float sample_rate);
+  explicit HRTFDatabase(float sample_rate);
 
   // getKernelsFromAzimuthElevation() returns a left and right ear kernel, and
   // an interpolated left and right frame delay for the given azimuth and
@@ -75,8 +75,6 @@
   static const unsigned kNumberOfRawElevations;
 
  private:
-  explicit HRTFDatabase(float sample_rate);
-
   // Minimum and maximum elevation angles (inclusive) for a HRTFDatabase.
   static const int kMinElevation;
   static const int kMaxElevation;
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
index 050cbb4..7086598 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
+++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
@@ -80,7 +80,7 @@
   // thread.
   MutexLocker locker(lock_);
   // Load the default HRTF database.
-  hrtf_database_ = HRTFDatabase::Create(database_sample_rate_);
+  hrtf_database_ = std::make_unique<HRTFDatabase>(database_sample_rate_);
 }
 
 void HRTFDatabaseLoader::LoadAsynchronously() {
diff --git a/third_party/blink/renderer/platform/audio/hrtf_elevation.cc b/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
index 96872c5..b8fc130 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
+++ b/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
@@ -184,10 +184,10 @@
   // Note that depending on the fftSize returned by the panner, we may be
   // truncating the impulse response we just loaded in.
   const size_t fft_size = HRTFPanner::FftSizeForSampleRate(sample_rate);
-  kernel_l =
-      HRTFKernel::Create(left_ear_impulse_response, fft_size, sample_rate);
-  kernel_r =
-      HRTFKernel::Create(right_ear_impulse_response, fft_size, sample_rate);
+  kernel_l = std::make_unique<HRTFKernel>(left_ear_impulse_response, fft_size,
+                                          sample_rate);
+  kernel_r = std::make_unique<HRTFKernel>(right_ear_impulse_response, fft_size,
+                                          sample_rate);
 
   return true;
 }
diff --git a/third_party/blink/renderer/platform/audio/hrtf_kernel.cc b/third_party/blink/renderer/platform/audio/hrtf_kernel.cc
index ab0b64d..c0e02a3 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_kernel.cc
+++ b/third_party/blink/renderer/platform/audio/hrtf_kernel.cc
@@ -140,8 +140,8 @@
   std::unique_ptr<FFTFrame> interpolated_frame =
       FFTFrame::CreateInterpolatedFrame(*kernel1->FftFrame(),
                                         *kernel2->FftFrame(), x);
-  return HRTFKernel::Create(std::move(interpolated_frame), frame_delay,
-                            sample_rate1);
+  return std::make_unique<HRTFKernel>(std::move(interpolated_frame),
+                                      frame_delay, sample_rate1);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/audio/hrtf_kernel.h b/third_party/blink/renderer/platform/audio/hrtf_kernel.h
index b9b9bf4..093f89d 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_kernel.h
+++ b/third_party/blink/renderer/platform/audio/hrtf_kernel.h
@@ -57,18 +57,13 @@
  public:
   // Note: this is destructive on the passed in AudioChannel.
   // The length of channel must be a power of two.
-  static std::unique_ptr<HRTFKernel> Create(AudioChannel* channel,
-                                            size_t fft_size,
-                                            float sample_rate) {
-    return base::WrapUnique(new HRTFKernel(channel, fft_size, sample_rate));
-  }
-
-  static std::unique_ptr<HRTFKernel> Create(std::unique_ptr<FFTFrame> fft_frame,
-                                            float frame_delay,
-                                            float sample_rate) {
-    return base::WrapUnique(
-        new HRTFKernel(std::move(fft_frame), frame_delay, sample_rate));
-  }
+  HRTFKernel(AudioChannel*, size_t fft_size, float sample_rate);
+  HRTFKernel(std::unique_ptr<FFTFrame> fft_frame,
+             float frame_delay,
+             float sample_rate)
+      : fft_frame_(std::move(fft_frame)),
+        frame_delay_(frame_delay),
+        sample_rate_(sample_rate) {}
 
   // Given two HRTFKernels, and an interpolation factor x: 0 -> 1, returns an
   // interpolated HRTFKernel.
@@ -87,16 +82,6 @@
   std::unique_ptr<AudioChannel> CreateImpulseResponse();
 
  private:
-  // Note: this is destructive on the passed in AudioChannel.
-  HRTFKernel(AudioChannel*, size_t fft_size, float sample_rate);
-
-  HRTFKernel(std::unique_ptr<FFTFrame> fft_frame,
-             float frame_delay,
-             float sample_rate)
-      : fft_frame_(std::move(fft_frame)),
-        frame_delay_(frame_delay),
-        sample_rate_(sample_rate) {}
-
   std::unique_ptr<FFTFrame> fft_frame_;
   float frame_delay_;
   float sample_rate_;
diff --git a/third_party/blink/renderer/platform/audio/stereo_panner.cc b/third_party/blink/renderer/platform/audio/stereo_panner.cc
index 9ba7245..9e619f0 100644
--- a/third_party/blink/renderer/platform/audio/stereo_panner.cc
+++ b/third_party/blink/renderer/platform/audio/stereo_panner.cc
@@ -17,10 +17,6 @@
 // Implement equal-power panning algorithm for mono or stereo input.
 // See: http://webaudio.github.io/web-audio-api/#panning-algorithm
 
-std::unique_ptr<StereoPanner> StereoPanner::Create(float sample_rate) {
-  return base::WrapUnique(new StereoPanner(sample_rate));
-}
-
 StereoPanner::StereoPanner(float sample_rate) {}
 
 void StereoPanner::PanWithSampleAccurateValues(const AudioBus* input_bus,
diff --git a/third_party/blink/renderer/platform/audio/stereo_panner.h b/third_party/blink/renderer/platform/audio/stereo_panner.h
index 96affa9..49dbdac 100644
--- a/third_party/blink/renderer/platform/audio/stereo_panner.h
+++ b/third_party/blink/renderer/platform/audio/stereo_panner.h
@@ -20,7 +20,7 @@
   USING_FAST_MALLOC(StereoPanner);
 
  public:
-  static std::unique_ptr<StereoPanner> Create(float sample_rate);
+  explicit StereoPanner(float sample_rate);
   ~StereoPanner() = default;
 
   void PanWithSampleAccurateValues(const AudioBus* input_bus,
@@ -33,8 +33,6 @@
                         uint32_t frames_to_process);
 
  private:
-  explicit StereoPanner(float sample_rate);
-
   DISALLOW_COPY_AND_ASSIGN(StereoPanner);
 };
 
diff --git a/third_party/blink/renderer/platform/bindings/script_state.cc b/third_party/blink/renderer/platform/bindings/script_state.cc
index cd270eb..67c312eb 100644
--- a/third_party/blink/renderer/platform/bindings/script_state.cc
+++ b/third_party/blink/renderer/platform/bindings/script_state.cc
@@ -20,7 +20,7 @@
     : isolate_(context->GetIsolate()),
       context_(isolate_, context),
       world_(std::move(world)),
-      per_context_data_(V8PerContextData::Create(context)),
+      per_context_data_(std::make_unique<V8PerContextData>(context)),
       reference_from_v8_context_(this) {
   DCHECK(world_);
   context_.SetWeak(this, &OnV8ContextCollectedCallback);
diff --git a/third_party/blink/renderer/platform/bindings/v0_custom_element_binding.cc b/third_party/blink/renderer/platform/bindings/v0_custom_element_binding.cc
index 68e534af..5413028b 100644
--- a/third_party/blink/renderer/platform/bindings/v0_custom_element_binding.cc
+++ b/third_party/blink/renderer/platform/bindings/v0_custom_element_binding.cc
@@ -36,12 +36,6 @@
 
 namespace blink {
 
-std::unique_ptr<V0CustomElementBinding> V0CustomElementBinding::Create(
-    v8::Isolate* isolate,
-    v8::Local<v8::Object> prototype) {
-  return base::WrapUnique(new V0CustomElementBinding(isolate, prototype));
-}
-
 V0CustomElementBinding::V0CustomElementBinding(v8::Isolate* isolate,
                                                v8::Local<v8::Object> prototype)
     : prototype_(isolate, prototype) {
diff --git a/third_party/blink/renderer/platform/bindings/v0_custom_element_binding.h b/third_party/blink/renderer/platform/bindings/v0_custom_element_binding.h
index c5a005f..46eae21 100644
--- a/third_party/blink/renderer/platform/bindings/v0_custom_element_binding.h
+++ b/third_party/blink/renderer/platform/bindings/v0_custom_element_binding.h
@@ -44,13 +44,10 @@
   USING_FAST_MALLOC(V0CustomElementBinding);
 
  public:
-  static std::unique_ptr<V0CustomElementBinding> Create(
-      v8::Isolate*,
-      v8::Local<v8::Object> prototype);
+  V0CustomElementBinding(v8::Isolate*, v8::Local<v8::Object> prototype);
   ~V0CustomElementBinding();
 
  private:
-  V0CustomElementBinding(v8::Isolate*, v8::Local<v8::Object> prototype);
   ScopedPersistent<v8::Object> prototype_;
 };
 
diff --git a/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc b/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc
index ee25586..386783f 100644
--- a/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc
+++ b/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc
@@ -78,11 +78,6 @@
   }
 }
 
-std::unique_ptr<V8PerContextData> V8PerContextData::Create(
-    v8::Local<v8::Context> context) {
-  return base::WrapUnique(new V8PerContextData(context));
-}
-
 V8PerContextData* V8PerContextData::From(v8::Local<v8::Context> context) {
   return ScriptState::From(context)->PerContextData();
 }
diff --git a/third_party/blink/renderer/platform/bindings/v8_per_context_data.h b/third_party/blink/renderer/platform/bindings/v8_per_context_data.h
index a65880d..89b5777 100644
--- a/third_party/blink/renderer/platform/bindings/v8_per_context_data.h
+++ b/third_party/blink/renderer/platform/bindings/v8_per_context_data.h
@@ -60,7 +60,7 @@
   USING_FAST_MALLOC(V8PerContextData);
 
  public:
-  static std::unique_ptr<V8PerContextData> Create(v8::Local<v8::Context>);
+  explicit V8PerContextData(v8::Local<v8::Context>);
 
   static V8PerContextData* From(v8::Local<v8::Context>);
 
@@ -125,8 +125,6 @@
   Data* GetData(const char* key);
 
  private:
-  V8PerContextData(v8::Local<v8::Context>);
-
   v8::Local<v8::Object> CreateWrapperFromCacheSlowCase(const WrapperTypeInfo*);
   v8::Local<v8::Function> ConstructorForTypeSlowCase(const WrapperTypeInfo*);
 
diff --git a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
index ea8cbfa..2f41550 100644
--- a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
+++ b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
@@ -85,7 +85,7 @@
       interface_template_map_for_v8_context_snapshot_(GetIsolate(),
                                                       kInterfaceMapLabel),
       string_cache_(std::make_unique<StringCache>(GetIsolate())),
-      private_property_(V8PrivateProperty::Create()),
+      private_property_(std::make_unique<V8PrivateProperty>()),
       constructor_mode_(ConstructorMode::kCreateNewObject),
       use_counter_disabled_(false),
       is_handling_recursion_level_error_(false),
@@ -114,7 +114,7 @@
                       gin::IsolateHolder::IsolateCreationMode::kCreateSnapshot),
       interface_template_map_for_v8_context_snapshot_(GetIsolate()),
       string_cache_(std::make_unique<StringCache>(GetIsolate())),
-      private_property_(V8PrivateProperty::Create()),
+      private_property_(std::make_unique<V8PrivateProperty>()),
       constructor_mode_(ConstructorMode::kCreateNewObject),
       use_counter_disabled_(false),
       is_handling_recursion_level_error_(false),
diff --git a/third_party/blink/renderer/platform/bindings/v8_private_property.h b/third_party/blink/renderer/platform/bindings/v8_private_property.h
index 48956be..3d75d560 100644
--- a/third_party/blink/renderer/platform/bindings/v8_private_property.h
+++ b/third_party/blink/renderer/platform/bindings/v8_private_property.h
@@ -87,6 +87,8 @@
     kWindowDocumentCachedAccessor,
   };
 
+  V8PrivateProperty() = default;
+
   // Provides fast access to V8's private properties.
   //
   // Retrieving/creating a global private symbol from a string is very
@@ -140,10 +142,6 @@
     v8::Isolate* isolate_;
   };
 
-  static std::unique_ptr<V8PrivateProperty> Create() {
-    return base::WrapUnique(new V8PrivateProperty());
-  }
-
 #define V8_PRIVATE_PROPERTY_DEFINE_GETTER(InterfaceName, KeyName)              \
   static Symbol V8_PRIVATE_PROPERTY_GETTER_NAME(/* // NOLINT */                \
                                                 InterfaceName, KeyName)(       \
@@ -197,8 +195,6 @@
   }
 
  private:
-  V8PrivateProperty() = default;
-
   static v8::Local<v8::Private> CreateV8Private(v8::Isolate*,
                                                 const char* symbol);
   // TODO(peria): Remove this method. We should not use v8::Private::ForApi().
diff --git a/third_party/blink/renderer/platform/blob/blob_data.cc b/third_party/blink/renderer/platform/blob/blob_data.cc
index aac50230..8a1c9ffa2 100644
--- a/third_party/blink/renderer/platform/blob/blob_data.cc
+++ b/third_party/blink/renderer/platform/blob/blob_data.cc
@@ -105,11 +105,6 @@
 
 RawData::RawData() = default;
 
-std::unique_ptr<BlobData> BlobData::Create() {
-  return base::WrapUnique(
-      new BlobData(FileCompositionStatus::NO_UNKNOWN_SIZE_FILES));
-}
-
 std::unique_ptr<BlobData> BlobData::CreateForFileWithUnknownSize(
     const String& path) {
   std::unique_ptr<BlobData> data = base::WrapUnique(
diff --git a/third_party/blink/renderer/platform/blob/blob_data.h b/third_party/blink/renderer/platform/blob/blob_data.h
index 6caf1fb..7ec4f688 100644
--- a/third_party/blink/renderer/platform/blob/blob_data.h
+++ b/third_party/blink/renderer/platform/blob/blob_data.h
@@ -73,8 +73,14 @@
 
  public:
   static constexpr int64_t kToEndOfFile = -1;
+  enum class FileCompositionStatus {
+    SINGLE_UNKNOWN_SIZE_FILE,
+    NO_UNKNOWN_SIZE_FILES
+  };
 
-  static std::unique_ptr<BlobData> Create();
+  explicit BlobData(FileCompositionStatus composition =
+                        FileCompositionStatus::NO_UNKNOWN_SIZE_FILES)
+      : file_composition_(composition) {}
 
   // Calling append* on objects returned by createFor___WithUnknownSize will
   // check-fail. The caller can only have an unknown-length file if it is the
@@ -129,14 +135,6 @@
   }
 
  private:
-  enum class FileCompositionStatus {
-    SINGLE_UNKNOWN_SIZE_FILE,
-    NO_UNKNOWN_SIZE_FILES
-  };
-
-  explicit BlobData(FileCompositionStatus composition)
-      : file_composition_(composition) {}
-
   void AppendDataInternal(base::span<const char> data,
                           scoped_refptr<RawData> = nullptr);
 
diff --git a/third_party/blink/renderer/platform/blob/blob_data_test.cc b/third_party/blink/renderer/platform/blob/blob_data_test.cc
index 5cc7d137..2657150 100644
--- a/third_party/blink/renderer/platform/blob/blob_data_test.cc
+++ b/third_party/blink/renderer/platform/blob/blob_data_test.cc
@@ -118,7 +118,7 @@
 
     empty_blob_ = BlobDataHandle::Create();
 
-    std::unique_ptr<BlobData> test_data = BlobData::Create();
+    auto test_data = std::make_unique<BlobData>();
     test_data->AppendBytes(large_test_data_.data(), large_test_data_.size());
     test_blob_ =
         BlobDataHandle::Create(std::move(test_data), large_test_data_.size());
@@ -257,7 +257,7 @@
 TEST_F(BlobDataHandleTest, CreateFromEmptyData) {
   String kType = "content/type";
 
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->SetContentType(kType);
 
   TestCreateBlob(std::move(data), {});
@@ -282,7 +282,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromEmptyElements) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendBytes(small_test_data_.data(), 0);
   data->AppendBlob(empty_blob_, 0, 0);
   data->AppendFile("path", 0, 0, 0.0);
@@ -292,7 +292,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromSmallBytes) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendBytes(small_test_data_.data(), small_test_data_.size());
 
   Vector<ExpectedElement> expected_elements;
@@ -302,7 +302,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromLargeBytes) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendBytes(large_test_data_.data(), large_test_data_.size());
 
   Vector<ExpectedElement> expected_elements;
@@ -312,7 +312,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromMergedBytes) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendBytes(medium_test_data_.data(), medium_test_data_.size());
   data->AppendBytes(small_test_data_.data(), small_test_data_.size());
   EXPECT_EQ(1u, data->Elements().size());
@@ -328,7 +328,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromMergedLargeAndSmallBytes) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendBytes(large_test_data_.data(), large_test_data_.size());
   data->AppendBytes(small_test_data_.data(), small_test_data_.size());
   EXPECT_EQ(1u, data->Elements().size());
@@ -344,7 +344,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromMergedSmallAndLargeBytes) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendBytes(small_test_data_.data(), small_test_data_.size());
   data->AppendBytes(large_test_data_.data(), large_test_data_.size());
   EXPECT_EQ(1u, data->Elements().size());
@@ -363,7 +363,7 @@
   double timestamp1 = CurrentTime();
   double timestamp2 = timestamp1 + 1;
   KURL url(NullURL(), "http://example.com/");
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendFile("path", 4, 32, timestamp1);
   data->AppendFileSystemURL(url, 15, 876, timestamp2);
 
@@ -398,7 +398,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromBlob) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendBlob(test_blob_, 13, 765);
 
   Vector<ExpectedElement> expected_elements;
@@ -408,7 +408,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromBlobsAndBytes) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendBlob(test_blob_, 10, 10);
   data->AppendBytes(medium_test_data_.data(), medium_test_data_.size());
   data->AppendBlob(test_blob_, 0, 0);
@@ -430,7 +430,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromSmallBytesAfterLargeBytes) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   data->AppendBytes(large_test_data_.data(), large_test_data_.size());
   data->AppendBlob(test_blob_, 0, 10);
   data->AppendBytes(small_test_data_.data(), small_test_data_.size());
@@ -444,7 +444,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromManyMergedBytes) {
-  std::unique_ptr<BlobData> data = BlobData::Create();
+  auto data = std::make_unique<BlobData>();
   Vector<uint8_t> merged_data;
   while (merged_data.size() <= DataElementBytes::kMaximumEmbeddedDataSize) {
     data->AppendBytes(medium_test_data_.data(), medium_test_data_.size());
diff --git a/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc b/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
index a19c8d7..0bf9ce6 100644
--- a/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
@@ -22,6 +22,12 @@
   return IsInfinite() || rect_.Intersects(EnclosingIntRect(rect));
 }
 
+bool CullRect::Intersects(const LayoutRect& rect,
+                          const LayoutPoint& offset) const {
+  return IsInfinite() || rect_.Intersects(EnclosingIntRect(LayoutRect(
+                             rect.Location() + offset, rect.Size())));
+}
+
 bool CullRect::IntersectsTransformed(const AffineTransform& transform,
                                      const FloatRect& rect) const {
   return IsInfinite() || transform.MapRect(rect).Intersects(rect_);
diff --git a/third_party/blink/renderer/platform/graphics/paint/cull_rect.h b/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
index 51590f59..3108d45 100644
--- a/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
+++ b/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
@@ -33,6 +33,7 @@
 
   bool Intersects(const IntRect&) const;
   bool Intersects(const LayoutRect&) const;
+  bool Intersects(const LayoutRect&, const LayoutPoint& offset) const;
   bool IntersectsTransformed(const AffineTransform&, const FloatRect&) const;
   bool IntersectsHorizontalRange(LayoutUnit lo, LayoutUnit hi) const;
   bool IntersectsVerticalRange(LayoutUnit lo, LayoutUnit hi) const;
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc b/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
index 4cdd66d9..51241b7 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
@@ -748,6 +748,7 @@
 size_t PaintController::sum_num_indexed_items_ = 0;
 size_t PaintController::sum_num_subsequences_ = 0;
 size_t PaintController::sum_num_cached_subsequences_ = 0;
+size_t PaintController::sum_num_paint_chunks_ = 0;
 
 void PaintController::UpdateUMACounts() {
   DCHECK_EQ(usage_, kMultiplePaints);
@@ -756,6 +757,7 @@
   sum_num_indexed_items_ += num_indexed_items_;
   sum_num_subsequences_ += new_cached_subsequences_.size();
   sum_num_cached_subsequences_ += num_cached_new_subsequences_;
+  sum_num_paint_chunks_ += new_paint_chunks_.LastChunkIndex() + 1;
 }
 
 void PaintController::UpdateUMACountsOnFullyCached() {
@@ -768,27 +770,34 @@
   int num_subsequences = current_cached_subsequences_.size();
   sum_num_subsequences_ += num_subsequences;
   sum_num_cached_subsequences_ += num_subsequences;
+
+  sum_num_paint_chunks_ += PaintChunks().size();
 }
 
 void PaintController::ReportUMACounts() {
-  static const int kReportThreshold = 1000;
-  if (sum_num_items_ < kReportThreshold)
+  if (sum_num_items_ == 0)
     return;
 
   UMA_HISTOGRAM_PERCENTAGE("Blink.Paint.CachedItemPercentage",
                            sum_num_cached_items_ * 100 / sum_num_items_);
   UMA_HISTOGRAM_PERCENTAGE("Blink.Paint.IndexedItemPercentage",
                            sum_num_indexed_items_ * 100 / sum_num_items_);
+  UMA_HISTOGRAM_COUNTS_100000("Blink.Paint.NumDisplayItems", sum_num_items_);
   if (sum_num_subsequences_) {
     UMA_HISTOGRAM_PERCENTAGE(
         "Blink.Paint.CachedSubsequencePercentage",
         sum_num_cached_subsequences_ * 100 / sum_num_subsequences_);
+    UMA_HISTOGRAM_COUNTS_10000("Blink.Paint.NumSubsequences",
+                               sum_num_subsequences_);
   }
+  UMA_HISTOGRAM_COUNTS_10000("Blink.Paint.NumPaintChunks",
+                             sum_num_paint_chunks_);
   sum_num_items_ = 0;
   sum_num_cached_items_ = 0;
   sum_num_indexed_items_ = 0;
   sum_num_subsequences_ = 0;
   sum_num_cached_subsequences_ = 0;
+  sum_num_paint_chunks_ = 0;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
index 8b3d800..fcb29cbb 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
@@ -425,14 +425,14 @@
   // Accumulated counts for UMA metrics. Updated by UpdateUMACounts() and
   // UpdateUMACountsOnFullyCached(), and reported as UMA metrics and reset by
   // ReportUMACounts(). The accumulation is mainly for pre-CompositeAfterPaint
-  // to weigh big and small GraphicsLayers properly when calculating the
-  // percentage UMA data. Also avoid reporting too frequently, to make the
-  // metrics more meaningful.
+  // to sum up the data from multiple PaintControllers during a paint in
+  // document life cycle update.
   static size_t sum_num_items_;
   static size_t sum_num_cached_items_;
   static size_t sum_num_indexed_items_;
   static size_t sum_num_subsequences_;
   static size_t sum_num_cached_subsequences_;
+  static size_t sum_num_paint_chunks_;
 
   class DisplayItemListAsJSON;
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
index 4a3b3cf..93e91e7 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
@@ -81,7 +81,6 @@
 void FetchContext::PrepareRequest(ResourceRequest&,
                                   const FetchInitiatorInfo&,
                                   WebScopedVirtualTimePauser&,
-                                  RedirectType,
                                   ResourceType) {}
 
 void FetchContext::DispatchWillSendRequest(unsigned long,
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
index a64558a1..1cde5db 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -120,11 +120,9 @@
   // create a new WebScopedVirtualTimePauser and set it to
   // |virtual_time_pauser|.
   // This is called on initial and every redirect request.
-  enum class RedirectType { kForRedirect, kNotForRedirect };
   virtual void PrepareRequest(ResourceRequest&,
                               const FetchInitiatorInfo&,
                               WebScopedVirtualTimePauser& virtual_time_pauser,
-                              RedirectType,
                               ResourceType);
 
   // The last callback before a request is actually sent to the browser process.
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 71d6ba0..7bd6eb81 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -846,9 +846,8 @@
 
   // For initial requests, call PrepareRequest() here before revalidation
   // policy is determined.
-  Context().PrepareRequest(
-      resource_request, options.initiator_info, virtual_time_pauser,
-      FetchContext::RedirectType::kNotForRedirect, resource_type);
+  Context().PrepareRequest(resource_request, options.initiator_info,
+                           virtual_time_pauser, resource_type);
 
   if (!params.Url().IsValid())
     return ResourceRequestBlockedReason::kOther;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index 8cecfbb..5491f27 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -808,7 +808,6 @@
   WebScopedVirtualTimePauser unused_virtual_time_pauser;
   Context().PrepareRequest(*new_request, resource_->Options().initiator_info,
                            unused_virtual_time_pauser,
-                           FetchContext::RedirectType::kForRedirect,
                            resource_->GetType());
   Context().DispatchWillSendRequest(
       resource_->Identifier(), *new_request, redirect_response_to_pass,
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
index 418af10..2ee56c4 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -98,7 +98,7 @@
 crbug.com/591099 css3/filters/effect-reference.html [ Failure ]
 crbug.com/591099 css3/filters/filter-repaint-composited-fallback-crash.html [ Pass ]
 crbug.com/591099 css3/filters/filter-repaint-composited-fallback.html [ Pass ]
-crbug.com/591099 css3/flexbox/intrinsic-width-orthogonal-writing-mode.html [ Failure ]
+crbug.com/591099 css3/flexbox/intrinsic-width-orthogonal-writing-mode.html [ Failure Pass ]
 crbug.com/591099 editing/selection/paint-hyphen.html [ Pass ]
 crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/pbkdf2.https.any.html?1001-2000 [ Pass ]
 crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/pbkdf2.https.any.html?2001-3000 [ Pass ]
@@ -221,7 +221,7 @@
 crbug.com/40634 external/wpt/css/css-text/white-space/trailing-space-before-br-001.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-transforms/transform-box/view-box-mutation.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-transitions/properties-value-003.html [ Pass ]
+crbug.com/591099 external/wpt/css/css-transitions/properties-value-003.html [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-ui/text-overflow-010.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-ui/text-overflow-026.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-values/attr-invalid-type-008.html [ Failure ]
@@ -344,7 +344,6 @@
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/emptyspan-4.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/remove-from-split-inline-6.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/split-inner-inline-2.html [ Pass ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/float-retry-push-image.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-border-box-border-radius-003.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-border-box-border-radius-004.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-border-box-border-radius-011.html [ Failure ]
@@ -361,7 +360,6 @@
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-margin-box-border-radius-008.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-padding-box-border-radius-002.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-002.html [ Failure ]
-crbug.com/591099 external/wpt/dom/events/EventListener-addEventListener.sub.window.html [ Pass ]
 crbug.com/591099 external/wpt/dom/ranges/Range-insertNode.html [ Pass ]
 crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc_5601.html [ Pass ]
 crbug.com/591099 external/wpt/event-timing/event-timing-bufferbeforeonload.html [ Pass ]
@@ -388,9 +386,8 @@
 crbug.com/591099 external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/execution-timing/111.html [ Pass ]
 crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/no-active-script-manual-module.html [ Timeout ]
-crbug.com/591099 external/wpt/html/user-activation/activation-transfer-with-click.tentative.html [ Pass ]
+crbug.com/591099 external/wpt/html/user-activation/activation-transfer-with-click.tentative.html [ Failure ]
 crbug.com/591099 external/wpt/html/user-activation/activation-transfer-without-click.tentative.html [ Pass ]
-crbug.com/591099 external/wpt/infrastructure/reftest/size.html [ Pass ]
 crbug.com/591099 external/wpt/mediacapture-fromelement/ended.html [ Pass ]
 crbug.com/591099 external/wpt/offscreen-canvas/drawing-images-to-the-canvas/2d.drawImage.9arg.destsize.worker.html [ Pass ]
 crbug.com/591099 external/wpt/offscreen-canvas/drawing-images-to-the-canvas/2d.drawImage.self.1.worker.html [ Pass ]
@@ -408,8 +405,9 @@
 crbug.com/591099 external/wpt/referrer-policy/no-referrer/meta-referrer/same-origin/http-http/shared-worker/keep-origin-redirect/generic.http.html [ Pass ]
 crbug.com/591099 external/wpt/referrer-policy/no-referrer/meta-referrer/same-origin/http-http/shared-worker/no-redirect/generic.http.html [ Pass ]
 crbug.com/591099 external/wpt/referrer-policy/same-origin/http-rp/same-origin/http-http/shared-worker/keep-origin-redirect/same-origin-insecure.http.html [ Failure ]
-crbug.com/591099 external/wpt/screen-orientation/onchange-event.html [ Timeout ]
+crbug.com/591099 external/wpt/screen-orientation/onchange-event.html [ Failure Timeout ]
 crbug.com/591099 external/wpt/service-workers/service-worker/fetch-frame-resource.https.html [ Pass ]
+crbug.com/591099 external/wpt/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html [ Failure Pass ]
 crbug.com/591099 external/wpt/svg/text/reftests/text-inline-size-101.svg [ Failure ]
 crbug.com/591099 external/wpt/wasm/webapi/rejected-arg.any.serviceworker.html [ Timeout ]
 crbug.com/591099 external/wpt/webauthn/createcredential-extensions.https.html [ Pass ]
@@ -448,7 +446,7 @@
 crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
 crbug.com/591099 fast/canvas/OffscreenCanvas-copyImage.html [ Pass ]
 crbug.com/591099 fast/css-grid-layout/grid-baseline.html [ Failure ]
-crbug.com/591099 fast/css-intrinsic-dimensions/height-css-tables-collapsed.html [ Pass ]
+crbug.com/591099 fast/css-intrinsic-dimensions/height-css-tables-collapsed.html [ Failure Pass ]
 crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned.html [ Pass ]
 crbug.com/591099 fast/css-intrinsic-dimensions/height-tables.html [ Failure Pass ]
 crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Pass ]
@@ -458,7 +456,7 @@
 crbug.com/591099 fast/dom/SelectorAPI/resig-SelectorsAPI-test.xhtml [ Pass ]
 crbug.com/591099 fast/dom/shadow/focus-controller-recursion-crash.html [ Pass ]
 crbug.com/591099 fast/dom/shadow/svg-style-in-shadow-tree-crash.html [ Pass ]
-crbug.com/591099 fast/events/before-unload-return-value-from-listener.html [ Pass Timeout ]
+crbug.com/591099 fast/events/before-unload-return-value-from-listener.html [ Pass ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-list-translate.html [ Failure ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
@@ -467,7 +465,6 @@
 crbug.com/591099 fast/multicol/border-radius-clipped-layer.html [ Pass ]
 crbug.com/591099 fast/peerconnection/RTCPeerConnection-many.html [ Pass ]
 crbug.com/591099 fast/replaced/replaced-breaking.html [ Failure Pass ]
-crbug.com/591099 fast/text/descent-clip-in-scaled-page.html [ Failure ]
 crbug.com/899902 fast/text/ellipsis-with-self-painting-layer.html [ Pass ]
 crbug.com/591099 fast/text/emoji-vertical-origin-visual.html [ Failure ]
 crbug.com/591099 fast/text/font-format-support-color-cff2-vertical.html [ Failure ]
@@ -511,7 +508,6 @@
 crbug.com/591099 http/tests/webfont/crbug-655076.html [ Pass ]
 crbug.com/591099 images/feature-policy-oversized-images-resize.html [ Pass ]
 crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-origin-url.js [ Crash Pass ]
-crbug.com/591099 inspector-protocol/input/dispatchTouchEvent.js [ Failure Pass ]
 crbug.com/591099 jquery/offset.html [ Pass ]
 crbug.com/591099 media/autoplay/webaudio-audio-context-resume.html [ Failure Pass ]
 crbug.com/591099 media_capabilities/encodingInfo-avc1.html [ Failure ]
@@ -541,6 +537,7 @@
 crbug.com/591099 virtual/bidi-caret-affinity/editing/selection/modify_move/move_left_word_09_rtl_multi_line.html [ Failure ]
 crbug.com/591099 virtual/bidi-caret-affinity/editing/selection/modify_move/move_right_word_01_rtl_multi_line.html [ Failure ]
 crbug.com/591099 virtual/bidi-caret-affinity/editing/selection/modify_move/move_right_word_05_rtl_multi_line.html [ Failure ]
+crbug.com/591099 virtual/binary-for-devtools/http/tests/devtools/elements/highlight/highlight-css-grid.js [ Failure ]
 crbug.com/916511 virtual/composite-after-paint/paint/background/scrolling-background-with-negative-z-child.html [ Crash ]
 crbug.com/591099 virtual/composite-after-paint/paint/invalidation/box/margin.html [ Failure Pass ]
 Bug(none) virtual/disable-blink-gen-property-trees/ [ Skip ]
@@ -579,6 +576,7 @@
 crbug.com/591099 virtual/omt-worker-fetch/external/wpt/referrer-policy/origin/http-rp/same-origin/http-http/shared-worker/no-redirect/generic.http.html [ Failure ]
 crbug.com/591099 virtual/omt-worker-fetch/external/wpt/referrer-policy/origin/meta-referrer/same-origin/http-http/shared-worker/no-redirect/generic.http.html [ Failure ]
 crbug.com/591099 virtual/omt-worker-fetch/external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-http/shared-worker/keep-origin-redirect/same-insecure.http.html [ Failure ]
+crbug.com/591099 virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations.html [ Failure Pass ]
 crbug.com/591099 virtual/omt-worker-fetch/external/wpt/workers/semantics/multiple-workers/003.html [ Timeout ]
 crbug.com/591099 virtual/omt-worker-fetch/external/wpt/xhr/send-redirect-bogus-sync.htm [ Pass ]
 crbug.com/591099 virtual/outofblink-cors/ [ Skip ]
@@ -597,7 +595,7 @@
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects-list-translate.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
-crbug.com/591099 virtual/user-activation-v2/fullscreen/model/fully-exit-fullscreen-nested-iframe.html [ Pass Timeout ]
+crbug.com/591099 virtual/user-activation-v2/fullscreen/model/fully-exit-fullscreen-nested-iframe.html [ Pass ]
 crbug.com/591099 virtual/video-surface-layer/media/W3C/video/networkState/networkState_during_progress.html [ Pass ]
 crbug.com/591099 virtual/video-surface-layer/media/autoplay-when-visible.html [ Pass ]
 crbug.com/591099 virtual/video-surface-layer/media/color-profile-video-seek-filter.html [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 27298d53..1ba0d0e 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3039,6 +3039,12 @@
 crbug.com/939181 virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Failure Timeout ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Retina ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStreamTrack-id.https.html [ Timeout ]
+crbug.com/626703 [ Retina ] virtual/layout_ng/external/wpt/css/CSS2/abspos/abspos-containing-block-initial-009e.xht [ Timeout ]
+crbug.com/626703 [ Retina ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStream-add-audio-track.https.html [ Timeout ]
+crbug.com/626703 [ Retina ] virtual/layout_ng/external/wpt/css/CSS2/abspos/static-inside-table-cell.html [ Timeout ]
+crbug.com/626703 [ Retina ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/GUM-unknownkey-option-param.https.html [ Timeout ]
+crbug.com/626703 [ Retina ] virtual/layout_ng/external/wpt/css/CSS2/abspos/abspos-containing-block-initial-004f.xht [ Timeout ]
 crbug.com/626703 external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-002.html [ Failure ]
 crbug.com/626703 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-grid/grid-items/grid-item-percentage-sizes-001.html [ Failure ]
@@ -5532,11 +5538,6 @@
 crbug.com/874703 [ Mac ] http/tests/devtools/extensions/extensions-panel.js [ Timeout Pass ]
 crbug.com/874703 [ Mac ] virtual/binary-for-devtools/http/tests/devtools/extensions/extensions-panel.js [ Timeout Pass ]
 
-# Wake Lock api test timeouts
-crbug.com/872530 external/wpt/wake-lock/wakelock-applicability-manual.https.html [ Pass Timeout ]
-crbug.com/872530 external/wpt/wake-lock/wakelock-document-hidden.https.html [ Pass Timeout ]
-crbug.com/872535 external/wpt/wake-lock/wakelock-state-is-global.https.html [ Pass Timeout ]
-
 # Sheriff 2018-08-20
 crbug.com/862589 [ Linux ] virtual/threaded/fast/idle-callback/long_idle_periods.html [ Timeout Pass ]
 crbug.com/862589 [ Mac ] virtual/threaded/fast/idle-callback/long_idle_periods.html [ Timeout Pass ]
@@ -6154,3 +6155,8 @@
 crbug.com/806357 virtual/threaded/fast/events/pointerevents/pinch/pointerevent_touch-action-pinch_zoom_touch.html [ Pass Failure Crash ]
 crbug.com/941931 [ Linux Win ] http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-disallowed.html [ Pass Failure ]
 crbug.com/942134 [ Win ] virtual/exotic-color-space/images/feature-policy-oversized-images.html [ Pass Failure ]
+
+# Sheriff 2019-03-15
+crbug.com/942517 [ Linux ] virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/fetch/fetch-basic.js [ Failure ]
+crbug.com/942517 [ Linux ] virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/fetch/fetch-renderer.js [ Failure ]
+crbug.com/942517 [ Linux ] virtual/binary-for-inspector-protocol/http/tests/inspector-protocol/network/interception-multiclient.js [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index 5351266..fc66b28 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -109105,6 +109105,18 @@
      {}
     ]
    ],
+   "mathml/presentation-markup/fractions/frac-linethickness-004.html": [
+    [
+     "/mathml/presentation-markup/fractions/frac-linethickness-004.html",
+     [
+      [
+       "/mathml/presentation-markup/fractions/frac-linethickness-004-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "mathml/presentation-markup/fractions/frac-mrow-001.html": [
     [
      "/mathml/presentation-markup/fractions/frac-mrow-001.html",
@@ -175932,6 +175944,11 @@
      {}
     ]
    ],
+   "html/webappapis/update-rendering/child-document-raf-order-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "idle-detection/META.yml": [
     [
      {}
@@ -177667,6 +177684,11 @@
      {}
     ]
    ],
+   "mathml/presentation-markup/fractions/frac-linethickness-004-ref.html": [
+    [
+     {}
+    ]
+   ],
    "mathml/presentation-markup/fractions/frac-mrow-001-ref.html": [
     [
      {}
@@ -196822,11 +196844,31 @@
      {}
     ]
    ],
+   "wake-lock/idlharness.https.any-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "wake-lock/idlharness.https.any.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "wake-lock/wakelock-applicability-manual.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "wake-lock/wakelock-disabled-by-feature-policy.https.sub.html.headers": [
     [
      {}
     ]
    ],
+   "wake-lock/wakelock-document-hidden.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "wake-lock/wakelock-enabled-by-feature-policy.https.sub.html.headers": [
     [
      {}
@@ -196837,6 +196879,21 @@
      {}
     ]
    ],
+   "wake-lock/wakelock-onactivechange.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "wake-lock/wakelock-state-is-global.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "wake-lock/wakelock-type.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "wasm/META.yml": [
     [
      {}
@@ -260144,6 +260201,12 @@
      {}
     ]
    ],
+   "html/webappapis/update-rendering/child-document-raf-order.html": [
+    [
+     "/html/webappapis/update-rendering/child-document-raf-order.html",
+     {}
+    ]
+   ],
    "idle-detection/basics.tentative.https.any.js": [
     [
      "/idle-detection/basics.tentative.https.any.html",
@@ -286345,12 +286408,24 @@
      {}
     ]
    ],
+   "resource-timing/TAO-case-insensitive-null-opaque-origin.sub.html": [
+    [
+     "/resource-timing/TAO-case-insensitive-null-opaque-origin.sub.html",
+     {}
+    ]
+   ],
    "resource-timing/TAO-crossorigin-port.sub.html": [
     [
      "/resource-timing/TAO-crossorigin-port.sub.html",
      {}
     ]
    ],
+   "resource-timing/TAO-null-opaque-origin.sub.html": [
+    [
+     "/resource-timing/TAO-null-opaque-origin.sub.html",
+     {}
+    ]
+   ],
    "resource-timing/buffer-full-add-after-full-event.html": [
     [
      "/resource-timing/buffer-full-add-after-full-event.html",
@@ -293571,21 +293646,13 @@
      {}
     ]
    ],
-   "wake-lock/idlharness.https.window.js": [
+   "wake-lock/idlharness.https.any.js": [
     [
-     "/wake-lock/idlharness.https.window.html",
+     "/wake-lock/idlharness.https.any.html",
      {}
-    ]
-   ],
-   "wake-lock/wakelock-api.https.html": [
+    ],
     [
-     "/wake-lock/wakelock-api.https.html",
-     {}
-    ]
-   ],
-   "wake-lock/wakelock-cancel-twice.https.html": [
-    [
-     "/wake-lock/wakelock-cancel-twice.https.html",
+     "/wake-lock/idlharness.https.any.worker.html",
      {}
     ]
    ],
@@ -293637,12 +293704,6 @@
      {}
     ]
    ],
-   "wake-lock/wakelock-promise.https.html": [
-    [
-     "/wake-lock/wakelock-promise.https.html",
-     {}
-    ]
-   ],
    "wake-lock/wakelock-state-is-global.https.html": [
     [
      "/wake-lock/wakelock-state-is-global.https.html",
@@ -293661,12 +293722,6 @@
      {}
     ]
    ],
-   "wake-lock/wakelockrequest-is-independent.https.html": [
-    [
-     "/wake-lock/wakelockrequest-is-independent.https.html",
-     {}
-    ]
-   ],
    "wasm/create_multiple_memory.worker.js": [
     [
      "/wasm/create_multiple_memory.worker.html",
@@ -433060,6 +433115,14 @@
    "31fa4f1264211e050864147db24216465e1ac62f",
    "testharness"
   ],
+  "html/webappapis/update-rendering/child-document-raf-order-expected.txt": [
+   "46bb22cb8fbd00692e75fb8ab43a7974535d6f3e",
+   "support"
+  ],
+  "html/webappapis/update-rendering/child-document-raf-order.html": [
+   "222c1af444e5c3f7aab2ac466b6bd1a7e2c93e3e",
+   "testharness"
+  ],
   "html/webappapis/user-prompts/newline-normalization-manual.html": [
    "55cb5ce527ea69fa23e6aba675719bb6524d7411",
    "manual"
@@ -434517,7 +434580,7 @@
    "support"
   ],
   "interfaces/wake-lock.idl": [
-   "ac8b70c157a2b42876b55b8ab67873d4a483c54d",
+   "89da0b8dc829b92a25f2b8895cdf2bbb25a45fe2",
    "support"
   ],
   "interfaces/wasm-js-api.idl": [
@@ -434997,7 +435060,7 @@
    "support"
   ],
   "lint.whitelist": [
-   "12b32126b6677b19836943aee6c604296f9a597d",
+   "fd4d4049d6d2bd5dd68b1a72864fb63496ec1bea",
    "support"
   ],
   "loading/preloader-css-import-no-quote.tentative.html": [
@@ -435260,6 +435323,14 @@
    "b23cce80be40dd53ff898a5bc7d2246ae3770322",
    "reftest"
   ],
+  "mathml/presentation-markup/fractions/frac-linethickness-004-ref.html": [
+   "8014f0a895252f4d37527c381c7c2b933ca32ca9",
+   "support"
+  ],
+  "mathml/presentation-markup/fractions/frac-linethickness-004.html": [
+   "ff96a3d753e226dcd2ecfa44808804f71ce02c45",
+   "reftest"
+  ],
   "mathml/presentation-markup/fractions/frac-mrow-001-ref.html": [
    "e42cb96fe8383959bef2d778cfb29d0638f1de03",
    "support"
@@ -457980,10 +458051,18 @@
    "26e0a8017d6c2c7b51c94998f34a79fa20eb1e12",
    "support"
   ],
+  "resource-timing/TAO-case-insensitive-null-opaque-origin.sub.html": [
+   "5b222cdf277a2b13115726af3b8780e646e428b0",
+   "testharness"
+  ],
   "resource-timing/TAO-crossorigin-port.sub.html": [
    "0601217d0ae3a7bc057853dd23901650ccfe4633",
    "testharness"
   ],
+  "resource-timing/TAO-null-opaque-origin.sub.html": [
+   "c78e590067717130fb8681c9c4fd7818816e6940",
+   "testharness"
+  ],
   "resource-timing/buffer-full-add-after-full-event.html": [
    "73ad841e92fddff1e05395241d69a0079e7a84da",
    "testharness"
@@ -458205,7 +458284,7 @@
    "testharness"
   ],
   "resource-timing/resources/TAOResponse.py": [
-   "d98098ccc83e56bfba7f48ae5dc39ffd6e9b969f",
+   "e84912808da4116e95a2505e6b269297536478f3",
    "support"
   ],
   "resource-timing/resources/all_resource_types.htm": [
@@ -466613,7 +466692,7 @@
    "support"
   ],
   "tools/manifest/item.py": [
-   "01a208eea05092cd2c448bca1affc45fa44d9957",
+   "5e313faa751e8f32dc92c14d0dfc0bde44fce535",
    "support"
   ],
   "tools/manifest/log.py": [
@@ -466625,7 +466704,7 @@
    "support"
   ],
   "tools/manifest/sourcefile.py": [
-   "78843b089b87c111efe24762e7bee55cf44f55ec",
+   "97fe89bbda89980d3e0e1ce620ccbe9e46c15275",
    "support"
   ],
   "tools/manifest/update.py": [
@@ -472720,22 +472799,26 @@
    "776c59be658f749fcdd0a8ea6a92ac82c88d344e",
    "support"
   ],
-  "wake-lock/idlharness.https.window.js": [
-   "21d559a7a26ac8e22bb9f0eaa02b7541015ad49d",
+  "wake-lock/idlharness.https.any-expected.txt": [
+   "e831363972f16d509dc0cc13a903fd67a9d637eb",
+   "support"
+  ],
+  "wake-lock/idlharness.https.any.js": [
+   "5e3ae75064c5f9c2be1b96ce763868066352889b",
    "testharness"
   ],
-  "wake-lock/wakelock-api.https.html": [
-   "45a906dfa1f23de34befdc68e9da17d179fb2474",
-   "testharness"
+  "wake-lock/idlharness.https.any.worker-expected.txt": [
+   "1c83aa7a51e5c183d7f2603158275903dd53b316",
+   "support"
+  ],
+  "wake-lock/wakelock-applicability-manual.https-expected.txt": [
+   "ae57e572eacc1ee9275c50fbe730837e98e19365",
+   "support"
   ],
   "wake-lock/wakelock-applicability-manual.https.html": [
-   "5dbd27818ddfee7564c8e4def594adc67ed276f2",
+   "2bd5c9dba4d7c7cbaab692f8f87f64d2708313d5",
    "manual"
   ],
-  "wake-lock/wakelock-cancel-twice.https.html": [
-   "68e8a1958165d9053eedf1bb97fd67e8eece15fb",
-   "testharness"
-  ],
   "wake-lock/wakelock-disabled-by-feature-policy.https.sub.html": [
    "75064767ceebeb3abfad31f9dc9a8a2b91e10e44",
    "testharness"
@@ -472744,8 +472827,12 @@
    "1d3769ec794b353e8c614e64ce2c1b0b1010e528",
    "support"
   ],
+  "wake-lock/wakelock-document-hidden.https-expected.txt": [
+   "b62e72000f2ed777ed92eac51b492e5eced5d9ba",
+   "support"
+  ],
   "wake-lock/wakelock-document-hidden.https.html": [
-   "6bb406a1c2e62a490e394ba1abceba9353ab6285",
+   "1edafee45fc11ba5ae3ebcc83d1e8a5c22da9f24",
    "testharness"
   ],
   "wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html": [
@@ -472773,31 +472860,35 @@
    "support"
   ],
   "wake-lock/wakelock-insecure-context.html": [
-   "8d728f83e5d14b951ba4f151a7eb06f5257df475",
+   "2c61f41311db3f9edf0502ea752ca27970eed3fb",
    "testharness"
   ],
+  "wake-lock/wakelock-onactivechange.https-expected.txt": [
+   "b1d8893242b8f530264f2c79d1251b0b41e434cc",
+   "support"
+  ],
   "wake-lock/wakelock-onactivechange.https.html": [
-   "899b9b78d95c66a41f33b57ceac55e12eba9ec6e",
+   "381e1e40f1cfb676e33d5c0374924164f4f6e2de",
    "testharness"
   ],
-  "wake-lock/wakelock-promise.https.html": [
-   "3d4c4868699c9c77a6636e3246c65de7b71dc36a",
-   "testharness"
+  "wake-lock/wakelock-state-is-global.https-expected.txt": [
+   "08b692aa24612df2abc368d9afd1075449409b65",
+   "support"
   ],
   "wake-lock/wakelock-state-is-global.https.html": [
-   "98cebe01c1126e0ebdc26784e15e9a057d1a03fb",
+   "2eee31982498caab44b5160237c7ce7f8ce9a569",
    "testharness"
   ],
   "wake-lock/wakelock-supported-by-feature-policy.html": [
    "d6289fff43c8717ac6e9ace59713e6fd70bd249d",
    "testharness"
   ],
-  "wake-lock/wakelock-type.https.html": [
-   "2f9e1242614d57a79b2aada32cdd3d2cb3ae012d",
-   "testharness"
+  "wake-lock/wakelock-type.https-expected.txt": [
+   "409d107ad314e8b92d69fd27e40f2e6a89c9c63c",
+   "support"
   ],
-  "wake-lock/wakelockrequest-is-independent.https.html": [
-   "a113b004fe2a5dbcea8d11b1cedcca70841506bc",
+  "wake-lock/wakelock-type.https.html": [
+   "df7a68a040bef273efcd2584dfe3612adc05d85b",
    "testharness"
   ],
   "wasm/META.yml": [
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-non-ascii-name-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-non-ascii-name-ref.html
new file mode 100644
index 0000000..012f6f9d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-non-ascii-name-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title>Reference for WorkletAnimation name should accept non-ASCII characters</title>
+<style>
+.box {
+  width: 100px;
+  height: 100px;
+  background-color: green;
+}
+</style>
+
+<div style="transform: translateX(50px);" class="box"></div>
+<div style="transform: translateX(150px);" class="box"></div>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-non-ascii-name.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-non-ascii-name.https.html
new file mode 100644
index 0000000..d3a3f4a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-non-ascii-name.https.html
@@ -0,0 +1,59 @@
+<html class="reftest-wait">
+<title>WorkletAnimation name should accept non-ASCII characters</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
+<meta name="assert" content="Worklet Animation name should accept non-ASCII characters">
+<link rel="match" href="worklet-animation-with-non-ascii-name-ref.html">
+
+<script src="/web-animations/testcommon.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<script src="common.js"></script>
+
+<style>
+  .box {
+    width: 100px;
+    height: 100px;
+    background-color: green;
+  }
+</style>
+
+<div id="t0" class="box"></div>
+<div id="t1" class="box"></div>
+<script id="visual_update"  type="text/worklet">
+  registerAnimator('bob', class {
+    animate(currentTime, effect) {
+      effect.localTime = 250;
+    }
+  });
+  registerAnimator('東京', class {
+    animate(currentTime, effect) {
+      effect.localTime = 750;
+    }
+  });
+</script>
+<script>
+  runInAnimationWorklet(
+    document.getElementById('visual_update').textContent
+  ).then(() => {
+    const keyframes = [
+      {transform: 'translateX(0)' },
+      {transform: 'translateX(200px)' }
+    ];
+    const options = {
+      duration: 1000
+    };
+    const $t0 = document.getElementById('t0');
+    const $t0_effect = new KeyframeEffect($t0, keyframes, options);
+    const $t0_animation = new WorkletAnimation('bob', $t0_effect);
+
+    const $t1 = document.getElementById('t1');
+    const $t1_effect = new KeyframeEffect($t1, keyframes, options);
+    const $t1_animation = new WorkletAnimation('東京', $t1_effect);
+
+    $t0_animation.play();
+    $t1_animation.play();
+
+    waitForAsyncAnimationFrames(1).then(_ => {
+      takeScreenshot();
+    });
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/update-rendering/child-document-raf-order-expected.txt b/third_party/blink/web_tests/external/wpt/html/webappapis/update-rendering/child-document-raf-order-expected.txt
new file mode 100644
index 0000000..46bb22cb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/update-rendering/child-document-raf-order-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Ordering of steps in "Update the Rendering" - child document requestAnimationFrame order assert_array_equals: expected order of notifications lengths differ, expected 3 got 6
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/update-rendering/child-document-raf-order.html b/third_party/blink/web_tests/external/wpt/html/webappapis/update-rendering/child-document-raf-order.html
new file mode 100644
index 0000000..222c1af
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/update-rendering/child-document-raf-order.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML>
+<meta charset=UTF-8>
+<title>Ordering of steps in "Update the Rendering" - child document requestAnimationFrame order</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering">
+<link rel="author" title="L. David Baron" href="https://dbaron.org/">
+<link rel="author" title="Mozilla" href="https://mozilla.org/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id=log></div>
+
+<!--
+
+This test tests the interaction of just two substeps of the "Update the
+rendering" steps in
+https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering
+
+These are:
+
+ 1. Let docs be the list of Document objects associated with the event
+    loop in question, sorted arbitrarily except that the following
+    conditions must be met:
+
+    - Any Document B that is nested through a Document A must be listed
+      after A in the list.
+
+    - If there are two documents A and B whose browsing contexts are
+      both nested browsing contexts and their browsing context
+      containers are both elements in the same Document C, then the
+      order of A and B in the list must match the relative tree order of
+      their respective browsing context containers in C.
+
+    In the steps below that iterate over docs, each Document must be
+    processed in the order it is found in the list.
+
+and later:
+
+10. For each fully active Document in docs, run the animation frame
+    callbacks for that Document, passing in now as the timestamp.
+
+
+It tests this by setting up a tree of three documents, two children and
+one parent, and testing for the relative order of the animation frame
+callbacks for each.
+
+-->
+
+<script>
+
+async_test(function (t) {
+  step_timeout(setup, 0);
+
+  let first_frame, second_frame;
+
+  let notification_sequence = [];
+
+  function setup() {
+    // Start by creating two iframes.  To test (a little bit) the rule
+    // about iteration being in document order, insert them in the reverse
+    // order of creation.
+    let body = document.body;
+    function make_iframe() {
+      let iframe = document.createElement("iframe");
+      iframe.setAttribute("srcdoc", "<body onload='parent.child_ready()'>");
+      iframe.setAttribute("width", "30");
+      iframe.setAttribute("height", "15");
+      return iframe;
+    }
+    second_frame = make_iframe();
+    body.prepend(second_frame);
+    first_frame = make_iframe();
+    body.prepend(first_frame);
+
+    let children_waiting = 2;
+    window.child_ready = function() {
+      if (--children_waiting == 0) {
+        // Call requestAnimationFrame in neither the order nor the reverse
+        // of the order in which we expect to be called (which is parent,
+        // first, second).
+        first_frame.contentWindow.requestAnimationFrame(first_child_raf);
+        second_frame.contentWindow.requestAnimationFrame(second_child_raf);
+        window.requestAnimationFrame(parent_raf);
+      }
+    };
+  }
+
+  let parent_raf = t.step_func(function() {
+    notification_sequence.push("parent_raf");
+
+    // Request another notification to help ensure we're getting expected behavior.
+    window.requestAnimationFrame(parent_raf);
+  });
+
+  let first_child_raf = t.step_func(function() {
+    notification_sequence.push("first_child_raf");
+
+    // Request another notification to help ensure we're getting expected behavior.
+    first_frame.contentWindow.requestAnimationFrame(first_child_raf);
+  });
+
+  let second_child_raf = t.step_func(function() {
+    notification_sequence.push("second_child_raf");
+
+    // Request another notification to help ensure we're getting expected behavior.
+    second_frame.contentWindow.requestAnimationFrame(second_child_raf);
+
+    step_timeout(finish, 0);
+  });
+
+  let finish = t.step_func(function() {
+    assert_array_equals(notification_sequence,
+                        ["parent_raf", "first_child_raf", "second_child_raf"],
+                        "expected order of notifications");
+    t.done();
+  });
+});
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl b/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl
index ac8b70c..89da0b8d 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl
@@ -5,17 +5,14 @@
 
 enum WakeLockType { "screen", "system" };
 
-partial interface Navigator {
-  [SecureContext] Promise<WakeLock> getWakeLock(WakeLockType type);
-};
-
-[SecureContext, Exposed=Window] interface WakeLock : EventTarget {
+[Constructor(WakeLockType type), SecureContext, Exposed=(DedicatedWorker, Window)]
+interface WakeLock : EventTarget {
   readonly attribute WakeLockType type;
   readonly attribute boolean active;
   attribute EventHandler onactivechange;
-  WakeLockRequest createRequest();
+  Promise<void> request(optional WakeLockRequestOptions options);
 };
 
-[SecureContext, Exposed=Window] interface WakeLockRequest {
-  void cancel();
+dictionary WakeLockRequestOptions {
+  AbortSignal? signal;
 };
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-004-ref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-004-ref.html
new file mode 100644
index 0000000..8014f0a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-004-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>fractions linethickness</title>
+    <style type="text/css">
+      @font-face {
+        font-family: TestFont;
+        src: url("/fonts/math/fraction-rulethickness10000.woff");
+      }
+      math {
+        /* FractionRuleThickness = 10000 * 1 / 1000 = 10px; */
+        font-family: "TestFont";
+        font-size: 1px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>This test passes if you see no fraction bar.</p>
+    <math>
+      <mfrac linethickness="0px">
+        <mspace width="20px" height="10px" style="background: blue"></mspace>
+        <mspace width="20px" height="10px" style="background: cyan"></mspace>
+      </mfrac>
+    </math>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-004.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-004.html
new file mode 100644
index 0000000..ff96a3d7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-004.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>fractions linethickness</title>
+    <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#mfrac">
+    <meta name="assert" content="Verifies that unitless value of zero causes no fraction bar to be painted">
+    <link rel="match" href="frac-linethickness-004-ref.html">
+    <style type="text/css">
+      @font-face {
+        font-family: TestFont;
+        src: url("/fonts/math/fraction-rulethickness10000.woff");
+      }
+      math {
+        /* FractionRuleThickness = 10000 * 1 / 1000 = 10px; */
+        font-family: "TestFont";
+        font-size: 1px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>This test passes if you see no fraction bar.</p>
+    <math>
+      <mfrac linethickness="0">
+        <mspace width="20px" height="10px" style="background: blue"></mspace>
+        <mspace width="20px" height="10px" style="background: cyan"></mspace>
+      </mfrac>
+    </math>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/tools/manifest/item.py b/third_party/blink/web_tests/external/wpt/tools/manifest/item.py
index 01a208e..5e313faa 100644
--- a/third_party/blink/web_tests/external/wpt/tools/manifest/item.py
+++ b/third_party/blink/web_tests/external/wpt/tools/manifest/item.py
@@ -39,18 +39,13 @@
         """A unique identifier for the test"""
         return (self.item_type, self.id)
 
-    def meta_key(self):
-        """Extra metadata that doesn't form part of the test identity, but for
-        which changes mean regenerating the manifest (e.g. the test timeout)."""
-        return ()
-
     def __eq__(self, other):
         if not hasattr(other, "key"):
             return False
         return self.key() == other.key()
 
     def __hash__(self):
-        return hash(self.key() + self.meta_key())
+        return hash(self.key())
 
     def __repr__(self):
         return "<%s.%s id=%s, path=%s>" % (self.__module__, self.__class__.__name__, self.id, self.path)
@@ -137,12 +132,6 @@
             # this branch should go when the manifest version is bumped
             return self._source_file.script_metadata
 
-    def meta_key(self):
-        script_metadata = self.script_metadata
-        if script_metadata is not None:
-            script_metadata = tuple(tuple(x) for x in script_metadata)
-        return (self.timeout, self.testdriver, self.jsshell, script_metadata)
-
     def to_json(self):
         rv = super(TestharnessTest, self).to_json()
         if self.timeout is not None:
@@ -189,9 +178,6 @@
                     for item in self._extras.get("fuzzy", [])}
         return rv
 
-    def meta_key(self):
-        return (self.timeout, self.viewport_size, self.dpi)
-
     def to_json(self):
         rv = [self._url, self.references, {}]
         extras = rv[-1]
diff --git a/third_party/blink/web_tests/external/wpt/tools/manifest/sourcefile.py b/third_party/blink/web_tests/external/wpt/tools/manifest/sourcefile.py
index 78843b0..97fe89bb 100644
--- a/third_party/blink/web_tests/external/wpt/tools/manifest/sourcefile.py
+++ b/third_party/blink/web_tests/external/wpt/tools/manifest/sourcefile.py
@@ -843,6 +843,8 @@
                     self.rel_path
                 )]
 
+        assert len(rv[1]) == len(set(rv[1]))
+
         self.items_cache = rv
 
         return rv
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt
new file mode 100644
index 0000000..e831363
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt
@@ -0,0 +1,21 @@
+This is a testharness.js-based test.
+PASS idl_test setup
+PASS WakeLock interface: existence and properties of interface object
+FAIL WakeLock interface object length assert_equals: wrong value for WakeLock.length expected 1 but got 0
+PASS WakeLock interface object name
+PASS WakeLock interface: existence and properties of interface prototype object
+PASS WakeLock interface: existence and properties of interface prototype object's "constructor" property
+PASS WakeLock interface: existence and properties of interface prototype object's @@unscopables property
+PASS WakeLock interface: attribute type
+PASS WakeLock interface: attribute active
+PASS WakeLock interface: attribute onactivechange
+FAIL WakeLock interface: operation request(WakeLockRequestOptions) assert_own_property: interface prototype object missing non-static operation expected property "request" missing
+FAIL WakeLock must be primary interface of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Stringification of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL WakeLock interface: new WakeLock("screen") must inherit property "type" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL WakeLock interface: new WakeLock("screen") must inherit property "active" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL WakeLock interface: new WakeLock("screen") must inherit property "onactivechange" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL WakeLock interface: new WakeLock("screen") must inherit property "request(WakeLockRequestOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL WakeLock interface: calling request(WakeLockRequestOptions) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.js b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.js
new file mode 100644
index 0000000..5e3ae750
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.js
@@ -0,0 +1,16 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://w3c.github.io/wake-lock/
+
+'use strict';
+
+idl_test(
+  ['wake-lock'],
+  ['dom', 'html'],
+  idl_array => {
+    idl_array.add_objects({
+      WakeLock: ['new WakeLock("screen")']
+    });
+  }
+);
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt
new file mode 100644
index 0000000..1c83aa7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt
@@ -0,0 +1,21 @@
+This is a testharness.js-based test.
+PASS idl_test setup
+FAIL WakeLock interface: existence and properties of interface object assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock interface object length assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock interface object name assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock interface: existence and properties of interface prototype object assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock interface: attribute type assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock interface: attribute active assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock interface: attribute onactivechange assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock interface: operation request(WakeLockRequestOptions) assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing
+FAIL WakeLock must be primary interface of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined"
+FAIL Stringification of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined"
+FAIL WakeLock interface: new WakeLock("screen") must inherit property "type" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined"
+FAIL WakeLock interface: new WakeLock("screen") must inherit property "active" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined"
+FAIL WakeLock interface: new WakeLock("screen") must inherit property "onactivechange" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined"
+FAIL WakeLock interface: new WakeLock("screen") must inherit property "request(WakeLockRequestOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined"
+FAIL WakeLock interface: calling request(WakeLockRequestOptions) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.window.js b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.window.js
deleted file mode 100644
index 21d559a..0000000
--- a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.window.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// META: script=/resources/WebIDLParser.js
-// META: script=/resources/idlharness.js
-
-// https://w3c.github.io/wake-lock/
-
-'use strict';
-
-promise_test(async () => {
-  const srcs = ['wake-lock', 'dom', 'html'];
-  const [wakelock, dom, html] = await Promise.all(
-    srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
-
-  const idl_array = new IdlArray();
-  idl_array.add_idls(wakelock);
-  idl_array.add_dependency_idls(dom);
-  idl_array.add_dependency_idls(html);
-
-  try {
-    window.wakelock = await navigator.getWakeLock("screen");
-    window.request = window.wakelock.createRequest();
-  } catch (e) {
-    // Surfaced in idlharness.js's test_object below.
-  }
-
-  idl_array.add_objects({
-    Navigator: ['navigator'],
-    WakeLock: ['wakelock'],
-    WakeLockRequest: ['request']
-  });
-  idl_array.test();
-}, 'Test IDL implementation of WakeLock API');
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-api.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-api.https.html
deleted file mode 100644
index 45a906d..0000000
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-api.https.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>Wake Lock API Test</title>
-<link rel="help" href="https://w3c.github.io/wake-lock/">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<script>
-
-promise_test(async t => {
-  assert_true("getWakeLock" in navigator, "Wake Lock API is present");
-  const wakeLock = await navigator.getWakeLock("screen");
-  const request = wakeLock.createRequest();
-  assert_true(wakeLock instanceof WakeLock, "wakeLock is a WakeLock");
-  assert_equals(typeof wakeLock.type, "string", "the type of wakeLock.type is string");
-  assert_equals(typeof wakeLock.active, "boolean", "the type of wakeLock.active is boolean");
-  assert_true(request instanceof WakeLockRequest, "request is a WakeLockRequest");
-}, "Test that the Wake Lock API is correct");
-
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-applicability-manual.https-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-applicability-manual.https-expected.txt
new file mode 100644
index 0000000..ae57e572
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-applicability-manual.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL The screen wake lock isn't applicable after the screen is manually swiched off by the user until it is switched on again. promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
+FAIL Manually switching off the screen will not affect the applicability of the system wake lock. promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-applicability-manual.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-applicability-manual.https.html
index 5dbd278..2bd5c9db 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-applicability-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-applicability-manual.https.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>wake lock applicability test</title>
-<link rel="help" href="https://w3c.github.io/wake-lock/#dfn-the-wake-lock-is-applicable">
+<link rel="help" href="https://w3c.github.io/wake-lock/#dfn-applicable-wake-lock">
 <meta name="flags" content="interact">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
@@ -16,10 +16,14 @@
 setup({ explicit_timeout: true });
 
 promise_test(async t => {
-  const wakeLock = await navigator.getWakeLock("screen");
-  const request = wakeLock.createRequest();
+  const wakeLock = new WakeLock("screen");
+
+  const controller = new AbortController();
+  const signal = controller.signal;
+
+  await wakeLock.request({ signal });
   assert_true(wakeLock.active, "the active is true when wake lock is acquired");
-  const eventWatcher = new EventWatcher(t, document, "visibilitychange")
+  const eventWatcher = new EventWatcher(t, document, "visibilitychange");
 
   //lock screen to fire 'visibilitychange'
   await eventWatcher.wait_for("visibilitychange");
@@ -30,22 +34,26 @@
   await eventWatcher.wait_for("visibilitychange");
   assert_false(document.hidden, "document is visiable when screen is unlocked");
   assert_true(wakeLock.active, "the screen wake lock is active when screen is switched on again");
-  request.cancel();
+  controller.abort();
 }, "The screen wake lock isn't applicable after the screen is manually swiched off"
   + " by the user until it is switched on again.");
 
 
 promise_test(async t => {
-  const wakeLock = await navigator.getWakeLock("system");
-  const request = wakeLock.createRequest();
+  const wakeLock = new WakeLock("system");
+
+  const controller = new AbortController();
+  const signal = controller.signal;
+
+  await wakeLock.request({ signal });
   assert_true(wakeLock.active, "the active is true when wake lock is acquired");
-  const eventWatcher = new EventWatcher(t, document, "visibilitychange")
+  const eventWatcher = new EventWatcher(t, document, "visibilitychange");
 
   //lock screen to fire 'visibilitychange'
   await eventWatcher.wait_for("visibilitychange");
   assert_true(document.hidden, "document is hidden when screen is locked");
   assert_true(wakeLock.active, "the system wake lock is still active when screen is switched off");
-  request.cancel();
+  controller.abort();
 }, "Manually switching off the screen will not affect the applicability of the system wake lock.");
 
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-cancel-twice.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-cancel-twice.https.html
deleted file mode 100644
index 68e8a195..0000000
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-cancel-twice.https.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>no exception is thrown when invoking cancel() twice</title>
-<link rel="help" href="https://w3c.github.io/wake-lock/#dom-wakelockrequest-cancel">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-
-promise_test(async t => {
-  const wakeLock = await navigator.getWakeLock("screen");
-  const request = wakeLock.createRequest();
-  assert_true(wakeLock.active, "the activate is true when wake lock is acquired");
-  request.cancel();
-  assert_false(wakeLock.active, "the activate is false when wake lock is released");
-  //If the cancel() method has already been invoked on this object,
-  //abort these steps, no error fired
-  request.cancel();
-}, "no exception is thrown when invoking cancel() twice");
-
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden.https-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden.https-expected.txt
new file mode 100644
index 0000000..b62e720
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test that screen wake lock will not be actived in hidden document promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden.https.html
index 6bb406a1..1edafee4 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden.https.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-document-hidden.https.html
@@ -7,8 +7,12 @@
 <script>
 
 promise_test(async t => {
-  const wakeLock = await navigator.getWakeLock("screen");
-  const request = wakeLock.createRequest();
+  const wakeLock = new WakeLock("screen");
+
+  const controller = new AbortController();
+  const signal = controller.signal;
+
+  await wakeLock.request({ signal });
   assert_true(wakeLock.active, "the active is true when wake lock is acquired");
   const eventWatcher = new EventWatcher(t, document, "visibilitychange");
   const win = window.open("about:blank", "_blank");
@@ -21,7 +25,7 @@
   await eventWatcher.wait_for("visibilitychange");
   assert_false(document.hidden, "document is visiable when new window is closed");
   assert_true(wakeLock.active, "the active is true when document regains visibility");
-  request.cancel();
+  controller.abort();
 }, "Test that screen wake lock will not be actived in hidden document");
 
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.html
index 8d728f8..2c61f41 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.html
@@ -7,7 +7,7 @@
 <script>
 
 test(t => {
-  assert_false("getWakeLock" in navigator, "'getWakeLock' must not be exposed");
+  assert_false("WakeLock" in self, "'WakeLock' must not be exposed");
 }, "Wake Lock API is not exposed in an insecure context");
 
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-onactivechange.https-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-onactivechange.https-expected.txt
new file mode 100644
index 0000000..b1d8893
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-onactivechange.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test that 'activechange' event is fire and wakeLock.active is valid promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-onactivechange.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-onactivechange.https.html
index 899b9b78..381e1e4 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-onactivechange.https.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-onactivechange.https.html
@@ -8,18 +8,21 @@
 <script>
 
 promise_test(async t => {
-  const wakeLock = await navigator.getWakeLock("screen");
+  const wakeLock = new WakeLock("screen");
   const eventWatcher = new EventWatcher(t, wakeLock, "activechange");
   assert_false(wakeLock.active, "the active is false before wake lock is acquired");
 
-  let request = wakeLock.createRequest();
+  const controller = new AbortController();
+  const signal = controller.signal;
+
+  await wakeLock.request({ signal });
   let evt1 = await eventWatcher.wait_for("activechange");
   assert_true(evt1.isTrusted && !evt1.bubbles && !evt1.cancelable && evt1 instanceof Event, "a simple event is fired");
   assert_equals(evt1.type, "activechange", "the event name is 'activechange'");
   assert_equals(evt1.target, wakeLock, "event.target is WakeLock.");
   assert_true(wakeLock.active, "the active is true when wake lock is acquired");
 
-  request.cancel();
+  controller.abort();
   let evt2 = await eventWatcher.wait_for("activechange");
   assert_true(evt2.isTrusted && !evt2.bubbles && !evt2.cancelable && evt2 instanceof Event, "a simple event is fired");
   assert_false(wakeLock.active, "the active is false when wake lock is released");
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-promise.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-promise.https.html
deleted file mode 100644
index 3d4c4868..0000000
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-promise.https.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>navigator.getWakeLock() for the same Document always return same WakeLock promise</title>
-<link rel="help" href="https://w3c.github.io/wake-lock/">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-promise_test(async t => {
-  const wakeLock1 = await navigator.getWakeLock("screen");
-  const wakeLock2 = await navigator.getWakeLock("screen");
-  assert_equals(wakeLock1, wakeLock2);
-}, "navigator.getWakeLock() for the same Document always return same WakeLock promise");
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https-expected.txt
new file mode 100644
index 0000000..08b692aa
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test that wake lock state should be global promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https.html
index 98cebe01..2eee319 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https.html
@@ -7,16 +7,18 @@
 
 <body>
 <script id="iframe" type="text/plain">
-let iframeWakeLock, iframeRequest;
+let iframeWakeLock;
+const controller = new AbortController();
+const signal = controller.signal;
 window.onmessage = async message => {
   switch(message.data) {
   case "ACQUIRED":
-    iframeWakeLock = await navigator.getWakeLock("screen");
-    iframeRequest = iframeWakeLock.createRequest();
+    iframeWakeLock = new WakeLock("screen");
+    await iframeWakeLock.request({ signal });
     parent.postMessage(iframeWakeLock.active, "*");
     break;
   case "RELEASED":
-    iframeRequest.cancel();
+    controller.abort();
     parent.postMessage(iframeWakeLock.active, "*");
     break;
   default:
@@ -49,7 +51,7 @@
 }
 
 promise_test(async t => {
-  const wakeLock = await navigator.getWakeLock("screen");
+  const wakeLock = await new WakeLock("screen");
   const iframe = await load_iframe();
   const eventWatcher = new EventWatcher(t, wakeLock, "activechange");
 
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https-expected.txt
new file mode 100644
index 0000000..409d107a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+FAIL Test that wakeLock.type is 'screen' when screen wake lock is invoked Illegal constructor
+FAIL Test that wakeLock.type is 'system' when system wake lock is invoked Illegal constructor
+PASS 'TypeError' is thrown when set an empty wake lock type
+PASS 'TypeError' is thrown when set an invalid wake lock type
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.html
index 2f9e1242..df7a68a0 100644
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.html
+++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.html
@@ -7,22 +7,32 @@
 
 <script>
 
-promise_test(async t => {
-  const wakeLock = await navigator.getWakeLock("screen");
+test(() => {
+  const wakeLock = new WakeLock("screen");
   assert_equals(wakeLock.type, "screen");
 }, "Test that wakeLock.type is 'screen' when screen wake lock is invoked");
 
-promise_test(async t => {
-  const wakeLock = await navigator.getWakeLock("system");
+test(() => {
+  const wakeLock = new WakeLock("system");
   assert_equals(wakeLock.type, "system");
 }, "Test that wakeLock.type is 'system' when system wake lock is invoked");
 
-promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.getWakeLock());
+test(() => {
+  assert_throws(new TypeError(), () => new WakeLock());
 }, "'TypeError' is thrown when set an empty wake lock type");
 
-promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.getWakeLock("unsupported"));
-}, "'TypeError' is thrown when set an unsupported wake lock type");
+test(() => {
+  const invalidTypes = [
+    "invalid",
+    null,
+    123,
+    {},
+    "",
+    true
+  ];
+  invalidTypes.map(invalidType => {
+    assert_throws(new TypeError(), () => new WakeLock(invalidType));
+  })
+}, "'TypeError' is thrown when set an invalid wake lock type");
 
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelockrequest-is-independent.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelockrequest-is-independent.https.html
deleted file mode 100644
index a113b00..0000000
--- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelockrequest-is-independent.https.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>WakeLockRequest object is independent</title>
-<link rel="help" href="https://w3c.github.io/wake-lock/">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-promise_test(async t => {
-  const wakeLock1 = await navigator.getWakeLock("screen");
-  const wakeLock2 = await navigator.getWakeLock("screen");
-  const request1 = wakeLock1.createRequest();
-  const request2 = wakeLock2.createRequest();
-  assert_not_equals(request1, request2);
-}, "Test that the WakeLockRequest object is independent.");
-</script>
diff --git a/third_party/blink/web_tests/fast/scroll-behavior/scroll-into-view-scrolls-layout-viewport.html b/third_party/blink/web_tests/fast/scroll-behavior/scroll-into-view-scrolls-layout-viewport.html
deleted file mode 100644
index c4ab0493..0000000
--- a/third_party/blink/web_tests/fast/scroll-behavior/scroll-into-view-scrolls-layout-viewport.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script>
-  function runTest() {
-    test( () => {
-      assert_true(typeof(window.internals) !== 'undefined',
-                  "This test requires window.internals");
-
-      internals.setPageScaleFactor(2.0);
-      const target = document.getElementById("box");
-
-      window.scrollTo(0, 0);
-      internals.setVisualViewportOffset(0, 0);
-
-      target.scrollIntoView();
-      assert_equals(window.visualViewport.pageLeft, window.scrollX);
-      assert_equals(window.visualViewport.pageTop, window.scrollY);
-      assert_equals(window.scrollX, 0);
-      assert_greater_than(window.scrollY, 0);
-
-      window.scrollTo(0, 0);
-      internals.setVisualViewportOffset(0, 0);
-
-      target.scrollIntoViewIfNeeded();
-      assert_equals(window.visualViewport.pageLeft, window.scrollX);
-      assert_equals(window.visualViewport.pageTop, window.scrollY);
-      assert_equals(window.scrollX, 0);
-      assert_greater_than(window.scrollY, 0);
-    }, "Test that element.scrollIntoView() scrolls only the layout viewport.");
-  }
-
-  onload = runTest;
-</script>
-
-<style>
-  body {
-    height: 800px;
-    width: 800px;
-  }
-  #box {
-    background-color: black;
-    top: 700px;
-    left: 100px;
-    height: 40px;
-    width: 40px;
-    position: absolute;
-  }
-</style>
-
-<div id="box"></div>
diff --git a/third_party/blink/web_tests/fast/scroll-behavior/scroll-into-view-scrolls-viewport.html b/third_party/blink/web_tests/fast/scroll-behavior/scroll-into-view-scrolls-viewport.html
new file mode 100644
index 0000000..6b24cd2
--- /dev/null
+++ b/third_party/blink/web_tests/fast/scroll-behavior/scroll-into-view-scrolls-viewport.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+  // All of the rects in this test are in document/page coordinates.
+  function rectFromElement(element) {
+    var rect = {};
+    rect.left = element.getBoundingClientRect().left + window.scrollX;
+    rect.top = element.getBoundingClientRect().top + window.scrollY;
+    rect.right = element.getBoundingClientRect().right + window.scrollX;
+    rect.bottom = element.getBoundingClientRect().bottom + window.scrollY;
+    return rect;
+  }
+
+  function visualViewportRect() {
+    var rect = {};
+    rect.left = window.visualViewport.pageLeft;
+    rect.top = window.visualViewport.pageTop;
+    rect.right = window.visualViewport.pageLeft + window.visualViewport.width;
+    rect.bottom = window.visualViewport.pageTop + window.visualViewport.height;
+    return rect;
+  }
+
+  function layoutViewportRect() {
+    var rect = {};
+    rect.left = window.scrollX;
+    rect.top = window.scrollY;
+    rect.right = window.scrollX + window.innerWidth;
+    rect.bottom = window.scrollY + window.innerHeight;
+    return rect;
+  }
+
+  function isContainedBy(rect1, rect2) {
+    return rect1.left >= rect2.left && rect1.top >= rect2.top &&
+           rect1.right <= rect2.right && rect1.bottom <= rect2.bottom;
+  }
+
+  function runTest() {
+    test( () => {
+      assert_true(typeof(window.internals) !== 'undefined',
+                  "This test requires window.internals");
+
+      internals.setPageScaleFactor(2.0);
+      const target = document.getElementById("box");
+
+      window.scrollTo(0, 0);
+      internals.setVisualViewportOffset(0, 0);
+      assert_false(isContainedBy(rectFromElement(target),
+                                 visualViewportRect()));
+      assert_false(isContainedBy(rectFromElement(target),
+                                 layoutViewportRect()));
+
+      target.scrollIntoView();
+      assert_true(isContainedBy(rectFromElement(target), visualViewportRect()));
+      assert_true(isContainedBy(rectFromElement(target), layoutViewportRect()));
+    }, "Test that element.scrollIntoView() scrolls the layout viewport and visual viewport.");
+
+    test( () => {
+      assert_true(typeof(window.internals) !== 'undefined',
+                  "This test requires window.internals");
+
+      internals.setPageScaleFactor(2.0);
+      const target = document.getElementById("box");
+
+      window.scrollTo(0, 0);
+      internals.setVisualViewportOffset(0, 0);
+      assert_false(isContainedBy(rectFromElement(target),
+                                 visualViewportRect()));
+      assert_false(isContainedBy(rectFromElement(target),
+                                 layoutViewportRect()));
+
+      target.scrollIntoViewIfNeeded();
+      assert_true(isContainedBy(rectFromElement(target), visualViewportRect()));
+      assert_true(isContainedBy(rectFromElement(target), layoutViewportRect()));
+    }, "Test that element.scrollIntoViewIfNeeded() scrolls the layout viewport and visual viewport.");
+  }
+
+  onload = runTest;
+</script>
+
+<style>
+  body {
+    height: 800px;
+    width: 800px;
+  }
+  #box {
+    background-color: black;
+    top: 700px;
+    left: 100px;
+    height: 40px;
+    width: 40px;
+    position: absolute;
+  }
+</style>
+
+<div id="box"></div>
diff --git a/third_party/blink/web_tests/media/controls/panel-removes-transparent-class-when-controls-are-not-shown.html b/third_party/blink/web_tests/media/controls/panel-removes-transparent-class-when-controls-are-not-shown.html
new file mode 100644
index 0000000..47f2383
--- /dev/null
+++ b/third_party/blink/web_tests/media/controls/panel-removes-transparent-class-when-controls-are-not-shown.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<title>Test that the panel doesn't stay transparent when the controls are hidden.</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
+<!-- video with native controls hidden -->
+<video width=500 preload=none src="../content/60_sec_video.webm"></video>
+<script>
+async_test(t => {
+  const video = document.querySelector('video');
+  const panel = panelElement(video);
+  enableTestMode(video);
+
+  video.addEventListener('canplaythrough', t.step_func(() => {
+    assert_false(isPanelTransparent(), 'panel should start opaque');
+    video.play();
+  }), { once: true });
+
+  video.addEventListener('playing', t.step_func(() => {
+    runAfterHideMediaControlsTimerFired(t.step_func(() => {
+      assert_true(isPanelTransparent(), 'panel should be transparent after hide timer fires');
+      video.pause();
+    }), video);
+  }), { once: true });
+
+  video.addEventListener('pause', t.step_func_done(() => {
+    assert_false(isPanelTransparent(), 'panel should now be opaque again');
+  }), { once: true });
+
+  function isPanelTransparent() {
+    return panel.classList.contains('transparent');
+  }
+
+  video.load();
+
+});
+</script>
+</html>
diff --git a/third_party/blink/web_tests/platform/android/editing/pasteboard/paste-text-016-expected.png b/third_party/blink/web_tests/platform/android/editing/pasteboard/paste-text-016-expected.png
deleted file mode 100644
index f4810c5..0000000
--- a/third_party/blink/web_tests/platform/android/editing/pasteboard/paste-text-016-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
rename to third_party/blink/web_tests/platform/mac-mac10.11/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/editing/pasteboard/paste-text-016-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/editing/pasteboard/paste-text-016-expected.png
deleted file mode 100644
index 507dfed..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/editing/pasteboard/paste-text-016-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/mac-retina/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/platform/mac-mac10.12/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
copy to third_party/blink/web_tests/platform/mac-retina/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py
index 43ebe8d..ecebf7c 100644
--- a/tools/grit/grit/tool/build.py
+++ b/tools/grit/grit/tool/build.py
@@ -457,8 +457,8 @@
         for i in self.res.GetOutputFiles()])
 
     if asserted != actual:
-      missing = list(set(actual) - set(asserted))
-      extra = list(set(asserted) - set(actual))
+      missing = list(set(asserted) - set(actual))
+      extra = list(set(actual) - set(asserted))
       error = '''Asserted file list does not match.
 
 Expected output files:
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index d31ef6e..2d9478a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -16021,6 +16021,9 @@
   <int value="535" label="DeviceWilcoDtcConfig"/>
   <int value="536" label="SpellcheckLanguageBlacklist"/>
   <int value="537" label="DeviceWiFiAllowed"/>
+  <int value="538" label="DevicePowerPeakShiftEnabled"/>
+  <int value="539" label="DevicePowerPeakShiftBatteryThreshold"/>
+  <int value="540" label="DevicePowerPeakShiftDayConfig"/>
 </enum>
 
 <enum name="EnterprisePolicyInvalidations">
@@ -34257,6 +34260,43 @@
   <int value="5" label="OTHER_DEVELOPER">Other Dev</int>
 </enum>
 
+<enum name="MacbookRetryGetDeviceInfosEvent">
+  <int value="0"
+      label="Provider received zero infos. Stopping service for retry."/>
+  <int value="1" label="Service has stopped. Provider issuing retry."/>
+  <int value="2" label="Provider received zero infos from retry. Giving up."/>
+  <int value="3" label="Provider received &gt; 0 infos from retry."/>
+  <int value="4"
+      label="Provider not attempting retry because a retry is already
+             pending."/>
+  <int value="5"
+      label="AVFoundation received zero device infos on first try and first
+             attempt since process start."/>
+  <int value="6"
+      label="AVFoundation received &gt; 0 device infos on first try and first
+             attempt since process start."/>
+  <int value="7"
+      label="AVFoundation received zero device infos on first try and
+             non-first attempt since process start (service was already
+             running)."/>
+  <int value="8"
+      label="AVFoundation received &gt; 0 device infos on first try and and
+             non-first attempt since process start (service was already
+             running)."/>
+  <int value="9"
+      label="AVFoundation received zero device infos on retry. Retry did not
+             help."/>
+  <int value="10"
+      label="AVFoundation received &gt; 0 device infos on retry. Retry has
+             helped."/>
+  <int value="11"
+      label="AVFoundation device count has changed from zero to &gt; 0 on a
+             subsequent attempt without restarting the process."/>
+  <int value="12"
+      label="AVFoundation device count has changed from &gt; 0 to zero on a
+             subsequent attempt without restarting the process."/>
+</enum>
+
 <enum name="MacBookVersions">
   <int value="0" label="Other"/>
   <int value="1" label="MacBook5,X"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 40eb9822..f528d949 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -11647,34 +11647,64 @@
   </summary>
 </histogram>
 
-<histogram name="Blink.Paint.CachedItemPercentage" units="%">
+<histogram name="Blink.Paint.CachedItemPercentage" units="%"
+    expires_after="2020-03-01">
   <owner>paint-dev@chromium.org</owner>
   <summary>
     Percentage of cached display items among all display items. Higher value
     means higher performance beause of less paint invalidation. Recorded when we
-    finish updating paint in the Blink document lifecycle if we have enough data
-    to report.
+    finish updating paint in the Blink document lifecycle.
   </summary>
 </histogram>
 
-<histogram name="Blink.Paint.CachedSubsequencePercentage" units="%">
+<histogram name="Blink.Paint.CachedSubsequencePercentage" units="%"
+    expires_after="2020-03-01">
   <owner>paint-dev@chromium.org</owner>
   <summary>
     Percentage of cached subsequences of display items among all subsequences.
     Higher value means higher performance beause of less subsequence
     invalidation. Recorded when we finish updating paint in the Blink document
-    lifecycle if we have enough data to report.
+    lifecycle.
   </summary>
 </histogram>
 
-<histogram name="Blink.Paint.IndexedItemPercentage" units="%">
+<histogram name="Blink.Paint.IndexedItemPercentage" units="%"
+    expires_after="2020-03-01">
   <owner>paint-dev@chromium.org</owner>
   <summary>
     Percentage of display items that are put into the index because of
     out-of-order display item matching. Higher value means lower performance
     beause of the cost of out-of-order matching and indexing. Recorded when we
-    finish updating paint in the Blink document lifecycle if we have enough data
-    to report.
+    finish updating paint in the Blink document lifecycle.
+  </summary>
+</histogram>
+
+<histogram name="Blink.Paint.NumDisplayItems" units="count"
+    expires_after="2020-03-01">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    Total number of display items (including cached and repainted) in the
+    painted result. Recorded when we finish updating paint in the Blink document
+    lifecycle.
+  </summary>
+</histogram>
+
+<histogram name="Blink.Paint.NumPaintChunks" units="count"
+    expires_after="2020-03-01">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    Total number of paint chunks in the painted result. Recorded when we finish
+    updating paint in the Blink document lifecycle.
+  </summary>
+</histogram>
+
+<histogram name="Blink.Paint.NumSubsequences" units="count"
+    expires_after="2020-03-01">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    Total number of subsequences (including cached and repainted) in the painted
+    result. Recorded when we finish updating paint in the Blink document
+    lifecycle.
   </summary>
 </histogram>
 
@@ -51762,6 +51792,17 @@
   </summary>
 </histogram>
 
+<histogram name="Media.VideoCapture.MacBook.AttemptCountWhenNoCamera"
+    units="attempts" expires_after="2020-03-15">
+  <owner>chfremer@chromium.org</owner>
+  <summary>
+    Indicates how many times Chrome has asked AVFoundation to enumerate devices
+    since the process start when zero devices are returned. This event is only
+    emitted for the first time that zero devices are returned since the process
+    start. This is used in the context of investigating http://crbug.com/582931.
+  </summary>
+</histogram>
+
 <histogram name="Media.VideoCapture.MacBook.HardwareVersionWhenNoCamera"
     enum="MacBookVersions">
   <owner>perkj@chromium.org</owner>
@@ -51780,15 +51821,13 @@
   </summary>
 </histogram>
 
-<histogram name="Media.VideoCapture.MacBook.NumberOfDevicesAfterServiceRestart"
-    units="devices" expires_after="2019-04-15">
+<histogram name="Media.VideoCapture.MacBook.RetryGetDeviceInfosEvent"
+    enum="MacbookRetryGetDeviceInfosEvent" expires_after="2019-05-15">
   <owner>chfremer@chromium.org</owner>
   <summary>
-    Number of video capture devices detected by Chrome when retrying device
-    enumeration after restarting the video capture service because a previous
-    device enumeration delivered zero devices.This is used for testing the
-    effectiveness of restarting the video capture service as a mitigation for
-    http://crbug.com/582931.
+    Counts events that are emitted in the context of attempting to mitigate the
+    issue of no cameras being found on Macbooks by restarting the video capture
+    service and retrying to obtain device infos, see http://crbug.com/582931.
   </summary>
 </histogram>
 
@@ -101292,6 +101331,17 @@
   </summary>
 </histogram>
 
+<histogram name="SBClientDownload.RarHeadersEncrypted" enum="Boolean"
+    expires_after="M79">
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <summary>
+    Records whether the RAR headers are encrypted, preventing any meaningful
+    content analysis. This is in contrast to encryption of the content of the
+    archive, which still exposes file name information. This histogram is
+    recorded every time a RAR archive is downloaded.
+  </summary>
+</histogram>
+
 <histogram name="SBClientDownload.RarOpenSuccess" enum="BooleanSuccess">
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -105689,6 +105739,20 @@
 </histogram>
 
 <histogram base="true" name="Security.TimeOnPage">
+  <obsolete>
+    Deprecated March 2019 in favor of Security.TimeOnPage2.
+  </obsolete>
+  <owner>cthomp@chromium.org</owner>
+  <summary>
+    Records the time spent on the page (the time that the page was in the
+    foreground from the start of the navigation to the page visit completing due
+    to a new navigation or the tab being closed). This aggregates all foreground
+    time over the entire visit (multiple times in the foreground are added
+    together).
+  </summary>
+</histogram>
+
+<histogram base="true" name="Security.TimeOnPage2">
   <owner>cthomp@chromium.org</owner>
   <summary>
     Records the time spent on the page (the time that the page was in the
@@ -109848,6 +109912,16 @@
   <summary>Track how a user interfacts with the android signin promo.</summary>
 </histogram>
 
+<histogram name="Signin.AndroidTimeBetweenUpdateAccountList" units="ms"
+    expires_after="2020-03-14">
+  <owner>bsazonov@chromium.org</owner>
+  <owner>droger@chromium.org</owner>
+  <summary>
+    Duration of time between UpdateAccountList calls. Recorded when
+    OAuth2TokenServiceDelegateAndroid::UpdateAccountList completes.
+  </summary>
+</histogram>
+
 <histogram name="Signin.AuthenticatedLaunchUserEvent"
     enum="AuthenticatedLaunchUserEvent">
   <owner>zmin@chromium.org</owner>
@@ -139968,6 +140042,9 @@
   <suffix name="GCMKeyStore" label="Databases for GCMKeyStore"/>
   <suffix name="ImageManager" label="Databases for ImageManager"/>
   <suffix name="Metadata" label="Metadata of shared databases"/>
+  <suffix name="NTPSnippetImages"
+      label="Database for RemoteSuggestion images."/>
+  <suffix name="NTPSnippets" label="Database for RemoteSuggestion snippets."/>
   <suffix name="OfflinePageMetadataStore"
       label="Databases for OfflinePageMetadataStore"/>
   <suffix name="PreviewsHintCacheStore" label="Databases for Previews Hints"/>
@@ -146620,6 +146697,7 @@
   <affected-histogram name="Security.SiteEngagement"/>
   <affected-histogram name="Security.SiteEngagementDelta"/>
   <affected-histogram name="Security.TimeOnPage"/>
+  <affected-histogram name="Security.TimeOnPage2"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="ServiceWorker.ContextRequestType" separator=".">
diff --git a/ui/accessibility/platform/atk_util_auralinux.cc b/ui/accessibility/platform/atk_util_auralinux.cc
index 08da557..945bc2c 100644
--- a/ui/accessibility/platform/atk_util_auralinux.cc
+++ b/ui/accessibility/platform/atk_util_auralinux.cc
@@ -156,6 +156,8 @@
 }
 
 // static
+// Disable CFI-icall since the key snooping function could be in another DSO.
+__attribute__((no_sanitize("cfi-icall")))
 DiscardAtkKeyEvent AtkUtilAuraLinux::HandleAtkKeyEvent(
     AtkKeyEventStruct* key_event) {
   DCHECK(key_event);
diff --git a/ui/android/java/res/drawable-v21/popup_bg_tinted.xml b/ui/android/java/res/drawable-v21/popup_bg_tinted.xml
index 19be5b61..b762955 100644
--- a/ui/android/java/res/drawable-v21/popup_bg_tinted.xml
+++ b/ui/android/java/res/drawable-v21/popup_bg_tinted.xml
@@ -5,5 +5,5 @@
 
 <nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
     android:src="@drawable/popup_bg"
-    android:tint="@color/modern_primary_color"
-    android:tintMode="multiply"/>
\ No newline at end of file
+    android:tint="@color/popup_bg_color"
+    android:tintMode="multiply" />
\ No newline at end of file
diff --git a/ui/android/java/res/drawable/popup_bg_tinted.xml b/ui/android/java/res/drawable/popup_bg_tinted.xml
index 8552a8f..a2157185 100644
--- a/ui/android/java/res/drawable/popup_bg_tinted.xml
+++ b/ui/android/java/res/drawable/popup_bg_tinted.xml
@@ -10,7 +10,7 @@
     <item>
         <shape>
             <corners android:radius="4dp" />
-            <solid android:color="@color/modern_primary_color" />
+            <solid android:color="@color/popup_bg_color" />
         </shape>
     </item>
 </layer-list>
diff --git a/ui/android/java/res/values-v17/styles.xml b/ui/android/java/res/values-v17/styles.xml
index a1b3491..fcf4e04 100644
--- a/ui/android/java/res/values-v17/styles.xml
+++ b/ui/android/java/res/values-v17/styles.xml
@@ -179,7 +179,7 @@
         <item name="android:textSize">@dimen/text_size_medium</item>
     </style>
     <style name="TextAppearance.WhiteButtonText" parent="TextAppearance.AccentMediumStyle">
-        <item name="android:textColor">@android:color/white</item>
+        <item name="android:textColor">@color/default_text_color_inverse</item>
         <item name="android:textSize">@dimen/text_size_medium</item>
     </style>
     <style name="TextAppearance.WhiteLink" tools:ignore="UnusedResources">
diff --git a/ui/android/java/res/values/color_palette.xml b/ui/android/java/res/values/color_palette.xml
index 4b7124a..2a943e62 100644
--- a/ui/android/java/res/values/color_palette.xml
+++ b/ui/android/java/res/values/color_palette.xml
@@ -6,7 +6,6 @@
     <color name="modern_grey_50" tools:ignore="UnusedResources">#F8F9FA</color>
     <color name="modern_grey_100" tools:ignore="UnusedResources">#F1F3F4</color>
     <color name="modern_grey_200" tools:ignore="UnusedResources">#E8EAED</color>
-    <color name="modern_grey_200_alpha_38" tools:ignore="UnusedResources">#61E8EAED</color>
     <color name="modern_grey_300" tools:ignore="UnusedResources">#DADCE0</color>
     <color name="modern_grey_400" tools:ignore="UnusedResources">#BDC1C6</color>
     <color name="modern_grey_500" tools:ignore="UnusedResources">#9AA0A6</color>
@@ -18,11 +17,13 @@
 
     <color name="modern_grey_900_with_white_alpha_6" tools:ignore="UnusedResources">#2D2E31</color>
     <color name="modern_grey_900_with_white_alpha_8" tools:ignore="UnusedResources">#313235</color>
+    <color name="modern_grey_900_with_white_alpha_10">#36373A</color>
 
     <color name="black_alpha_38">#61000000</color>
 
     <color name="white_alpha_10" tools:ignore="UnusedResources">#1AFFFFFF</color>
     <color name="white_alpha_20">#33FFFFFF</color>
+    <color name="white_alpha_38" tools:ignore="UnusedResources">#61FFFFFF</color>
     <color name="white_alpha_50" tools:ignore="UnusedResources">#80FFFFFF</color>
     <color name="white_alpha_70">#B3FFFFFF</color>
 
@@ -45,8 +46,10 @@
     <color name="default_icon_color_white_pressed" tools:ignore="UnusedResources">
         @color/white_alpha_50
     </color>
+
     <!-- Common text colors -->
     <color name="default_text_color_dark">@color/modern_grey_900</color>
+    <color name="default_text_color_light">@android:color/white</color>
 
     <color name="default_red_light" tools:ignore="UnusedResources">@color/google_red_300</color>
     <color name="default_red_dark" tools:ignore="UnusedResources">@color/google_red_700</color>
@@ -65,4 +68,7 @@
     <color name="default_bg_color_dark_elev_3" tools:ignore="UnusedResources">
         @color/modern_grey_900_with_white_alpha_8
     </color>
+    <color name="default_bg_color_dark_elev_4" tools:ignore="UnusedResources">
+        @color/modern_grey_900_with_white_alpha_10
+    </color>
 </resources>
\ No newline at end of file
diff --git a/ui/android/java/res/values/colors.xml b/ui/android/java/res/values/colors.xml
index 1d021bae..983634c 100644
--- a/ui/android/java/res/values/colors.xml
+++ b/ui/android/java/res/values/colors.xml
@@ -8,6 +8,7 @@
     <!-- TODO(huayinz): remove tools:ignore once these colors are used in ui/android -->
     <!-- Common text colors -->
     <color name="default_text_color">@color/default_text_color_dark</color>
+    <color name="default_text_color_inverse">@color/default_text_color_light</color>
     <color name="default_text_color_secondary">@color/modern_grey_700</color>
     <!-- Text color for non-clickable blue text. -->
     <color name="default_text_color_blue" tools:ignore="UnusedResources">@color/modern_blue_600</color>
@@ -45,6 +46,10 @@
     <color name="default_bg_color_elev_3" tools:ignore="UnusedResources">
         @color/default_bg_color_light
     </color>
+    <color name="default_bg_color_elev_4">@color/default_bg_color_light</color>
+
+    <!-- Popup colors -->
+    <color name="popup_bg_color">@color/default_bg_color_elev_4</color>
 
     <color name="dropdown_divider_color">#E5E5E5</color>
     <color name="dropdown_dark_divider_color">#C0C0C0</color>
diff --git a/ui/android/java/res_night/values-night/colors.xml b/ui/android/java/res_night/values-night/colors.xml
index 1a9548f..754a258 100644
--- a/ui/android/java/res_night/values-night/colors.xml
+++ b/ui/android/java/res_night/values-night/colors.xml
@@ -5,10 +5,11 @@
 
 <resources>
     <!-- Common text colors -->
-    <color name="default_text_color">@color/modern_grey_200</color>
+    <color name="default_text_color">@color/default_text_color_light</color>
+    <color name="default_text_color_inverse">@color/default_text_color_dark</color>
     <color name="default_text_color_secondary">@color/modern_grey_500</color>
     <color name="default_text_color_link">@color/modern_blue_300</color>
-    <color name="disabled_text_color">@color/modern_grey_200_alpha_38</color>
+    <color name="disabled_text_color">@color/white_alpha_38</color>
 
     <!-- Common icon colors for drawables. -->
     <color name="default_icon_color">@color/default_icon_color_white</color>
@@ -22,5 +23,5 @@
     <color name="default_bg_color_elev_0">@color/default_bg_color_dark</color>
     <color name="default_bg_color_elev_2">@color/default_bg_color_dark_elev_2</color>
     <color name="default_bg_color_elev_3">@color/default_bg_color_dark_elev_3</color>
-
+    <color name="default_bg_color_elev_4">@color/default_bg_color_dark_elev_4</color>
 </resources>
\ No newline at end of file
diff --git a/ui/aura/mus/capture_synchronizer.cc b/ui/aura/mus/capture_synchronizer.cc
index f1bd68e..8afbb3e 100644
--- a/ui/aura/mus/capture_synchronizer.cc
+++ b/ui/aura/mus/capture_synchronizer.cc
@@ -53,8 +53,26 @@
 }
 
 void CaptureSynchronizer::SetCaptureWindow(WindowMus* window) {
-  if (capture_window_)
+  if (capture_window_) {
     capture_window_->GetWindow()->RemoveObserver(this);
+
+    // If |window| is in a different root, then need to tell the old
+    // CaptureClient that it lost capture. This assumes that if |window| is null
+    // the change was initiated from the old CaptureClient.
+    Window* old_capture_window_root =
+        capture_window_->GetWindow()->GetRootWindow();
+    if (old_capture_window_root && window &&
+        window->GetWindow()->GetRootWindow() != old_capture_window_root) {
+      client::CaptureClient* capture_client =
+          client::GetCaptureClient(old_capture_window_root);
+      if (capture_client) {
+        // Remove this as an observer to avoid trying to react to the change.
+        capture_client->RemoveObserver(this);
+        capture_client->ReleaseCapture(capture_window_->GetWindow());
+        capture_client->AddObserver(this);
+      }
+    }
+  }
   capture_window_ = window;
   if (capture_window_)
     capture_window_->GetWindow()->AddObserver(this);
diff --git a/ui/aura/mus/capture_synchronizer.h b/ui/aura/mus/capture_synchronizer.h
index c2202165..d20aba34 100644
--- a/ui/aura/mus/capture_synchronizer.h
+++ b/ui/aura/mus/capture_synchronizer.h
@@ -26,7 +26,7 @@
 class CaptureClient;
 }
 
-// CaptureSynchronizer is resonsible for keeping capture in sync between aura
+// CaptureSynchronizer is responsible for keeping capture in sync between aura
 // and the mus server.
 class AURA_EXPORT CaptureSynchronizer : public WindowObserver,
                                         public client::CaptureClientObserver {
diff --git a/ui/aura/mus/embed_root.cc b/ui/aura/mus/embed_root.cc
index 4ef7a75..94f7d7d8d 100644
--- a/ui/aura/mus/embed_root.cc
+++ b/ui/aura/mus/embed_root.cc
@@ -6,9 +6,12 @@
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
+#include "base/scoped_observer.h"
 #include "ui/aura/client/focus_change_observer.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/mus/embed_root_delegate.h"
+#include "ui/aura/mus/focus_synchronizer.h"
+#include "ui/aura/mus/focus_synchronizer_observer.h"
 #include "ui/aura/mus/window_tree_client.h"
 #include "ui/aura/mus/window_tree_host_mus.h"
 #include "ui/aura/window.h"
@@ -20,9 +23,12 @@
 
 // FocusClient implementation used for embedded windows. This has minimal
 // checks as to what can get focus.
-class EmbeddedFocusClient : public client::FocusClient, public WindowObserver {
+class EmbeddedFocusClient : public client::FocusClient,
+                            public WindowObserver,
+                            public FocusSynchronizerObserver {
  public:
-  explicit EmbeddedFocusClient(Window* root) : root_(root) {
+  EmbeddedFocusClient(FocusSynchronizer* focus_synchronizer, Window* root)
+      : focus_synchronizer_(focus_synchronizer), root_(root) {
     client::SetFocusClient(root, this);
   }
 
@@ -42,6 +48,16 @@
   void FocusWindow(Window* window) override {
     if (IsValidWindowForFocus(window) && window != GetFocusedWindow())
       FocusWindowImpl(window);
+
+    if (GetFocusedWindow() &&
+        focus_synchronizer_->active_focus_client() != this) {
+      focus_synchronizer_->SetActiveFocusClient(this, root_);
+      scoped_focus_synchronizer_observer_.Add(focus_synchronizer_);
+    } else if (!GetFocusedWindow() &&
+               focus_synchronizer_->active_focus_client() == this) {
+      scoped_focus_synchronizer_observer_.RemoveAll();
+      focus_synchronizer_->SetActiveFocusClient(nullptr, nullptr);
+    }
   }
   void ResetFocusWithinActiveWindow(Window* window) override {
     // This is never called in the embedding case.
@@ -92,9 +108,23 @@
     DCHECK_EQ(window, focused_window_);
   }
 
+  // FocusSynchronizerObserver:
+  void OnActiveFocusClientChanged(client::FocusClient* focus_client,
+                                  Window* focus_client_root) override {
+    DCHECK_NE(this, focus_client);
+    scoped_focus_synchronizer_observer_.RemoveAll();
+    FocusWindowImpl(nullptr);
+  }
+
+  // FocusSynchronizer instance of our WindowTreeClient. Not owned.
+  FocusSynchronizer* const focus_synchronizer_;
+
   // Root of the hierarchy this is the FocusClient for.
   Window* const root_;
 
+  ScopedObserver<FocusSynchronizer, FocusSynchronizerObserver>
+      scoped_focus_synchronizer_observer_{this};
+
   Window* focused_window_ = nullptr;
 
   base::ObserverList<client::FocusChangeObserver>::Unchecked observers_;
@@ -133,13 +163,17 @@
 }
 
 void EmbedRoot::OnEmbed(std::unique_ptr<WindowTreeHostMus> window_tree_host) {
-  focus_client_ =
-      std::make_unique<EmbeddedFocusClient>(window_tree_host->window());
+  focus_client_ = std::make_unique<EmbeddedFocusClient>(
+      window_tree_client_->focus_synchronizer(), window_tree_host->window());
   window_tree_host_ = std::move(window_tree_host);
   delegate_->OnEmbed(window());
 }
 
 void EmbedRoot::OnUnembed() {
+  window_tree_host_.reset();
+  focus_client_.reset();
+
+  // |delegate_| may delete us.
   delegate_->OnUnembed();
 }
 
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc
index 798ae301..db34545 100644
--- a/ui/aura/mus/window_tree_client_unittest.cc
+++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -2284,6 +2284,9 @@
   // Releasing capture of root2 shouldn't affect root1 capture.
   root2->SetCapture();
   root1->SetCapture();
+  // Only one root should have capture at a time.
+  EXPECT_FALSE(root2->HasCapture());
+  EXPECT_TRUE(root1->HasCapture());
   root2->ReleaseCapture();
   EXPECT_EQ(1, capture_recorder1->capture_changed_count());
   EXPECT_EQ(2, capture_recorder2->capture_changed_count());
@@ -2627,6 +2630,27 @@
   window_tree_client()->OnWindowFocused(server_id(embed_root->window()));
 }
 
+// Verifies EmbedRoot window focus calls through to WindowTree and the focus is
+// cleared when the focus moves away at WS side.
+TEST_F(WindowTreeClientTest, EmbedRootWindowFocus) {
+  TestEmbedRootDelegate embed_root_delegate;
+  std::unique_ptr<EmbedRoot> embed_root =
+      window_tree_client_impl()->CreateEmbedRoot(&embed_root_delegate);
+  WindowTreeClientTestApi(window_tree_client_impl())
+      .CallOnEmbedFromToken(embed_root.get());
+  ASSERT_TRUE(embed_root->window());
+
+  embed_root->window()->Focus();
+  EXPECT_TRUE(
+      window_tree()->AckSingleChangeOfType(WindowTreeChangeType::FOCUS, true));
+  EXPECT_EQ(server_id(embed_root->window()),
+            window_tree()->last_focused_window_id());
+  EXPECT_TRUE(embed_root->window()->HasFocus());
+
+  window_tree_client_impl()->focus_synchronizer()->SetFocusFromServer(nullptr);
+  EXPECT_FALSE(embed_root->window()->HasFocus());
+}
+
 // Verifies visibility from server is applied properly when an embed root is
 // created.
 TEST_F(WindowTreeClientTest, EmbedRootVisibility) {
diff --git a/ui/aura/test/mus/test_window_tree.cc b/ui/aura/test/mus/test_window_tree.cc
index e9d8fd3..e9b4ff8 100644
--- a/ui/aura/test/mus/test_window_tree.cc
+++ b/ui/aura/test/mus/test_window_tree.cc
@@ -348,6 +348,7 @@
 void TestWindowTree::UnattachFrameSinkId(uint64_t window_id) {}
 
 void TestWindowTree::SetFocus(uint32_t change_id, ws::Id window_id) {
+  last_focused_window_id_ = window_id;
   OnChangeReceived(change_id, WindowTreeChangeType::FOCUS);
 }
 
diff --git a/ui/aura/test/mus/test_window_tree.h b/ui/aura/test/mus/test_window_tree.h
index e9a7187..084bfc4 100644
--- a/ui/aura/test/mus/test_window_tree.h
+++ b/ui/aura/test/mus/test_window_tree.h
@@ -141,6 +141,7 @@
   ws::Id last_cancelled_window_id() const { return last_cancelled_window_id_; }
   ws::Id last_transfer_current() const { return last_transfer_current_; }
   ws::Id last_transfer_new() const { return last_transfer_new_; }
+  ws::Id last_focused_window_id() const { return last_focused_window_id_; }
   bool last_transfer_should_cancel() const {
     return last_transfer_should_cancel_;
   }
@@ -352,6 +353,7 @@
   ws::Id last_cancelled_window_id_ = 0u;
   ws::Id last_transfer_current_ = 0u;
   ws::Id last_transfer_new_ = 0u;
+  ws::Id last_focused_window_id_ = 0u;
   bool last_transfer_should_cancel_ = false;
   bool last_accepts_drops_ = false;
   size_t can_focus_count_ = 0u;
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 258286c..dbe9fc1d 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -320,13 +320,6 @@
       "dragdrop/file_info.cc",
       "dragdrop/file_info.h",
       "emoji/emoji_panel_helper.h",
-      "idle/idle.cc",
-      "idle/idle.h",
-      "idle/idle_android.cc",
-      "idle/idle_chromeos.cc",
-      "idle/idle_linux.cc",
-      "idle/idle_mac.mm",
-      "idle/idle_win.cc",
       "pointer/pointer_device.h",
       "pointer/pointer_device_util.cc",
       "pointer/touch_editing_controller.cc",
@@ -385,7 +378,6 @@
 
   if (is_fuchsia) {
     sources += [
-      "idle/idle_fuchsia.cc",
       "l10n/l10n_util_posix.cc",
       "resource/resource_bundle_fuchsia.cc",
     ]
@@ -448,12 +440,6 @@
     configs += [ "//build/config/linux:x11" ]
 
     if (!is_chromeos) {
-      sources += [
-        "idle/idle_query_x11.cc",
-        "idle/idle_query_x11.h",
-        "idle/screensaver_window_finder_x11.cc",
-        "idle/screensaver_window_finder_x11.h",
-      ]
       configs += [ "//build/config/linux:xscrnsaver" ]
       deps += [ "//ui/gfx/x" ]
     }
@@ -514,14 +500,6 @@
     ]
   }
 
-  if (is_chromeos) {
-    deps += [
-      "//chromeos",
-      "//chromeos/dbus",
-    ]
-    sources -= [ "idle/idle_linux.cc" ]
-  }
-
   if (is_chromeos || (use_aura && is_linux && !use_x11)) {
     sources += [
       "dragdrop/os_exchange_data_provider_aura.cc",
@@ -623,7 +601,6 @@
     sources -= [
       "cursor/cursor_android.cc",
       "default_theme_provider.cc",
-      "idle/idle.cc",
       "l10n/l10n_font_util.cc",
       "models/button_menu_item_model.cc",
       "pointer/touch_editing_controller.cc",
diff --git a/ui/base/idle/BUILD.gn b/ui/base/idle/BUILD.gn
new file mode 100644
index 0000000..ba4ea15a
--- /dev/null
+++ b/ui/base/idle/BUILD.gn
@@ -0,0 +1,68 @@
+# Copyright 2019 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.
+
+import("//build/config/ui.gni")
+
+if (is_mac) {
+  import("//build/config/mac/rules.gni")
+}
+
+component("idle") {
+  output_name = "ui_base_idle"
+
+  defines = [ "IS_UI_BASE_IDLE_IMPL" ]
+
+  deps = [
+    "//base",
+    "//ui/base",
+  ]
+
+  if (is_chromeos) {
+    deps += [ "//chromeos/dbus" ]
+  }
+
+  sources = [
+    "idle.cc",
+    "idle.h",
+    "idle_chromeos.cc",
+    "idle_mac.mm",
+    "idle_win.cc",
+  ]
+
+  if (is_fuchsia) {
+    sources += [ "idle_fuchsia.cc" ]
+  }
+
+  if (is_linux && !is_chromeos) {
+    sources += [ "idle_linux.cc" ]
+  }
+
+  if (use_x11 && !is_chromeos) {
+    configs += [
+      "//build/config/linux:x11",
+      "//build/config/linux:xscrnsaver",
+    ]
+    deps += [ "//ui/gfx/x" ]
+    sources += [
+      "idle_query_x11.cc",
+      "idle_query_x11.h",
+      "screensaver_window_finder_x11.cc",
+      "screensaver_window_finder_x11.h",
+    ]
+  }
+
+  if (is_android) {
+    deps += [ "//ui/base:ui_base_jni_headers" ]
+    sources -= [ "idle.cc" ]
+    sources += [ "idle_android.cc" ]
+  }
+
+  if (is_mac) {
+    libs = [
+      "AppKit.framework",
+      "Carbon.framework",
+      "Foundation.framework",
+    ]
+  }
+}
diff --git a/ui/base/idle/idle.h b/ui/base/idle/idle.h
index 269ca44..83420c7 100644
--- a/ui/base/idle/idle.h
+++ b/ui/base/idle/idle.h
@@ -5,8 +5,8 @@
 #ifndef UI_BASE_IDLE_IDLE_H_
 #define UI_BASE_IDLE_IDLE_H_
 
+#include "base/component_export.h"
 #include "build/build_config.h"
-#include "ui/base/ui_base_export.h"
 
 namespace ui {
 
@@ -20,18 +20,18 @@
 
 // For MacOSX, InitIdleMonitor needs to be called first to setup the monitor.
 #if defined(OS_MACOSX)
-UI_BASE_EXPORT void InitIdleMonitor();
+COMPONENT_EXPORT(UI_BASE_IDLE) void InitIdleMonitor();
 #endif
 
 // Calculate the Idle state. |idle_threshold| is the amount of time (in seconds)
 // before the user is considered idle.
-UI_BASE_EXPORT IdleState CalculateIdleState(int idle_threshold);
+COMPONENT_EXPORT(UI_BASE_IDLE) IdleState CalculateIdleState(int idle_threshold);
 
 // Calculate Idle time in seconds.
-UI_BASE_EXPORT int CalculateIdleTime();
+COMPONENT_EXPORT(UI_BASE_IDLE) int CalculateIdleTime();
 
 // Checks synchronously if Idle state is IDLE_STATE_LOCKED.
-UI_BASE_EXPORT bool CheckIdleStateIsLocked();
+COMPONENT_EXPORT(UI_BASE_IDLE) bool CheckIdleStateIsLocked();
 
 }  // namespace ui
 
diff --git a/ui/chromeos/OWNERS b/ui/chromeos/OWNERS
index 50cce3ef..94f5eddc 100644
--- a/ui/chromeos/OWNERS
+++ b/ui/chromeos/OWNERS
@@ -2,3 +2,5 @@
 jamescook@chromium.org
 oshima@chromium.org
 stevenjb@chromium.org
+
+per-file file_manager_strings.grdp=*
diff --git a/chrome/app/file_manager_strings.grdp b/ui/chromeos/file_manager_strings.grdp
similarity index 99%
rename from chrome/app/file_manager_strings.grdp
rename to ui/chromeos/file_manager_strings.grdp
index dd40795f..38d65a42 100644
--- a/chrome/app/file_manager_strings.grdp
+++ b/ui/chromeos/file_manager_strings.grdp
@@ -65,6 +65,9 @@
   <message name="IDS_FILE_BROWSER_LINUX_FILES_ROOT_LABEL" desc="A label for the 'Linux files' root which shows crostini files. Use sentence case.">
     Linux files
   </message>
+  <message name="IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL" desc="A label for the 'My files' root which is parent of Downloads, Linux and Android files. Use sentence case.">
+    My files
+  </message>
   <message name="IDS_FILE_BROWSER_MEDIA_VIEW_IMAGES_ROOT_LABEL" desc="A label for the 'Images' root of media views.">
     Images
   </message>
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_A11Y_VOLUME_EJECT.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_A11Y_VOLUME_EJECT.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_A11Y_VOLUME_EJECT.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_A11Y_VOLUME_EJECT.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_DRIVE_COMPUTERS_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_DRIVE_COMPUTERS_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_DRIVE_COMPUTERS_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_DRIVE_COMPUTERS_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_EXTERNAL_STORAGE_ROOT_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_EXTERNAL_STORAGE_ROOT_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_EXTERNAL_STORAGE_ROOT_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_EXTERNAL_STORAGE_ROOT_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI_PLURAL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI_PLURAL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI_PLURAL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI_PLURAL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_APPLICATION_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_APPLICATION_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_APPLICATION_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_APPLICATION_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_DESCRIPTION_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_DESCRIPTION_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_DESCRIPTION_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_DESCRIPTION_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_LOADING.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_LOADING.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_LOADING.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_LOADING.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_NOT_AVAILABLE.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_NOT_AVAILABLE.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_NOT_AVAILABLE.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_NOT_AVAILABLE.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_VERSION_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_VERSION_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_VERSION_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_DETAILS_VERSION_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_TITLE.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_TITLE.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_TITLE.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_INSTALL_LINUX_PACKAGE_TITLE.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_OPEN_A11Y.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_OPEN_A11Y.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_OPEN_A11Y.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_OPEN_A11Y.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_OPEN_A11Y_PLURAL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_OPEN_A11Y_PLURAL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_OPEN_A11Y_PLURAL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_OPEN_A11Y_PLURAL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SEARCH_CLEAR_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SEARCH_CLEAR_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SEARCH_CLEAR_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SEARCH_CLEAR_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SEND_FEEDBACK_BUTTON_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SEND_FEEDBACK_BUTTON_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SEND_FEEDBACK_BUTTON_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SEND_FEEDBACK_BUTTON_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SET_WALLPAPER_BUTTON_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SET_WALLPAPER_BUTTON_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SET_WALLPAPER_BUTTON_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SET_WALLPAPER_BUTTON_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_MULTIPLE.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_MULTIPLE.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_MULTIPLE.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_MULTIPLE.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_SINGLE.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_SINGLE.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_SINGLE.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_SINGLE.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_TITLE.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_TITLE.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_TITLE.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_BEFORE_OPEN_CROSTINI_TITLE.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_WITH_LINUX_BUTTON_LABEL.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_WITH_LINUX_BUTTON_LABEL.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_WITH_LINUX_BUTTON_LABEL.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHARE_WITH_LINUX_BUTTON_LABEL.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHOW_ALL_ANDROID_FOLDERS_OPTION.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHOW_ALL_ANDROID_FOLDERS_OPTION.png.sha1
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_SHOW_ALL_ANDROID_FOLDERS_OPTION.png.sha1
rename to ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_SHOW_ALL_ANDROID_FOLDERS_OPTION.png.sha1
diff --git a/chrome/app/file_manager_strings_grdp/OWNERS b/ui/chromeos/file_manager_strings_grdp/OWNERS
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/OWNERS
rename to ui/chromeos/file_manager_strings_grdp/OWNERS
diff --git a/chrome/app/file_manager_strings_grdp/README.md b/ui/chromeos/file_manager_strings_grdp/README.md
similarity index 100%
rename from chrome/app/file_manager_strings_grdp/README.md
rename to ui/chromeos/file_manager_strings_grdp/README.md
diff --git a/ui/chromeos/ui_chromeos_strings.grd b/ui/chromeos/ui_chromeos_strings.grd
index 6db39ff..50b7ae9 100644
--- a/ui/chromeos/ui_chromeos_strings.grd
+++ b/ui/chromeos/ui_chromeos_strings.grd
@@ -120,6 +120,9 @@
   </translations>
   <release seq="1" allow_pseudo="false">
     <messages fallback_to_english="true">
+      <!-- Files app strings. It's shared with ARC++ (//components/arc). -->
+      <part file="file_manager_strings.grdp" />
+
       <!-- Default user profile images. -->
       <!-- User Image default image accessible descriptions -->
       <message name="IDS_LOGIN_DEFAULT_USER_DESC_19" desc="Description of the default user icon with a picture of a bicycle">
@@ -1096,11 +1099,6 @@
       <message name="IDS_IME_NAME_TRANSLITERATION_UR" desc="The input method name shows in system tray menu. Please translate only for 'transliteration'.">
         Transliteration (salam &#x2190; &#x0633;&#x0644;&#x0627;&#x0645;)
       </message>
-
-      <!-- Strings shared between ARC++ (//components/arc) and Files app (//chrome/browser/chromeos/file_manager)  -->
-      <message name="IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL" desc="A label for the 'My files' root which is parent of Downloads, Linux and Android files. Use sentence case.">
-        My files
-      </message>
     </messages>
   </release>
 </grit>
diff --git a/ui/chromeos/ui_chromeos_strings_grd/IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL.png.sha1 b/ui/chromeos/ui_chromeos_strings_grd/IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL.png.sha1
deleted file mode 100644
index f19d5d0..0000000
--- a/ui/chromeos/ui_chromeos_strings_grd/IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ee9bd055cf1f7c484fcc2a8e4c555fefa372daad
\ No newline at end of file
diff --git a/ui/chromeos/user_activity_power_manager_notifier.cc b/ui/chromeos/user_activity_power_manager_notifier.cc
index a39b36a4..4f65a06 100644
--- a/ui/chromeos/user_activity_power_manager_notifier.cc
+++ b/ui/chromeos/user_activity_power_manager_notifier.cc
@@ -5,7 +5,7 @@
 #include "ui/chromeos/user_activity_power_manager_notifier.h"
 
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/user_activity/user_activity_detector.h"
diff --git a/ui/events/blink/blink_features.cc b/ui/events/blink/blink_features.cc
index 7a76b7d..5f0c016 100644
--- a/ui/events/blink/blink_features.cc
+++ b/ui/events/blink/blink_features.cc
@@ -22,7 +22,7 @@
                                          base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kCompositorTouchAction{"CompositorTouchAction",
-                                           base::FEATURE_DISABLED_BY_DEFAULT};
+                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kFallbackCursorMode{"FallbackCursorMode",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ui/file_manager/file_manager/test/BUILD.gn b/ui/file_manager/file_manager/test/BUILD.gn
index 682ecb3c..d65a38d 100644
--- a/ui/file_manager/file_manager/test/BUILD.gn
+++ b/ui/file_manager/file_manager/test/BUILD.gn
@@ -17,8 +17,8 @@
     "../foreground/js/elements_importer.js",
     "../foreground/js/main_scripts.js",
     "../main.html",
-    "//chrome/app/file_manager_strings.grdp",
     "//chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc",
+    "//ui/chromeos/file_manager_strings.grdp",
     "//ui/webui/resources/css/text_defaults.css",
     "check_select.js",
     "crostini_mount.js",
diff --git a/ui/file_manager/file_manager/test/scripts/create_test_main.py b/ui/file_manager/file_manager/test/scripts/create_test_main.py
index 25db423..ed3dc4f 100755
--- a/ui/file_manager/file_manager/test/scripts/create_test_main.py
+++ b/ui/file_manager/file_manager/test/scripts/create_test_main.py
@@ -102,8 +102,7 @@
     }
 grdp_files = [
     'chrome/app/chromeos_strings.grdp',
-    'chrome/app/file_manager_strings.grdp',
-    'ui/chromeos/ui_chromeos_strings.grd',
+    'ui/chromeos/file_manager_strings.grdp',
     ]
 resource_bundle = {}
 for grdp in grdp_files:
diff --git a/ui/message_center/views/bounded_label.cc b/ui/message_center/views/bounded_label.cc
index 086e977..9e3d2e5 100644
--- a/ui/message_center/views/bounded_label.cc
+++ b/ui/message_center/views/bounded_label.cc
@@ -358,9 +358,8 @@
   return HitTestPoint(point) ? this : nullptr;
 }
 
-bool BoundedLabel::GetTooltipText(const gfx::Point& p,
-                                  base::string16* tooltip) const {
-  return label_->GetTooltipText(p, tooltip);
+base::string16 BoundedLabel::GetTooltipText(const gfx::Point& p) const {
+  return label_->GetTooltipText(p);
 }
 
 void BoundedLabel::OnBoundsChanged(const gfx::Rect& previous_bounds) {
diff --git a/ui/message_center/views/bounded_label.h b/ui/message_center/views/bounded_label.h
index 095c0db..9e25e39a 100644
--- a/ui/message_center/views/bounded_label.h
+++ b/ui/message_center/views/bounded_label.h
@@ -62,8 +62,7 @@
   bool CanProcessEventsWithinSubtree() const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
 
  protected:
   // Overridden from views::View.
diff --git a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
index 843de8c..50f95f8 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
@@ -133,7 +133,7 @@
 }
 
 WaylandWindow* WaylandConnectionProxy::GetWindow(
-    gfx::AcceleratedWidget widget) {
+    gfx::AcceleratedWidget widget) const {
   if (connection_)
     return connection_->GetWindow(widget);
   return nullptr;
@@ -147,8 +147,7 @@
                 "when multi-process moe is used";
 }
 
-
-intptr_t WaylandConnectionProxy::Display() {
+intptr_t WaylandConnectionProxy::Display() const {
   if (connection_)
     return reinterpret_cast<intptr_t>(connection_->display());
 
diff --git a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h
index 8da7a18..2790987 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h
+++ b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h
@@ -99,7 +99,7 @@
   // hosted in the browser process).
   //
   // Return a WaylandWindow based on the |widget|.
-  WaylandWindow* GetWindow(gfx::AcceleratedWidget widget);
+  WaylandWindow* GetWindow(gfx::AcceleratedWidget widget) const;
   // Schedule flush in the Wayland message loop.
   void ScheduleFlush();
 
@@ -108,13 +108,13 @@
   // Returns a pointer to native display. When used in single process mode,
   // a wl_display pointer is returned. For the the mode, when there are GPU
   // and browser processes, EGL_DEFAULT_DISPLAY is returned.
-  intptr_t Display();
+  intptr_t Display() const;
 
   // Adds a WaylandConnectionClient binding.
   void AddBindingWaylandConnectionClient(
       ozone::mojom::WaylandConnectionClientRequest request);
 
-  WaylandConnection* connection() { return connection_; }
+  WaylandConnection* connection() const { return connection_; }
 
  private:
   void CreateZwpLinuxDmabufInternal(base::File file,
@@ -129,7 +129,7 @@
 
   // Non-owned pointer to a WaylandConnection. It is only used in a single
   // process mode, when a shared dmabuf approach is not used.
-  WaylandConnection* connection_ = nullptr;
+  WaylandConnection* const connection_;
 
 #if defined(WAYLAND_GBM)
   // A DRM render node based gbm device.
diff --git a/ui/ozone/platform/wayland/wayland_connection.cc b/ui/ozone/platform/wayland/wayland_connection.cc
index e7095507..05e23b5 100644
--- a/ui/ozone/platform/wayland/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/wayland_connection.cc
@@ -123,12 +123,13 @@
   scheduled_flush_ = true;
 }
 
-WaylandWindow* WaylandConnection::GetWindow(gfx::AcceleratedWidget widget) {
+WaylandWindow* WaylandConnection::GetWindow(
+    gfx::AcceleratedWidget widget) const {
   auto it = window_map_.find(widget);
   return it == window_map_.end() ? nullptr : it->second;
 }
 
-WaylandWindow* WaylandConnection::GetWindowWithLargestBounds() {
+WaylandWindow* WaylandConnection::GetWindowWithLargestBounds() const {
   WaylandWindow* window_with_largest_bounds = nullptr;
   for (auto entry : window_map_) {
     if (!window_with_largest_bounds) {
@@ -142,7 +143,7 @@
   return window_with_largest_bounds;
 }
 
-WaylandWindow* WaylandConnection::GetCurrentFocusedWindow() {
+WaylandWindow* WaylandConnection::GetCurrentFocusedWindow() const {
   for (auto entry : window_map_) {
     WaylandWindow* window = entry.second;
     if (window->has_pointer_focus())
@@ -151,7 +152,7 @@
   return nullptr;
 }
 
-WaylandWindow* WaylandConnection::GetCurrentKeyboardFocusedWindow() {
+WaylandWindow* WaylandConnection::GetCurrentKeyboardFocusedWindow() const {
   for (auto entry : window_map_) {
     WaylandWindow* window = entry.second;
     if (window->has_keyboard_focus())
@@ -178,7 +179,7 @@
   pointer_->cursor()->UpdateBitmap(bitmaps, location, serial_);
 }
 
-int WaylandConnection::GetKeyboardModifiers() {
+int WaylandConnection::GetKeyboardModifiers() const {
   int modifiers = 0;
   if (keyboard_)
     modifiers = keyboard_->modifiers();
diff --git a/ui/ozone/platform/wayland/wayland_connection.h b/ui/ozone/platform/wayland/wayland_connection.h
index c7da42b..86228edc6 100644
--- a/ui/ozone/platform/wayland/wayland_connection.h
+++ b/ui/ozone/platform/wayland/wayland_connection.h
@@ -82,45 +82,47 @@
   // Schedules a flush of the Wayland connection.
   void ScheduleFlush();
 
-  wl_display* display() { return display_.get(); }
-  wl_compositor* compositor() { return compositor_.get(); }
-  wl_subcompositor* subcompositor() { return subcompositor_.get(); }
-  wl_shm* shm() { return shm_.get(); }
+  wl_display* display() const { return display_.get(); }
+  wl_compositor* compositor() const { return compositor_.get(); }
+  wl_subcompositor* subcompositor() const { return subcompositor_.get(); }
+  wl_shm* shm() const { return shm_.get(); }
   xdg_shell* shell() const { return shell_.get(); }
   zxdg_shell_v6* shell_v6() const { return shell_v6_.get(); }
-  wl_seat* seat() { return seat_.get(); }
-  wl_data_device* data_device() { return data_device_->data_device(); }
+  wl_seat* seat() const { return seat_.get(); }
+  wl_data_device* data_device() const { return data_device_->data_device(); }
   wp_presentation* presentation() const { return presentation_.get(); }
-  zwp_text_input_manager_v1* text_input_manager_v1() {
+  zwp_text_input_manager_v1* text_input_manager_v1() const {
     return text_input_manager_v1_.get();
   }
 
-  WaylandWindow* GetWindow(gfx::AcceleratedWidget widget);
-  WaylandWindow* GetWindowWithLargestBounds();
-  WaylandWindow* GetCurrentFocusedWindow();
-  WaylandWindow* GetCurrentKeyboardFocusedWindow();
+  WaylandWindow* GetWindow(gfx::AcceleratedWidget widget) const;
+  WaylandWindow* GetWindowWithLargestBounds() const;
+  WaylandWindow* GetCurrentFocusedWindow() const;
+  WaylandWindow* GetCurrentKeyboardFocusedWindow() const;
   void AddWindow(gfx::AcceleratedWidget widget, WaylandWindow* window);
   void RemoveWindow(gfx::AcceleratedWidget widget);
 
   void set_serial(uint32_t serial) { serial_ = serial; }
-  uint32_t serial() { return serial_; }
+  uint32_t serial() const { return serial_; }
 
   void SetCursorBitmap(const std::vector<SkBitmap>& bitmaps,
                        const gfx::Point& location);
 
-  int GetKeyboardModifiers();
+  int GetKeyboardModifiers() const;
 
   // Returns the current pointer, which may be null.
-  WaylandPointer* pointer() { return pointer_.get(); }
+  WaylandPointer* pointer() const { return pointer_.get(); }
 
-  WaylandDataSource* drag_data_source() { return drag_data_source_.get(); }
+  WaylandDataSource* drag_data_source() const {
+    return drag_data_source_.get();
+  }
 
   WaylandOutputManager* wayland_output_manager() const {
     return wayland_output_manager_.get();
   }
 
   // Returns the cursor position, which may be null.
-  WaylandCursorPosition* wayland_cursor_position() {
+  WaylandCursorPosition* wayland_cursor_position() const {
     return wayland_cursor_position_.get();
   }
 
diff --git a/ui/views/accessibility/view_accessibility.cc b/ui/views/accessibility/view_accessibility.cc
index bd82fee..a380c61f 100644
--- a/ui/views/accessibility/view_accessibility.cc
+++ b/ui/views/accessibility/view_accessibility.cc
@@ -164,8 +164,7 @@
   }
 
   if (!data->HasStringAttribute(ax::mojom::StringAttribute::kDescription)) {
-    base::string16 tooltip;
-    view_->GetTooltipText(gfx::Point(), &tooltip);
+    base::string16 tooltip = view_->GetTooltipText(gfx::Point());
     // Some screen readers announce the accessible description right after the
     // accessible name. Only use the tooltip as the accessible description if
     // it's different from the name, otherwise users might be puzzled as to why
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.mm b/ui/views/cocoa/bridged_native_widget_host_impl.mm
index 291c8bb..6c09a27 100644
--- a/ui/views/cocoa/bridged_native_widget_host_impl.mm
+++ b/ui/views/cocoa/bridged_native_widget_host_impl.mm
@@ -883,8 +883,7 @@
     gfx::Point view_point = location_in_content;
     views::View::ConvertPointToScreen(root_view_, &view_point);
     views::View::ConvertPointFromScreen(view, &view_point);
-    if (!view->GetTooltipText(view_point, new_tooltip_text))
-      DCHECK(new_tooltip_text->empty());
+    *new_tooltip_text = view->GetTooltipText(view_point);
   }
   return true;
 }
diff --git a/ui/views/controls/button/button.cc b/ui/views/controls/button/button.cc
index 50fb844..07fa1cb1 100644
--- a/ui/views/controls/button/button.cc
+++ b/ui/views/controls/button/button.cc
@@ -384,13 +384,8 @@
   return GetKeyClickActionForEvent(event) != KeyClickAction::CLICK_NONE;
 }
 
-bool Button::GetTooltipText(const gfx::Point& p,
-                            base::string16* tooltip) const {
-  if (tooltip_text_.empty())
-    return false;
-
-  *tooltip = tooltip_text_;
-  return true;
+base::string16 Button::GetTooltipText(const gfx::Point& p) const {
+  return tooltip_text_;
 }
 
 void Button::ShowContextMenu(const gfx::Point& p,
diff --git a/ui/views/controls/button/button.h b/ui/views/controls/button/button.h
index 6cdedf4..71d2e776 100644
--- a/ui/views/controls/button/button.h
+++ b/ui/views/controls/button/button.h
@@ -173,8 +173,7 @@
   void OnGestureEvent(ui::GestureEvent* event) override;
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
   bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
   void ShowContextMenu(const gfx::Point& p,
                        ui::MenuSourceType source_type) override;
   void OnDragDone() override;
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc
index ca6b7a78..c366f55 100644
--- a/ui/views/controls/button/image_button.cc
+++ b/ui/views/controls/button/image_button.cc
@@ -279,20 +279,15 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ToggleImageButton, View overrides:
 
-bool ToggleImageButton::GetTooltipText(const gfx::Point& p,
-                                       base::string16* tooltip) const {
-  if (!toggled_ || toggled_tooltip_text_.empty())
-    return Button::GetTooltipText(p, tooltip);
-
-  *tooltip = toggled_tooltip_text_;
-  return true;
+base::string16 ToggleImageButton::GetTooltipText(const gfx::Point& p) const {
+  return (!toggled_ || toggled_tooltip_text_.empty())
+             ? Button::GetTooltipText(p)
+             : toggled_tooltip_text_;
 }
 
 void ToggleImageButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   ImageButton::GetAccessibleNodeData(node_data);
-  base::string16 name;
-  GetTooltipText(gfx::Point(), &name);
-  node_data->SetName(name);
+  node_data->SetName(GetTooltipText(gfx::Point()));
 
   // Use the visual pressed image as a cue for making this control into an
   // accessible toggle button.
diff --git a/ui/views/controls/button/image_button.h b/ui/views/controls/button/image_button.h
index 6e5b0cb..be4b081 100644
--- a/ui/views/controls/button/image_button.h
+++ b/ui/views/controls/button/image_button.h
@@ -157,8 +157,7 @@
   void SetImage(ButtonState state, const gfx::ImageSkia& image) override;
 
   // Overridden from View:
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
   bool toggled_for_testing() const;
diff --git a/ui/views/controls/button/label_button_unittest.cc b/ui/views/controls/button/label_button_unittest.cc
index af7f28d..344cadf 100644
--- a/ui/views/controls/button/label_button_unittest.cc
+++ b/ui/views/controls/button/label_button_unittest.cc
@@ -208,10 +208,7 @@
   EXPECT_EQ(label_text, accessible_node_data.GetString16Attribute(
                             ax::mojom::StringAttribute::kName));
   EXPECT_EQ(label_text, button_->GetText());
-
-  base::string16 tooltip;
-  EXPECT_TRUE(button_->GetTooltipText(gfx::Point(), &tooltip));
-  EXPECT_EQ(tooltip_text, tooltip);
+  EXPECT_EQ(tooltip_text, button_->GetTooltipText(gfx::Point()));
 }
 
 // Test View::GetAccessibleNodeData() for default buttons.
diff --git a/ui/views/controls/image_view_base.cc b/ui/views/controls/image_view_base.cc
index 9c15144..0a7d593 100644
--- a/ui/views/controls/image_view_base.cc
+++ b/ui/views/controls/image_view_base.cc
@@ -67,13 +67,8 @@
   return accessible_name_.empty() ? tooltip_text_ : accessible_name_;
 }
 
-bool ImageViewBase::GetTooltipText(const gfx::Point& p,
-                                   base::string16* tooltip) const {
-  if (tooltip_text_.empty())
-    return false;
-
-  *tooltip = tooltip_text();
-  return true;
+base::string16 ImageViewBase::GetTooltipText(const gfx::Point& p) const {
+  return tooltip_text();
 }
 
 gfx::Size ImageViewBase::CalculatePreferredSize() const {
diff --git a/ui/views/controls/image_view_base.h b/ui/views/controls/image_view_base.h
index 8046584d..d94c62448 100644
--- a/ui/views/controls/image_view_base.h
+++ b/ui/views/controls/image_view_base.h
@@ -53,8 +53,7 @@
   void OnPaint(gfx::Canvas* canvas) override = 0;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   const char* GetClassName() const override = 0;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
   gfx::Size CalculatePreferredSize() const override;
   views::PaintInfo::ScaleType GetPaintScaleType() const override;
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc
index fe1328c..0d1c15c 100644
--- a/ui/views/controls/label.cc
+++ b/ui/views/controls/label.cc
@@ -398,21 +398,16 @@
   node_data->SetName(full_text_->GetDisplayText());
 }
 
-bool Label::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const {
-  if (!handles_tooltips_)
-    return false;
+base::string16 Label::GetTooltipText(const gfx::Point& p) const {
+  if (handles_tooltips_) {
+    if (!tooltip_text_.empty())
+      return tooltip_text_;
 
-  if (!tooltip_text_.empty()) {
-    tooltip->assign(tooltip_text_);
-    return true;
+    if (ShouldShowDefaultTooltip())
+      return full_text_->GetDisplayText();
   }
 
-  if (ShouldShowDefaultTooltip()) {
-    tooltip->assign(full_text_->GetDisplayText());
-    return true;
-  }
-
-  return false;
+  return base::string16();
 }
 
 std::unique_ptr<gfx::RenderText> Label::CreateRenderText() const {
diff --git a/ui/views/controls/label.h b/ui/views/controls/label.h
index cad3c4e..6f01e96 100644
--- a/ui/views/controls/label.h
+++ b/ui/views/controls/label.h
@@ -223,8 +223,7 @@
   bool CanProcessEventsWithinSubtree() const override;
   WordLookupClient* GetWordLookupClient() override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
 
  protected:
   // Create a single RenderText instance to actually be painted.
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc
index f6b1ccc..b89f759 100644
--- a/ui/views/controls/label_unittest.cc
+++ b/ui/views/controls/label_unittest.cc
@@ -452,77 +452,71 @@
 
   // Initially, label has no bounds, its text does not fit, and therefore its
   // text should be returned as the tooltip text.
-  base::string16 tooltip;
-  EXPECT_TRUE(label()->GetTooltipText(gfx::Point(), &tooltip));
-  EXPECT_EQ(label()->text(), tooltip);
+  EXPECT_EQ(label()->text(), label()->GetTooltipText(gfx::Point()));
 
   // While tooltip handling is disabled, GetTooltipText() should fail.
   label()->SetHandlesTooltips(false);
-  EXPECT_FALSE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_TRUE(label()->GetTooltipText(gfx::Point()).empty());
   label()->SetHandlesTooltips(true);
 
   // When set, custom tooltip text should be returned instead of the label's
   // text.
   base::string16 tooltip_text(ASCIIToUTF16("The tooltip!"));
   label()->SetTooltipText(tooltip_text);
-  EXPECT_TRUE(label()->GetTooltipText(gfx::Point(), &tooltip));
-  EXPECT_EQ(tooltip_text, tooltip);
+  EXPECT_EQ(tooltip_text, label()->GetTooltipText(gfx::Point()));
 
   // While tooltip handling is disabled, GetTooltipText() should fail.
   label()->SetHandlesTooltips(false);
-  EXPECT_FALSE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_TRUE(label()->GetTooltipText(gfx::Point()).empty());
   label()->SetHandlesTooltips(true);
 
   // When the tooltip text is set to an empty string, the original behavior is
   // restored.
   label()->SetTooltipText(base::string16());
-  EXPECT_TRUE(label()->GetTooltipText(gfx::Point(), &tooltip));
-  EXPECT_EQ(label()->text(), tooltip);
+  EXPECT_EQ(label()->text(), label()->GetTooltipText(gfx::Point()));
 
   // While tooltip handling is disabled, GetTooltipText() should fail.
   label()->SetHandlesTooltips(false);
-  EXPECT_FALSE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_TRUE(label()->GetTooltipText(gfx::Point()).empty());
   label()->SetHandlesTooltips(true);
 
   // Make the label big enough to hold the text
   // and expect there to be no tooltip.
   label()->SetBounds(0, 0, 1000, 40);
-  EXPECT_FALSE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_TRUE(label()->GetTooltipText(gfx::Point()).empty());
 
   // Shrinking the single-line label's height shouldn't trigger a tooltip.
   label()->SetBounds(0, 0, 1000, label()->GetPreferredSize().height() / 2);
-  EXPECT_FALSE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_TRUE(label()->GetTooltipText(gfx::Point()).empty());
 
   // Verify that explicitly set tooltip text is shown, regardless of size.
   label()->SetTooltipText(tooltip_text);
-  EXPECT_TRUE(label()->GetTooltipText(gfx::Point(), &tooltip));
-  EXPECT_EQ(tooltip_text, tooltip);
+  EXPECT_EQ(tooltip_text, label()->GetTooltipText(gfx::Point()));
   // Clear out the explicitly set tooltip text.
   label()->SetTooltipText(base::string16());
 
   // Shrink the bounds and the tooltip should come back.
   label()->SetBounds(0, 0, 10, 10);
-  EXPECT_TRUE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_FALSE(label()->GetTooltipText(gfx::Point()).empty());
 
   // Make the label obscured and there is no tooltip.
   label()->SetObscured(true);
-  EXPECT_FALSE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_TRUE(label()->GetTooltipText(gfx::Point()).empty());
 
   // Obscuring the text shouldn't permanently clobber the tooltip.
   label()->SetObscured(false);
-  EXPECT_TRUE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_FALSE(label()->GetTooltipText(gfx::Point()).empty());
 
   // Making the label multiline shouldn't eliminate the tooltip.
   label()->SetMultiLine(true);
-  EXPECT_TRUE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_FALSE(label()->GetTooltipText(gfx::Point()).empty());
   // Expanding the multiline label bounds should eliminate the tooltip.
   label()->SetBounds(0, 0, 1000, 1000);
-  EXPECT_FALSE(label()->GetTooltipText(gfx::Point(), &tooltip));
+  EXPECT_TRUE(label()->GetTooltipText(gfx::Point()).empty());
 
   // Verify that setting the tooltip still shows it.
   label()->SetTooltipText(tooltip_text);
-  EXPECT_TRUE(label()->GetTooltipText(gfx::Point(), &tooltip));
-  EXPECT_EQ(tooltip_text, tooltip);
+  EXPECT_EQ(tooltip_text, label()->GetTooltipText(gfx::Point()));
   // Clear out the tooltip.
   label()->SetTooltipText(base::string16());
 }
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index 3a78590..2f349a2 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -59,10 +59,9 @@
     SetEnabled(false);
   }
 
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override {
+  base::string16 GetTooltipText(const gfx::Point& p) const override {
     // Empty menu items shouldn't have a tooltip.
-    return false;
+    return base::string16();
   }
 
  private:
@@ -128,20 +127,18 @@
   PreferredSizeChanged();
 }
 
-bool MenuItemView::GetTooltipText(const gfx::Point& p,
-                                  base::string16* tooltip) const {
-  *tooltip = tooltip_;
-  if (!tooltip->empty())
-    return true;
+base::string16 MenuItemView::GetTooltipText(const gfx::Point& p) const {
+  if (!tooltip_.empty())
+    return tooltip_;
 
   if (GetType() == SEPARATOR)
-    return false;
+    return base::string16();
 
   const MenuController* controller = GetMenuController();
   if (!controller || controller->exit_type() != MenuController::EXIT_NONE) {
     // Either the menu has been closed or we're in the process of closing the
     // menu. Don't attempt to query the delegate as it may no longer be valid.
-    return false;
+    return base::string16();
   }
 
   const MenuItemView* root_menu_item = GetRootMenuItem();
@@ -149,15 +146,14 @@
     // TODO(sky): if |canceled_| is true, controller->exit_type() should be
     // something other than EXIT_NONE, but crash reports seem to indicate
     // otherwise. Figure out why this is needed.
-    return false;
+    return base::string16();
   }
 
   const MenuDelegate* delegate = GetDelegate();
   CHECK(delegate);
   gfx::Point location(p);
   ConvertPointToScreen(this, &location);
-  *tooltip = delegate->GetTooltipText(command_, location);
-  return !tooltip->empty();
+  return delegate->GetTooltipText(command_, location);
 }
 
 void MenuItemView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h
index 6ef514d4..57f0185 100644
--- a/ui/views/controls/menu/menu_item_view.h
+++ b/ui/views/controls/menu/menu_item_view.h
@@ -132,8 +132,7 @@
   explicit MenuItemView(MenuDelegate* delegate);
 
   // Overridden from View:
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   bool HandleAccessibleAction(const ui::AXActionData& action_data) override;
 
diff --git a/ui/views/controls/styled_label_unittest.cc b/ui/views/controls/styled_label_unittest.cc
index 90dc1c1..9e70a550 100644
--- a/ui/views/controls/styled_label_unittest.cc
+++ b/ui/views/controls/styled_label_unittest.cc
@@ -477,12 +477,10 @@
             styled()->child_at(3)->x());
   EXPECT_EQ(0, styled()->child_at(4)->x());
 
-  base::string16 tooltip;
-  EXPECT_TRUE(
-      styled()->child_at(1)->GetTooltipText(gfx::Point(1, 1), &tooltip));
+  base::string16 tooltip =
+      styled()->child_at(1)->GetTooltipText(gfx::Point(1, 1));
   EXPECT_EQ(ASCIIToUTF16("tooltip"), tooltip);
-  EXPECT_TRUE(
-      styled()->child_at(2)->GetTooltipText(gfx::Point(1, 1), &tooltip));
+  tooltip = styled()->child_at(2)->GetTooltipText(gfx::Point(1, 1));
   EXPECT_EQ(ASCIIToUTF16("tooltip"), tooltip);
 }
 
diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view.cc
index 514a6062..0826696f 100644
--- a/ui/views/controls/table/table_view.cc
+++ b/ui/views/controls/table/table_view.cc
@@ -550,9 +550,10 @@
   SetSelectionModel(std::move(new_model));
 }
 
-bool TableView::GetTooltipText(const gfx::Point& p,
-                               base::string16* tooltip) const {
-  return GetTooltipImpl(p, tooltip, NULL);
+base::string16 TableView::GetTooltipText(const gfx::Point& p) const {
+  base::string16 tooltip;
+  GetTooltipImpl(p, &tooltip, NULL);
+  return tooltip;
 }
 
 bool TableView::GetTooltipTextOrigin(const gfx::Point& p,
diff --git a/ui/views/controls/table/table_view.h b/ui/views/controls/table/table_view.h
index c904e57..4dcd8ca 100644
--- a/ui/views/controls/table/table_view.h
+++ b/ui/views/controls/table/table_view.h
@@ -206,8 +206,7 @@
   bool OnKeyPressed(const ui::KeyEvent& event) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
   bool GetTooltipTextOrigin(const gfx::Point& p,
                             gfx::Point* loc) const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
diff --git a/ui/views/corewm/tooltip_controller_test_helper.cc b/ui/views/corewm/tooltip_controller_test_helper.cc
index 45d940f..626824d 100644
--- a/ui/views/corewm/tooltip_controller_test_helper.cc
+++ b/ui/views/corewm/tooltip_controller_test_helper.cc
@@ -51,10 +51,8 @@
 TooltipTestView::~TooltipTestView() {
 }
 
-bool TooltipTestView::GetTooltipText(const gfx::Point& p,
-                                     base::string16* tooltip) const {
-  *tooltip = tooltip_text_;
-  return true;
+base::string16 TooltipTestView::GetTooltipText(const gfx::Point& p) const {
+  return tooltip_text_;
 }
 
 }  // namespace test
diff --git a/ui/views/corewm/tooltip_controller_test_helper.h b/ui/views/corewm/tooltip_controller_test_helper.h
index 9a710f0..aa61d12 100644
--- a/ui/views/corewm/tooltip_controller_test_helper.h
+++ b/ui/views/corewm/tooltip_controller_test_helper.h
@@ -56,8 +56,7 @@
   }
 
   // Overridden from views::View
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
+  base::string16 GetTooltipText(const gfx::Point& p) const override;
 
  private:
   base::string16 tooltip_text_;
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 3c7de1f..6f8ef16 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -1251,8 +1251,8 @@
 
 // Tooltips --------------------------------------------------------------------
 
-bool View::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const {
-  return false;
+base::string16 View::GetTooltipText(const gfx::Point& p) const {
+  return base::string16();
 }
 
 bool View::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* loc) const {
diff --git a/ui/views/view.h b/ui/views/view.h
index b0f106e2..63acf6a2 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -1018,13 +1018,11 @@
   // Tooltips ------------------------------------------------------------------
 
   // Gets the tooltip for this View. If the View does not have a tooltip,
-  // return false. If the View does have a tooltip, copy the tooltip into
-  // the supplied string and return true.
+  // the returned value should be empty.
   // Any time the tooltip text that a View is displaying changes, it must
   // invoke TooltipTextChanged.
   // |p| provides the coordinates of the mouse (relative to this view).
-  virtual bool GetTooltipText(const gfx::Point& p,
-                              base::string16* tooltip) const;
+  virtual base::string16 GetTooltipText(const gfx::Point& p) const;
 
   // Returns the location (relative to this View) for the text on the tooltip
   // to display. If false is returned (the default), the tooltip is placed at
diff --git a/ui/views/widget/desktop_aura/desktop_capture_client.cc b/ui/views/widget/desktop_aura/desktop_capture_client.cc
index 38447dc9..50d80cc 100644
--- a/ui/views/widget/desktop_aura/desktop_capture_client.cc
+++ b/ui/views/widget/desktop_aura/desktop_capture_client.cc
@@ -13,30 +13,38 @@
 
 namespace views {
 
+namespace {
+
+// This comparator facilitates constructing DesktopCaptureClient WeakPtr sets.
+bool CompareWeakPtrs(const base::WeakPtr<DesktopCaptureClient>& lhs,
+                     const base::WeakPtr<DesktopCaptureClient>& rhs) {
+  return lhs.get() < rhs.get();
+}
+
+}  // namespace
+
 // static
-DesktopCaptureClient::CaptureClients* DesktopCaptureClient::capture_clients_ =
-    nullptr;
+DesktopCaptureClient::ClientSet* DesktopCaptureClient::clients_ = nullptr;
 
 // static
 aura::Window* DesktopCaptureClient::GetCaptureWindowGlobal() {
-  for (auto* client : *capture_clients_) {
-    if (client->capture_window_)
+  for (const auto& client : *clients_) {
+    if (client && client->capture_window_)
       return client->capture_window_;
   }
   return nullptr;
 }
 
-DesktopCaptureClient::DesktopCaptureClient(aura::Window* root)
-    : root_(root), capture_window_(nullptr) {
-  if (!capture_clients_)
-    capture_clients_ = new CaptureClients;
-  capture_clients_->insert(this);
+DesktopCaptureClient::DesktopCaptureClient(aura::Window* root) : root_(root) {
+  if (!clients_)
+    clients_ = new ClientSet(&CompareWeakPtrs);
+  clients_->insert(weak_factory_.GetWeakPtr());
   aura::client::SetCaptureClient(root, this);
 }
 
 DesktopCaptureClient::~DesktopCaptureClient() {
   aura::client::SetCaptureClient(root_, nullptr);
-  capture_clients_->erase(this);
+  base::EraseIf(*clients_, [this](const auto& c) { return c.get() == this; });
 }
 
 void DesktopCaptureClient::SetCapture(aura::Window* new_capture_window) {
@@ -77,12 +85,12 @@
     delegate->SetNativeCapture();
 
     // Notify the other roots that we got capture. This is important so that
-    // they reset state.
-    CaptureClients capture_clients(*capture_clients_);
-    for (auto i = capture_clients.begin(); i != capture_clients.end(); ++i) {
-      if (*i != this) {
+    // they reset state. Clients may be destroyed during the loop.
+    ClientSet clients(*clients_);
+    for (auto client : clients) {
+      if (client && client.get() != this) {
         aura::client::CaptureDelegate* delegate =
-            (*i)->root_->GetHost()->dispatcher();
+            client->root_->GetHost()->dispatcher();
         delegate->OnOtherRootGotCapture();
       }
     }
@@ -93,9 +101,8 @@
 }
 
 void DesktopCaptureClient::ReleaseCapture(aura::Window* window) {
-  if (capture_window_ != window)
-    return;
-  SetCapture(nullptr);
+  if (capture_window_ == window)
+    SetCapture(nullptr);
 }
 
 aura::Window* DesktopCaptureClient::GetCaptureWindow() {
diff --git a/ui/views/widget/desktop_aura/desktop_capture_client.h b/ui/views/widget/desktop_aura/desktop_capture_client.h
index 8c0811bc..647e6c0 100644
--- a/ui/views/widget/desktop_aura/desktop_capture_client.h
+++ b/ui/views/widget/desktop_aura/desktop_capture_client.h
@@ -50,16 +50,20 @@
   void RemoveObserver(aura::client::CaptureClientObserver* observer) override;
 
  private:
-  typedef std::set<DesktopCaptureClient*> CaptureClients;
+  using Comparator = bool (*)(const base::WeakPtr<DesktopCaptureClient>&,
+                              const base::WeakPtr<DesktopCaptureClient>&);
+  using ClientSet = std::set<base::WeakPtr<DesktopCaptureClient>, Comparator>;
 
   aura::Window* root_;
-  aura::Window* capture_window_;
+  aura::Window* capture_window_ = nullptr;
 
-  // Set of DesktopCaptureClients.
-  static CaptureClients* capture_clients_;
+  // The global set of DesktopCaptureClients.
+  static ClientSet* clients_;
 
   base::ObserverList<aura::client::CaptureClientObserver>::Unchecked observers_;
 
+  base::WeakPtrFactory<DesktopCaptureClient> weak_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(DesktopCaptureClient);
 };
 
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
index e961f2f..4a1542f 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
@@ -90,7 +90,7 @@
   X11MoveLoopDelegate* delegate_;
 
   // Ends the move loop.
-  base::Closure quit_closure_;
+  base::OnceClosure quit_closure_;
 
   bool is_running_;
 };
@@ -244,7 +244,7 @@
   if (is_running_) {
     delegate_->OnMoveLoopEnded();
     is_running_ = false;
-    quit_closure_.Run();
+    std::move(quit_closure_).Run();
   }
 }
 
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm
index 2d09c6f..e63b5ed 100644
--- a/ui/views/widget/native_widget_mac_unittest.mm
+++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -7,6 +7,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/bind.h"
+#include "base/callback.h"
 #import "base/mac/foundation_util.h"
 #include "base/mac/mac_util.h"
 #import "base/mac/scoped_nsautorelease_pool.h"
@@ -279,10 +280,8 @@
       : tooltip_(tooltip), tooltip_handler_(tooltip_handler) {}
 
   // View:
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override {
-    *tooltip = tooltip_;
-    return true;
+  base::string16 GetTooltipText(const gfx::Point& p) const override {
+    return tooltip_;
   }
 
   View* GetTooltipHandlerForPoint(const gfx::Point& point) override {
@@ -456,10 +455,11 @@
 
   // Wait and check that child is really visible.
   // TODO(kirr): remove the fixed delay.
+  base::RunLoop run_loop;
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
+      FROM_HERE, run_loop.QuitWhenIdleClosure(),
       base::TimeDelta::FromSeconds(2));
-  base::RunLoop().Run();
+  run_loop.Run();
 
   EXPECT_FALSE(widget->IsMinimized());
   EXPECT_TRUE(widget->IsVisible());
diff --git a/ui/views/widget/tooltip_manager_aura.cc b/ui/views/widget/tooltip_manager_aura.cc
index dde96c1..161a8db 100644
--- a/ui/views/widget/tooltip_manager_aura.cc
+++ b/ui/views/widget/tooltip_manager_aura.cc
@@ -127,11 +127,7 @@
   if (target) {
     gfx::Point view_point = point;
     View::ConvertPointFromWidget(target, &view_point);
-    base::string16 new_tooltip_text;
-    if (!target->GetTooltipText(view_point, &new_tooltip_text))
-      tooltip_text_.clear();
-    else
-      tooltip_text_ = new_tooltip_text;
+    tooltip_text_ = target->GetTooltipText(view_point);
   } else {
     tooltip_text_.clear();
   }