diff --git a/DEPS b/DEPS
index 3bfe9800..9aa8ddf 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,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': 'cf79ee5626ddf9c5fb5315a560d10c25f4270c6f',
+  'skia_revision': 'fc4ee229a653d0e9d71f828e513c9d458c1eab57',
   # 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': '3921afc2b86b11cdcddadfa8098278caf3b0dfa8',
+  'v8_revision': '1115d8724ce832a77e1a85e0ba3fbee527ea7eb0',
   # 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.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '57f228d7527594de55951fa05e6082ba62382c57',
+  'pdfium_revision': '21dd189fe50d297dd1224c06319e166c1ac6bae2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,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': 'b63abe05c65413bfc03a8ff398d66d0846ffb644',
+  'catapult_revision': 'ebf00ecf2e8397f7774dcd90c73f40fcba8097d5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index a63bd08..945df0d 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -180,8 +180,6 @@
   }
 }
 
-webview_license_path = "$target_gen_dir/webview_licenses.notice"
-
 android_assets("pak_file_assets") {
   sources = [
     "$target_gen_dir/chrome_100_percent.pak",
@@ -222,28 +220,10 @@
 }
 
 android_assets("license_assets") {
-  sources = [
-    webview_license_path,
-  ]
+  renaming_sources = [ "$root_gen_dir/components/resources/about_credits.html" ]
+  renaming_destinations = [ "webview_licenses.notice" ]
   deps = [
-    ":generate_webview_license_notice",
-  ]
-}
-
-action("generate_webview_license_notice") {
-  script = "tools/webview_licenses.py"
-  depfile = "$target_gen_dir/$target_name.d"
-  inputs = [
-    "tools/licenses_notice.tmpl",
-  ]
-  outputs = [
-    webview_license_path,
-  ]
-  args = [
-    "notice",
-    rebase_path(webview_license_path, root_build_dir),
-    "--depfile",
-    rebase_path(depfile, root_build_dir),
+    "//components/resources:about_credits",
   ]
 }
 
diff --git a/android_webview/browser/aw_autofill_client.cc b/android_webview/browser/aw_autofill_client.cc
index 8920c51..2a0dd210 100644
--- a/android_webview/browser/aw_autofill_client.cc
+++ b/android_webview/browser/aw_autofill_client.cc
@@ -217,6 +217,10 @@
 
 void AwAutofillClient::ShowHttpNotSecureExplanation() {}
 
+bool AwAutofillClient::IsAutofillSupported() {
+  return true;
+}
+
 void AwAutofillClient::Dismissed(JNIEnv* env,
                                  const JavaParamRef<jobject>& obj) {
   anchor_view_.Reset();
diff --git a/android_webview/browser/aw_autofill_client.h b/android_webview/browser/aw_autofill_client.h
index cfa3770..70cd6f16 100644
--- a/android_webview/browser/aw_autofill_client.h
+++ b/android_webview/browser/aw_autofill_client.h
@@ -107,6 +107,7 @@
   bool ShouldShowSigninPromo() override;
   void StartSigninFlow() override;
   void ShowHttpNotSecureExplanation() override;
+  bool IsAutofillSupported() override;
 
   void Dismissed(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
   void SuggestionSelected(JNIEnv* env,
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index 03b8edff..ea499630 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -29,6 +29,7 @@
 #include "components/prefs/in_memory_pref_store.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/pref_service_factory.h"
+#include "components/safe_browsing/common/safe_browsing_prefs.h"
 #include "components/safe_browsing/triggers/trigger_manager.h"
 #include "components/url_formatter/url_fixer.h"
 #include "components/user_prefs/user_prefs.h"
@@ -200,8 +201,8 @@
   web_restriction_provider_->SetAuthority(
       user_pref_service_->GetString(prefs::kWebRestrictionsAuthority));
 
-  safe_browsing_ui_manager_ =
-      new AwSafeBrowsingUIManager(GetAwURLRequestContext());
+  safe_browsing_ui_manager_ = new AwSafeBrowsingUIManager(
+      GetAwURLRequestContext(), user_pref_service_.get());
   safe_browsing_db_manager_ =
       new safe_browsing::RemoteSafeBrowsingDatabaseManager();
   safe_browsing_trigger_manager_ =
@@ -251,6 +252,7 @@
                                     std::string());
 
   metrics::MetricsService::RegisterPrefs(pref_registry);
+  safe_browsing::RegisterProfilePrefs(pref_registry);
 
   PrefServiceFactory pref_service_factory;
   pref_service_factory.set_user_prefs(make_scoped_refptr(
diff --git a/android_webview/browser/aw_safe_browsing_blocking_page.cc b/android_webview/browser/aw_safe_browsing_blocking_page.cc
index c45f6bd5..391eb21 100644
--- a/android_webview/browser/aw_safe_browsing_blocking_page.cc
+++ b/android_webview/browser/aw_safe_browsing_blocking_page.cc
@@ -7,6 +7,7 @@
 #include "android_webview/browser/aw_browser_context.h"
 #include "android_webview/browser/aw_safe_browsing_ui_manager.h"
 #include "android_webview/browser/net/aw_url_request_context_getter.h"
+#include "components/prefs/pref_service.h"
 #include "components/safe_browsing/browser/threat_details.h"
 #include "components/safe_browsing/triggers/trigger_manager.h"
 #include "components/security_interstitials/content/security_interstitial_controller_client.h"
@@ -71,7 +72,7 @@
 void AwSafeBrowsingBlockingPage::ShowBlockingPage(
     AwSafeBrowsingUIManager* ui_manager,
     const UnsafeResource& unsafe_resource,
-    bool extended_reporting_allowed) {
+    PrefService* pref_service) {
   DVLOG(1) << __func__ << " " << unsafe_resource.url.spec();
   WebContents* web_contents = unsafe_resource.web_contents_getter.Run();
 
@@ -89,11 +90,13 @@
     const UnsafeResourceList unsafe_resources{unsafe_resource};
     BaseSafeBrowsingErrorUI::SBErrorDisplayOptions display_options =
         BaseSafeBrowsingErrorUI::SBErrorDisplayOptions(
-            IsMainPageLoadBlocked(unsafe_resources), extended_reporting_allowed,
-            false,                    // is_off_the_record
-            false,                    // is_extended_reporting
-            false,                    // is_scout
-            false,                    // kSafeBrowsingProceedAnywayDisabled
+            IsMainPageLoadBlocked(unsafe_resources),
+            safe_browsing::IsExtendedReportingOptInAllowed(*pref_service),
+            false,  // is_off_the_record
+            safe_browsing::IsExtendedReportingEnabled(*pref_service),
+            safe_browsing::IsScout(*pref_service),
+            pref_service->GetBoolean(
+                ::prefs::kSafeBrowsingProceedAnywayDisabled),
             false,                    // should_open_links_in_new_tab
             "cpn_safe_browsing_wv");  // help_center_article_link
 
@@ -103,7 +106,8 @@
     AwSafeBrowsingBlockingPage* blocking_page = new AwSafeBrowsingBlockingPage(
         ui_manager, web_contents, entry ? entry->GetURL() : GURL(),
         unsafe_resources,
-        CreateControllerClient(web_contents, unsafe_resources, ui_manager),
+        CreateControllerClient(web_contents, unsafe_resources, ui_manager,
+                               pref_service),
         display_options, errorType);
     blocking_page->Show();
   }
diff --git a/android_webview/browser/aw_safe_browsing_blocking_page.h b/android_webview/browser/aw_safe_browsing_blocking_page.h
index 9084d1a..b65c192 100644
--- a/android_webview/browser/aw_safe_browsing_blocking_page.h
+++ b/android_webview/browser/aw_safe_browsing_blocking_page.h
@@ -8,6 +8,8 @@
 #include "components/safe_browsing/base_blocking_page.h"
 #include "components/security_interstitials/core/base_safe_browsing_error_ui.h"
 
+class PrefService;
+
 namespace security_interstitials {
 struct UnsafeResource;
 }  // namespace security_interstitials
@@ -22,7 +24,7 @@
 
   static void ShowBlockingPage(AwSafeBrowsingUIManager* ui_manager,
                                const UnsafeResource& unsafe_resource,
-                               bool extended_reporting_allowed);
+                               PrefService* pref_service);
 
  protected:
   // Used to specify which BaseSafeBrowsingErrorUI to instantiate, and
diff --git a/android_webview/browser/aw_safe_browsing_resource_throttle.cc b/android_webview/browser/aw_safe_browsing_resource_throttle.cc
index 4a30851..1f54c40 100644
--- a/android_webview/browser/aw_safe_browsing_resource_throttle.cc
+++ b/android_webview/browser/aw_safe_browsing_resource_throttle.cc
@@ -89,9 +89,9 @@
     SafeBrowsingAction action,
     bool reporting) {
   if (!reporting) {
-    AwSafeBrowsingUIManager* casted_ui_manager =
+    AwSafeBrowsingUIManager* aw_ui_manager =
         static_cast<AwSafeBrowsingUIManager*>(ui_manager.get());
-    casted_ui_manager->set_extended_reporting_allowed(false);
+    aw_ui_manager->SetExtendedReportingAllowed(false);
   }
   // TODO(ntfschr): fully handle reporting once we add support (crbug/688629)
   bool proceed;
diff --git a/android_webview/browser/aw_safe_browsing_ui_manager.cc b/android_webview/browser/aw_safe_browsing_ui_manager.cc
index 5346c56..ca87019 100644
--- a/android_webview/browser/aw_safe_browsing_ui_manager.cc
+++ b/android_webview/browser/aw_safe_browsing_ui_manager.cc
@@ -9,6 +9,7 @@
 #include "android_webview/common/aw_paths.h"
 #include "base/command_line.h"
 #include "base/path_service.h"
+#include "components/prefs/pref_service.h"
 #include "components/safe_browsing/base_ping_manager.h"
 #include "components/safe_browsing/base_ui_manager.h"
 #include "components/safe_browsing/browser/safe_browsing_url_request_context_getter.h"
@@ -31,7 +32,9 @@
 namespace android_webview {
 
 AwSafeBrowsingUIManager::AwSafeBrowsingUIManager(
-    AwURLRequestContextGetter* browser_url_request_context_getter) {
+    AwURLRequestContextGetter* browser_url_request_context_getter,
+    PrefService* pref_service)
+    : pref_service_(pref_service) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // TODO(timvolodine): verify this is what we want regarding the directory.
@@ -65,8 +68,12 @@
 
 void AwSafeBrowsingUIManager::ShowBlockingPageForResource(
     const UnsafeResource& resource) {
-  AwSafeBrowsingBlockingPage::ShowBlockingPage(this, resource,
-                                               extended_reporting_allowed_);
+  AwSafeBrowsingBlockingPage::ShowBlockingPage(this, resource, pref_service_);
+}
+
+void AwSafeBrowsingUIManager::SetExtendedReportingAllowed(bool allowed) {
+  pref_service_->SetBoolean(::prefs::kSafeBrowsingExtendedReportingOptInAllowed,
+                            allowed);
 }
 
 int AwSafeBrowsingUIManager::GetErrorUiType(
diff --git a/android_webview/browser/aw_safe_browsing_ui_manager.h b/android_webview/browser/aw_safe_browsing_ui_manager.h
index 688ea3b..3bfeb06 100644
--- a/android_webview/browser/aw_safe_browsing_ui_manager.h
+++ b/android_webview/browser/aw_safe_browsing_ui_manager.h
@@ -12,6 +12,8 @@
 #include "components/safe_browsing/base_ui_manager.h"
 #include "content/public/browser/web_contents.h"
 
+class PrefService;
+
 namespace safe_browsing {
 class BasePingManager;
 class SafeBrowsingURLRequestContextGetter;
@@ -35,7 +37,8 @@
 
   // Construction needs to happen on the UI thread.
   explicit AwSafeBrowsingUIManager(
-      AwURLRequestContextGetter* browser_url_request_context_getter);
+      AwURLRequestContextGetter* browser_url_request_context_getter,
+      PrefService* pref_service);
 
   // Gets the correct ErrorUiType for the web contents
   int GetErrorUiType(const UnsafeResource& resource) const;
@@ -47,9 +50,7 @@
   // protocol buffer, so the service can send it over.
   void SendSerializedThreatDetails(const std::string& serialized) override;
 
-  void set_extended_reporting_allowed(bool allowed) {
-    extended_reporting_allowed_ = allowed;
-  }
+  void SetExtendedReportingAllowed(bool allowed);
 
  protected:
   ~AwSafeBrowsingUIManager() override;
@@ -65,7 +66,8 @@
   scoped_refptr<safe_browsing::SafeBrowsingURLRequestContextGetter>
       url_request_context_getter_;
 
-  bool extended_reporting_allowed_ = false;
+  // non-owning
+  PrefService* pref_service_;
 
   DISALLOW_COPY_AND_ASSIGN(AwSafeBrowsingUIManager);
 };
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
index db8d51d..4ff65e9 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
@@ -19,7 +19,7 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.SkipCommandLineParameterization;
 import org.chromium.content_public.browser.GestureStateListener;
 import org.chromium.net.test.util.TestWebServer;
 import org.chromium.ui.display.DisplayAndroid;
@@ -442,7 +442,7 @@
 
     @SmallTest
     @Feature({"AndroidWebView"})
-    @ParameterizedTest.Set  // crbug.com/616505
+    @SkipCommandLineParameterization // crbug.com/616505
     @RetryOnFailure
     public void testTouchScrollCanBeAlteredByUi() throws Throwable {
         final TestAwContentsClient contentsClient = new TestAwContentsClient();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientCallbackHelperTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientCallbackHelperTest.java
index 23a1c9a..2e562d1 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientCallbackHelperTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientCallbackHelperTest.java
@@ -16,7 +16,7 @@
 import org.chromium.android_webview.test.TestAwContentsClient.PictureListenerHelper;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.SkipCommandLineParameterization;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageStartedHelper;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
 
@@ -25,7 +25,7 @@
 /**
  * Test suite for AwContentsClientCallbackHelper.
  */
-@ParameterizedTest.Set  // These are unit tests. No need to repeat for multiprocess.
+@SkipCommandLineParameterization // These are unit tests. No need to repeat for multiprocess.
 public class AwContentsClientCallbackHelperTest extends AwTestBase {
     /**
      * Callback helper for OnLoadedResource.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
index 36a08c2..8c7658c 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
@@ -150,7 +150,7 @@
     /*
     @MediumTest
     @Feature({"AndroidWebView"})
-    @ParameterizedTest.Set  // crbug.com/616501
+    @SkipCommandLineParameterization  // crbug.com/616501
     */
     @DisabledTest(message = "crbug.com/618749")
     public void testOnShowAndHideCustomViewWithBackKey_video() throws Throwable {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java
index 1e8a2bc..cc54555 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java
@@ -14,7 +14,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.SkipCommandLineParameterization;
 
 import java.util.concurrent.TimeUnit;
 
@@ -56,12 +56,11 @@
         }
     }
 
-    @DisabledTest  // http://crbug.com/689292
+    @DisabledTest // http://crbug.com/689292
     @Feature({"AndroidWebView"})
     @SmallTest
-    @CommandLineFlags
-            .Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
-            @ParameterizedTest.Set
+    @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
+    @SkipCommandLineParameterization
     public void testOnRenderProcessCrash() throws Throwable {
         RenderProcessGoneTestAwContentsClient contentsClient =
                 new RenderProcessGoneTestAwContentsClient();
@@ -80,9 +79,8 @@
 
     @Feature({"AndroidWebView"})
     @SmallTest
-    @CommandLineFlags
-            .Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
-            @ParameterizedTest.Set
+    @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
+    @SkipCommandLineParameterization
     public void testOnRenderProcessKill() throws Throwable {
         RenderProcessGoneTestAwContentsClient contentsClient =
                 new RenderProcessGoneTestAwContentsClient();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
index e9a8012..ce37246 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -31,7 +31,7 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.SkipCommandLineParameterization;
 import org.chromium.content.browser.BindingManager;
 import org.chromium.content.browser.ChildProcessLauncherHelper;
 import org.chromium.content_public.common.ContentUrlConstants;
@@ -615,7 +615,7 @@
     @Feature({"AndroidWebView"})
     @SmallTest
     @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
-    @ParameterizedTest.Set
+    @SkipCommandLineParameterization
     public void testSandboxedRendererWorks() throws Throwable {
         MockBindingManager bindingManager = new MockBindingManager();
         ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager);
@@ -644,7 +644,7 @@
     @Feature({"AndroidWebView"})
     @SmallTest
     @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
-    @ParameterizedTest.Set
+    @SkipCommandLineParameterization
     public void testRendererPriorityStartsHigh() throws Throwable {
         MockBindingManager bindingManager = new MockBindingManager();
         ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager);
@@ -666,7 +666,7 @@
     @Feature({"AndroidWebView"})
     @SmallTest
     @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
-    @ParameterizedTest.Set
+    @SkipCommandLineParameterization
     public void testRendererPriorityLow() throws Throwable {
         MockBindingManager bindingManager = new MockBindingManager();
         ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager);
@@ -696,7 +696,7 @@
     @Feature({"AndroidWebView"})
     @SmallTest
     @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
-    @ParameterizedTest.Set
+    @SkipCommandLineParameterization
     public void testRendererPriorityManaged() throws Throwable {
         MockBindingManager bindingManager = new MockBindingManager();
         ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager);
@@ -729,7 +729,7 @@
     @SmallTest
     @UiThreadTest
     @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
-    @ParameterizedTest.Set
+    @SkipCommandLineParameterization
     public void testPauseDestroyResume() throws Throwable {
         AwContents awContents;
         awContents = createAwTestContainerView(mContentsClient).getAwContents();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java
index 691ed0a..aa6fb19 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java
@@ -8,7 +8,7 @@
 
 import org.chromium.android_webview.AwDebug;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.SkipCommandLineParameterization;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -19,7 +19,7 @@
  * A test suite for AwDebug class.
  */
 // Only works in single-process mode, crbug.com/568825.
-@ParameterizedTest.Set
+@SkipCommandLineParameterization
 public class AwDebugTest extends AwTestBase {
     private static final String TAG = "cr_AwDebugTest";
     private static final String WHITELISTED_DEBUG_KEY = "AW_WHITELISTED_DEBUG_KEY";
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
index 92ade85..f67a272 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
@@ -27,11 +27,9 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.BaseActivityInstrumentationTestCase;
 import org.chromium.base.test.util.CallbackHelper;
-import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.InMemorySharedPreferences;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.CommandLineParameter;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper;
@@ -56,23 +54,11 @@
  * If a test doesn't yet work with sandboxed renderer, an entire class, or an individual test
  * method can be marked for single-process testing only by adding the following annotation:
  *
- * @ParameterizedTest.Set
+ * @SkipCommandLineParameterization
  */
 @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT)
-@ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                        @Parameter(
-                                tag = CommandLineFlags.Parameter.PARAMETER_TAG)}),
-            @ParameterizedTest(parameters = {
-                        @Parameter(
-                                tag = CommandLineFlags.Parameter.PARAMETER_TAG,
-                                arguments = {
-                                    @Parameter.Argument(
-                                        name = CommandLineFlags.Parameter.ADD_ARG,
-                                        stringArray = {AwSwitches.WEBVIEW_SANDBOXED_RENDERER})
-            })})})
-public class AwTestBase
-        extends BaseActivityInstrumentationTestCase<AwTestRunnerActivity> {
+@CommandLineParameter({"", AwSwitches.WEBVIEW_SANDBOXED_RENDERER})
+public class AwTestBase extends BaseActivityInstrumentationTestCase<AwTestRunnerActivity> {
     public static final long WAIT_TIMEOUT_MS = scaleTimeout(15000);
     public static final int CHECK_INTERVAL = 100;
     private static final String TAG = "AwTestBase";
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java
index 5fb81ffc..724bc0f 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java
@@ -14,7 +14,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.SkipCommandLineParameterization;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
 import org.chromium.net.test.util.TestWebServer;
 import org.chromium.policy.AbstractAppRestrictionsProvider;
@@ -63,7 +63,7 @@
     @MediumTest
     @Feature({"AndroidWebView", "Policy"})
     // Run in single process only. crbug.com/615484
-    @ParameterizedTest.Set
+    @SkipCommandLineParameterization
     @RetryOnFailure
     public void testBlacklistedUrl() throws Throwable {
         final AwPolicyProvider testProvider =
@@ -91,7 +91,7 @@
             @Policies.Item(key = sBlacklistPolicyName, stringArray = {"*"}),
             @Policies.Item(key = sWhitelistPolicyName, stringArray = {sFooWhitelistFilter})})
     // Run in single process only. crbug.com/660517
-    @ParameterizedTest.Set
+    @SkipCommandLineParameterization
     public void testWhitelistedUrl() throws Throwable {
         navigateAndCheckOutcome(mFooTestUrl, 0 /* error count before */, 0 /* error count after */);
 
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/crash/VisualStateCallbackTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/crash/VisualStateCallbackTest.java
index 373be1fc..b63c4ed4 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/crash/VisualStateCallbackTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/crash/VisualStateCallbackTest.java
@@ -27,7 +27,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.SkipCommandLineParameterization;
 import org.chromium.content_public.common.ContentUrlConstants;
 
 import java.util.concurrent.TimeUnit;
@@ -152,9 +152,8 @@
     // process gone, but before the AwContentsClient knows about it.
     @Feature({"AndroidWebView"})
     @SmallTest
-    @CommandLineFlags
-            .Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
-    @ParameterizedTest.Set
+    @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
+    @SkipCommandLineParameterization
     public void testAddVisualStateCallbackAfterRendererGone() throws Throwable {
         final VisualStateCallbackImpl vsImpl = new VisualStateCallbackImpl();
         mHelper.setOnRenderProcessGoneTask(new Runnable() {
@@ -177,11 +176,9 @@
     @Feature({"AndroidWebView"})
     @SmallTest
     @RetryOnFailure
-    @CommandLineFlags
-            .Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
-    @ParameterizedTest.Set
+    @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER)
+    @SkipCommandLineParameterization
     public void testVisualStateCallbackNotCalledAfterRendererGone() throws Throwable {
-
         VisualStateCallbackImpl vsImpl = new VisualStateCallbackImpl();
         insertVisualStateCallbackOnUIThread(mAwContents, vsImpl.requestId(), vsImpl);
         VisualStateCallbackHelper vsCallbackHelper = mAwContents.getVisualStateCallbackHelper();
diff --git a/android_webview/tools/PRESUBMIT.py b/android_webview/tools/PRESUBMIT.py
index 1df3894f..935205d 100644
--- a/android_webview/tools/PRESUBMIT.py
+++ b/android_webview/tools/PRESUBMIT.py
@@ -15,7 +15,6 @@
       input_api, output_api, pylintrc='pylintrc',
       # TODO: lint these and eliminate the blacklist.
       black_list=[
-          r'webview_licenses.py',
           r'webview_repack_locales.py',
       ]))
   return input_api.RunTests(checks, False)
diff --git a/android_webview/tools/webview_licenses.py b/android_webview/tools/webview_licenses.py
deleted file mode 100755
index 0e5d37c..0000000
--- a/android_webview/tools/webview_licenses.py
+++ /dev/null
@@ -1,303 +0,0 @@
-#!/usr/bin/python
-# Copyright 2014 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.
-
-"""Checks third-party licenses for the purposes of the Android WebView build.
-
-The Android tree includes a snapshot of Chromium in order to power the system
-WebView.  This tool checks that all code uses open-source licenses compatible
-with Android, and that we meet the requirements of those licenses. It can also
-be used to generate an Android NOTICE file for the third-party code.
-
-It makes use of src/tools/licenses.py and the README.chromium files on which
-it depends. It also makes use of a data file, third_party_files_whitelist.txt,
-which whitelists individual files which contain third-party code but which
-aren't in a third-party directory with a README.chromium file.
-"""
-
-import imp
-import json
-import multiprocessing
-import optparse
-import os
-import re
-import sys
-import textwrap
-
-
-REPOSITORY_ROOT = os.path.abspath(os.path.join(
-    os.path.dirname(__file__), '..', '..'))
-
-# Import third_party/PRESUBMIT.py via imp to avoid importing a random
-# PRESUBMIT.py from $PATH, also make sure we don't generate a .pyc file.
-sys.dont_write_bytecode = True
-third_party = \
-  imp.load_source('PRESUBMIT', \
-                  os.path.join(REPOSITORY_ROOT, 'third_party', 'PRESUBMIT.py'))
-
-sys.path.append(os.path.join(REPOSITORY_ROOT, 'build/android/gyp/util'))
-import build_utils
-sys.path.append(os.path.join(REPOSITORY_ROOT, 'third_party'))
-import jinja2
-sys.path.append(os.path.join(REPOSITORY_ROOT, 'tools'))
-from copyright_scanner import copyright_scanner
-import licenses
-
-
-class InputApi(object):
-  def __init__(self):
-    self.os_path = os.path
-    self.os_walk = os.walk
-    self.re = re
-    self.ReadFile = _ReadFile
-    self.change = InputApiChange()
-
-class InputApiChange(object):
-  def __init__(self):
-    self.RepositoryRoot = lambda: REPOSITORY_ROOT
-
-class ScanResult(object):
-  Ok, Warnings, Errors = range(3)
-
-# Needs to be a top-level function for multiprocessing
-def _FindCopyrightViolations(files_to_scan_as_string):
-  return copyright_scanner.FindCopyrightViolations(
-    InputApi(), REPOSITORY_ROOT, files_to_scan_as_string)
-
-def _ShardList(l, shard_len):
-  return [l[i:i + shard_len] for i in range(0, len(l), shard_len)]
-
-def _CheckLicenseHeaders(excluded_dirs_list, whitelisted_files):
-  """Checks that all files which are not in a listed third-party directory,
-  and which do not use the standard Chromium license, are whitelisted.
-  Args:
-    excluded_dirs_list: The list of directories to exclude from scanning.
-    whitelisted_files: The whitelist of files.
-  Returns:
-    ScanResult.Ok if all files with non-standard license headers are whitelisted
-    and the whitelist contains no stale entries;
-    ScanResult.Warnings if there are stale entries;
-    ScanResult.Errors if new non-whitelisted entries found.
-  """
-  input_api = InputApi()
-  files_to_scan = copyright_scanner.FindFiles(
-    input_api, REPOSITORY_ROOT, ['.'], excluded_dirs_list)
-  sharded_files_to_scan = _ShardList(files_to_scan, 2000)
-  pool = multiprocessing.Pool()
-  offending_files_chunks = pool.map_async(
-      _FindCopyrightViolations, sharded_files_to_scan).get(999999)
-  pool.close()
-  pool.join()
-  # Flatten out the result
-  offending_files = \
-    [item for sublist in offending_files_chunks for item in sublist]
-
-  (unknown, missing, stale) = copyright_scanner.AnalyzeScanResults(
-    input_api, whitelisted_files, offending_files)
-
-  if unknown:
-    print 'The following files contain a third-party license but are not in ' \
-          'a listed third-party directory and are not whitelisted. You must ' \
-          'add the following files to the whitelist.\n' \
-          '(Note that if the code you are adding does not actually contain ' \
-          'any third-party code, it may contain the word "copyright", which ' \
-          'should be masked out, e.g. by writing it as "copy-right")\n%s' % \
-          '\n'.join(sorted(unknown))
-  if missing:
-    print 'The following files are whitelisted, but do not exist.\n%s' % \
-          '\n'.join(sorted(missing))
-  if stale:
-    print 'The following files are whitelisted unnecessarily. You must ' \
-          'remove the following files from the whitelist.\n%s' % \
-          '\n'.join(sorted(stale))
-
-  if unknown:
-    code = ScanResult.Errors
-  elif stale or missing:
-    code = ScanResult.Warnings
-  else:
-    code = ScanResult.Ok
-
-  problem_paths = sorted(set(unknown + missing + stale))
-  return (code, problem_paths)
-
-
-def _ReadFile(full_path, mode='rU'):
-  """Reads a file from disk. This emulates presubmit InputApi.ReadFile func.
-  Args:
-    full_path: The path of the file to read.
-  Returns:
-    The contents of the file as a string.
-  """
-
-  with open(full_path, mode) as f:
-    return f.read()
-
-
-def _Scan():
-  """Checks that license meta-data is present for all third-party code and
-     that all non third-party code doesn't contain external copyrighted code.
-  Returns:
-    ScanResult.Ok if everything is in order;
-    ScanResult.Warnings if there are non-fatal problems (e.g. stale whitelist
-      entries)
-    ScanResult.Errors otherwise.
-  """
-
-  third_party_dirs = licenses.FindThirdPartyDirsWithFiles(REPOSITORY_ROOT)
-
-  problem_paths = []
-
-  # First, check designated third-party directories using src/tools/licenses.py.
-  all_licenses_valid = True
-  for path in sorted(third_party_dirs):
-    try:
-      licenses.ParseDir(path, REPOSITORY_ROOT)
-    except licenses.LicenseError, e:
-      print 'Got LicenseError "%s" while scanning %s' % (e, path)
-      problem_paths.append(path)
-      all_licenses_valid = False
-
-  # Second, check for non-standard license text.
-  whitelisted_files = copyright_scanner.LoadWhitelistedFilesList(InputApi())
-  licenses_check, more_problem_paths = _CheckLicenseHeaders(
-      third_party_dirs, whitelisted_files)
-
-  problem_paths.extend(more_problem_paths)
-
-  return (licenses_check if all_licenses_valid else ScanResult.Errors,
-          problem_paths)
-
-
-class TemplateEntryGenerator(object):
-  def __init__(self):
-    self._toc_index = 0
-
-  def _ReadFileGuessEncoding(self, name):
-    contents = ''
-    with open(name, 'rb') as input_file:
-      contents = input_file.read()
-    try:
-      return contents.decode('utf8')
-    except UnicodeDecodeError:
-      pass
-    # If it's not UTF-8, it must be CP-1252. Fail otherwise.
-    return contents.decode('cp1252')
-
-  def MetadataToTemplateEntry(self, metadata):
-    self._toc_index += 1
-    return {
-      'name': metadata['Name'],
-      'url': metadata['URL'],
-      'license_file': metadata['License File'],
-      'license': self._ReadFileGuessEncoding(metadata['License File']),
-      'toc_href': 'entry' + str(self._toc_index),
-    }
-
-
-def GenerateNoticeFile():
-  """Generates the contents of an Android NOTICE file for the third-party code.
-  This is used by the snapshot tool.
-  Returns:
-    A tuple of (input paths, contents of the NOTICE file).
-  """
-  generator = TemplateEntryGenerator()
-  # Start from Chromium's LICENSE file
-  entries = [generator.MetadataToTemplateEntry({
-    'Name': 'The Chromium Project',
-    'URL': 'http://www.chromium.org',
-    'License File': os.path.join(REPOSITORY_ROOT, 'LICENSE') })
-  ]
-
-  third_party_dirs = licenses.FindThirdPartyDirsWithFiles(REPOSITORY_ROOT)
-  # We provide attribution for all third-party directories.
-  # TODO(mnaganov): Limit this to only code used by the WebView binary.
-  for directory in sorted(third_party_dirs):
-    try:
-      metadata = licenses.ParseDir(directory, REPOSITORY_ROOT,
-                                   require_license_file=False)
-    except licenses.LicenseError:
-      # Since this code is called during project files generation,
-      # we don't want to break the it. But we assume that release
-      # WebView apks are built using checkouts that pass
-      # 'webview_licenses.py scan' check, thus they don't contain
-      # projects with non-compatible licenses.
-      continue
-    license_file = metadata['License File']
-    if license_file and license_file != licenses.NOT_SHIPPED:
-      entries.append(generator.MetadataToTemplateEntry(metadata))
-
-  entries.sort(key=lambda entry: entry['name'])
-
-  license_file_list = sorted(set([entry['license_file'] for entry in entries]))
-  license_file_list = [os.path.relpath(p) for p in license_file_list]
-  env = jinja2.Environment(
-    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
-    extensions=['jinja2.ext.autoescape'])
-  template = env.get_template('licenses_notice.tmpl')
-  notice_file_contents = template.render({'entries': entries}).encode('utf8')
-  return (license_file_list, notice_file_contents)
-
-
-def main():
-  class FormatterWithNewLines(optparse.IndentedHelpFormatter):
-    def format_description(self, description):
-      paras = description.split('\n')
-      formatted_paras = [textwrap.fill(para, self.width) for para in paras]
-      return '\n'.join(formatted_paras) + '\n'
-
-  parser = optparse.OptionParser(formatter=FormatterWithNewLines(),
-                                 usage='%prog [options]')
-  parser.add_option('--json', help='Path to JSON output file')
-  build_utils.AddDepfileOption(parser)
-  parser.description = (__doc__ +
-                        '\nCommands:\n'
-                        '  scan Check licenses.\n'
-                        'Android NOTICE file.\n'
-                        '  notice [file] Generate Android NOTICE file on '
-                        'stdout or into |file|.\n'
-                        '  display_copyrights Display autorship on the files'
-                        ' using names provided via stdin.\n')
-  options, args = parser.parse_args()
-  if len(args) < 1:
-    parser.print_help()
-    return ScanResult.Errors
-
-  if args[0] == 'scan':
-    scan_result, problem_paths = _Scan()
-    if scan_result == ScanResult.Ok:
-      print 'OK!'
-    if options.json:
-      with open(options.json, 'w') as f:
-        json.dump(problem_paths, f)
-    return scan_result
-  elif args[0] == 'notice':
-    license_file_list, notice_file_contents = GenerateNoticeFile()
-    if len(args) == 1:
-      print notice_file_contents
-    else:
-      with open(args[1], 'w') as output_file:
-        output_file.write(notice_file_contents)
-    if options.depfile:
-      assert args[1]
-      # Add in build.ninja so that the target will be considered dirty whenever
-      # gn gen is run. Otherwise, it will fail to notice new files being added.
-      # This is still no perfect, as it will fail if no build files are changed,
-      # but a new README.chromium / LICENSE is added. This shouldn't happen in
-      # practice however.
-      build_utils.WriteDepfile(options.depfile, args[1],
-                               license_file_list + ['build.ninja'])
-
-    return ScanResult.Ok
-  elif args[0] == 'display_copyrights':
-    files = sys.stdin.read().splitlines()
-    for f, c in \
-        zip(files, copyright_scanner.FindCopyrights(InputApi(), '.', files)):
-      print f, '\t', ' / '.join(sorted(c))
-    return ScanResult.Ok
-  parser.print_help()
-  return ScanResult.Errors
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 1fb9216..f090447 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1107,6 +1107,7 @@
     "//components/quirks",
     "//components/signin/core/account_id",
     "//components/user_manager",
+    "//components/viz/test:test_support",
     "//content/public/browser",
     "//content/test:test_support",
     "//device/bluetooth",
@@ -1457,11 +1458,13 @@
     "//ash/touch_hud",
     "//base",
     "//base/test:test_support",
+    "//cc:test_support",
     "//chromeos",
     "//chromeos:test_support_without_gmock",
     "//components/quirks",
     "//components/signin/core/account_id",
     "//components/user_manager",
+    "//components/viz/test:test_support",
     "//device/bluetooth",
     "//mojo/edk/system",
     "//net:net",
@@ -1534,7 +1537,9 @@
     "//ash/public/cpp:ash_public_cpp",
     "//ash/test:test_support_without_content",
     "//base/test:test_support",
+    "//cc:test_support",
     "//cc/base",
+    "//components/viz/test:test_support",
     "//mojo/edk/embedder:headers",
     "//testing/gtest",
     "//testing/perf",
diff --git a/ash/system/network/network_icon.cc b/ash/system/network/network_icon.cc
index f096341..b19b3a0 100644
--- a/ash/system/network/network_icon.cc
+++ b/ash/system/network/network_icon.cc
@@ -21,12 +21,10 @@
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/canvas.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size_conversions.h"
-#include "ui/gfx/image/canvas_image_source.h"
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/image/image_skia_source.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -184,10 +182,6 @@
 //------------------------------------------------------------------------------
 // Utilities for generating icon images.
 
-// 'NONE' will default to ARCS behavior where appropriate (e.g. no network or
-// if a new type gets added).
-enum ImageType { ARCS, BARS, NONE };
-
 // Amount to fade icons while connecting.
 const double kConnectingImageAlpha = 0.5;
 
@@ -198,6 +192,14 @@
 // Number of discrete images to use for alpha fade animation
 const int kNumFadeImages = 10;
 
+// Padding between outside of icon and edge of the canvas, in dp. This value
+// stays the same regardless of the canvas size.
+static constexpr int kSignalStrengthImageInset = 2;
+
+// TODO(estade): share this alpha with other things in ash (battery, etc.).
+// See crbug.com/623987 and crbug.com/632827
+static constexpr int kSignalStrengthImageBgAlpha = 0x4D;
+
 SkColor GetDefaultColorForIconType(IconType icon_type) {
   return icon_type == ICON_TYPE_TRAY ? kTrayIconColor : kMenuIconColor;
 }
@@ -285,141 +287,6 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSource);
 };
 
-// Depicts a given signal strength using arcs (e.g. for WiFi connections) or
-// bars (e.g. for cell connections).
-class SignalStrengthImageSource : public gfx::CanvasImageSource {
- public:
-  SignalStrengthImageSource(ImageType image_type,
-                            IconType icon_type,
-                            int signal_strength)
-      : CanvasImageSource(GetSizeForIconType(icon_type), false),
-        image_type_(image_type),
-        icon_type_(icon_type),
-        color_(GetDefaultColorForIconType(icon_type_)),
-        signal_strength_(signal_strength) {
-    if (image_type_ == NONE)
-      image_type_ = ARCS;
-
-    DCHECK_GE(signal_strength, 0);
-    DCHECK_LT(signal_strength, kNumNetworkImages);
-  }
-  ~SignalStrengthImageSource() override {}
-
-  void set_color(SkColor color) { color_ = color; }
-
-  // gfx::CanvasImageSource:
-  void Draw(gfx::Canvas* canvas) override {
-    if (image_type_ == ARCS)
-      DrawArcs(canvas);
-    else
-      DrawBars(canvas);
-  }
-
-  bool HasRepresentationAtAllScales() const override { return true; }
-
- private:
-  static gfx::Size GetSizeForIconType(IconType icon_type) {
-    int side = icon_type == ICON_TYPE_TRAY ? kTrayIconSize : kMenuIconSize;
-    return gfx::Size(side, side);
-  }
-
-  void DrawArcs(gfx::Canvas* canvas) {
-    gfx::RectF oval_bounds((gfx::Rect(size())));
-    oval_bounds.Inset(gfx::Insets(kIconInset));
-    // Double the width and height. The new midpoint should be the former
-    // bottom center.
-    oval_bounds.Inset(-oval_bounds.width() / 2, 0, -oval_bounds.width() / 2,
-                      -oval_bounds.height());
-
-    const SkScalar kAngleAboveHorizontal = 51.f;
-    const SkScalar kStartAngle = 180.f + kAngleAboveHorizontal;
-    const SkScalar kSweepAngle = 180.f - 2 * kAngleAboveHorizontal;
-
-    cc::PaintFlags flags;
-    flags.setAntiAlias(true);
-    flags.setStyle(cc::PaintFlags::kFill_Style);
-    // Background. Skip drawing for full signal.
-    if (signal_strength_ != kNumNetworkImages - 1) {
-      flags.setColor(SkColorSetA(color_, kBgAlpha));
-      canvas->sk_canvas()->drawArc(gfx::RectFToSkRect(oval_bounds), kStartAngle,
-                                   kSweepAngle, true, flags);
-    }
-    // Foreground (signal strength).
-    if (signal_strength_ != 0) {
-      flags.setColor(color_);
-      // Percent of the height of the background wedge that we draw the
-      // foreground wedge, indexed by signal strength.
-      static const float kWedgeHeightPercentages[] = {0.f, 0.375f, 0.5833f,
-                                                      0.75f, 1.f};
-      const float wedge_percent = kWedgeHeightPercentages[signal_strength_];
-      oval_bounds.Inset(
-          gfx::InsetsF((oval_bounds.height() / 2) * (1.f - wedge_percent)));
-      canvas->sk_canvas()->drawArc(gfx::RectFToSkRect(oval_bounds), kStartAngle,
-                                   kSweepAngle, true, flags);
-    }
-  }
-
-  void DrawBars(gfx::Canvas* canvas) {
-    // Undo the canvas's device scaling and round values to the nearest whole
-    // number so we can draw on exact pixel boundaries.
-    const float dsf = canvas->UndoDeviceScaleFactor();
-    auto scale = [dsf](SkScalar dimension) {
-      return std::round(dimension * dsf);
-    };
-
-    // Length of short side of an isosceles right triangle, in dip.
-    const SkScalar kFullTriangleSide =
-        SkIntToScalar(size().width()) - kIconInset * 2;
-
-    auto make_triangle = [scale, kFullTriangleSide](SkScalar side) {
-      SkPath triangle;
-      triangle.moveTo(scale(kIconInset), scale(kIconInset + kFullTriangleSide));
-      triangle.rLineTo(scale(side), 0);
-      triangle.rLineTo(0, -scale(side));
-      triangle.close();
-      return triangle;
-    };
-
-    cc::PaintFlags flags;
-    flags.setAntiAlias(true);
-    flags.setStyle(cc::PaintFlags::kFill_Style);
-    // Background. Skip drawing for full signal.
-    if (signal_strength_ != kNumNetworkImages - 1) {
-      flags.setColor(SkColorSetA(color_, kBgAlpha));
-      canvas->DrawPath(make_triangle(kFullTriangleSide), flags);
-    }
-    // Foreground (signal strength).
-    if (signal_strength_ != 0) {
-      flags.setColor(color_);
-      // As a percentage of the bg triangle, the length of one of the short
-      // sides of the fg triangle, indexed by signal strength.
-      static const float kTriangleSidePercents[] = {0.f, 0.5f, 0.625f, 0.75f,
-                                                    1.f};
-      canvas->DrawPath(make_triangle(kTriangleSidePercents[signal_strength_] *
-                                     kFullTriangleSide),
-                       flags);
-    }
-  }
-
-  ImageType image_type_;
-  IconType icon_type_;
-  SkColor color_;
-
-  // On a scale of 0 to kNum{Arcs,Bars}Images - 1, how connected we are.
-  int signal_strength_;
-
-  // Padding between outside of icon and edge of the canvas, in dp. This value
-  // stays the same regardless of the canvas size (which depends on
-  // |icon_type_|).
-  static constexpr int kIconInset = 2;
-
-  // TODO(estade): share this alpha with other things in ash (battery, etc.).
-  // See crbug.com/623987 and crbug.com/632827
-  static constexpr int kBgAlpha = 0x4D;
-
-  DISALLOW_COPY_AND_ASSIGN(SignalStrengthImageSource);
-};
-
 //------------------------------------------------------------------------------
 // Utilities for extracting icon images.
 
@@ -770,6 +637,134 @@
 }  // namespace
 
 //------------------------------------------------------------------------------
+// SignalStrengthImageSource
+
+SignalStrengthImageSource::SignalStrengthImageSource(ImageType image_type,
+                                                     SkColor color,
+                                                     const gfx::Size& size,
+                                                     int signal_strength)
+    : CanvasImageSource(size, false),
+      image_type_(image_type /* is_opaque */),
+      color_(color),
+      signal_strength_(signal_strength) {
+  if (image_type_ == NONE)
+    image_type_ = ARCS;
+
+  DCHECK_GE(signal_strength, 0);
+  DCHECK_LT(signal_strength, kNumNetworkImages);
+}
+
+SignalStrengthImageSource::SignalStrengthImageSource(ImageType image_type,
+                                                     IconType icon_type,
+                                                     int signal_strength)
+    : SignalStrengthImageSource(image_type,
+                                GetDefaultColorForIconType(icon_type),
+                                GetSizeForIconType(icon_type),
+                                signal_strength) {}
+
+SignalStrengthImageSource::~SignalStrengthImageSource() {}
+
+void SignalStrengthImageSource::set_color(SkColor color) {
+  color_ = color;
+}
+
+// gfx::CanvasImageSource:
+void SignalStrengthImageSource::Draw(gfx::Canvas* canvas) {
+  if (image_type_ == ARCS)
+    DrawArcs(canvas);
+  else
+    DrawBars(canvas);
+}
+
+bool SignalStrengthImageSource::HasRepresentationAtAllScales() const {
+  return true;
+}
+
+gfx::Size SignalStrengthImageSource::GetSizeForIconType(IconType icon_type) {
+  int side = icon_type == ICON_TYPE_TRAY ? kTrayIconSize : kMenuIconSize;
+  return gfx::Size(side, side);
+}
+
+void SignalStrengthImageSource::DrawArcs(gfx::Canvas* canvas) {
+  gfx::RectF oval_bounds((gfx::Rect(size())));
+  oval_bounds.Inset(gfx::Insets(kSignalStrengthImageInset));
+  // Double the width and height. The new midpoint should be the former
+  // bottom center.
+  oval_bounds.Inset(-oval_bounds.width() / 2, 0, -oval_bounds.width() / 2,
+                    -oval_bounds.height());
+
+  const SkScalar kAngleAboveHorizontal = 51.f;
+  const SkScalar kStartAngle = 180.f + kAngleAboveHorizontal;
+  const SkScalar kSweepAngle = 180.f - 2 * kAngleAboveHorizontal;
+
+  cc::PaintFlags flags;
+  flags.setAntiAlias(true);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  // Background. Skip drawing for full signal.
+  if (signal_strength_ != kNumNetworkImages - 1) {
+    flags.setColor(SkColorSetA(color_, kSignalStrengthImageBgAlpha));
+    canvas->sk_canvas()->drawArc(gfx::RectFToSkRect(oval_bounds), kStartAngle,
+                                 kSweepAngle, true, flags);
+  }
+  // Foreground (signal strength).
+  if (signal_strength_ != 0) {
+    flags.setColor(color_);
+    // Percent of the height of the background wedge that we draw the
+    // foreground wedge, indexed by signal strength.
+    static constexpr float kWedgeHeightPercentages[] = {0.f, 0.375f, 0.5833f,
+                                                        0.75f, 1.f};
+    const float wedge_percent = kWedgeHeightPercentages[signal_strength_];
+    oval_bounds.Inset(
+        gfx::InsetsF((oval_bounds.height() / 2) * (1.f - wedge_percent)));
+    canvas->sk_canvas()->drawArc(gfx::RectFToSkRect(oval_bounds), kStartAngle,
+                                 kSweepAngle, true, flags);
+  }
+}
+
+void SignalStrengthImageSource::DrawBars(gfx::Canvas* canvas) {
+  // Undo the canvas's device scaling and round values to the nearest whole
+  // number so we can draw on exact pixel boundaries.
+  const float dsf = canvas->UndoDeviceScaleFactor();
+  auto scale = [dsf](SkScalar dimension) {
+    return std::round(dimension * dsf);
+  };
+
+  // Length of short side of an isosceles right triangle, in dip.
+  const SkScalar kFullTriangleSide =
+      SkIntToScalar(size().width()) - kSignalStrengthImageInset * 2;
+
+  auto make_triangle = [scale, kFullTriangleSide](SkScalar side) {
+    SkPath triangle;
+    triangle.moveTo(scale(kSignalStrengthImageInset),
+                    scale(kSignalStrengthImageInset + kFullTriangleSide));
+    triangle.rLineTo(scale(side), 0);
+    triangle.rLineTo(0, -scale(side));
+    triangle.close();
+    return triangle;
+  };
+
+  cc::PaintFlags flags;
+  flags.setAntiAlias(true);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  // Background. Skip drawing for full signal.
+  if (signal_strength_ != kNumNetworkImages - 1) {
+    flags.setColor(SkColorSetA(color_, kSignalStrengthImageBgAlpha));
+    canvas->DrawPath(make_triangle(kFullTriangleSide), flags);
+  }
+  // Foreground (signal strength).
+  if (signal_strength_ != 0) {
+    flags.setColor(color_);
+    // As a percentage of the bg triangle, the length of one of the short
+    // sides of the fg triangle, indexed by signal strength.
+    static constexpr float kTriangleSidePercents[] = {0.f, 0.5f, 0.625f, 0.75f,
+                                                      1.f};
+    canvas->DrawPath(make_triangle(kTriangleSidePercents[signal_strength_] *
+                                   kFullTriangleSide),
+                     flags);
+  }
+}
+
+//------------------------------------------------------------------------------
 // Public interface
 
 gfx::ImageSkia GetImageForNetwork(const NetworkState* network,
diff --git a/ash/system/network/network_icon.h b/ash/system/network/network_icon.h
index a7b2640..448f986 100644
--- a/ash/system/network/network_icon.h
+++ b/ash/system/network/network_icon.h
@@ -9,6 +9,8 @@
 
 #include "ash/ash_export.h"
 #include "base/strings/string16.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/image/canvas_image_source.h"
 #include "ui/gfx/image/image_skia.h"
 
 namespace chromeos {
@@ -26,6 +28,46 @@
   ICON_TYPE_MENU_LIST,     // dark icons without VPN badges; separate status
 };
 
+// 'NONE' will default to ARCS behavior where appropriate (e.g. no network or
+// if a new type gets added).
+enum ImageType { ARCS, BARS, NONE };
+
+// Depicts a given signal strength using arcs (e.g. for WiFi connections) or
+// bars (e.g. for cell connections).
+class SignalStrengthImageSource : public gfx::CanvasImageSource {
+ public:
+  ASH_EXPORT SignalStrengthImageSource(ImageType image_type,
+                                       SkColor color,
+                                       const gfx::Size& size,
+                                       int signal_strength);
+
+  // This version intuits color and size from icon_type.
+  ASH_EXPORT SignalStrengthImageSource(ImageType image_type,
+                                       IconType icon_type,
+                                       int signal_strength);
+
+  ~SignalStrengthImageSource() override;
+
+  void set_color(SkColor color);
+
+  // gfx::CanvasImageSource:
+  void Draw(gfx::Canvas* canvas) override;
+  bool HasRepresentationAtAllScales() const override;
+
+ private:
+  static gfx::Size GetSizeForIconType(IconType icon_type);
+  void DrawArcs(gfx::Canvas* canvas);
+  void DrawBars(gfx::Canvas* canvas);
+
+  ImageType image_type_;
+  SkColor color_;
+
+  // On a scale of 0 to kNumNetworkImages - 1, how connected we are.
+  int signal_strength_;
+
+  DISALLOW_COPY_AND_ASSIGN(SignalStrengthImageSource);
+};
+
 // Gets the image for provided |network|. |network| must not be NULL.
 // |icon_type| determines the color theme and whether or not to show the VPN
 // badge. This caches badged icons per network per |icon_type|.
diff --git a/ash/test/DEPS b/ash/test/DEPS
index 5178d95..f15a004 100644
--- a/ash/test/DEPS
+++ b/ash/test/DEPS
@@ -1,5 +1,7 @@
 include_rules = [
   # In general files in this directory should not depend upon content.
+  "+cc/test",
+  "+components/viz/test",
   "+mojo/edk",
 ]
 
diff --git a/ash/test/ash_test_suite.cc b/ash/test/ash_test_suite.cc
index a14aed95..76c38033 100644
--- a/ash/test/ash_test_suite.cc
+++ b/ash/test/ash_test_suite.cc
@@ -4,6 +4,8 @@
 
 #include "ash/test/ash_test_suite.h"
 
+#include <set>
+
 #include "ash/public/cpp/config.h"
 #include "ash/test/ash_test_environment.h"
 #include "ash/test/ash_test_helper.h"
@@ -13,6 +15,9 @@
 #include "base/metrics/statistics_recorder.h"
 #include "base/path_service.h"
 #include "build/build_config.h"
+#include "cc/test/fake_output_surface.h"
+#include "cc/test/test_context_provider.h"
+#include "components/viz/test/test_layer_tree_frame_sink.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_paths.h"
@@ -22,6 +27,68 @@
 
 namespace ash {
 namespace test {
+namespace {
+
+class FrameSinkClient : public viz::TestLayerTreeFrameSinkClient {
+ public:
+  explicit FrameSinkClient(
+      scoped_refptr<cc::ContextProvider> display_context_provider)
+      : display_context_provider_(std::move(display_context_provider)) {}
+
+  std::unique_ptr<cc::OutputSurface> CreateDisplayOutputSurface(
+      scoped_refptr<cc::ContextProvider> compositor_context_provider) override {
+    return cc::FakeOutputSurface::Create3d(
+        std::move(display_context_provider_));
+  }
+
+  void DisplayReceivedLocalSurfaceId(
+      const viz::LocalSurfaceId& local_surface_id) override {}
+  void DisplayReceivedCompositorFrame(
+      const cc::CompositorFrame& frame) override {}
+  void DisplayWillDrawAndSwap(
+      bool will_draw_and_swap,
+      const cc::RenderPassList& render_passes) override {}
+  void DisplayDidDrawAndSwap() override {}
+
+ private:
+  scoped_refptr<cc::ContextProvider> display_context_provider_;
+
+  DISALLOW_COPY_AND_ASSIGN(FrameSinkClient);
+};
+
+class AshTestContextFactory : public ui::FakeContextFactory {
+ public:
+  AshTestContextFactory() = default;
+  ~AshTestContextFactory() override = default;
+
+  // ui::FakeContextFactory
+  void CreateLayerTreeFrameSink(
+      base::WeakPtr<ui::Compositor> compositor) override {
+    scoped_refptr<cc::TestContextProvider> context_provider =
+        cc::TestContextProvider::Create();
+    std::unique_ptr<FrameSinkClient> frame_sink_client =
+        base::MakeUnique<FrameSinkClient>(context_provider);
+    constexpr bool synchronous_composite = false;
+    constexpr bool disable_display_vsync = false;
+    const double refresh_rate = GetRefreshRate();
+    auto frame_sink = base::MakeUnique<viz::TestLayerTreeFrameSink>(
+        context_provider, cc::TestContextProvider::CreateWorker(), nullptr,
+        GetGpuMemoryBufferManager(), renderer_settings(),
+        base::ThreadTaskRunnerHandle::Get().get(), synchronous_composite,
+        disable_display_vsync, refresh_rate);
+    frame_sink->SetClient(frame_sink_client.get());
+    compositor->SetLayerTreeFrameSink(std::move(frame_sink));
+    frame_sink_clients_.insert(std::move(frame_sink_client));
+  }
+
+ private:
+  std::set<std::unique_ptr<viz::TestLayerTreeFrameSinkClient>>
+      frame_sink_clients_;
+
+  DISALLOW_COPY_AND_ASSIGN(AshTestContextFactory);
+};
+
+}  // namespace
 
 AshTestSuite::AshTestSuite(int argc, char** argv) : TestSuite(argc, argv) {}
 
@@ -71,7 +138,7 @@
                                                      : aura::Env::Mode::LOCAL);
 
   if (is_mus || is_mash) {
-    context_factory_ = base::MakeUnique<ui::FakeContextFactory>();
+    context_factory_ = base::MakeUnique<AshTestContextFactory>();
     env_->set_context_factory(context_factory_.get());
     env_->set_context_factory_private(nullptr);
   }
diff --git a/ash/test/ash_test_suite.h b/ash/test/ash_test_suite.h
index d42ec0e..4fac428 100644
--- a/ash/test/ash_test_suite.h
+++ b/ash/test/ash_test_suite.h
@@ -13,7 +13,7 @@
 #include "ui/aura/env.h"
 
 namespace ui {
-class FakeContextFactory;
+class ContextFactory;
 }
 
 namespace ash {
@@ -34,9 +34,9 @@
 
   base::TestDiscardableMemoryAllocator discardable_memory_allocator_;
 
-  // Only used when running in Config::MUS, and is set as the context_factory
+  // Only used when running in mus/mash, and is set as the context_factory
   // on aura::Env.
-  std::unique_ptr<ui::FakeContextFactory> context_factory_;
+  std::unique_ptr<ui::ContextFactory> context_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(AshTestSuite);
 };
diff --git a/base/BUILD.gn b/base/BUILD.gn
index b1f6bcc..df4abcc 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2723,11 +2723,8 @@
       "test/android/javatests/src/org/chromium/base/test/util/TimeoutScale.java",
       "test/android/javatests/src/org/chromium/base/test/util/UserActionTester.java",
       "test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java",
-      "test/android/javatests/src/org/chromium/base/test/util/parameter/BaseParameter.java",
-      "test/android/javatests/src/org/chromium/base/test/util/parameter/Parameter.java",
-      "test/android/javatests/src/org/chromium/base/test/util/parameter/Parameterizable.java",
-      "test/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTest.java",
-      "test/android/javatests/src/org/chromium/base/test/util/parameter/parameters/MethodParameter.java",
+      "test/android/javatests/src/org/chromium/base/test/util/parameter/CommandLineParameter.java",
+      "test/android/javatests/src/org/chromium/base/test/util/parameter/SkipCommandLineParameterization.java",
     ]
   }
 
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseActivityInstrumentationTestCase.java b/base/test/android/javatests/src/org/chromium/base/test/BaseActivityInstrumentationTestCase.java
index 7937284..275671c 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseActivityInstrumentationTestCase.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseActivityInstrumentationTestCase.java
@@ -7,24 +7,13 @@
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase2;
 
-import org.chromium.base.test.util.parameter.BaseParameter;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.base.test.util.parameter.Parameterizable;
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
-
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * Base class for all Activity-based Instrumentation tests.
  *
  * @param <T> The Activity type.
  */
 public class BaseActivityInstrumentationTestCase<T extends Activity>
-        extends ActivityInstrumentationTestCase2<T> implements Parameterizable {
-    private Parameter.Reader mParameterReader;
-    private Map<String, BaseParameter> mAvailableParameters;
-
+        extends ActivityInstrumentationTestCase2<T> {
     /**
      * Creates a instance for running tests against an Activity of the given class.
      *
@@ -33,57 +22,4 @@
     public BaseActivityInstrumentationTestCase(Class<T> activityClass) {
         super(activityClass);
     }
-
-    /**
-     * Creates the {@link Map} of available parameters for the test to use.
-     *
-     * @return a {@link Map} of {@link BaseParameter} objects.
-     */
-    protected Map<String, BaseParameter> createAvailableParameters() {
-        Map<String, BaseParameter> availableParameters = new HashMap<>();
-        availableParameters
-                .put(MethodParameter.PARAMETER_TAG, new MethodParameter(getParameterReader()));
-        return availableParameters;
-    }
-
-    /**
-     * Gets the {@link Map} of available parameters that inherited classes can use.
-     *
-     * @return a {@link Map} of {@link BaseParameter} objects to set as the available parameters.
-     */
-    public Map<String, BaseParameter> getAvailableParameters() {
-        return mAvailableParameters;
-    }
-
-    /**
-     * Gets a specific parameter from the current test.
-     *
-     * @param parameterTag a string with the name of the {@link BaseParameter} we want.
-     * @return a parameter that extends {@link BaseParameter} that has the matching parameterTag.
-     */
-    @SuppressWarnings("unchecked")
-    public <T extends BaseParameter> T getAvailableParameter(String parameterTag) {
-        return (T) mAvailableParameters.get(parameterTag);
-    }
-
-    /**
-     * Setter method for {@link Parameter.Reader}.
-     *
-     * @param parameterReader the {@link Parameter.Reader} to set.
-     */
-    public void setParameterReader(Parameter.Reader parameterReader) {
-        mParameterReader = parameterReader;
-        mAvailableParameters = createAvailableParameters();
-    }
-
-    /**
-     * Getter method for {@link Parameter.Reader} object to be used by test cases reading the
-     * parameter.
-     *
-     * @return the {@link Parameter.Reader} for the current {@link
-     * org.chromium.base.test.util.parameter.ParameterizedTest} being run.
-     */
-    protected Parameter.Reader getParameterReader() {
-        return mParameterReader;
-    }
 }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java b/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
index 7e31a5d..a80e0cc 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
@@ -9,27 +9,15 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 
-import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 import junit.framework.TestResult;
 
 import org.chromium.base.Log;
-import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.SkipCheck;
-import org.chromium.base.test.util.parameter.BaseParameter;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.base.test.util.parameter.Parameterizable;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
 
 /**
  * A test result that can skip tests.
@@ -119,250 +107,7 @@
 
             endTest(test);
         } else {
-            if (test instanceof Parameterizable) {
-                try {
-                    runParameterized(test);
-                } catch (ThreadDeath e) {
-                    Log.e(TAG, "Parameterized test run failed: %s", e);
-                }
-            } else {
-                super.run(test);
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private <T extends TestCase & Parameterizable> void runParameterized(TestCase test)
-            throws ThreadDeath {
-        T testCase = (T) test;
-
-        // Prepare test.
-        Parameter.Reader parameterReader = new Parameter.Reader(test);
-        testCase.setParameterReader(parameterReader);
-        List<ParameterizedTest> parameterizedTests = parameterReader.getParameterizedTests();
-        List<ParameterError> errors = new ArrayList<>();
-        List<ParameterError> failures = new ArrayList<>();
-        Map<String, BaseParameter> availableParameters = testCase.getAvailableParameters();
-
-        // Remove all @ParameterizedTests that contain CommandLineFlags.Parameter -- those
-        // are handled in test_runner.py as it is needed to re-launch the whole test activity
-        // to apply command-line args correctly. Note that this way we will also ignore any
-        // other parameters that may present in these @ParameterizedTests.
-        for (Iterator<ParameterizedTest> iter = parameterizedTests.iterator(); iter.hasNext();) {
-            ParameterizedTest paramTest = iter.next();
-            for (Parameter p: paramTest.parameters()) {
-                if (CommandLineFlags.Parameter.PARAMETER_TAG.equals(p.tag())) {
-                    iter.remove();
-                }
-            }
-        }
-
-        if (parameterizedTests.isEmpty()) {
             super.run(test);
-        } else {
-            // Start test.
-            startTest(testCase);
-            for (ParameterizedTest parameterizedTest : parameterizedTests) {
-                parameterReader.setCurrentParameterizedTest(parameterizedTest);
-                try {
-                    setUpParameters(availableParameters, parameterReader);
-                    testCase.runBare();
-                    tearDownParameters(availableParameters, parameterReader);
-                } catch (AssertionFailedError e) {
-                    failures.add(new ParameterError(e, parameterizedTest));
-                } catch (ThreadDeath e) {
-                    throw e;
-                } catch (Throwable e) {
-                    errors.add(new ParameterError(e, parameterizedTest));
-                }
-            }
-
-            // Generate failures and errors.
-            if (!failures.isEmpty()) {
-                addFailure(test, new ParameterizedTestFailure(failures));
-            }
-            if (!errors.isEmpty()) {
-                addError(test, new ParameterizedTestError(errors));
-            }
-
-            // End test.
-            endTest(testCase);
-        }
-    }
-
-    private static <T extends TestCase & Parameterizable> void setUpParameters(
-            Map<String, BaseParameter> availableParameters, Parameter.Reader reader)
-            throws Exception {
-        for (Entry<String, BaseParameter> entry : availableParameters.entrySet()) {
-            if (reader.getParameter(entry.getValue().getTag()) != null) {
-                entry.getValue().setUp();
-            }
-        }
-    }
-
-    private static <T extends TestCase & Parameterizable> void tearDownParameters(
-            Map<String, BaseParameter> availableParameters, Parameter.Reader reader)
-            throws Exception {
-        for (Entry<String, BaseParameter> entry : availableParameters.entrySet()) {
-            if (reader.getParameter(entry.getValue().getTag()) != null) {
-                entry.getValue().tearDown();
-            }
-        }
-    }
-
-    private static class ParameterError {
-        private final Throwable mThrowable;
-        private final ParameterizedTest mParameterizedTest;
-
-        public ParameterError(Throwable throwable, ParameterizedTest parameterizedTest) {
-            mThrowable = throwable;
-            mParameterizedTest = parameterizedTest;
-        }
-
-        private Throwable getThrowable() {
-            return mThrowable;
-        }
-
-        private ParameterizedTest getParameterizedTest() {
-            return mParameterizedTest;
-        }
-    }
-
-    private static class ParameterizedTestFailure extends AssertionFailedError {
-        public ParameterizedTestFailure(List<ParameterError> failures) {
-            super(new ParameterizedTestError(failures).toString());
-        }
-    }
-
-    private static class ParameterizedTestError extends Exception {
-        private final List<ParameterError> mErrors;
-
-        public ParameterizedTestError(List<ParameterError> errors) {
-            mErrors = errors;
-        }
-
-        /**
-         * Error output is as follows.
-         *
-         * DEFINITIONS:
-         * {{ERROR}} is the standard error output from
-         * {@link ParameterError#getThrowable().toString()}.
-         * {{PARAMETER_TAG}} is the {@link Parameter#tag()} value associated with the parameter.
-         * {{ARGUMENT_NAME}} is the {@link Parameter.Argument#name()} associated with the argument.
-         * {{ARGUMENT_VALUE}} is the value associated with the {@link Parameter.Argument}. This can
-         * be a String, int, String[], or int[].
-         *
-         * With no {@link Parameter}:
-         * {{ERROR}} (with no parameters)
-         *
-         * With Single {@link Parameter} and no {@link Parameter.Argument}:
-         * {{ERROR}} (with parameters: {{PARAMETER_TAG}} with no arguments)
-         *
-         * With Single {@link Parameter} and one {@link Parameter.Argument}:
-         * {{ERROR}} (with parameters: {{PARAMETER_TAG}} with arguments:
-         * {{ARGUMENT_NAME}}={{ARGUMENT_VALUE}})
-         *
-         * With Single {@link Parameter} and multiple {@link Parameter.Argument}s:
-         * {{ERROR}} (with parameters: {{PARAMETER_TAG}} with arguments:
-         * {{ARGUMENT_NAME}}={{ARGUMENT_VALUE}}, {{ARGUMENT_NAME}}={{ARGUMENT_VALUE}}, ...)
-         *
-         * DEFINITION:
-         * {{PARAMETER_ERROR}} is the output of a single {@link Parameter}'s error. Format:
-         * {{PARAMETER_TAG}} with arguments: {{ARGUMENT_NAME}}={{ARGUMENT_NAME}}, ...
-         *
-         * With Multiple {@link Parameter}s:
-         * {{ERROR}} (with parameters: {{PARAMETER_ERROR}}; {{PARAMETER_ERROR}}; ...)
-         *
-         * There will be a trace after this. And this is shown for every possible {@link
-         * ParameterizedTest} that is failed in the {@link ParameterizedTest.Set} if there is one.
-         *
-         * @return the error message and trace of the test failures.
-         */
-        @Override
-        public String toString() {
-            if (mErrors.isEmpty()) return "\n";
-            StringBuilder builder = new StringBuilder();
-            Iterator<ParameterError> iter = mErrors.iterator();
-            if (iter.hasNext()) {
-                builder.append(createErrorBuilder(iter.next()));
-            }
-            while (iter.hasNext()) {
-                builder.append("\n").append(createErrorBuilder(iter.next()));
-            }
-            return builder.toString();
-        }
-
-        private static StringBuilder createErrorBuilder(ParameterError error) {
-            StringBuilder builder = new StringBuilder("\n").append(error.getThrowable().toString());
-            List<Parameter> parameters =
-                    Arrays.asList(error.getParameterizedTest().parameters());
-            if (parameters.isEmpty()) {
-                builder.append(" (with no parameters)");
-            } else {
-                Iterator<Parameter> iter = parameters.iterator();
-                builder.append(" (with parameters: ").append(createParameterBuilder(iter.next()));
-                while (iter.hasNext()) {
-                    builder.append("; ").append(createParameterBuilder(iter.next()));
-                }
-                builder.append(")");
-            }
-            return builder.append("\n").append(trace(error));
-        }
-
-        private static StringBuilder createParameterBuilder(Parameter parameter) {
-            StringBuilder builder = new StringBuilder(parameter.tag());
-            List<Parameter.Argument> arguments = Arrays.asList(parameter.arguments());
-            if (arguments.isEmpty()) {
-                builder.append(" with no arguments");
-            } else {
-                Iterator<Parameter.Argument> iter = arguments.iterator();
-                builder.append(" with arguments: ").append(createArgumentBuilder(iter.next()));
-                while (iter.hasNext()) {
-                    builder.append(", ").append(createArgumentBuilder(iter.next()));
-                }
-            }
-            return builder;
-        }
-
-        private static StringBuilder createArgumentBuilder(Parameter.Argument argument) {
-            StringBuilder builder = new StringBuilder(argument.name()).append("=");
-            if (!Parameter.ArgumentDefault.STRING.equals(argument.stringVar())) {
-                builder.append(argument.stringVar());
-            } else if (Parameter.ArgumentDefault.INT != argument.intVar()) {
-                builder.append(argument.intVar());
-            } else if (argument.stringArray().length > 0) {
-                builder.append(Arrays.toString(argument.stringArray()));
-            } else if (argument.intArray().length > 0) {
-                builder.append(Arrays.toString(argument.intArray()));
-            }
-            return builder;
-        }
-
-        /**
-         * @return the trace without the error message
-         */
-        private static StringBuilder trace(ParameterError error) {
-            StringWriter stringWriter = new StringWriter();
-            PrintWriter writer = new PrintWriter(stringWriter);
-            error.getThrowable().printStackTrace(writer);
-            StringBuilder builder = new StringBuilder(stringWriter.getBuffer());
-            return trim(deleteFirstLine(builder));
-        }
-
-        private static StringBuilder deleteFirstLine(StringBuilder builder) {
-            return builder.delete(0, builder.indexOf("\n") + 1);
-        }
-
-        private static StringBuilder trim(StringBuilder sb) {
-            if (sb == null || sb.length() == 0) return sb;
-            for (int i = sb.length() - 1; i >= 0; i--) {
-                if (Character.isWhitespace(sb.charAt(i))) {
-                    sb.deleteCharAt(i);
-                } else {
-                    return sb;
-                }
-            }
-            return sb;
         }
     }
 
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
index a140ff1..bd23f26 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
@@ -12,7 +12,6 @@
 import org.chromium.base.BaseChromiumApplication;
 import org.chromium.base.CommandLine;
 import org.chromium.base.test.BaseTestResult.PreTestHook;
-import org.chromium.base.test.util.parameter.BaseParameter;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Inherited;
@@ -168,36 +167,4 @@
 
         };
     }
-
-    /**
-     * Instructs the test runner to execute the test with modified command-line flags.
-     * Flags to add are specified using 'stringArray' of argument named 'add',
-     * and flags to remove -- in the argument named 'remove'. A parameter without arguments
-     * instructs to run the test with default command-line flags.
-     *
-     * Example:
-     *
-     * @ParameterizedTest.Set(tests = {
-     * @ParameterizedTest(parameters = {
-     * @Parameter( tag = CommandLineFlags.Parameter.PARAMETER_TAG)}),
-     * @ParameterizedTest(parameters = {
-     * @Parameter( tag = CommandLineFlags.Parameter.PARAMETER_TAG,
-     * arguments = {
-     * @Parameter.Argument( name = CommandLineFlags.Parameter.ADD_ARG,
-     * stringArray = {'arg1', 'arg2'})
-     * })})})
-     *
-     * Note that because the entire instrumentation test process needs to be restarted to apply
-     * modified command-line arguments, this annotation is handled by test_runner.py, not by
-     * BaseTestResult class.
-     */
-    public static class Parameter extends BaseParameter {
-        public static final String PARAMETER_TAG = "cmdlinearg-parameter";
-        public static final String ADD_ARG = "add";
-        public static final String REMOVE_ARG = "remove";
-
-        public Parameter(org.chromium.base.test.util.parameter.Parameter.Reader parameterReader) {
-            super(PARAMETER_TAG, parameterReader);
-        }
-    }
 }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/BaseParameter.java b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/BaseParameter.java
deleted file mode 100644
index bc4c8e4..0000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/BaseParameter.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-/**
- * The attributes of a single parameter.
- */
-public class BaseParameter {
-    private final String mTag;
-    private final Parameter.Reader mParameterReader;
-
-    public BaseParameter(String tag, Parameter.Reader parameterReader) {
-        mTag = tag;
-        mParameterReader = parameterReader;
-    }
-
-    public String getTag() {
-        return mTag;
-    }
-
-    public String getStringArgument(String argumentName, String defaultString) {
-        Parameter.Argument parameterArgument = getArgument(argumentName);
-        return parameterArgument != null ? parameterArgument.stringVar() : defaultString;
-    }
-
-    public String getStringArgument(String argumentName) {
-        Parameter.Argument parameterArgument = getArgument(argumentName);
-        checkArgumentExists(parameterArgument);
-        return parameterArgument.stringVar();
-    }
-
-    public int getIntArgument(String argumentName, int defaultInt) {
-        Parameter.Argument parameterArgument = getArgument(argumentName);
-        return parameterArgument != null ? parameterArgument.intVar() : defaultInt;
-    }
-
-    public int getIntArgument(String argumentName) {
-        Parameter.Argument parameterArgument = getArgument(argumentName);
-        checkArgumentExists(parameterArgument);
-        return parameterArgument.intVar();
-    }
-
-    public String[] getStringArrayArgument(String argumentName, String[] defaultStringArray) {
-        Parameter.Argument parameterArgument = getArgument(argumentName);
-        return parameterArgument != null ? parameterArgument.stringArray() : defaultStringArray;
-    }
-
-    public String[] getStringArrayArgument(String argumentName) {
-        Parameter.Argument parameterArgument = getArgument(argumentName);
-        checkArgumentExists(parameterArgument);
-        return parameterArgument.stringArray();
-    }
-
-    public int[] getIntArrayArgument(String argumentName, int[] defaultIntArray) {
-        Parameter.Argument parameterArgument = getArgument(argumentName);
-        return parameterArgument != null ? parameterArgument.intArray() : defaultIntArray;
-    }
-
-    public int[] getIntArrayArgument(String argumentName) {
-        Parameter.Argument parameterArgument = getArgument(argumentName);
-        checkArgumentExists(parameterArgument);
-        return parameterArgument.intArray();
-    }
-
-    private Parameter.Argument getArgument(String argumentName) {
-        return mParameterReader.getParameterArgument(getTag(), argumentName);
-    }
-
-    private static void checkArgumentExists(Parameter.Argument parameterArgument) {
-        if (parameterArgument == null) {
-            throw new IllegalArgumentException("Argument must be specified");
-        }
-    }
-
-    public void setUp() throws Exception {}
-
-    public void tearDown() throws Exception {}
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/CommandLineParameter.java b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/CommandLineParameter.java
new file mode 100644
index 0000000..e6f5506
--- /dev/null
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/CommandLineParameter.java
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.test.util.parameter;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The annotation for parametering CommandLineFlags in JUnit3 instrumentation tests.
+ *
+ * E.g. if you add the following annotation to your test class:
+ *
+ * <code>
+ * @CommandLineParameter({"", FLAG_A, FLAG_B})
+ * public class MyTestClass
+ * </code>
+ *
+ * The test harness would run the test 3 times with each of the flag added to commandline
+ * file.
+ */
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface CommandLineParameter {
+    String[] value() default {};
+}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/Parameter.java b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/Parameter.java
deleted file mode 100644
index 0d122d20..0000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/Parameter.java
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import junit.framework.TestCase;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * The annotation for an individual parameter in a {@link ParameterizedTest}.
- *
- * Contains all annotations required to run tests ParameterizedTests.
- */
-public @interface Parameter {
-    String tag();
-    Argument[] arguments() default {};
-
-    /**
-     * The annotation for an individual argument in a {@link Parameter}.
-     */
-    @interface Argument {
-        String name();
-        String stringVar() default Parameter.ArgumentDefault.STRING;
-        String[] stringArray() default {};
-        int intVar() default Parameter.ArgumentDefault.INT;
-        int[] intArray() default {};
-    }
-
-    /**
-     * Default values for {@link Parameter.Argument}s.
-     *
-     * TODO (crbug.com/520232): Move to within {@link Parameter.Argument} and rename to Default
-     * when fixed.
-     */
-    final class ArgumentDefault {
-        public static final String STRING = "";
-        public static final int INT = 0;
-    }
-
-    /**
-     * The tool to read Parameter related annotations.
-     */
-    class Reader {
-        private Class mAnnotatedTestClass;
-        private AnnotatedElement mAnnotatedTestMethod;
-        private ParameterizedTest mParameterizedTest;
-
-        public Reader(TestCase testCase) {
-            try {
-                mAnnotatedTestClass = testCase.getClass();
-                mAnnotatedTestMethod = testCase.getClass().getMethod(testCase.getName());
-            } catch (NoSuchMethodException e) {
-                // ignore
-            }
-        }
-
-        /**
-         * Gets the {@link ParameterizedTest}s for the current test.
-         *
-         * @return a list of all the {@link ParameterizedTest}s for the current test.
-         */
-        public List<ParameterizedTest> getParameterizedTests() {
-            return new ArrayList<ParameterizedTest>(getParameterizedTestsImpl());
-        }
-
-        /**
-         * Gets the {@link ParameterizedTest}s for the current test as immutable list.
-         *
-         * @return a list of all the {@link ParameterizedTest}s for the current test.
-         */
-        private List<ParameterizedTest> getParameterizedTestsImpl() {
-            // Note: this must be aligned with Python code in
-            // instrumentation_test_instance.ParseCommandLineFlagParameters (regarding priority of
-            // ParameterizedTest.Set vs. ParameterizedTest) and in test_jar._GetProguardData
-            // (regarding composition of method annotations with class and superclasses
-            // annotations). Composition precedes selecting the annotation to process.
-            if (mAnnotatedTestMethod.isAnnotationPresent(ParameterizedTest.Set.class)) {
-                return Arrays.asList(getParameterizedTestSet(mAnnotatedTestMethod).tests());
-            }
-            AnnotatedElement classWithAnnotation = findClassWithAnnotation(
-                    mAnnotatedTestClass, ParameterizedTest.Set.class);
-            if (classWithAnnotation != null) {
-                return Arrays.asList(getParameterizedTestSet(classWithAnnotation).tests());
-            }
-            if (mAnnotatedTestMethod.isAnnotationPresent(ParameterizedTest.class)) {
-                return Collections.singletonList(getParameterizedTest(mAnnotatedTestMethod));
-            }
-            classWithAnnotation = findClassWithAnnotation(
-                    mAnnotatedTestClass, ParameterizedTest.class);
-            if (classWithAnnotation != null) {
-                return Collections.singletonList(getParameterizedTest(classWithAnnotation));
-            }
-            return Collections.emptyList();
-        }
-
-        /**
-         * Finds a class with the given annotation class starting from the given clazz.
-         *
-         * @return the class as {@link AnnotatedElement} or null if the class is not found.
-         */
-        private AnnotatedElement findClassWithAnnotation(
-                Class<?> clazz, Class<? extends Annotation> annotationClass) {
-            if (clazz == null || clazz.isAnnotationPresent(annotationClass)) {
-                return clazz;
-            } else {
-                return findClassWithAnnotation(clazz.getSuperclass(), annotationClass);
-            }
-        }
-
-        /**
-         * Gets the {@link ParameterizedTest} annotation of the current test.
-         *
-         * @return a {@link ParameterizedTest} of the current test's parameters.
-         */
-        private ParameterizedTest getParameterizedTest(AnnotatedElement element) {
-            return element.getAnnotation(ParameterizedTest.class);
-        }
-
-        /**
-         * Gets the {@link ParameterizedTest.Set} annotation of the current test.
-         *
-         * @return a {@link ParameterizedTest.Set} of the current test's parameters.
-         */
-        private ParameterizedTest.Set getParameterizedTestSet(AnnotatedElement element) {
-            return element.getAnnotation(ParameterizedTest.Set.class);
-        }
-
-        public boolean isParameterizedTest() {
-            return mAnnotatedTestMethod.isAnnotationPresent(ParameterizedTest.Set.class)
-                    || mAnnotatedTestMethod.isAnnotationPresent(ParameterizedTest.class)
-                    || findClassWithAnnotation(
-                            mAnnotatedTestClass, ParameterizedTest.Set.class) != null
-                    || findClassWithAnnotation(
-                            mAnnotatedTestClass, ParameterizedTest.class) != null;
-        }
-
-        public void setCurrentParameterizedTest(ParameterizedTest parameterizedTest) {
-            mParameterizedTest = parameterizedTest;
-        }
-
-        /**
-         * Gets a {@link Parameter} object for a given target parameter.
-         *
-         * @param targetParameter the name of the {@link Parameter} to get in the current
-         * parameterized test.
-         * @return the {@link Parameter} for a given {@link ParameterizedTest} with the
-         * targetParameter as its tag if it exists, otherwise returns null.
-         */
-        public Parameter getParameter(String targetParameter) {
-            if (mParameterizedTest == null || targetParameter == null) {
-                return null;
-            }
-            for (Parameter parameter : mParameterizedTest.parameters()) {
-                if (targetParameter.equals(parameter.tag())) {
-                    return parameter;
-                }
-            }
-            return null;
-        }
-
-        /**
-         * Gets the {@link Parameter.Argument} for a given {@link Parameter}.
-         *
-         * @param targetParameter the name of the {@link Parameter} to search for when looking for
-         * a {@link Parameter.Argument}.
-         * @param targetArgument the name of the {@link Parameter.Argument} to look for in the
-         * target {@link Parameter}.
-         * @return the {@link Parameter.Argument} for a given {@link ParameterizedTest} for the
-         * {@link Parameter} with the tag matching targetParameter and the argument name being
-         * targetArgument if it exists, otherwise returns null.
-         */
-        public Parameter.Argument getParameterArgument(String targetParameter,
-                String targetArgument) {
-            Parameter parameter = getParameter(targetParameter);
-            return (parameter == null) ? null : getParameterArgument(parameter, targetArgument);
-        }
-
-        public static Parameter.Argument getParameterArgument(Parameter parameter,
-                String targetArgument) {
-            if (targetArgument == null) {
-                return null;
-            }
-            for (Parameter.Argument argument : parameter.arguments()) {
-                if (targetArgument.equals(argument.name())) {
-                    return argument;
-                }
-            }
-            return null;
-        }
-    }
-}
-
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/Parameterizable.java b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/Parameterizable.java
deleted file mode 100644
index f5c8ce8..0000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/Parameterizable.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import java.util.Map;
-
-/**
- * An interface to implement on test cases to run {@link ParameterizedTest}s.
- */
-public interface Parameterizable {
-
-    /**
-     * Gets the {@link Map} of available parameters for the test to use.
-     *
-     * @return a {@link Map} of {@link BaseParameter} objects.
-     */
-    Map<String, BaseParameter> getAvailableParameters();
-
-
-    /**
-     * Setter method for {@link Parameter.Reader}.
-     *
-     * @param parameterReader the {@link Parameter.Reader} to set.
-     */
-    void setParameterReader(Parameter.Reader parameterReader);
-
-    /**
-     * Gets a specific parameter from the current test.
-     *
-     * @param parameterTag a string with the name of the {@link BaseParameter} we want.
-     * @return a parameter that extends {@link BaseParameter} that has the matching parameterTag.
-     */
-    <T extends BaseParameter> T getAvailableParameter(String parameterTag);
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTest.java b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTest.java
deleted file mode 100644
index 65e929fb..0000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * The annotation for an individual set of {@link Parameter}s to run on a single test.
- */
-@Inherited
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface ParameterizedTest {
-    Parameter[] parameters() default {};
-
-    /**
-     * The annotation that contains a set of {@link ParameterizedTest}s to run. A test method
-     * is attempted for every set of {@link Parameter}s in each {@link ParameterizedTest}.
-     */
-    @Inherited
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.METHOD, ElementType.TYPE})
-    @interface Set {
-        ParameterizedTest[] tests() default {};
-    }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/SkipCommandLineParameterization.java b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/SkipCommandLineParameterization.java
new file mode 100644
index 0000000..2181031
--- /dev/null
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/SkipCommandLineParameterization.java
@@ -0,0 +1,23 @@
+// 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.
+package org.chromium.base.test.util.parameter;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * BaseJUnit4ClassRunner and host side test harness skips commandline parameterization for test
+ * classes or methods annotated with SkipCommandLineParameterization.
+ *
+ * This usually used by test that only runs in WebView javatests that only runs in sandboxed mode
+ * or single process mode.
+ */
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface SkipCommandLineParameterization {}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/parameters/MethodParameter.java b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/parameters/MethodParameter.java
deleted file mode 100644
index c314540..0000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/parameters/MethodParameter.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter.parameters;
-
-import org.chromium.base.test.util.parameter.BaseParameter;
-import org.chromium.base.test.util.parameter.Parameter;
-
-/**
- * Allows for passing of certain parameters arguments to function when this parameter is used.
- */
-public class MethodParameter extends BaseParameter {
-    public static final String PARAMETER_TAG = "method-parameter";
-
-    public MethodParameter(Parameter.Reader parameterReader) {
-        super(PARAMETER_TAG, parameterReader);
-    }
-}
-
-
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
index 8959e1e0..e087d93 100644
--- a/base/test/launcher/test_launcher.cc
+++ b/base/test/launcher/test_launcher.cc
@@ -1193,13 +1193,10 @@
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   CommandLine::SwitchMap switches = command_line->GetSwitches();
 
-  size_t jobs = 0U;
+  if (command_line->HasSwitch(switches::kTestLauncherJobs)) {
+    // If the number of test launcher jobs was specified, return that number.
+    size_t jobs = 0U;
 
-  if (command_line->HasSwitch(kGTestFilterFlag) && !BotModeEnabled()) {
-    // Do not run jobs in parallel by default if we are running a subset of
-    // the tests and if bot mode is off.
-    return 1U;
-  } else if (command_line->HasSwitch(switches::kTestLauncherJobs)) {
     if (!StringToSizeT(
             command_line->GetSwitchValueASCII(switches::kTestLauncherJobs),
             &jobs) ||
@@ -1207,10 +1204,13 @@
       LOG(ERROR) << "Invalid value for " << switches::kTestLauncherJobs;
       return 0U;
     }
-
-    return jobs;
+  } else if (command_line->HasSwitch(kGTestFilterFlag) && !BotModeEnabled()) {
+    // Do not run jobs in parallel by default if we are running a subset of
+    // the tests and if bot mode is off.
+    return 1U;
   }
 
+  // Default to the number of processor cores.
   return base::checked_cast<size_t>(SysInfo::NumberOfProcessors());
 }
 
diff --git a/build/android/play_services/update.py b/build/android/play_services/update.py
index d1ec955..5297b3cf 100755
--- a/build/android/play_services/update.py
+++ b/build/android/play_services/update.py
@@ -47,7 +47,7 @@
 
 LICENSE_FILE_NAME = 'LICENSE'
 ZIP_FILE_NAME = 'google_play_services_library.zip'
-GMS_PACKAGE_ID = 'extra-google-m2repository'  # used by sdk manager
+GMS_PACKAGE_ID = 'extras;google;m2repository'  # used by sdk manager
 
 LICENSE_PATTERN = re.compile(r'^Pkg\.License=(?P<text>.*)$', re.MULTILINE)
 
@@ -256,9 +256,8 @@
     with open(paths.source_prop, 'w') as prop_file:
       prop_file.write('Pkg.Revision=0.0.0\n')
 
-  sdk_manager = os.path.join(args.sdk_root, 'tools', 'android')
-  cmd = [sdk_manager, 'update', 'sdk', '--no-ui', '--filter', GMS_PACKAGE_ID]
-  cmd_helper.Call(cmd)
+  sdk_manager = os.path.join(args.sdk_root, 'tools', 'bin', 'sdkmanager')
+  cmd_helper.Call([sdk_manager, GMS_PACKAGE_ID])
   # If no update is needed, it still returns successfully so we just do nothing
 
   return 0
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index d6077404..2443384 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import collections
 import copy
 import logging
 import os
@@ -47,12 +46,12 @@
 _EXTRA_TIMEOUT_SCALE = (
     'org.chromium.test.driver.OnDeviceInstrumentationDriver.TimeoutScale')
 
-_PARAMETERIZED_TEST_ANNOTATION = 'ParameterizedTest'
-_PARAMETERIZED_TEST_SET_ANNOTATION = 'ParameterizedTest$Set'
+_SKIP_PARAMETERIZATION = 'SkipCommandLineParameterization'
+_COMMANDLINE_PARAMETERIZATION = 'CommandLineParameter'
 _NATIVE_CRASH_RE = re.compile('(process|native) crash', re.IGNORECASE)
 _CMDLINE_NAME_SEGMENT_RE = re.compile(
     r' with(?:out)? \{[^\}]*\}')
-_PICKLE_FORMAT_VERSION = 11
+_PICKLE_FORMAT_VERSION = 12
 
 
 class MissingSizeAnnotationError(test_exception.TestException):
@@ -157,56 +156,6 @@
   return results
 
 
-def ParseCommandLineFlagParameters(annotations):
-  """Determines whether the test is parameterized to be run with different
-     command-line flags.
-
-  Args:
-    annotations: The annotations of the test.
-
-  Returns:
-    If the test is parameterized, returns a list of named tuples
-    with lists of flags, e.g.:
-
-      [(add=['--flag-to-add']), (remove=['--flag-to-remove']), ()]
-
-    That means, the test must be run three times, the first time with
-    "--flag-to-add" added to command-line, the second time with
-    "--flag-to-remove" to be removed from command-line, and the third time
-    with default command-line args. If the same flag is listed both for adding
-    and for removing, it is left unchanged.
-
-    If the test is not parametrized, returns None.
-
-  """
-  ParamsTuple = collections.namedtuple('ParamsTuple', ['add', 'remove'])
-  parameterized_tests = []
-  if _PARAMETERIZED_TEST_SET_ANNOTATION in annotations:
-    if annotations[_PARAMETERIZED_TEST_SET_ANNOTATION]:
-      parameterized_tests = annotations[
-        _PARAMETERIZED_TEST_SET_ANNOTATION].get('tests', [])
-  elif _PARAMETERIZED_TEST_ANNOTATION in annotations:
-    parameterized_tests = [annotations[_PARAMETERIZED_TEST_ANNOTATION]]
-  else:
-    return None
-
-  result = []
-  for pt in parameterized_tests:
-    if not pt:
-      continue
-    for p in pt['parameters']:
-      if p['tag'] == _COMMAND_LINE_PARAMETER:
-        to_add = []
-        to_remove = []
-        for a in p.get('arguments', []):
-          if a['name'] == 'add':
-            to_add = ['--%s' % f for f in a['stringArray']]
-          elif a['name'] == 'remove':
-            to_remove = ['--%s' % f for f in a['stringArray']]
-        result.append(ParamsTuple(to_add, to_remove))
-  return result if result else None
-
-
 def FilterTests(tests, test_filter=None, annotations=None,
                 excluded_annotations=None):
   """Filter a list of tests
@@ -313,7 +262,6 @@
     _SaveTestsToPickle(pickle_path, test_apk, tests)
   return tests
 
-
 def _GetTestsFromPickle(pickle_path, jar_path):
   if not os.path.exists(pickle_path):
     raise TestListPickleException('%s does not exist.' % pickle_path)
@@ -332,6 +280,7 @@
   return pickle_data['TEST_METHODS']
 
 
+# TODO(yolandyan): remove this once the test listing from java runner lands
 def _GetTestsFromProguard(jar_path):
   p = proguard.Dump(jar_path)
   class_lookup = dict((c['class'], c) for c in p['classes'])
@@ -443,12 +392,8 @@
     The unique test name as a string.
   """
   display_name = GetTestName(test, sep=sep)
-  if 'flags' in test:
-    flags = test['flags']
-    if flags.add:
-      display_name = '%s with {%s}' % (display_name, ' '.join(flags.add))
-    if flags.remove:
-      display_name = '%s without {%s}' % (display_name, ' '.join(flags.remove))
+  if test.get('flags', [None])[0]:
+    display_name = '%s with %s' % (display_name, ' '.join(test['flags']))
   return display_name
 
 
@@ -574,23 +519,23 @@
 
     self._test_package = self._test_apk.GetPackageName()
     all_instrumentations = self._test_apk.GetAllInstrumentations()
-    junit3_runners = [
+    test_runners = [
         x for x in all_instrumentations if ('true' not in x.get(
             'chromium-junit4', ''))]
-    junit4_runners = [
+    test_runners_junit4 = [
         x for x in all_instrumentations if ('true' in x.get(
             'chromium-junit4', ''))]
 
-    if len(junit3_runners) > 1:
+    if len(test_runners) > 1:
       logging.warning('This test apk has more than one JUnit3 instrumentation')
-    if len(junit4_runners) > 1:
+    if len(test_runners_junit4) > 1:
       logging.warning('This test apk has more than one JUnit4 instrumentation')
 
     self._test_runner = (
-      junit3_runners[0]['android:name'] if junit3_runners else
+      test_runners[0]['android:name'] if test_runners else
       self.test_apk.GetInstrumentationName())
     self._test_runner_junit4 = (
-      junit4_runners[0]['android:name'] if junit4_runners else None)
+      test_runners_junit4[0]['android:name'] if test_runners_junit4 else None)
 
     self._package_info = None
     if self._apk_under_test:
@@ -828,7 +773,7 @@
       tests = GetAllTestsFromJar(self.test_jar)
     else:
       tests = GetAllTestsFromApk(self.test_apk.path)
-    inflated_tests = self._ParametrizeTestsWithFlags(self._InflateTests(tests))
+    inflated_tests = self._ParameterizeTestsWithFlags(self._InflateTests(tests))
     if self._test_runner_junit4 is None and any(
         t['is_junit4'] for t in inflated_tests):
       raise MissingJUnit4RunnerException()
@@ -856,15 +801,19 @@
         })
     return inflated_tests
 
-  def _ParametrizeTestsWithFlags(self, tests):
+  def _ParameterizeTestsWithFlags(self, tests):
     new_tests = []
     for t in tests:
-      parameters = ParseCommandLineFlagParameters(t['annotations'])
+      annotations = t['annotations']
+      parameters = None
+      if (annotations.get(_COMMANDLINE_PARAMETERIZATION)
+          and _SKIP_PARAMETERIZATION not in annotations):
+        parameters = annotations[_COMMANDLINE_PARAMETERIZATION]['value']
       if parameters:
-        t['flags'] = parameters[0]
+        t['flags'] = [parameters[0]]
         for p in parameters[1:]:
           parameterized_t = copy.copy(t)
-          parameterized_t['flags'] = p
+          parameterized_t['flags'] = [p]
           new_tests.append(parameterized_t)
     return tests + new_tests
 
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index b51330d2..7ba90321 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -319,7 +319,6 @@
     extras = {}
 
     flags_to_add = []
-    flags_to_remove = []
     test_timeout_scale = None
     if self._test_instance.coverage_directory:
       coverage_basename = '%s.ec' % ('%s_group' % test[0]['method']
@@ -375,9 +374,8 @@
         target = '%s/%s' % (
             self._test_instance.test_package, self._test_instance.test_runner)
       extras['class'] = test_name
-      if 'flags' in test:
-        flags_to_add.extend(test['flags'].add)
-        flags_to_remove.extend(test['flags'].remove)
+      if 'flags' in test and test['flags']:
+        flags_to_add.extend(test['flags'])
       timeout = self._GetTimeoutFromAnnotations(
         test['annotations'], test_display_name)
 
@@ -398,10 +396,9 @@
       flags_to_add.append('--render-test-output-dir=%s' %
                           render_tests_device_output_dir)
 
-    if flags_to_add or flags_to_remove:
+    if flags_to_add:
       self._CreateFlagChangerIfNeeded(device)
-      self._flag_changers[str(device)].PushFlags(
-        add=flags_to_add, remove=flags_to_remove)
+      self._flag_changers[str(device)].PushFlags(add=flags_to_add)
 
     time_ms = lambda: int(time.time() * 1e3)
     start_ms = time_ms()
@@ -433,7 +430,7 @@
         result_code, result_bundle, statuses, start_ms, duration_ms)
 
     def restore_flags():
-      if flags_to_add or flags_to_remove:
+      if flags_to_add:
         self._flag_changers[str(device)].Restore()
 
     def restore_timeout_scale():
@@ -480,7 +477,7 @@
         result.SetLink('logcat', logcat_url)
 
     # Update the result name if the test used flags.
-    if flags_to_add or flags_to_remove:
+    if flags_to_add:
       for r in results:
         if r.GetName() == test_name:
           r.SetName(test_display_name)
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index d9ac8bd..7995d39 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -841,7 +841,6 @@
     "surfaces/referenced_surface_tracker_unittest.cc",
     "surfaces/surface_hittest_unittest.cc",
     "surfaces/surface_manager_ref_unittest.cc",
-    "surfaces/surface_sequence_generator_unittest.cc",
     "surfaces/surface_synchronization_unittest.cc",
     "surfaces/surface_unittest.cc",
 
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc
index 37e6eaed..a34e731a7 100644
--- a/cc/test/test_context_provider.cc
+++ b/cc/test/test_context_provider.cc
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <set>
+#include <string>
 #include <vector>
 
 #include "base/bind.h"
@@ -17,24 +18,90 @@
 #include "cc/output/context_cache_controller.h"
 #include "cc/test/test_gles2_interface.h"
 #include "cc/test/test_web_graphics_context_3d.h"
+#include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
 
 namespace cc {
 
+namespace {
+
+// Various tests rely on functionality (capabilities) enabled by these extension
+// strings.
+const char* const kExtensions[] = {"GL_EXT_stencil_wrap",
+                                   "GL_EXT_texture_format_BGRA8888",
+                                   "GL_OES_rgb8_rgba8"};
+
+class TestGLES2InterfaceForContextProvider : public TestGLES2Interface {
+ public:
+  TestGLES2InterfaceForContextProvider()
+      : extension_string_(BuildExtensionString()) {}
+  ~TestGLES2InterfaceForContextProvider() override = default;
+
+  // TestGLES2Interface:
+  const GLubyte* GetString(GLenum name) override {
+    switch (name) {
+      case GL_EXTENSIONS:
+        return reinterpret_cast<const GLubyte*>(extension_string_.c_str());
+      case GL_VERSION:
+        return reinterpret_cast<const GrGLubyte*>("4.0 Null GL");
+      case GL_SHADING_LANGUAGE_VERSION:
+        return reinterpret_cast<const GrGLubyte*>("4.20.8 Null GLSL");
+      case GL_VENDOR:
+        return reinterpret_cast<const GrGLubyte*>("Null Vendor");
+      case GL_RENDERER:
+        return reinterpret_cast<const GrGLubyte*>("The Null (Non-)Renderer");
+    }
+    return nullptr;
+  }
+  const GrGLubyte* GetStringi(GrGLenum name, GrGLuint i) override {
+    if (name == GL_EXTENSIONS && i < arraysize(kExtensions))
+      return reinterpret_cast<const GLubyte*>(kExtensions[i]);
+    return nullptr;
+  }
+  void GetIntegerv(GLenum name, GLint* params) override {
+    switch (name) {
+      case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+        *params = 8;
+        return;
+      default:
+        break;
+    }
+    TestGLES2Interface::GetIntegerv(name, params);
+  }
+
+ private:
+  static std::string BuildExtensionString() {
+    std::string extension_string = kExtensions[0];
+    for (size_t i = 1; i < arraysize(kExtensions); ++i) {
+      extension_string += " ";
+      extension_string += kExtensions[i];
+    }
+    return extension_string;
+  }
+
+  const std::string extension_string_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestGLES2InterfaceForContextProvider);
+};
+
+}  // namespace
+
 // static
 scoped_refptr<TestContextProvider> TestContextProvider::Create() {
-  return new TestContextProvider(base::MakeUnique<TestContextSupport>(),
-                                 base::MakeUnique<TestGLES2Interface>(),
-                                 TestWebGraphicsContext3D::Create());
+  return new TestContextProvider(
+      base::MakeUnique<TestContextSupport>(),
+      base::MakeUnique<TestGLES2InterfaceForContextProvider>(),
+      TestWebGraphicsContext3D::Create());
 }
 
 // static
 scoped_refptr<TestContextProvider> TestContextProvider::CreateWorker() {
   scoped_refptr<TestContextProvider> worker_context_provider(
-      new TestContextProvider(base::MakeUnique<TestContextSupport>(),
-                              base::MakeUnique<TestGLES2Interface>(),
-                              TestWebGraphicsContext3D::Create()));
+      new TestContextProvider(
+          base::MakeUnique<TestContextSupport>(),
+          base::MakeUnique<TestGLES2InterfaceForContextProvider>(),
+          TestWebGraphicsContext3D::Create()));
   // Worker contexts are bound to the thread they are created on.
   if (!worker_context_provider->BindToCurrentThread())
     return nullptr;
@@ -45,9 +112,10 @@
 scoped_refptr<TestContextProvider> TestContextProvider::Create(
     std::unique_ptr<TestWebGraphicsContext3D> context) {
   DCHECK(context);
-  return new TestContextProvider(base::MakeUnique<TestContextSupport>(),
-                                 base::MakeUnique<TestGLES2Interface>(),
-                                 std::move(context));
+  return new TestContextProvider(
+      base::MakeUnique<TestContextSupport>(),
+      base::MakeUnique<TestGLES2InterfaceForContextProvider>(),
+      std::move(context));
 }
 
 // static
@@ -65,9 +133,10 @@
     std::unique_ptr<TestContextSupport> support) {
   DCHECK(context);
   DCHECK(support);
-  return new TestContextProvider(std::move(support),
-                                 base::MakeUnique<TestGLES2Interface>(),
-                                 std::move(context));
+  return new TestContextProvider(
+      std::move(support),
+      base::MakeUnique<TestGLES2InterfaceForContextProvider>(),
+      std::move(context));
 }
 
 TestContextProvider::TestContextProvider(
@@ -141,20 +210,17 @@
   DCHECK(context_thread_checker_.CalledOnValidThread());
 
   if (gr_context_)
-    return gr_context_.get();
+    return gr_context_->get();
 
-  sk_sp<const GrGLInterface> gl_interface(GrGLCreateNullInterface());
-  gr_context_ = sk_sp<::GrContext>(GrContext::Create(
-      kOpenGL_GrBackend,
-      reinterpret_cast<GrBackendContext>(gl_interface.get())));
-
-  cache_controller_->SetGrContext(gr_context_.get());
+  gr_context_ = base::MakeUnique<skia_bindings::GrContextForGLES2Interface>(
+      context_gl_.get(), context3d_->test_capabilities());
+  cache_controller_->SetGrContext(gr_context_->get());
 
   // If GlContext is already lost, also abandon the new GrContext.
   if (ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
-    gr_context_->abandonContext();
+    gr_context_->get()->abandonContext();
 
-  return gr_context_.get();
+  return gr_context_->get();
 }
 
 ContextCacheController* TestContextProvider::CacheController() {
@@ -167,7 +233,7 @@
   DCHECK(context_thread_checker_.CalledOnValidThread());
 
   if (gr_context_)
-    gr_context_.get()->resetContext(state);
+    gr_context_->get()->resetContext(state);
 }
 
 base::Lock* TestContextProvider::GetLock() {
@@ -179,7 +245,7 @@
   if (!lost_context_callback_.is_null())
     lost_context_callback_.Run();
   if (gr_context_)
-    gr_context_->abandonContext();
+    gr_context_->get()->abandonContext();
 }
 
 TestWebGraphicsContext3D* TestContextProvider::TestContext3d() {
diff --git a/cc/test/test_context_provider.h b/cc/test/test_context_provider.h
index 816c9ae..7d47431 100644
--- a/cc/test/test_context_provider.h
+++ b/cc/test/test_context_provider.h
@@ -20,6 +20,10 @@
 #include "gpu/command_buffer/client/gles2_interface_stub.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 
+namespace skia_bindings {
+class GrContextForGLES2Interface;
+}
+
 namespace cc {
 class TestWebGraphicsContext3D;
 class TestGLES2Interface;
@@ -75,7 +79,7 @@
   std::unique_ptr<TestContextSupport> support_;
   std::unique_ptr<TestWebGraphicsContext3D> context3d_;
   std::unique_ptr<TestGLES2Interface> context_gl_;
-  sk_sp<class GrContext> gr_context_;
+  std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
   std::unique_ptr<ContextCacheController> cache_controller_;
   bool bound_ = false;
 
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 21047c5..d0a6196f 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -8805,7 +8805,7 @@
 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
   scoped_refptr<TestContextProvider> context_provider =
       TestContextProvider::Create();
-  FrameSinkClient test_client_(context_provider);
+  FrameSinkClient test_client(context_provider);
 
   constexpr bool synchronous_composite = true;
   constexpr bool disable_display_vsync = false;
@@ -8814,7 +8814,7 @@
       context_provider, TestContextProvider::CreateWorker(), nullptr, nullptr,
       RendererSettings(), base::ThreadTaskRunnerHandle::Get().get(),
       synchronous_composite, disable_display_vsync, refresh_rate);
-  layer_tree_frame_sink->SetClient(&test_client_);
+  layer_tree_frame_sink->SetClient(&test_client);
 
   CreateHostImpl(DefaultSettings(), std::move(layer_tree_frame_sink));
 
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index fa08d14..9b433783 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -422,6 +422,16 @@
             android:windowSoftInputMode="stateHidden|adjustPan"
             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize">
         </activity>
+        {% if enable_vr == "true" %}
+        <activity android:name="org.chromium.chrome.browser.vr_shell.VrFirstRunActivity"
+            android:exported="false"
+            android:theme="@style/VrActivityTheme"
+            android:excludeFromRecents="true"
+            android:enableVrMode="@string/gvr_vr_mode_component"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize|uiMode">
+            {{ self.supports_vr() }}
+        </activity>
+        {% endif %}
         <activity android:name="org.chromium.chrome.browser.signin.AccountSigninActivity"
             android:theme="@style/DialogWhenLarge"
             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize">
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index 87b04a0..540a1a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1143,6 +1143,16 @@
             mToolbarManager = null;
         }
 
+        if (mBottomSheet != null) {
+            mBottomSheet.destroy();
+            mBottomSheet = null;
+        }
+
+        if (mBottomSheetContentController != null) {
+            mBottomSheetContentController.destroy();
+            mBottomSheetContentController = null;
+        }
+
         if (mTabModelsInitialized) {
             TabModelSelector selector = getTabModelSelector();
             if (selector != null) selector.destroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java
index 47b25c28..60d705e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java
@@ -63,6 +63,7 @@
     private final int mVerticalFadeDistance;
     private final int mNegativeSoftwareVerticalOffset;
     private final int[] mTempLocation;
+    private final boolean mTranslateMenuItemsOnShow;
 
     private PopupWindow mPopup;
     private ListView mListView;
@@ -82,9 +83,11 @@
      * @param itemDividerHeight Desired height for the divider between app menu items.
      * @param handler AppMenuHandler receives callbacks from AppMenu.
      * @param res Resources object used to get dimensions and style attributes.
+     * @param translateMenuItemsOnShow Whether menu items should be translated during the animation
+     *                                 that is run when the menu is shown.
      */
     AppMenu(Menu menu, int itemRowHeight, int itemDividerHeight, AppMenuHandler handler,
-            Resources res) {
+            Resources res, boolean translateMenuItemsOnShow) {
         mMenu = menu;
 
         mItemRowHeight = itemRowHeight;
@@ -100,6 +103,7 @@
         mVerticalFadeDistance = res.getDimensionPixelSize(R.dimen.menu_vertical_fade_distance);
 
         mTempLocation = new int[2];
+        mTranslateMenuItemsOnShow = translateMenuItemsOnShow;
     }
 
     /**
@@ -237,8 +241,8 @@
 
         // A List adapter for visible items in the Menu. The first row is added as a header to the
         // list view.
-        mAdapter = new AppMenuAdapter(
-                this, menuItems, LayoutInflater.from(context), highlightedItemId);
+        mAdapter = new AppMenuAdapter(this, menuItems, LayoutInflater.from(context),
+                highlightedItemId, mTranslateMenuItemsOnShow);
 
         ViewGroup contentView =
                 (ViewGroup) LayoutInflater.from(context).inflate(R.layout.app_menu_layout, null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
index e2b5d39..56214441 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -103,6 +103,7 @@
     private final int mNumMenuItems;
     private final Integer mHighlightedItemId;
     private final float mDpToPx;
+    private final boolean mTranslateMenuItemsOnShow;
 
     // Use a single PulseDrawable to spawn the other drawables so that the ConstantState gets
     // shared.  This allows the animation to stay in step even as the views are recycled and the
@@ -111,12 +112,13 @@
     private PulseDrawable mHighlightDrawableSource;
 
     public AppMenuAdapter(AppMenu appMenu, List<MenuItem> menuItems, LayoutInflater inflater,
-            Integer highlightedItemId) {
+            Integer highlightedItemId, boolean translateMenuItemsOnShow) {
         mAppMenu = appMenu;
         mMenuItems = menuItems;
         mInflater = inflater;
         mHighlightedItemId = highlightedItemId;
         mNumMenuItems = menuItems.size();
+        mTranslateMenuItemsOnShow = translateMenuItemsOnShow;
         mDpToPx = inflater.getContext().getResources().getDisplayMetrics().density;
     }
 
@@ -376,15 +378,18 @@
      * @return         The {@link Animator}.
      */
     private Animator buildStandardItemEnterAnimator(final View view, int position) {
-        final float offsetYPx = ENTER_STANDARD_ITEM_OFFSET_Y_DP * mDpToPx;
         final int startDelay = ENTER_ITEM_BASE_DELAY_MS + ENTER_ITEM_ADDL_DELAY_MS * position;
 
         AnimatorSet animation = new AnimatorSet();
-        animation.playTogether(
-                ObjectAnimator.ofFloat(view, View.ALPHA, 0.f, 1.f),
-                ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, offsetYPx, 0.f));
+        if (mTranslateMenuItemsOnShow) {
+            final float offsetYPx = ENTER_STANDARD_ITEM_OFFSET_Y_DP * mDpToPx;
+            animation.playTogether(ObjectAnimator.ofFloat(view, View.ALPHA, 0.f, 1.f),
+                    ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, offsetYPx, 0.f));
+            animation.setStartDelay(startDelay);
+        } else {
+            animation.playTogether(ObjectAnimator.ofFloat(view, View.ALPHA, 0.f, 1.f));
+        }
         animation.setDuration(ENTER_ITEM_DURATION_MS);
-        animation.setStartDelay(startDelay);
         animation.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE);
 
         animation.addListener(new AnimatorListenerAdapter() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java
index 150a279..ca4c2e4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java
@@ -18,6 +18,7 @@
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeActivity;
 
 import java.util.ArrayList;
 
@@ -139,8 +140,10 @@
             Drawable itemDivider = a.getDrawable(1);
             int itemDividerHeight = itemDivider != null ? itemDivider.getIntrinsicHeight() : 0;
             a.recycle();
+            boolean translateMenuItemsOnShow = !(mActivity instanceof ChromeActivity)
+                    || ((ChromeActivity) mActivity).getBottomSheet() == null;
             mAppMenu = new AppMenu(mMenu, itemRowHeight, itemDividerHeight, this,
-                    mActivity.getResources());
+                    mActivity.getResources(), translateMenuItemsOnShow);
             mAppMenuDragHelper = new AppMenuDragHelper(mActivity, mAppMenu, itemRowHeight);
         }
 
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 3de96e67..de4082e 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
@@ -29,6 +29,7 @@
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.vr_shell.VrShellDelegate;
 import org.chromium.components.signin.AccountManagerHelper;
 import org.chromium.components.signin.ChromeSigninController;
 
@@ -396,12 +397,19 @@
                 }
             }
 
+            boolean isVrIntent = VrShellDelegate.isVrIntent(intent);
+            if (isVrIntent) {
+                // Remove VR-specific extras from the intent to Chrome because we don't want the
+                // VR intent to auto-present after the FRE is complete.
+                VrShellDelegate.removeVrExtras(intent);
+            }
             // Add a PendingIntent so that the intent used to launch Chrome will be resent when
             // First Run is completed or canceled.
             addPendingIntent(caller, freIntent, intent, requiresBroadcast);
             freIntent.putExtra(FirstRunActivity.EXTRA_FINISH_ON_TOUCH_OUTSIDE, true);
 
             if (!(caller instanceof Activity)) freIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            if (isVrIntent) freIntent = VrShellDelegate.setupVrFreIntent(caller, freIntent);
             IntentUtils.safeStartActivity(caller, freIntent);
         } else {
             // First Run requires that the Intent contains NEW_TASK so that it doesn't sit on top
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrFirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrFirstRunActivity.java
new file mode 100644
index 0000000..add3c6cb
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrFirstRunActivity.java
@@ -0,0 +1,74 @@
+// 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.
+
+package org.chromium.chrome.browser.vr_shell;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+
+import org.chromium.chrome.browser.util.IntentUtils;
+
+/**
+ * Handles the DOFF flow when Chrome is launched in VR mode and the FRE is not complete. This is
+ * needed because VrCore doesn't allow calling DOFF from a non-active VR activity (b/63435686), so
+ * we can't do it from {@link FirstRunActivity}. The android:enableVrMode attribute in the manifest
+ * makes this a VR activity allowing us to call DOFF before triggering the standard 2D FRE flow.
+ * This should be removed when b/63435686 is fixed.
+ */
+public class VrFirstRunActivity extends Activity {
+    private static final long SHOW_DOFF_TIMEOUT_MS = 500;
+
+    private VrDaydreamApi mApi;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        assert VrShellDelegate.isVrIntent(getIntent());
+        VrClassesWrapper wrapper = VrShellDelegate.createVrClassesWrapper();
+        if (wrapper == null) {
+            showFre();
+            return;
+        }
+
+        // VrCore version M21 allows a transitioning VR activity to call DOFF and requires that
+        // we set VR mode programmatically. Up until then, this hack of having a pure VR activity
+        // works, but there's still a race every now and then that causes Chrome to crash and
+        // that's why we have a timeout below before we call DOFF. Redundantly setting VR mode
+        // here ensures that this never happens for users running the latest version of VrCore.
+        wrapper.setVrModeEnabled(this, true);
+        mApi = wrapper.createVrDaydreamApi(this);
+        if (!mApi.isDaydreamCurrentViewer()) {
+            showFre();
+            return;
+        }
+        // Show DOFF with a timeout so that this activity has enough time to be the active VR app.
+        new Handler().postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                mApi.exitFromVr(VrShellDelegate.EXIT_VR_RESULT, new Intent());
+            }
+        }, SHOW_DOFF_TIMEOUT_MS);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
+        if (requestCode != VrShellDelegate.EXIT_VR_RESULT) return;
+        if (resultCode == Activity.RESULT_OK) {
+            showFre();
+            return;
+        }
+        finish();
+        mApi.launchVrHomescreen();
+    }
+
+    private void showFre() {
+        // Start the actual 2D FRE if the user successfully exited VR.
+        Intent freIntent = (Intent) IntentUtils.safeGetParcelableExtra(
+                getIntent(), VrShellDelegate.VR_FRE_INTENT_EXTRA);
+        IntentUtils.safeStartActivity(this, freIntent);
+        finish();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index 3d675a7..0652f6c73 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -94,6 +94,7 @@
 
     private static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAUNCH";
     private static final String DAYDREAM_HOME_PACKAGE = "com.google.android.vr.home";
+    static final String VR_FRE_INTENT_EXTRA = "org.chromium.chrome.browser.vr_shell.VR_FRE";
 
     // Linter and formatter disagree on how the line below should be formatted.
     /* package */
@@ -420,7 +421,7 @@
     }
 
     @SuppressWarnings("unchecked")
-    private static VrClassesWrapper createVrClassesWrapper() {
+    /* package */ static VrClassesWrapper createVrClassesWrapper() {
         try {
             Class<? extends VrClassesWrapper> vrClassesBuilderClass =
                     (Class<? extends VrClassesWrapper>) Class.forName(
@@ -484,6 +485,13 @@
         return ChromeFeatureList.isEnabled(ChromeFeatureList.VR_SHELL);
     }
 
+    /**
+     *  @return Whether or not VR is supported on this platform.
+     */
+    private static boolean isVrEnabled() {
+        return getVrClassesWrapper() != null;
+    }
+
     private class VSyncEstimator {
         private static final long NANOS_PER_SECOND = 1000000000;
 
@@ -869,12 +877,33 @@
     }
 
     /**
+     * @return An intent that will launch a VR activity that will prompt the
+     * user to take off their headset and foward the freIntent to the standard
+     * 2D FRE activity.
+     */
+    public static Intent setupVrFreIntent(Context context, Intent freIntent) {
+        if (!isVrEnabled()) return freIntent;
+        Intent intent = new Intent();
+        intent.setClassName(context, VrFirstRunActivity.class.getName());
+        intent.putExtra(VR_FRE_INTENT_EXTRA, new Intent(freIntent));
+        intent.putExtra(DAYDREAM_VR_EXTRA, true);
+        return intent;
+    }
+
+    /**
      * @return Whether or not the given intent is a VR-specific intent.
      */
     public static boolean isVrIntent(Intent intent) {
         return IntentUtils.safeGetBooleanExtra(intent, DAYDREAM_VR_EXTRA, false);
     }
 
+    /*
+     * Remove VR-specific extras from the given intent.
+     */
+    public static void removeVrExtras(Intent intent) {
+        intent.removeExtra(DAYDREAM_VR_EXTRA);
+    }
+
     /**
      * @return Options that a VR-specific Chrome activity should be launched with.
      */
@@ -1066,7 +1095,7 @@
 
         if (mInVr) mVSyncEstimator.pause();
 
-        cancelPendingVrEntry();
+        if (!mInVr) cancelPendingVrEntry();
 
         // When the active web page has a vrdisplayactivate event handler,
         // mListeningForWebVrActivate should be set to true, which means a vrdisplayactive event
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
index c73dc37..7f3eed3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -245,6 +245,9 @@
     /** Whether or not the back button was used to enter the tab switcher. */
     private boolean mBackButtonDismissesChrome;
 
+    /** Whether {@link #destroy()} has been called. **/
+    private boolean mIsDestroyed;
+
     /**
      * An interface defining content that can be displayed inside of the bottom sheet for Chrome
      * Home.
@@ -488,6 +491,16 @@
     }
 
     /**
+     * Called when the activity containing the {@link BottomSheet} is destroyed.
+     */
+    public void destroy() {
+        mIsDestroyed = true;
+        mIsTouchEnabled = false;
+        mObservers.clear();
+        endAnimations();
+    }
+
+    /**
      * Handle a back press event.
      *     - If the navigation stack is empty, the sheet will be opened to the half state.
      *         - If the tab switcher is visible, {@link ChromeActivity} will handle the event.
@@ -530,6 +543,13 @@
         setSheetState(BottomSheet.SHEET_STATE_HALF, true);
     }
 
+    /** Immediately end all animations and null the animators. */
+    public void endAnimations() {
+        if (mSettleAnimator != null) mSettleAnimator.end();
+        mSettleAnimator = null;
+        endTransitionAnimations();
+    }
+
     /**
      * Immediately end the bottom sheet content transition animations and null the animator.
      */
@@ -895,6 +915,8 @@
         mContentSwapAnimatorSet.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
+                if (mIsDestroyed) return;
+
                 mSheetContent = content;
                 for (BottomSheetObserver o : mObservers) {
                     o.onSheetContentChanged(content);
@@ -1094,6 +1116,8 @@
         mSettleAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animator) {
+                if (mIsDestroyed) return;
+
                 mSettleAnimator = null;
                 setInternalCurrentState(targetState);
                 mTargetState = SHEET_STATE_NONE;
@@ -1491,12 +1515,4 @@
         mHasShownTextBubble = true;
         preferences.edit().putBoolean(BOTTOM_SHEET_HELP_BUBBLE_SHOWN, true).apply();
     }
-
-    /** Ends all animations. */
-    @VisibleForTesting
-    public void endAnimationsForTests() {
-        if (mSettleAnimator != null) mSettleAnimator.end();
-        mSettleAnimator = null;
-        endTransitionAnimations();
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
index 3a6cc75..7d321f806 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
@@ -34,6 +34,7 @@
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
 import org.chromium.chrome.browser.util.MathUtils;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.BottomSheetContent;
 
@@ -103,7 +104,7 @@
             if (mSelectedItemId != 0 && mSelectedItemId != R.id.action_home) {
                 showBottomSheetContent(R.id.action_home);
             } else {
-                clearBottomSheetContents();
+                clearBottomSheetContents(false);
             }
             // TODO(twellington): determine a policy for destroying the
             //                    SuggestionsBottomSheetContent.
@@ -122,7 +123,7 @@
             }
 
             if (mBottomSheet.getSheetState() == BottomSheet.SHEET_STATE_PEEK) {
-                clearBottomSheetContents();
+                clearBottomSheetContents(false);
             }
         }
 
@@ -142,6 +143,7 @@
     private boolean mShouldOpenSheetOnNextContentChange;
     private PlaceholderSheetContent mPlaceholderContent;
     private boolean mOmniboxHasFocus;
+    private TabModelSelectorObserver mTabModelSelectorObserver;
 
     public BottomSheetContentController(Context context, AttributeSet atts) {
         super(context, atts);
@@ -149,6 +151,19 @@
         mPlaceholderContent = new PlaceholderSheetContent(context);
     }
 
+    /** Called when the activity containing the bottom sheet is destroyed. */
+    public void destroy() {
+        clearBottomSheetContents(true);
+        if (mPlaceholderContent != null) {
+            mPlaceholderContent.destroy();
+            mPlaceholderContent = null;
+        }
+        if (mTabModelSelector != null) {
+            mTabModelSelector.removeObserver(mTabModelSelectorObserver);
+            mTabModelSelector = null;
+        }
+    }
+
     /**
      * Initializes the {@link BottomSheetContentController}.
      * @param bottomSheet The {@link BottomSheet} associated with this bottom nav.
@@ -162,7 +177,7 @@
         mBottomSheet.addObserver(mBottomSheetObserver);
         mActivity = activity;
         mTabModelSelector = tabModelSelector;
-        mTabModelSelector.addObserver(new EmptyTabModelSelectorObserver() {
+        mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() {
             @Override
             public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
                 updateVisuals(newModel.isIncognito());
@@ -176,7 +191,8 @@
                     mBottomSheetContents.remove(INCOGNITO_HOME_ID);
                 }
             }
-        });
+        };
+        mTabModelSelector.addObserver(mTabModelSelectorObserver);
 
         Resources res = getContext().getResources();
         mDistanceBelowToolbarPx = controlContainerHeight
@@ -349,12 +365,14 @@
         return mSelectedItemId;
     }
 
-    public void clearBottomSheetContents() {
+    private void clearBottomSheetContents(boolean destroyHomeContent) {
         Iterator<Entry<Integer, BottomSheetContent>> contentIterator =
                 mBottomSheetContents.entrySet().iterator();
         while (contentIterator.hasNext()) {
             Entry<Integer, BottomSheetContent> entry = contentIterator.next();
-            if (entry.getKey() == R.id.action_home || entry.getKey() == INCOGNITO_HOME_ID) {
+            if (!destroyHomeContent
+                    && (entry.getKey() == R.id.action_home
+                               || entry.getKey() == INCOGNITO_HOME_ID)) {
                 continue;
             }
 
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 46e91dee..ebabaca5 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1168,6 +1168,7 @@
   "java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApi.java",
   "java/src/org/chromium/chrome/browser/vr_shell/VrFeedbackStatus.java",
   "java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java",
+  "java/src/org/chromium/chrome/browser/vr_shell/VrFirstRunActivity.java",
   "java/src/org/chromium/chrome/browser/vr_shell/VrShell.java",
   "java/src/org/chromium/chrome/browser/webapps/ActivityAssigner.java",
   "java/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialog.java",
@@ -1314,13 +1315,6 @@
 
 chrome_test_java_sources = [
   "javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java",
-  "javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestAnnotationTest.java",
-  "javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationInheritanceTest.java",
-  "javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParameterSetAndTest.java",
-  "javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTest.java",
-  "javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTestSetInheritanceTest.java",
-  "javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTestSetTest.java",
-  "javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationTest.java",
   "javatests/src/org/chromium/chrome/browser/AudioTest.java",
   "javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java",
   "javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java",
@@ -1718,10 +1712,8 @@
   "javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetObserverTest.java",
   "javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java",
   "javatests/src/org/chromium/chrome/browser/widget/findinpage/FindTest.java",
-  "javatests/src/org/chromium/chrome/test/ParametersOnMultiTest.java",
   "javatests/src/org/chromium/chrome/test/crash/IntentionalCrashTest.java",
   "javatests/src/org/chromium/chrome/test/util/ChromeSigninUtilsTest.java",
-  "javatests/src/org/chromium/chrome/test/util/parameters/SigninParametersTest.java",
 ]
 
 chrome_junit_test_java_sources = [
diff --git a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestAnnotationTest.java b/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestAnnotationTest.java
deleted file mode 100644
index ae133dc..0000000
--- a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestAnnotationTest.java
+++ /dev/null
@@ -1,388 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import android.app.Activity;
-import android.support.test.filters.SmallTest;
-import android.test.MoreAsserts;
-
-import org.chromium.base.test.BaseActivityInstrumentationTestCase;
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
-
-/**
- * Tester class for the {@link ParameterizedTest} annotation and the {@link ParameterizedTest.Set}
- * annotation.
- *
- * Also, tests the {@link MethodParameter} parameter.
- */
-public class ParameterizedTestAnnotationTest extends
-        BaseActivityInstrumentationTestCase<Activity> {
-    public ParameterizedTestAnnotationTest() {
-        super(Activity.class);
-    }
-
-    @SmallTest
-    public void testNoParameterizedTestAnnotation() {
-        assertFalse("This is a parameterized test when it should not be.", getParameterReader()
-                .isParameterizedTest());
-        assertNull("someParameter should not exist.", getParameterReader()
-                .getParameter("someParameter"));
-        assertNull("someParameterArgument should not exist.", getParameterReader()
-                .getParameterArgument("someParameter", "someParameterArgument"));
-    }
-
-    @SmallTest
-    @ParameterizedTest()
-    public void testEmptyParameterizedTestAnnotation() {
-        assertTrue("This is not a parameterized test.", getParameterReader()
-                .isParameterizedTest());
-        assertNull("someParameter should not exist.", getParameterReader()
-                .getParameter("someParameter"));
-        assertNull("someParameterArgument should not exist.", getParameterReader()
-                .getParameterArgument("someParameter", "someParameterArgument"));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {})
-    public void testParameterizedTestWithEmptyParameters() {
-        assertTrue("This is not a parameterized test.", getParameterReader()
-                .isParameterizedTest());
-        assertNull("someParameter should not exist.", getParameterReader()
-                .getParameter("someParameter"));
-        assertNull("someParameterArgument should not exist.", getParameterReader()
-                .getParameterArgument("someParameter", "someParameterArgument"));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {})
-    public void testParameterDoesNotExist() {
-        Parameter parameter = getParameterReader().getParameter(MethodParameter.PARAMETER_TAG);
-        assertNull("method-parameter should not exist.", parameter);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {@Parameter(tag = MethodParameter.PARAMETER_TAG)})
-    public void testGetParameter() {
-        String expected = "method-parameter";
-        String actual = getParameterReader().getParameter(MethodParameter.PARAMETER_TAG).tag();
-        assertEquals("Parameter tag did not match expected.", expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {@Parameter(tag = MethodParameter.PARAMETER_TAG)})
-    public void testParameterArgumentDoesNotExist() {
-        Parameter.Argument actual = getArgument("arg");
-        assertNull("arg should not exist.", actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "string", stringVar = "value")})})
-    public void testMethodParametersWithOneStringValue() {
-        String expected = "value";
-        String actual = getArgument("string").stringVar();
-        assertEquals(mismatchMessage("string"), expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "int", intVar = 0)})})
-    public void testMethodParametersWithOneIntValue() {
-        int expected = 0;
-        int actual = getArgument("int").intVar();
-        assertEquals(mismatchMessage("int"), expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(name = "intArray", intArray = {5, 10, -6, 0, -1})})
-            })
-    public void testMethodParametersWithOneIntArrayValue() {
-        int[] expected = new int[] {5, 10, -6, 0, -1};
-        int[] actual = getArgument("intArray").intArray();
-        assertEquals("Expected length and actual length are different.", expected.length,
-                actual.length);
-        MoreAsserts.assertEquals(mismatchMessage("intArray"), expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "stringArray", stringArray = {
-                            "apple", "banana", "orange", "melon", "lemon"})})})
-    public void testMethodParametersWithOneStringArrayValue() {
-        String[] expected = new String[] {"apple", "banana", "orange", "melon", "lemon"};
-        String[] actual = getArgument("stringArray").stringArray();
-        assertEquals("Expected length and actual length are different.", expected.length,
-                actual.length);
-        MoreAsserts.assertEquals(mismatchMessage("stringArary"), expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(name = "string1", stringVar = "has vowel"),
-                            @Parameter.Argument(name = "string2", stringVar = "hs vwl"),
-                            @Parameter.Argument(name = "stringArray1", stringArray = {
-                                    "apple", "banana", "orange", "melon", "lemon"}),
-                            @Parameter.Argument(name = "stringArray2", stringArray = {
-                                    "ppl", "bnn", "mln", "lmn"}),
-                            @Parameter.Argument(name = "int1", intVar = 2),
-                            @Parameter.Argument(name = "int2", intVar = 10),
-                            @Parameter.Argument(name = "intArray1", intArray = {
-                                    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}),
-                            @Parameter.Argument(name = "intArray2", intArray = {4})})})
-    public void testMethodParametersWithMultipleArguments1() {
-        String stringVar = getArgument("string1").stringVar();
-        assertEquals(mismatchMessage("string1"), "has vowel", stringVar);
-
-        stringVar = getArgument("string2").stringVar();
-        assertEquals(mismatchMessage("string2"), "hs vwl", stringVar);
-
-        int intVar = getArgument("int1").intVar();
-        assertEquals(mismatchMessage("int1"), 2, intVar);
-
-        intVar = getArgument("int2").intVar();
-        assertEquals(mismatchMessage("int2"), 10, intVar);
-
-        String[] stringArray = getArgument("stringArray1").stringArray();
-        String[] expectedStringArray = new String[] {"apple", "banana", "orange", "melon", "lemon"};
-        MoreAsserts.assertEquals("stringArray1 did not match", expectedStringArray, stringArray);
-
-        stringArray = getArgument("stringArray2").stringArray();
-        expectedStringArray = new String[] {"ppl", "bnn", "mln", "lmn"};
-        MoreAsserts.assertEquals("stringArray2 did not match", expectedStringArray, stringArray);
-
-        int[] intArray = getArgument("intArray1").intArray();
-        int[] expectedIntArray = new int[] {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
-        MoreAsserts.assertEquals("intArray1 did not match", expectedIntArray, intArray);
-
-        intArray = getArgument("intArray2").intArray();
-        expectedIntArray = new int[] {4};
-        MoreAsserts.assertEquals("intArray2 did not match", expectedIntArray, intArray);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(
-                    tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(name = "string1", stringVar = "testvalue"),
-                            @Parameter.Argument(name = "string2", stringVar = "blahblah"),
-                            @Parameter.Argument(name = "int1", intVar = 4),
-                            @Parameter.Argument(name = "int2", intVar = 0)})})
-    public void testMethodParametersWithMultipleArguments2() {
-        assertEquals("bar variable should equals \"testvalue\"", "testvalue",
-                getArgument("string1").stringVar());
-        assertEquals("foo variable should equals \"blahblah\"", "blahblah",
-                getArgument("string2").stringVar());
-        assertEquals("intArg1 variable should equals 4", 4,
-                getArgument("int1").intVar());
-        assertEquals("intArg2 variable should equals 0", 0,
-                getArgument("int2").intVar());
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "string", stringVar = "t_val")})})
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "string", stringVar = "s_val")})})})
-    public void testParameterizedSetOverridesParameterizedTest() {
-        String expected = "s_val";
-        String actual = getArgument("string").stringVar();
-        assertEquals("Expected the value set via @ParameterizedTest.Set", expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "string1", stringVar = "testvalue"),
-                                    @Parameter.Argument(name = "string2", stringVar = "blahblah"),
-                                    @Parameter.Argument(name = "int1", intVar = 4),
-                                    @Parameter.Argument(name = "int2", intVar = 0)})})})
-    public void testParameterArgumentsWithParameterSetOfOneTest() {
-        assertEquals("bar variable should equals \"testvalue\"", "testvalue",
-                getArgument("string1").stringVar());
-        assertEquals("foo variable should equals \"blahblah\"", "blahblah",
-                getArgument("string2").stringVar());
-        assertEquals("intArg1 variable should equals 4", 4,
-                getArgument("int1").intVar());
-        assertEquals("intArg2 variable should equals 0", 0,
-                getArgument("int2").intVar());
-    }
-
-    /**
-     *  These next three tests all accomplish the same task but in different ways.
-     *
-     *  testParameterArgumentsWithParameterSetOfMoreThanOneTest tests fib() by having a set for
-     *  each possible input. While this is fine, it is rather verbose.
-     *
-     *  Continued @ testSingleTestParameterArgumentsWithParameterSet
-     */
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 1),
-                                    @Parameter.Argument(name = "output", intVar = 0)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 2),
-                                    @Parameter.Argument(name = "output", intVar = 1)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 3),
-                                    @Parameter.Argument(name = "output", intVar = 1)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 4),
-                                    @Parameter.Argument(name = "output", intVar = 2)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 5),
-                                    @Parameter.Argument(name = "output", intVar = 3)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 6),
-                                    @Parameter.Argument(name = "output", intVar = 5)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 7),
-                                    @Parameter.Argument(name = "output", intVar = 8)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 8),
-                                    @Parameter.Argument(name = "output", intVar = 13)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 9),
-                                    @Parameter.Argument(name = "output", intVar = 21)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 10),
-                                    @Parameter.Argument(name = "output", intVar = 34)})})})
-    public void testParameterArgumentsWithParameterSetOfMoreThanOneTest() {
-        int input = getArgument("input").intVar();
-        int expected = getArgument("output").intVar();
-        int actual = fib(input);
-        assertEquals("Output should be the fibonacci number at index input.", expected, actual);
-    }
-
-    /**
-     * This is better than the implementation of
-     * testParameterArgumentsWithParameterSetOfMoreThanOneTest. It reduces the number of
-     * {@link ParameterizedTest} annotations by using an intArray instead of an intVar.
-     * Computationally, this will be faster too because it only has to set up the parameters once
-     * for the single ParameterizedTest.
-     *
-     * Continued @ testSingleTestParameterArgumentsWithParameterSet
-     */
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input",
-                                            intArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}),
-                                    @Parameter.Argument(name = "expected",
-                                            intArray = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34})})})})
-    public void testSingleTestParameterArgumentsWithParameterSet() {
-        int[] input = getArgument("input").intArray();
-        int[] expected = getArgument("expected").intArray();
-        int[] actual = new int[input.length];
-        for (int i = 0; i < input.length; i++) {
-            actual[i] = fib(input[i]);
-        }
-        MoreAsserts.assertEquals("Output should be the fibonacci number at each index input.",
-                expected, actual);
-    }
-
-    /**
-     * This is the best implementation to test fibonacci.
-     *
-     * It's computationally the same speed at testSingleTestParameterArgumentsWithParameterSet. But
-     * we don't need to actually have a ParameterizedTestSet.
-     */
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(
-                    tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(name = "input",
-                                    intArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}),
-                            @Parameter.Argument(name = "expected",
-                                    intArray = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34})})})
-    public void testSingleTestParameterArgumentsWithoutParameterSet() {
-        int[] input = getArgument("input").intArray();
-        int[] expected = getArgument("expected").intArray();
-        int[] actual = new int[input.length];
-        for (int i = 0; i < input.length; i++) {
-            actual[i] = fib(input[i]);
-        }
-        MoreAsserts.assertEquals("Output should be the fibonacci number at each index input.",
-                expected, actual);
-    }
-
-    private static String mismatchMessage(String name) {
-        return String.format("The ParameterArgument %s does not match expected value.", name);
-    }
-
-    private static int fib(int input) {
-        if (input <= 0) {
-            throw new IllegalArgumentException("Input must be greater than 0.");
-        }
-        if (input == 1) {
-            return 0;
-        }
-        if (input == 2) {
-            return 1;
-        }
-        int[] temp = new int[input];
-        temp[0] = 0;
-        temp[1] = 1;
-        for (int i = 2; i < input; i++) {
-            temp[i] = temp[i - 1] + temp[i - 2];
-        }
-        return temp[input - 1];
-    }
-
-    private Parameter.Argument getArgument(String name) {
-        return getParameterReader().getParameterArgument(MethodParameter.PARAMETER_TAG, name);
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationInheritanceTest.java b/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationInheritanceTest.java
deleted file mode 100644
index 95fafd0d..0000000
--- a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationInheritanceTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import android.support.test.filters.SmallTest;
-
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
-
-/**
- * Tester class for inheritance of the {@link ParameterizedTest} annotation applied to a TestCase
- * class.
- */
-public class ParameterizedTestClassAnnotationInheritanceTest extends
-        ParameterizedTestClassAnnotationTest {
-    public ParameterizedTestClassAnnotationInheritanceTest() {
-        super();
-    }
-
-    @SmallTest
-    public void testNoParameterizedTestAnnotation() {
-        super.testNoParameterizedTestAnnotation();
-    }
-
-    @SmallTest
-    @ParameterizedTest()
-    public void testEmptyParameterizedTestAnnotation() {
-        super.testEmptyParameterizedTestAnnotation();
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "string", stringVar = "value")})})
-    public void testMethodParametersWithOneStringValue() {
-        super.testMethodParametersWithOneStringValue();
-    }
-
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "string", stringVar = "s_val")})})})
-    public void testParameterizedSetOverridesParameterizedTest() {
-        super.testParameterizedSetOverridesParameterizedTest();
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParameterSetAndTest.java b/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParameterSetAndTest.java
deleted file mode 100644
index adf3f97..0000000
--- a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParameterSetAndTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import android.app.Activity;
-import android.support.test.filters.SmallTest;
-
-import org.chromium.base.test.BaseActivityInstrumentationTestCase;
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
-
-/**
- * Tester class for priority of {@link ParameterizedTest} and {@link ParameterizedTest.Set}
- * annotations applied to a TestCase class.
- */
-@ParameterizedTest(parameters = {
-        @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                arguments = {@Parameter.Argument(name = "string", stringVar = "t_val")})})
-@ParameterizedTest.Set(tests = {
-        @ParameterizedTest(parameters = {
-                @Parameter(
-                        tag = MethodParameter.PARAMETER_TAG,
-                        arguments = {
-                                @Parameter.Argument(name = "string", stringVar = "s_val")})})})
-public class ParameterizedTestClassAnnotationParameterSetAndTest extends
-        BaseActivityInstrumentationTestCase<Activity> {
-    public ParameterizedTestClassAnnotationParameterSetAndTest() {
-        super(Activity.class);
-    }
-
-    @SmallTest
-    public void testParameterizedSetOverridesParameterizedTest() {
-        String expected = "s_val";
-        String actual = getArgument("string").stringVar();
-        assertEquals("Expected the value set via @ParameterizedTest.Set", expected, actual);
-    }
-
-    private Parameter.Argument getArgument(String name) {
-        return getParameterReader().getParameterArgument(MethodParameter.PARAMETER_TAG, name);
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTest.java b/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTest.java
deleted file mode 100644
index f916b0e8..0000000
--- a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import android.app.Activity;
-import android.support.test.filters.SmallTest;
-
-import org.chromium.base.test.BaseActivityInstrumentationTestCase;
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
-
-/**
- * Tester class for the {@link ParameterizedTest} annotation with parameters
- * applied to a TestCase class.
- */
-@ParameterizedTest(parameters = {
-        @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                arguments = {
-                        @Parameter.Argument(name = "c_string", stringVar = "value"),
-                        @Parameter.Argument(name = "c_int", intVar = 0)})})
-public class ParameterizedTestClassAnnotationParametersTest extends
-        BaseActivityInstrumentationTestCase<Activity> {
-    public ParameterizedTestClassAnnotationParametersTest() {
-        super(Activity.class);
-    }
-
-    @SmallTest
-    public void testClassParametersFromClassAnnotation() {
-        String expectedString = "value";
-        String actualString = getArgument("c_string").stringVar();
-        assertEquals(mismatchMessage("c_string"), expectedString, actualString);
-        int expectedInt = 0;
-        int actualInt = getArgument("c_int").intVar();
-        assertEquals(mismatchMessage("c_int"), expectedInt, actualInt);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "m_string", stringVar = "value")})})
-    public void testMethodParametersWithOneStringValue() {
-        // Method parameter overrides class parameter.
-        assertNotNull("m_string parameter should exist", getArgument("m_string"));
-        String expected = "value";
-        String actual = getArgument("m_string").stringVar();
-        assertEquals(mismatchMessage("m_string"), expected, actual);
-        assertNull("c_string parameter should not exist", getArgument("c_string"));
-        assertNull("c_int parameter should not exist", getArgument("c_int"));
-    }
-
-    private static String mismatchMessage(String name) {
-        return String.format("The ParameterArgument %s does not match expected value.", name);
-    }
-
-    private Parameter.Argument getArgument(String name) {
-        return getParameterReader().getParameterArgument(MethodParameter.PARAMETER_TAG, name);
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTestSetInheritanceTest.java b/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTestSetInheritanceTest.java
deleted file mode 100644
index f1e77c2..0000000
--- a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTestSetInheritanceTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import android.support.test.filters.SmallTest;
-
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
-
-/**
- * Tester class for inheritance of the {@link ParameterizedTest.Set} annotation applied to a
- * TestCase class.
- */
-public class ParameterizedTestClassAnnotationParametersTestSetInheritanceTest extends
-        ParameterizedTestClassAnnotationParametersTestSetTest {
-    public ParameterizedTestClassAnnotationParametersTestSetInheritanceTest() {
-        super();
-    }
-
-    @SmallTest
-    public void testMethodParametersFromClassAnnotation() {
-        super.testMethodParametersFromClassAnnotation();
-    }
-
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "m_string", stringVar = "value"),
-                                    @Parameter.Argument(name = "m_int", intVar = 0)})})})
-    public void testClassAndMethodParameterSets() {
-        super.testClassAndMethodParameterSets();
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "c_string1", stringVar = "t_val")})})
-    public void testParameterizedSetOverridesParameterizedTest() {
-        super.testParameterizedSetOverridesParameterizedTest();
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTestSetTest.java b/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTestSetTest.java
deleted file mode 100644
index e86bb58..0000000
--- a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationParametersTestSetTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import android.app.Activity;
-import android.support.test.filters.SmallTest;
-
-import org.chromium.base.test.BaseActivityInstrumentationTestCase;
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
-
-/**
- * Tester class for the {@link ParameterizedTest.Set} annotation applied to a TestCase class.
- */
-@ParameterizedTest.Set(tests = {
-        @ParameterizedTest(parameters = {
-                @Parameter(
-                        tag = MethodParameter.PARAMETER_TAG,
-                        arguments = {
-                                @Parameter.Argument(name = "c_string1", stringVar = "testvalue"),
-                                @Parameter.Argument(name = "c_string2", stringVar = "blahblah"),
-                                @Parameter.Argument(name = "c_int1", intVar = 4),
-                                @Parameter.Argument(name = "c_int2", intVar = 0)})})})
-public class ParameterizedTestClassAnnotationParametersTestSetTest extends
-        BaseActivityInstrumentationTestCase<Activity> {
-    public ParameterizedTestClassAnnotationParametersTestSetTest() {
-        super(Activity.class);
-    }
-
-    @SmallTest
-    public void testMethodParametersFromClassAnnotation() {
-        assertEquals("c_string1 variable should equals \"testvalue\"", "testvalue",
-                getArgument("c_string1").stringVar());
-        assertEquals("c_string2 variable should equals \"blahblah\"", "blahblah",
-                getArgument("c_string2").stringVar());
-        assertEquals("c_int1 variable should equals 4", 4, getArgument("c_int1").intVar());
-        assertEquals("c_int2 variable should equals 0", 0, getArgument("c_int2").intVar());
-    }
-
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "m_string", stringVar = "value"),
-                                    @Parameter.Argument(name = "m_int", intVar = 0)})})})
-    public void testClassAndMethodParameterSets() {
-        // Method parameter overrides class parameter.
-        assertNotNull("m_string parameter should exist", getArgument("m_string"));
-        String expectedString = "value";
-        String actualString = getArgument("m_string").stringVar();
-        assertEquals(mismatchMessage("m_string"), expectedString, actualString);
-        int expectedInt = 0;
-        int actualInt = getArgument("m_int").intVar();
-        assertEquals(mismatchMessage("m_int"), expectedInt, actualInt);
-        assertNull("c_string1 parameter should not exist", getArgument("c_string1"));
-        assertNull("c_string2 parameter should not exist", getArgument("c_string2"));
-        assertNull("c_int1 parameter should not exist", getArgument("c_int1"));
-        assertNull("c_int2 parameter should not exist", getArgument("c_int2"));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "c_string1", stringVar = "t_val")})})
-    public void testParameterizedSetOverridesParameterizedTest() {
-        String expected = "testvalue";
-        String actual = getArgument("c_string1").stringVar();
-        assertEquals("Expected the value set via @ParameterizedTest.Set", expected, actual);
-    }
-
-    private static String mismatchMessage(String name) {
-        return String.format("The ParameterArgument %s does not match expected value.", name);
-    }
-
-    private Parameter.Argument getArgument(String name) {
-        return getParameterReader().getParameterArgument(MethodParameter.PARAMETER_TAG, name);
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationTest.java b/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationTest.java
deleted file mode 100644
index b7c1fcce..0000000
--- a/chrome/android/javatests/src/org/chromium/base/test/util/parameter/ParameterizedTestClassAnnotationTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.test.util.parameter;
-
-import android.app.Activity;
-import android.support.test.filters.SmallTest;
-
-import org.chromium.base.test.BaseActivityInstrumentationTestCase;
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
-
-/**
- * Tester class for the {@link ParameterizedTest} annotation applied to a TestCase class.
- */
-@ParameterizedTest(parameters = {@Parameter(tag = MethodParameter.PARAMETER_TAG)})
-public class ParameterizedTestClassAnnotationTest extends
-        BaseActivityInstrumentationTestCase<Activity> {
-    public ParameterizedTestClassAnnotationTest() {
-        super(Activity.class);
-    }
-
-    @SmallTest
-    public void testNoParameterizedTestAnnotation() {
-        // The test is parametrized because the entire test case class is parametrized.
-        assertTrue("This is not a parameterized test.", getParameterReader()
-                .isParameterizedTest());
-        assertEquals(0,
-                getParameterReader().getParameter(
-                        MethodParameter.PARAMETER_TAG).arguments().length);
-        assertNull("someParameter should not exist.", getParameterReader()
-                .getParameter("someParameter"));
-        assertNull("someParameterArgument should not exist.", getParameterReader()
-                .getParameterArgument("someParameter", "someParameterArgument"));
-    }
-
-    @SmallTest
-    @ParameterizedTest()
-    public void testEmptyParameterizedTestAnnotation() {
-        assertTrue("This is not a parameterized test.", getParameterReader()
-                .isParameterizedTest());
-        assertNull("someParameter should not exist.", getParameterReader()
-                .getParameter("someParameter"));
-        assertNull("someParameterArgument should not exist.", getParameterReader()
-                .getParameterArgument("someParameter", "someParameterArgument"));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "string", stringVar = "value")})})
-    public void testMethodParametersWithOneStringValue() {
-        // Method parameter overrides class parameter.
-        assertNotNull("string parameter should exist.", getArgument("string"));
-        String expected = "value";
-        String actual = getArgument("string").stringVar();
-        assertEquals(mismatchMessage("string"), expected, actual);
-        assertNull("someParameter should not exist.", getParameterReader()
-                .getParameter("someParameter"));
-        assertNull("someParameterArgument should not exist.", getParameterReader()
-                .getParameterArgument("someParameter", "someParameterArgument"));
-    }
-
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "string", stringVar = "s_val")})})})
-    public void testParameterizedSetOverridesParameterizedTest() {
-        String expected = "s_val";
-        String actual = getArgument("string").stringVar();
-        assertEquals("Expected the value set via @ParameterizedTest.Set", expected, actual);
-    }
-
-    private static String mismatchMessage(String name) {
-        return String.format("The ParameterArgument %s does not match expected value.", name);
-    }
-
-    private Parameter.Argument getArgument(String name) {
-        return getParameterReader().getParameterArgument(MethodParameter.PARAMETER_TAG, name);
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
index 0e897e1..b667c9a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
@@ -35,8 +35,7 @@
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.base.test.util.ScalableTimeout;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.CommandLineParameter;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
@@ -69,23 +68,14 @@
 
 /**
  * Tests of the Omnibox.
+ *
+ * TODO(yolandyan): Replace the CommandLineParameter with new JUnit4 parameterized
+ * framework once it supports Test Rule Parameterization
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
-@ParameterizedTest.Set(tests = {
-        @ParameterizedTest(parameters = {
-                @Parameter(
-                        tag = CommandLineFlags.Parameter.PARAMETER_TAG)}),
-        @ParameterizedTest(parameters = {
-                @Parameter(
-                        tag = CommandLineFlags.Parameter.PARAMETER_TAG,
-                        arguments = {
-                                @Parameter.Argument(
-                                        name = CommandLineFlags.Parameter.ADD_ARG,
-                                        stringArray = {"enable-features="
-                                                + ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE})
-        })})})
+@CommandLineParameter({"", "enable-features=" + ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE})
 public class OmniboxTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
index 01225c1..932c3ee 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
@@ -31,8 +31,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
+import org.chromium.base.test.util.parameter.CommandLineParameter;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
@@ -54,23 +53,14 @@
 
 /**
  * Tests for the URL bar UI component.
+ *
+ * TODO(yolandyan): Replace the CommandLineParameter with new JUnit4 parameterized
+ * framework once it supports Test Rule Parameterization
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
-@ParameterizedTest.Set(tests = {
-        @ParameterizedTest(parameters = {
-                @Parameter(
-                        tag = CommandLineFlags.Parameter.PARAMETER_TAG)}),
-        @ParameterizedTest(parameters = {
-                @Parameter(
-                        tag = CommandLineFlags.Parameter.PARAMETER_TAG,
-                        arguments = {
-                                @Parameter.Argument(
-                                        name = CommandLineFlags.Parameter.ADD_ARG,
-                                        stringArray = {"enable-features="
-                                                + ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE})
-        })})})
+@CommandLineParameter({"", "enable-features=" + ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE})
 public class UrlBarTest {
     // 9000+ chars of goodness
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java
index 7320f19..6f6eacf9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java
@@ -275,7 +275,7 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mBottomSheet.endAnimationsForTests();
+                mBottomSheet.endAnimations();
             }
         });
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java
index 80ae4b39..982449c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java
@@ -520,7 +520,7 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mBottomSheet.endAnimationsForTests();
+                mBottomSheet.endAnimations();
             }
         });
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/test/ParametersOnMultiTest.java b/chrome/android/javatests/src/org/chromium/chrome/test/ParametersOnMultiTest.java
deleted file mode 100644
index d346bb0..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/test/ParametersOnMultiTest.java
+++ /dev/null
@@ -1,557 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.test;
-
-import android.support.test.filters.SmallTest;
-import android.test.MoreAsserts;
-
-import org.chromium.base.test.util.EnormousTest;
-import org.chromium.base.test.util.FlakyTest;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
-import org.chromium.chrome.test.util.parameters.AddFakeAccountToAppParameter;
-import org.chromium.chrome.test.util.parameters.AddFakeAccountToOsParameter;
-import org.chromium.chrome.test.util.parameters.AddGoogleAccountToOsParameter;
-
-/**
- * Tester class for the {@link ParameterizedTest} annotation and the {@link ParameterizedTest.Set}
- * annotation on {@link MultiActivityTestBase}.
- *
- * TODO (crbug.com/522503): Merge these tests with {@link ParameterizedTestAnnotationTest} when a
- * parameter that runs tests on different test base activites exists.
- */
-public class ParametersOnMultiTest extends MultiActivityTestBase {
-    private static final String GOOGLE_ACCOUNT_USERNAME = "chromiumforandroid01@gmail.com";
-    private static final String GOOGLE_ACCOUNT_PASSWORD = "chromeforandroid";
-
-    private AddFakeAccountToAppParameter mAddFakeAccountToAppParameter;
-    private AddFakeAccountToOsParameter mAddFakeAccountToOsParameter;
-    private AddGoogleAccountToOsParameter mAddGoogleAccountToOsParameter;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mAddFakeAccountToAppParameter =
-                getAvailableParameter(AddFakeAccountToAppParameter.PARAMETER_TAG);
-        mAddFakeAccountToOsParameter =
-                getAvailableParameter(AddFakeAccountToOsParameter.PARAMETER_TAG);
-        mAddGoogleAccountToOsParameter =
-                getAvailableParameter(AddGoogleAccountToOsParameter.PARAMETER_TAG);
-    }
-
-    @SmallTest
-    @RetryOnFailure
-    public void testNoParameterizedTestAnnotation() {
-        assertFalse("This is a parameterized test when it should not be.", getParameterReader()
-                .isParameterizedTest());
-        assertNull("someParameter should not exist.", getParameterReader()
-                .getParameter("someParameter"));
-        assertNull("someParameterArgument should not exist.", getParameterReader()
-                .getParameterArgument("someParameter", "someParameterArgument"));
-    }
-
-    @SmallTest
-    @ParameterizedTest()
-    @RetryOnFailure
-    public void testEmptyParameterizedTestAnnotation() {
-        assertTrue("This is not a parameterized test.", getParameterReader()
-                .isParameterizedTest());
-        assertNull("someParameter should not exist.", getParameterReader()
-                .getParameter("someParameter"));
-        assertNull("someParameterArgument should not exist.", getParameterReader()
-                .getParameterArgument("someParameter", "someParameterArgument"));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {})
-    @RetryOnFailure
-    public void testParameterizedTestWithEmptyParameters() {
-        assertTrue("This is not a parameterized test.", getParameterReader()
-                .isParameterizedTest());
-        assertNull("someParameter should not exist.", getParameterReader()
-                .getParameter("someParameter"));
-        assertNull("someParameterArgument should not exist.", getParameterReader()
-                .getParameterArgument("someParameter", "someParameterArgument"));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {})
-    @RetryOnFailure
-    public void testParameterDoesNotExist() {
-        Parameter parameter = getParameterReader().getParameter(MethodParameter.PARAMETER_TAG);
-        assertNull("method-parameter should not exist.", parameter);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {@Parameter(tag = MethodParameter.PARAMETER_TAG)})
-    @RetryOnFailure
-    public void testGetParameter() {
-        String expected = "method-parameter";
-        String actual = getParameterReader().getParameter(MethodParameter.PARAMETER_TAG).tag();
-        assertEquals("Parameter tag did not match expected.", expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {@Parameter(tag = MethodParameter.PARAMETER_TAG)})
-    @RetryOnFailure
-    public void testParameterArgumentDoesNotExist() {
-        Parameter.Argument actual = getArgument("arg");
-        assertNull("arg should not exist.", actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "string", stringVar = "value")})})
-    @RetryOnFailure
-    public void testMethodParametersWithOneStringValue() {
-        String expected = "value";
-        String actual = getArgument("string").stringVar();
-        assertEquals(mismatchMessage("string"), expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "int", intVar = 0)})})
-    @RetryOnFailure
-    public void testMethodParametersWithOneIntValue() {
-        int expected = 0;
-        int actual = getArgument("int").intVar();
-        assertEquals(mismatchMessage("int"), expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(name = "intArray", intArray = {5, 10, -6, 0, -1})})
-            })
-    @RetryOnFailure
-    public void testMethodParametersWithOneIntArrayValue() {
-        int[] expected = new int[] {5, 10, -6, 0, -1};
-        int[] actual = getArgument("intArray").intArray();
-        assertEquals("Expected length and actual length are different.", expected.length,
-                actual.length);
-        MoreAsserts.assertEquals(mismatchMessage("intArray"), expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {@Parameter.Argument(name = "stringArray", stringArray = {
-                            "apple", "banana", "orange", "melon", "lemon"})})})
-    @RetryOnFailure
-    public void testMethodParametersWithOneStringArrayValue() {
-        String[] expected = new String[] {"apple", "banana", "orange", "melon", "lemon"};
-        String[] actual = getArgument("stringArray").stringArray();
-        assertEquals("Expected length and actual length are different.", expected.length,
-                actual.length);
-        MoreAsserts.assertEquals(mismatchMessage("stringArary"), expected, actual);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(name = "string1", stringVar = "has vowel"),
-                            @Parameter.Argument(name = "string2", stringVar = "hs vwl"),
-                            @Parameter.Argument(name = "stringArray1", stringArray = {
-                                    "apple", "banana", "orange", "melon", "lemon"}),
-                            @Parameter.Argument(name = "stringArray2", stringArray = {
-                                    "ppl", "bnn", "mln", "lmn"}),
-                            @Parameter.Argument(name = "int1", intVar = 2),
-                            @Parameter.Argument(name = "int2", intVar = 10),
-                            @Parameter.Argument(name = "intArray1", intArray = {
-                                    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}),
-                            @Parameter.Argument(name = "intArray2", intArray = {4})})})
-    @RetryOnFailure
-    public void testMethodParametersWithMultipleArguments1() {
-        String stringVar = getArgument("string1").stringVar();
-        assertEquals(mismatchMessage("string1"), "has vowel", stringVar);
-
-        stringVar = getArgument("string2").stringVar();
-        assertEquals(mismatchMessage("string2"), "hs vwl", stringVar);
-
-        int intVar = getArgument("int1").intVar();
-        assertEquals(mismatchMessage("int1"), 2, intVar);
-
-        intVar = getArgument("int2").intVar();
-        assertEquals(mismatchMessage("int2"), 10, intVar);
-
-        String[] stringArray = getArgument("stringArray1").stringArray();
-        String[] expectedStringArray = new String[] {"apple", "banana", "orange", "melon", "lemon"};
-        MoreAsserts.assertEquals("stringArray1 did not match", expectedStringArray, stringArray);
-
-        stringArray = getArgument("stringArray2").stringArray();
-        expectedStringArray = new String[] {"ppl", "bnn", "mln", "lmn"};
-        MoreAsserts.assertEquals("stringArray2 did not match", expectedStringArray, stringArray);
-
-        int[] intArray = getArgument("intArray1").intArray();
-        int[] expectedIntArray = new int[] {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
-        MoreAsserts.assertEquals("intArray1 did not match", expectedIntArray, intArray);
-
-        intArray = getArgument("intArray2").intArray();
-        expectedIntArray = new int[] {4};
-        MoreAsserts.assertEquals("intArray2 did not match", expectedIntArray, intArray);
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(
-                    tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(name = "string1", stringVar = "testvalue"),
-                            @Parameter.Argument(name = "string2", stringVar = "blahblah"),
-                            @Parameter.Argument(name = "int1", intVar = 4),
-                            @Parameter.Argument(name = "int2", intVar = 0)})})
-    @RetryOnFailure
-    public void testMethodParametersWithMultipleArguments2() {
-        assertEquals("bar variable should equals \"testvalue\"", "testvalue",
-                getArgument("string1").stringVar());
-        assertEquals("foo variable should equals \"blahblah\"", "blahblah",
-                getArgument("string2").stringVar());
-        assertEquals("intArg1 variable should equals 4", 4,
-                getArgument("int1").intVar());
-        assertEquals("intArg2 variable should equals 0", 0,
-                getArgument("int2").intVar());
-    }
-
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "string1", stringVar = "testvalue"),
-                                    @Parameter.Argument(name = "string2", stringVar = "blahblah"),
-                                    @Parameter.Argument(name = "int1", intVar = 4),
-                                    @Parameter.Argument(name = "int2", intVar = 0)})})})
-    @RetryOnFailure
-    public void testParameterArgumentsWithParameterSetOfOneTest() {
-        assertEquals("bar variable should equals \"testvalue\"", "testvalue",
-                getArgument("string1").stringVar());
-        assertEquals("foo variable should equals \"blahblah\"", "blahblah",
-                getArgument("string2").stringVar());
-        assertEquals("intArg1 variable should equals 4", 4,
-                getArgument("int1").intVar());
-        assertEquals("intArg2 variable should equals 0", 0,
-                getArgument("int2").intVar());
-    }
-
-    /**
-     *  These next three tests all accomplish the same task but in different ways.
-     *
-     *  testParameterArgumentsWithParameterSetOfMoreThanOneTest tests fib() by having a set for
-     *  each possible input. While this is fine, it is rather verbose.
-     *
-     *  Continued @ testSingleTestParameterArgumentsWithParameterSet
-     */
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 1),
-                                    @Parameter.Argument(name = "output", intVar = 0)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 2),
-                                    @Parameter.Argument(name = "output", intVar = 1)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 3),
-                                    @Parameter.Argument(name = "output", intVar = 1)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 4),
-                                    @Parameter.Argument(name = "output", intVar = 2)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 5),
-                                    @Parameter.Argument(name = "output", intVar = 3)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 6),
-                                    @Parameter.Argument(name = "output", intVar = 5)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 7),
-                                    @Parameter.Argument(name = "output", intVar = 8)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 8),
-                                    @Parameter.Argument(name = "output", intVar = 13)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 9),
-                                    @Parameter.Argument(name = "output", intVar = 21)})}),
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input", intVar = 10),
-                                    @Parameter.Argument(name = "output", intVar = 34)})})})
-    @RetryOnFailure
-    public void testParameterArgumentsWithParameterSetOfMoreThanOneTest() {
-        int input = getArgument("input").intVar();
-        int expected = getArgument("output").intVar();
-        int actual = fib(input);
-        assertEquals("Output should be the fibonacci number at index input.", expected, actual);
-    }
-
-    /**
-     * This is better than the implementation of
-     * testParameterArgumentsWithParameterSetOfMoreThanOneTest. It reduces the number of
-     * {@link ParameterizedTest} annotations by using an intArray instead of an intVar.
-     * Computationally, this will be faster too because it only has to set up the parameters once
-     * for the single ParameterizedTest.
-     *
-     * Continued @ testSingleTestParameterArgumentsWithParameterSet
-     */
-    @SmallTest
-    @ParameterizedTest.Set(tests = {
-            @ParameterizedTest(parameters = {
-                    @Parameter(
-                            tag = MethodParameter.PARAMETER_TAG,
-                            arguments = {
-                                    @Parameter.Argument(name = "input",
-                                            intArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}),
-                                    @Parameter.Argument(name = "expected",
-                                            intArray = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34})})})})
-    @RetryOnFailure
-    public void testSingleTestParameterArgumentsWithParameterSet() {
-        int[] input = getArgument("input").intArray();
-        int[] expected = getArgument("expected").intArray();
-        int[] actual = new int[input.length];
-        for (int i = 0; i < input.length; i++) {
-            actual[i] = fib(input[i]);
-        }
-        MoreAsserts.assertEquals("Output should be the fibonacci number at each index input.",
-                expected, actual);
-    }
-
-    /**
-     * This is the best implementation to test fibonacci.
-     *
-     * It's computationally the same speed at testSingleTestParameterArgumentsWithParameterSet. But
-     * we don't need to actually have a ParameterizedTestSet.
-     */
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(
-                    tag = MethodParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(name = "input",
-                                    intArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}),
-                            @Parameter.Argument(name = "expected",
-                                    intArray = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34})})})
-    @RetryOnFailure
-    public void testSingleTestParameterArgumentsWithoutParameterSet() {
-        int[] input = getArgument("input").intArray();
-        int[] expected = getArgument("expected").intArray();
-        int[] actual = new int[input.length];
-        for (int i = 0; i < input.length; i++) {
-            actual[i] = fib(input[i]);
-        }
-        MoreAsserts.assertEquals("Output should be the fibonacci number at each index input.",
-                expected, actual);
-    }
-
-    private static String mismatchMessage(String name) {
-        return String.format("The ParameterArgument %s does not match expected value.", name);
-    }
-
-    private static int fib(int input) {
-        if (input <= 0) {
-            throw new IllegalArgumentException("Input must be greater than 0.");
-        }
-        if (input == 1) {
-            return 0;
-        }
-        if (input == 2) {
-            return 1;
-        }
-        int[] temp = new int[input];
-        temp[0] = 0;
-        temp[1] = 1;
-        for (int i = 2; i < input; i++) {
-            temp[i] = temp[i - 1] + temp[i - 2];
-        }
-        return temp[input - 1];
-    }
-
-    /**
-     * These are from {@link org.chromium.chrome.test.util.parameters.SigninParametersTest.
-     *
-     * TODO (crbug.com/522503): Merge tests together when this is fixed.
-     */
-    @SmallTest
-    @RetryOnFailure
-    public void testActivityIsNotSignedInOnAppOrFakeOSorGoogleOS() {
-        assertFalse("Should not be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertFalse("Should not be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertFalse("Should not be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToAppParameter.PARAMETER_TAG)})
-    @RetryOnFailure
-    public void testIsSignedInOnApp() {
-        assertTrue("Should not be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertFalse("Should not be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertFalse("Should not be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToOsParameter.PARAMETER_TAG)})
-    @RetryOnFailure
-    public void testIsSignedInOnFakeOS() {
-        assertFalse("Should not be signed in on app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertFalse("Should not be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @FlakyTest
-    @EnormousTest
-    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
-    @ParameterizedTest(parameters = {
-            @Parameter(
-                    tag = AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.USERNAME,
-                                    stringVar = GOOGLE_ACCOUNT_USERNAME),
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.PASSWORD,
-                                    stringVar = GOOGLE_ACCOUNT_PASSWORD)})})
-    public void testIsSignedInOnGoogleOS() {
-        assertFalse("Should not be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertFalse("Should not be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToAppParameter.PARAMETER_TAG),
-            @Parameter(tag = AddFakeAccountToOsParameter.PARAMETER_TAG)})
-    @RetryOnFailure
-    public void testIsSignedInOnFakeOSandApp() {
-        assertTrue("Should be signed in on app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertFalse("Should not be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @FlakyTest
-    @EnormousTest
-    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToAppParameter.PARAMETER_TAG),
-            @Parameter(
-                    tag = AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.USERNAME,
-                                    stringVar = GOOGLE_ACCOUNT_USERNAME),
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.PASSWORD,
-                                    stringVar = GOOGLE_ACCOUNT_PASSWORD)})})
-    public void testIsSignedInOnAppAndGoogleOS() {
-        assertTrue("Should be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertFalse("Should not be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @FlakyTest
-    @EnormousTest
-    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToOsParameter.PARAMETER_TAG),
-            @Parameter(
-                    tag = AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.USERNAME,
-                                    stringVar = GOOGLE_ACCOUNT_USERNAME),
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.PASSWORD,
-                                    stringVar = GOOGLE_ACCOUNT_PASSWORD)})})
-    public void testIsSignedInOnFakeOSandGoogleOS() {
-        assertFalse("Should not be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertTrue("Should be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @FlakyTest
-    @EnormousTest
-    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToAppParameter.PARAMETER_TAG),
-            @Parameter(tag = AddFakeAccountToOsParameter.PARAMETER_TAG),
-            @Parameter(
-                    tag = AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.USERNAME,
-                                    stringVar = GOOGLE_ACCOUNT_USERNAME),
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.PASSWORD,
-                                    stringVar = GOOGLE_ACCOUNT_PASSWORD)})})
-    public void testIsSignedInOnAppAndFakeOSandGoogleOS() {
-        assertTrue("Should be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertTrue("Should be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    private Parameter.Argument getArgument(String name) {
-        return getParameterReader().getParameterArgument(MethodParameter.PARAMETER_TAG, name);
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/test/util/parameters/SigninParametersTest.java b/chrome/android/javatests/src/org/chromium/chrome/test/util/parameters/SigninParametersTest.java
deleted file mode 100644
index 1fccb61..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/test/util/parameters/SigninParametersTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.test.util.parameters;
-
-import android.support.test.filters.SmallTest;
-
-import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.EnormousTest;
-import org.chromium.base.test.util.FlakyTest;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.base.test.util.parameter.ParameterizedTest;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.test.ChromeActivityTestCaseBase;
-
-/**
- * Tester class for implementation of Signin testing and ParameterizedTest.
- */
-@RetryOnFailure
-public class SigninParametersTest extends ChromeActivityTestCaseBase<ChromeActivity> {
-    private static final String GOOGLE_ACCOUNT_USERNAME = "chromiumforandroid01@gmail.com";
-    private static final String GOOGLE_ACCOUNT_PASSWORD = "chromeforandroid";
-
-    private AddFakeAccountToAppParameter mAddFakeAccountToAppParameter;
-    private AddFakeAccountToOsParameter mAddFakeAccountToOsParameter;
-    private AddGoogleAccountToOsParameter mAddGoogleAccountToOsParameter;
-
-    public SigninParametersTest() {
-        super(ChromeActivity.class);
-    }
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mAddFakeAccountToAppParameter =
-                getAvailableParameter(AddFakeAccountToAppParameter.PARAMETER_TAG);
-        mAddFakeAccountToOsParameter =
-                getAvailableParameter(AddFakeAccountToOsParameter.PARAMETER_TAG);
-        mAddGoogleAccountToOsParameter =
-                getAvailableParameter(AddGoogleAccountToOsParameter.PARAMETER_TAG);
-    }
-
-    @SmallTest
-    public void testActivityIsNotSignedInOnAppOrFakeOSorGoogleOS() {
-        assertFalse("Should not be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertFalse("Should not be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertFalse("Should not be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    /*
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToAppParameter.PARAMETER_TAG)})
-    */
-    @DisabledTest(message = "crbug.com/524189")
-    public void testIsSignedInOnApp() {
-        assertTrue("Should not be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertFalse("Should not be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertFalse("Should not be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToOsParameter.PARAMETER_TAG)})
-    public void testIsSignedInOnFakeOS() {
-        assertFalse("Should not be signed in on app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertFalse("Should not be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @FlakyTest
-    @EnormousTest
-    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
-    @ParameterizedTest(parameters = {
-            @Parameter(
-                    tag = AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.USERNAME,
-                                    stringVar = GOOGLE_ACCOUNT_USERNAME),
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.PASSWORD,
-                                    stringVar = GOOGLE_ACCOUNT_PASSWORD)})})
-    public void testIsSignedInOnGoogleOS() {
-        assertFalse("Should not be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertFalse("Should not be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    /*
-    @SmallTest
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToAppParameter.PARAMETER_TAG),
-            @Parameter(tag = AddFakeAccountToOsParameter.PARAMETER_TAG)})
-    */
-    @DisabledTest(message = "crbug.com/524189")
-    public void testIsSignedInOnFakeOSandApp() {
-        assertTrue("Should be signed in on app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertFalse("Should not be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    /*
-    @FlakyTest
-    @EnormousTest
-    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToAppParameter.PARAMETER_TAG),
-            @Parameter(
-                    tag = AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.USERNAME,
-                                    stringVar = GOOGLE_ACCOUNT_USERNAME),
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.PASSWORD,
-                                    stringVar = GOOGLE_ACCOUNT_PASSWORD)})})
-    */
-    @DisabledTest(message = "crbug.com/524189")
-    public void testIsSignedInOnAppAndGoogleOS() {
-        assertTrue("Should be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertFalse("Should not be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @FlakyTest
-    @EnormousTest
-    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToOsParameter.PARAMETER_TAG),
-            @Parameter(
-                    tag = AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.USERNAME,
-                                    stringVar = GOOGLE_ACCOUNT_USERNAME),
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.PASSWORD,
-                                    stringVar = GOOGLE_ACCOUNT_PASSWORD)})})
-    public void testIsSignedInOnFakeOSandGoogleOS() {
-        assertFalse("Should not be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertTrue("Should be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    /*
-    @FlakyTest
-    @EnormousTest
-    @Restriction(Restriction.RESTRICTION_TYPE_INTERNET)
-    @ParameterizedTest(parameters = {
-            @Parameter(tag = AddFakeAccountToAppParameter.PARAMETER_TAG),
-            @Parameter(tag = AddFakeAccountToOsParameter.PARAMETER_TAG),
-            @Parameter(
-                    tag = AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                    arguments = {
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.USERNAME,
-                                    stringVar = GOOGLE_ACCOUNT_USERNAME),
-                            @Parameter.Argument(
-                                    name = AddGoogleAccountToOsParameter.ARGUMENT.PASSWORD,
-                                    stringVar = GOOGLE_ACCOUNT_PASSWORD)})})
-    */
-    @DisabledTest(message = "crbug.com/524189")
-    public void testIsSignedInOnAppAndFakeOSandGoogleOS() {
-        assertTrue("Should be signed into app.",
-                mAddFakeAccountToAppParameter.isSignedIn());
-        assertTrue("Should be signed into OS with fake account.",
-                mAddFakeAccountToOsParameter.isSignedIn());
-        assertTrue("Should be signed in on OS with Google account.",
-                mAddGoogleAccountToOsParameter.isSignedIn(GOOGLE_ACCOUNT_USERNAME));
-    }
-
-    @Override
-    public void startMainActivity() throws InterruptedException {
-        startMainActivityOnBlankPage();
-    }
-}
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc
index 3e481f2..f0af59f6 100644
--- a/chrome/browser/chrome_browser_main_win.cc
+++ b/chrome/browser/chrome_browser_main_win.cc
@@ -231,9 +231,14 @@
   // base::Unretained() here because the ModuleDatabase is never freed.
   EnumerateShellExtensions(
       base::BindRepeating(&ModuleDatabase::OnShellExtensionEnumerated,
-                          base::Unretained(module_database)));
-  EnumerateInputMethodEditors(base::BindRepeating(
-      &ModuleDatabase::OnImeEnumerated, base::Unretained(module_database)));
+                          base::Unretained(module_database)),
+      base::BindOnce(&ModuleDatabase::OnShellExtensionEnumerationFinished,
+                     base::Unretained(module_database)));
+  EnumerateInputMethodEditors(
+      base::BindRepeating(&ModuleDatabase::OnImeEnumerated,
+                          base::Unretained(module_database)),
+      base::BindOnce(&ModuleDatabase::OnImeEnumerationFinished,
+                     base::Unretained(module_database)));
 }
 
 void ShowCloseBrowserFirstMessageBox() {
diff --git a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
index c662be2..3f9951e 100644
--- a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
+++ b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
@@ -161,7 +161,7 @@
   pairing_chromeos::BluetoothHostPairingController* controller_ = nullptr;
 
   bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client_ = nullptr;
-  base::MessageLoop message_loop_;
+  base::MessageLoopForUI message_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(BluetoothHostPairingNoInputTest);
 };
diff --git a/chrome/browser/chromeos/net/DEPS b/chrome/browser/chromeos/net/DEPS
index 7b42810..777e45bf 100644
--- a/chrome/browser/chromeos/net/DEPS
+++ b/chrome/browser/chromeos/net/DEPS
@@ -2,6 +2,7 @@
   # Chrome under mustash cannot call directly into ash internals.
   "-ash",
   "+ash/public",
+  "+ash/system/network",
   "+components/captive_portal",
 ]
 
diff --git a/chrome/browser/chromeos/net/tether_notification_presenter.cc b/chrome/browser/chromeos/net/tether_notification_presenter.cc
index 590ac5f3..5f477a3 100644
--- a/chrome/browser/chromeos/net/tether_notification_presenter.cc
+++ b/chrome/browser/chromeos/net/tether_notification_presenter.cc
@@ -12,6 +12,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/proximity_auth/logging/logging.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/color_palette.h"
 #include "ui/gfx/image/image.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/notification_types.h"
@@ -23,6 +24,12 @@
 
 namespace {
 
+// Mean value of NetworkStat's signal_strength() range.
+const int kMediumSignalStrength = 50;
+
+// Dimensions of Tether notification icon in pixels.
+constexpr gfx::Size kTetherSignalIconSize(40, 40);
+
 const char kTetherSettingsSubpage[] = "networks?type=Tether";
 
 class SettingsUiDelegateImpl
@@ -37,6 +44,15 @@
   }
 };
 
+// Gets the normalized signal strength that can range from 0 to 4. This return
+// value is then used to get an appropriate image to display on the
+// notification.  Defaults to full signal strength (4) if |signal_strength|
+// is out of bounds.
+int GetNormalizedSignalStrength(int signal_strength) {
+  int normalized_signal_strength = signal_strength / 25;
+  return std::min(std::max(normalized_signal_strength, 0), 4);
+}
+
 }  // namespace
 
 // static
@@ -59,11 +75,13 @@
 
 // static
 std::unique_ptr<message_center::Notification>
-TetherNotificationPresenter::CreateNotification(const std::string& id,
-                                                const base::string16& title,
-                                                const base::string16& message) {
+TetherNotificationPresenter::CreateNotificationWithMediumSignalStrengthIcon(
+    const std::string& id,
+    const base::string16& title,
+    const base::string16& message) {
   return CreateNotification(id, title, message,
-                            message_center::RichNotificationData());
+                            message_center::RichNotificationData(),
+                            kMediumSignalStrength);
 }
 
 // static
@@ -72,13 +90,16 @@
     const std::string& id,
     const base::string16& title,
     const base::string16& message,
-    const message_center::RichNotificationData rich_notification_data) {
+    const message_center::RichNotificationData rich_notification_data,
+    int signal_strength) {
+  auto source = base::MakeUnique<ash::network_icon::SignalStrengthImageSource>(
+      ash::network_icon::BARS, gfx::kGoogleBlue500, kTetherSignalIconSize,
+      GetNormalizedSignalStrength(signal_strength));
   return base::MakeUnique<message_center::Notification>(
       message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE, id, title,
       message,
-      // TODO(khorimoto): Add tether icon.
-      gfx::Image() /* icon */, base::string16() /* display_source */,
-      GURL() /* origin_url */,
+      gfx::Image(gfx::ImageSkia(std::move(source), kTetherSignalIconSize)),
+      base::string16() /* display_source */, GURL() /* origin_url */,
       message_center::NotifierId(
           message_center::NotifierId::NotifierType::SYSTEM_COMPONENT,
           kTetherNotifierId),
@@ -102,7 +123,8 @@
 }
 
 void TetherNotificationPresenter::NotifyPotentialHotspotNearby(
-    const cryptauth::RemoteDevice& remote_device) {
+    const cryptauth::RemoteDevice& remote_device,
+    int signal_strength) {
   PA_LOG(INFO) << "Displaying \"potential hotspot nearby\" notification for "
                << "device with name \"" << remote_device.name << "\". "
                << "Notification ID = " << kPotentialHotspotNotificationId;
@@ -113,7 +135,6 @@
   rich_notification_data.buttons.push_back(
       message_center::ButtonInfo(l10n_util::GetStringUTF16(
           IDS_TETHER_NOTIFICATION_WIFI_AVAILABLE_ONE_DEVICE_CONNECT)));
-
   ShowNotification(CreateNotification(
       std::string(kPotentialHotspotNotificationId),
       l10n_util::GetStringUTF16(
@@ -121,7 +142,7 @@
       l10n_util::GetStringFUTF16(
           IDS_TETHER_NOTIFICATION_WIFI_AVAILABLE_ONE_DEVICE_MESSAGE,
           base::ASCIIToUTF16(hotspot_nearby_device_.name)),
-      rich_notification_data));
+      rich_notification_data, signal_strength));
 }
 
 void TetherNotificationPresenter::NotifyMultiplePotentialHotspotsNearby() {
@@ -129,7 +150,7 @@
                << "multiple devices. Notification ID = "
                << kPotentialHotspotNotificationId;
 
-  ShowNotification(CreateNotification(
+  ShowNotification(CreateNotificationWithMediumSignalStrengthIcon(
       std::string(kPotentialHotspotNotificationId),
       l10n_util::GetStringUTF16(
           IDS_TETHER_NOTIFICATION_WIFI_AVAILABLE_MULTIPLE_DEVICES_TITLE),
@@ -150,7 +171,7 @@
   PA_LOG(INFO) << "Displaying \"setup required\" notification. Notification "
                << "ID = " << kSetupRequiredNotificationId;
 
-  ShowNotification(CreateNotification(
+  ShowNotification(CreateNotificationWithMediumSignalStrengthIcon(
       std::string(kSetupRequiredNotificationId),
       l10n_util::GetStringFUTF16(IDS_TETHER_NOTIFICATION_SETUP_REQUIRED_TITLE,
                                  base::ASCIIToUTF16(device_name)),
@@ -170,7 +191,7 @@
   PA_LOG(INFO) << "Displaying \"connection attempt failed\" notification. "
                << "Notification ID = " << kActiveHostNotificationId;
 
-  ShowNotification(CreateNotification(
+  ShowNotification(CreateNotificationWithMediumSignalStrengthIcon(
       std::string(kActiveHostNotificationId),
       l10n_util::GetStringUTF16(
           IDS_TETHER_NOTIFICATION_CONNECTION_FAILED_TITLE),
diff --git a/chrome/browser/chromeos/net/tether_notification_presenter.h b/chrome/browser/chromeos/net/tether_notification_presenter.h
index 53f0548..e883f987c 100644
--- a/chrome/browser/chromeos/net/tether_notification_presenter.h
+++ b/chrome/browser/chromeos/net/tether_notification_presenter.h
@@ -8,12 +8,14 @@
 #include <memory>
 #include <string>
 
+#include "ash/system/network/network_icon.h"
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "chromeos/components/tether/notification_presenter.h"
 #include "chromeos/network/network_connect.h"
+#include "chromeos/network/network_state.h"
 #include "components/cryptauth/remote_device.h"
 #include "ui/message_center/message_center_observer.h"
 #include "ui/message_center/notification.h"
@@ -44,7 +46,8 @@
 
   // NotificationPresenter:
   void NotifyPotentialHotspotNearby(
-      const cryptauth::RemoteDevice& remote_device) override;
+      const cryptauth::RemoteDevice& remote_device,
+      int signal_strength) override;
   void NotifyMultiplePotentialHotspotsNearby() override;
   void RemovePotentialHotspotNotification() override;
   void NotifySetupRequired(const std::string& device_name) override;
@@ -73,15 +76,16 @@
   static const char kActiveHostNotificationId[];
   static const char kSetupRequiredNotificationId[];
 
-  static std::unique_ptr<message_center::Notification> CreateNotification(
-      const std::string& id,
-      const base::string16& title,
-      const base::string16& message);
+  static std::unique_ptr<message_center::Notification>
+  CreateNotificationWithMediumSignalStrengthIcon(const std::string& id,
+                                                 const base::string16& title,
+                                                 const base::string16& message);
   static std::unique_ptr<message_center::Notification> CreateNotification(
       const std::string& id,
       const base::string16& title,
       const base::string16& message,
-      const message_center::RichNotificationData rich_notification_data);
+      const message_center::RichNotificationData rich_notification_data,
+      int signal_strength);
 
   friend class TetherNotificationPresenterTest;
 
diff --git a/chrome/browser/chromeos/net/tether_notification_presenter_unittest.cc b/chrome/browser/chromeos/net/tether_notification_presenter_unittest.cc
index 0f4ad413..a5cd9f8 100644
--- a/chrome/browser/chromeos/net/tether_notification_presenter_unittest.cc
+++ b/chrome/browser/chromeos/net/tether_notification_presenter_unittest.cc
@@ -16,6 +16,10 @@
 #include "ui/message_center/fake_message_center.h"
 #include "ui/message_center/message_center_observer.h"
 
+namespace {
+const int kTestNetworkSignalStrength = 50;
+}  // namespace
+
 namespace chromeos {
 
 namespace tether {
@@ -202,7 +206,6 @@
   std::unique_ptr<TestMessageCenter> test_message_center_;
   std::unique_ptr<TestNetworkConnect> test_network_connect_;
   TestSettingsUiDelegate* test_settings_ui_delegate_;
-
   std::unique_ptr<TetherNotificationPresenter> notification_presenter_;
 
  private:
@@ -272,7 +275,8 @@
        TestSinglePotentialHotspotNotification_RemoveProgrammatically) {
   EXPECT_FALSE(test_message_center_->FindVisibleNotificationById(
       GetPotentialHotspotNotificationId()));
-  notification_presenter_->NotifyPotentialHotspotNearby(test_device_);
+  notification_presenter_->NotifyPotentialHotspotNearby(
+      test_device_, kTestNetworkSignalStrength);
 
   message_center::Notification* notification =
       test_message_center_->FindVisibleNotificationById(
@@ -291,7 +295,8 @@
        TestSinglePotentialHotspotNotification_TapNotification) {
   EXPECT_FALSE(test_message_center_->FindVisibleNotificationById(
       GetPotentialHotspotNotificationId()));
-  notification_presenter_->NotifyPotentialHotspotNearby(test_device_);
+  notification_presenter_->NotifyPotentialHotspotNearby(
+      test_device_, kTestNetworkSignalStrength);
 
   message_center::Notification* notification =
       test_message_center_->FindVisibleNotificationById(
@@ -312,7 +317,8 @@
        TestSinglePotentialHotspotNotification_TapNotificationButton) {
   EXPECT_FALSE(test_message_center_->FindVisibleNotificationById(
       GetPotentialHotspotNotificationId()));
-  notification_presenter_->NotifyPotentialHotspotNearby(test_device_);
+  notification_presenter_->NotifyPotentialHotspotNearby(
+      test_device_, kTestNetworkSignalStrength);
 
   message_center::Notification* notification =
       test_message_center_->FindVisibleNotificationById(
@@ -375,7 +381,8 @@
        TestPotentialHotspotNotifications_UpdatesOneNotification) {
   EXPECT_FALSE(test_message_center_->FindVisibleNotificationById(
       GetPotentialHotspotNotificationId()));
-  notification_presenter_->NotifyPotentialHotspotNearby(test_device_);
+  notification_presenter_->NotifyPotentialHotspotNearby(
+      test_device_, kTestNetworkSignalStrength);
 
   message_center::Notification* notification =
       test_message_center_->FindVisibleNotificationById(
diff --git a/chrome/browser/conflicts/enumerate_input_method_editors_win.cc b/chrome/browser/conflicts/enumerate_input_method_editors_win.cc
index a6d2345..9fd77cb 100644
--- a/chrome/browser/conflicts/enumerate_input_method_editors_win.cc
+++ b/chrome/browser/conflicts/enumerate_input_method_editors_win.cc
@@ -74,7 +74,8 @@
 
 void EnumerateImesOnBlockingSequence(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
-    OnImeEnumeratedCallback on_ime_enumerated) {
+    OnImeEnumeratedCallback on_ime_enumerated,
+    base::OnceClosure on_enumeration_finished) {
   int nb_imes = 0;
   for (base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, kImeRegistryKey);
        iter.Valid(); ++iter) {
@@ -101,6 +102,8 @@
                                               size_of_image, time_date_stamp));
   }
 
+  task_runner->PostTask(FROM_HERE, std::move(on_enumeration_finished));
+
   base::UmaHistogramCounts100("ThirdPartyModules.InputMethodEditorsCount",
                               nb_imes);
 }
@@ -109,12 +112,14 @@
 
 const wchar_t kImeRegistryKey[] = L"SOFTWARE\\Microsoft\\CTF\\TIP";
 
-void EnumerateInputMethodEditors(OnImeEnumeratedCallback on_ime_enumerated) {
+void EnumerateInputMethodEditors(OnImeEnumeratedCallback on_ime_enumerated,
+                                 base::OnceClosure on_enumeration_finished) {
   base::PostTaskWithTraits(
       FROM_HERE,
       {base::MayBlock(), base::TaskPriority::BACKGROUND,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&EnumerateImesOnBlockingSequence,
                      base::SequencedTaskRunnerHandle::Get(),
-                     std::move(on_ime_enumerated)));
+                     std::move(on_ime_enumerated),
+                     std::move(on_enumeration_finished)));
 }
diff --git a/chrome/browser/conflicts/enumerate_input_method_editors_win.h b/chrome/browser/conflicts/enumerate_input_method_editors_win.h
index 7f400c563..db1fdcc 100644
--- a/chrome/browser/conflicts/enumerate_input_method_editors_win.h
+++ b/chrome/browser/conflicts/enumerate_input_method_editors_win.h
@@ -18,9 +18,10 @@
 
 // Finds third-party IMEs (Input Method Editor) installed on the computer by
 // enumerating the registry. In addition to the file path, the SizeOfImage and
-// TimeDateStamp of the module is returned via the callback.
+// TimeDateStamp of the module is returned via the |on_ime_enumerated| callback.
 using OnImeEnumeratedCallback =
     base::RepeatingCallback<void(const base::FilePath&, uint32_t, uint32_t)>;
-void EnumerateInputMethodEditors(OnImeEnumeratedCallback callback);
+void EnumerateInputMethodEditors(OnImeEnumeratedCallback on_ime_enumerated,
+                                 base::OnceClosure on_enumeration_finished);
 
 #endif  // CHROME_BROWSER_CONFLICTS_ENUMERATE_INPUT_METHOD_EDITORS_WIN_H_
diff --git a/chrome/browser/conflicts/enumerate_input_method_editors_win_unittest.cc b/chrome/browser/conflicts/enumerate_input_method_editors_win_unittest.cc
index 38c5604..3ad64cd 100644
--- a/chrome/browser/conflicts/enumerate_input_method_editors_win_unittest.cc
+++ b/chrome/browser/conflicts/enumerate_input_method_editors_win_unittest.cc
@@ -23,9 +23,8 @@
   EnumerateInputMethodEditorsTest() = default;
   ~EnumerateInputMethodEditorsTest() override = default;
 
+  // Override all registry hives so that real IMEs don't mess up the unit tests.
   void SetUp() override {
-    // Override all registry hives so that real IMEs don't mess up the unit
-    // tests.
     ASSERT_NO_FATAL_FAILURE(
         registry_override_manager_.OverrideRegistry(HKEY_CLASSES_ROOT));
     ASSERT_NO_FATAL_FAILURE(
@@ -66,6 +65,10 @@
   imes->push_back(ime_path);
 }
 
+void OnEnumerationFinished(bool* is_enumeration_finished) {
+  *is_enumeration_finished = true;
+}
+
 }  // namespace
 
 // Registers a few fake IMEs then see if the enumeration finds them.
@@ -78,12 +81,16 @@
 
   // Do the asynchronous enumeration.
   std::vector<base::FilePath> imes;
+  bool is_enumeration_finished = false;
   EnumerateInputMethodEditors(
-      base::Bind(&OnImeEnumerated, base::Unretained(&imes)));
+      base::BindRepeating(&OnImeEnumerated, base::Unretained(&imes)),
+      base::BindOnce(&OnEnumerationFinished,
+                     base::Unretained(&is_enumeration_finished)));
 
   RunUntilIdle();
 
-  EXPECT_EQ(1u, imes.size());
+  EXPECT_TRUE(is_enumeration_finished);
+  ASSERT_EQ(1u, imes.size());
   EXPECT_EQ(file_exe, imes[0]);
 }
 
@@ -97,10 +104,14 @@
 
   // Do the asynchronous enumeration.
   std::vector<base::FilePath> imes;
+  bool is_enumeration_finished = false;
   EnumerateInputMethodEditors(
-      base::Bind(&OnImeEnumerated, base::Unretained(&imes)));
+      base::BindRepeating(&OnImeEnumerated, base::Unretained(&imes)),
+      base::BindOnce(&OnEnumerationFinished,
+                     base::Unretained(&is_enumeration_finished)));
 
   RunUntilIdle();
 
+  EXPECT_TRUE(is_enumeration_finished);
   EXPECT_TRUE(imes.empty());
 }
diff --git a/chrome/browser/conflicts/enumerate_shell_extensions_win.cc b/chrome/browser/conflicts/enumerate_shell_extensions_win.cc
index 795cbc7..ba3e1be 100644
--- a/chrome/browser/conflicts/enumerate_shell_extensions_win.cc
+++ b/chrome/browser/conflicts/enumerate_shell_extensions_win.cc
@@ -23,7 +23,7 @@
 
 void ReadShellExtensions(
     HKEY parent,
-    const base::Callback<void(const base::FilePath&)>& callback,
+    const base::RepeatingCallback<void(const base::FilePath&)>& callback,
     int* nb_shell_extensions) {
   for (base::win::RegistryValueIterator iter(parent,
                                              kShellExtensionRegistryKey);
@@ -62,10 +62,13 @@
 
 void EnumerateShellExtensionsOnBlockingSequence(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
-    OnShellExtensionEnumeratedCallback on_shell_extension_enumerated) {
-  EnumerateShellExtensionPaths(base::BindRepeating(
-      &OnShellExtensionPathEnumerated, std::move(task_runner),
-      std::move(on_shell_extension_enumerated)));
+    OnShellExtensionEnumeratedCallback on_shell_extension_enumerated,
+    base::OnceClosure on_enumeration_finished) {
+  EnumerateShellExtensionPaths(
+      base::BindRepeating(&OnShellExtensionPathEnumerated, task_runner,
+                          std::move(on_shell_extension_enumerated)));
+
+  task_runner->PostTask(FROM_HERE, std::move(on_enumeration_finished));
 }
 
 }  // namespace
@@ -74,7 +77,7 @@
     L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
 
 void EnumerateShellExtensionPaths(
-    const base::Callback<void(const base::FilePath&)>& callback) {
+    const base::RepeatingCallback<void(const base::FilePath&)>& callback) {
   base::ThreadRestrictions::AssertIOAllowed();
 
   int nb_shell_extensions = 0;
@@ -86,12 +89,14 @@
 }
 
 void EnumerateShellExtensions(
-    OnShellExtensionEnumeratedCallback on_shell_extension_enumerated) {
+    OnShellExtensionEnumeratedCallback on_shell_extension_enumerated,
+    base::OnceClosure on_enumeration_finished) {
   base::PostTaskWithTraits(
       FROM_HERE,
       {base::MayBlock(), base::TaskPriority::BACKGROUND,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&EnumerateShellExtensionsOnBlockingSequence,
                      base::SequencedTaskRunnerHandle::Get(),
-                     std::move(on_shell_extension_enumerated)));
+                     std::move(on_shell_extension_enumerated),
+                     std::move(on_enumeration_finished)));
 }
diff --git a/chrome/browser/conflicts/enumerate_shell_extensions_win.h b/chrome/browser/conflicts/enumerate_shell_extensions_win.h
index de74ef1..59ba43f 100644
--- a/chrome/browser/conflicts/enumerate_shell_extensions_win.h
+++ b/chrome/browser/conflicts/enumerate_shell_extensions_win.h
@@ -21,14 +21,15 @@
 // TODO(pmonette): Move this implementation detail to the .cc file when
 //                 enumerate_modules_model.cc gets deleted.
 void EnumerateShellExtensionPaths(
-    const base::Callback<void(const base::FilePath&)>& callback);
+    const base::RepeatingCallback<void(const base::FilePath&)>& callback);
 
 // Finds shell extensions installed on the computer by enumerating the registry.
 // In addition to the file path, the SizeOfImage and TimeDateStamp of the module
-// is returned via the callback.
+// is returned via the |on_shell_extension_enumerated| callback.
 using OnShellExtensionEnumeratedCallback =
-    base::Callback<void(const base::FilePath&, uint32_t, uint32_t)>;
+    base::RepeatingCallback<void(const base::FilePath&, uint32_t, uint32_t)>;
 void EnumerateShellExtensions(
-    OnShellExtensionEnumeratedCallback on_shell_extension_enumerated);
+    OnShellExtensionEnumeratedCallback on_shell_extension_enumerated,
+    base::OnceClosure on_enumeration_finished);
 
 #endif  // CHROME_BROWSER_CONFLICTS_ENUMERATE_SHELL_EXTENSIONS_WIN_H_
diff --git a/chrome/browser/conflicts/enumerate_shell_extensions_win_unittest.cc b/chrome/browser/conflicts/enumerate_shell_extensions_win_unittest.cc
index 52de0b26..3ea07bd 100644
--- a/chrome/browser/conflicts/enumerate_shell_extensions_win_unittest.cc
+++ b/chrome/browser/conflicts/enumerate_shell_extensions_win_unittest.cc
@@ -22,7 +22,6 @@
 class EnumerateShellExtensionsTest : public testing::Test {
  public:
   EnumerateShellExtensionsTest() = default;
-
   ~EnumerateShellExtensionsTest() override = default;
 
   // Override all registry hives so that real shell extensions don't mess up
@@ -77,6 +76,10 @@
   shell_extension_paths->push_back(path);
 }
 
+void OnEnumerationFinished(bool* is_enumeration_finished) {
+  *is_enumeration_finished = true;
+}
+
 }  // namespace
 
 // Registers a few fake shell extensions then see if
@@ -116,11 +119,16 @@
       HKEY_LOCAL_MACHINE, L"{FAKE_GUID}", file_exe.value().c_str()));
 
   std::vector<base::FilePath> shell_extension_paths;
-  EnumerateShellExtensions(base::BindRepeating(
-      &OnShellExtensionEnumerated, base::Unretained(&shell_extension_paths)));
+  bool is_enumeration_finished = false;
+  EnumerateShellExtensions(
+      base::BindRepeating(&OnShellExtensionEnumerated,
+                          base::Unretained(&shell_extension_paths)),
+      base::BindOnce(&OnEnumerationFinished,
+                     base::Unretained(&is_enumeration_finished)));
 
   RunUntilIdle();
 
+  EXPECT_TRUE(is_enumeration_finished);
   ASSERT_EQ(1u, shell_extension_paths.size());
   EXPECT_EQ(file_exe, shell_extension_paths[0]);
 }
diff --git a/chrome/browser/conflicts/module_database_win.cc b/chrome/browser/conflicts/module_database_win.cc
index 65417ec..980281e 100644
--- a/chrome/browser/conflicts/module_database_win.cc
+++ b/chrome/browser/conflicts/module_database_win.cc
@@ -30,6 +30,8 @@
 ModuleDatabase::ModuleDatabase(
     scoped_refptr<base::SequencedTaskRunner> task_runner)
     : task_runner_(std::move(task_runner)),
+      shell_extensions_enumerated_(false),
+      ime_enumerated_(false),
       // ModuleDatabase owns |module_inspector_|, so it is safe to use
       // base::Unretained().
       module_inspector_(base::Bind(&ModuleDatabase::OnModuleInspected,
@@ -63,8 +65,8 @@
 }
 
 bool ModuleDatabase::IsIdle() {
-  return has_started_processing_ && !idle_timer_.IsRunning() &&
-         module_inspector_.IsIdle();
+  return has_started_processing_ && RegisteredModulesEnumerated() &&
+         !idle_timer_.IsRunning() && module_inspector_.IsIdle();
 }
 
 void ModuleDatabase::OnProcessStarted(uint32_t process_id,
@@ -86,6 +88,16 @@
   module_info->second.module_types |= ModuleInfoData::kTypeShellExtension;
 }
 
+void ModuleDatabase::OnShellExtensionEnumerationFinished() {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+  DCHECK(!shell_extensions_enumerated_);
+
+  shell_extensions_enumerated_ = true;
+
+  if (RegisteredModulesEnumerated())
+    OnRegisteredModulesEnumerated();
+}
+
 void ModuleDatabase::OnImeEnumerated(const base::FilePath& path,
                                      uint32_t size_of_image,
                                      uint32_t time_date_stamp) {
@@ -98,6 +110,16 @@
   module_info->second.module_types |= ModuleInfoData::kTypeIme;
 }
 
+void ModuleDatabase::OnImeEnumerationFinished() {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+  DCHECK(!ime_enumerated_);
+
+  ime_enumerated_ = true;
+
+  if (RegisteredModulesEnumerated())
+    OnRegisteredModulesEnumerated();
+}
+
 void ModuleDatabase::OnModuleLoad(uint32_t process_id,
                                   uint64_t creation_time,
                                   const base::FilePath& module_path,
@@ -201,10 +223,13 @@
 
 void ModuleDatabase::AddObserver(ModuleDatabaseObserver* observer) {
   observer_list_.AddObserver(observer);
-  for (const auto& module : modules_) {
-    if (module.second.inspection_result)
-      observer->OnNewModuleFound(module.first, module.second);
-  }
+
+  // If the registered modules enumeration is not finished yet, the |observer|
+  // will be notified later in OnRegisteredModulesEnumerated().
+  if (!RegisteredModulesEnumerated())
+    return;
+
+  NotifyLoadedModules(observer);
 
   if (IsIdle())
     observer->OnModuleDatabaseIdle();
@@ -397,6 +422,18 @@
   processes_.erase(key);
 }
 
+bool ModuleDatabase::RegisteredModulesEnumerated() {
+  return shell_extensions_enumerated_ && ime_enumerated_;
+}
+
+void ModuleDatabase::OnRegisteredModulesEnumerated() {
+  for (auto& observer : observer_list_)
+    NotifyLoadedModules(&observer);
+
+  if (IsIdle())
+    EnterIdleState();
+}
+
 void ModuleDatabase::OnModuleInspected(
     const ModuleInfoKey& module_key,
     std::unique_ptr<ModuleInspectionResult> inspection_result) {
@@ -408,8 +445,9 @@
 
   it->second.inspection_result = std::move(inspection_result);
 
-  for (auto& observer : observer_list_)
-    observer.OnNewModuleFound(it->first, it->second);
+  if (RegisteredModulesEnumerated())
+    for (auto& observer : observer_list_)
+      observer.OnNewModuleFound(it->first, it->second);
 
   // Notify the observers if this was the last outstanding module inspection and
   // the delay has already expired.
@@ -428,6 +466,13 @@
     observer.OnModuleDatabaseIdle();
 }
 
+void ModuleDatabase::NotifyLoadedModules(ModuleDatabaseObserver* observer) {
+  for (const auto& module : modules_) {
+    if (module.second.inspection_result)
+      observer->OnNewModuleFound(module.first, module.second);
+  }
+}
+
 // ModuleDatabase::ProcessInfoKey ----------------------------------------------
 
 ModuleDatabase::ProcessInfoKey::ProcessInfoKey(
diff --git a/chrome/browser/conflicts/module_database_win.h b/chrome/browser/conflicts/module_database_win.h
index ba1d1c2..cc7a6a9 100644
--- a/chrome/browser/conflicts/module_database_win.h
+++ b/chrome/browser/conflicts/module_database_win.h
@@ -84,12 +84,18 @@
                                   uint32_t size_of_image,
                                   uint32_t time_date_stamp);
 
+  // Indicates that all shell extensions have been enumerated.
+  void OnShellExtensionEnumerationFinished();
+
   // Indicates that a new registered input method editor was found. Must be
   // called in the same sequence as |task_runner_|.
   void OnImeEnumerated(const base::FilePath& path,
                        uint32_t size_of_image,
                        uint32_t time_date_stamp);
 
+  // Indicates that all input method editors have been enumerated.
+  void OnImeEnumerationFinished();
+
   // Indicates that a module has been loaded. The data passed to this function
   // is taken as gospel, so if it originates from a remote process it should be
   // independently validated first. (In practice, see ModuleEventSinkImpl for
@@ -185,6 +191,20 @@
   // Deletes a process info entry.
   void DeleteProcessInfo(uint32_t process_id, uint64_t creation_time);
 
+  // Returns true if the enumeration of the IMEs and the shell extensions is
+  // finished.
+  //
+  // To avoid sending an improperly tagged module to an observer (in case a race
+  // condition happens and the module is loaded before the enumeration is done),
+  // it's important that this function returns true before any calls to
+  // OnNewModuleFound() is made.
+  bool RegisteredModulesEnumerated();
+
+  // Called when RegisteredModulesEnumerated() becomes true. Notifies the
+  // observers of each already inspected modules and checks if the idle state
+  // should be entered.
+  void OnRegisteredModulesEnumerated();
+
   // Callback for ModuleInspector.
   void OnModuleInspected(
       const ModuleInfoKey& module_key,
@@ -196,12 +216,22 @@
   // Notifies the observers that ModuleDatabase is now idle.
   void EnterIdleState();
 
+  // Notifies the |observer| of already found and inspected modules via
+  // OnNewModuleFound().
+  void NotifyLoadedModules(ModuleDatabaseObserver* observer);
+
   // The task runner to which this object is bound.
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   // A map of all known modules.
   ModuleMap modules_;
 
+  // Indicates if all shell extensions have been enumerated.
+  bool shell_extensions_enumerated_;
+
+  // Indicates if all input method editors have been enumerated.
+  bool ime_enumerated_;
+
   // Inspects new modules on a blocking task runner.
   ModuleInspector module_inspector_;
 
diff --git a/chrome/browser/conflicts/module_database_win_unittest.cc b/chrome/browser/conflicts/module_database_win_unittest.cc
index a210828..50b4ca5 100644
--- a/chrome/browser/conflicts/module_database_win_unittest.cc
+++ b/chrome/browser/conflicts/module_database_win_unittest.cc
@@ -94,7 +94,7 @@
     mock_time_task_runner_->RunUntilIdle();
   }
 
-  void FastForwardToModuleDatabaseIdle() {
+  void FastForwardToIdleTimer() {
     RunSchedulerUntilIdle();
     mock_time_task_runner_->FastForwardBy(ModuleDatabase::kIdleTimeout);
   }
@@ -552,6 +552,10 @@
 };
 
 TEST_F(ModuleDatabaseTest, Observers) {
+  // Assume there is no shell extensions or IMEs.
+  module_database()->OnShellExtensionEnumerationFinished();
+  module_database()->OnImeEnumerationFinished();
+
   module_database()->OnProcessStarted(kPid1, kCreateTime1,
                                       content::PROCESS_TYPE_BROWSER);
 
@@ -580,6 +584,10 @@
 
 // Tests the idle cycle of the ModuleDatabase.
 TEST_F(ModuleDatabaseTest, IsIdle) {
+  // Assume there is no shell extensions or IMEs.
+  module_database()->OnShellExtensionEnumerationFinished();
+  module_database()->OnImeEnumerationFinished();
+
   module_database()->OnProcessStarted(kPid1, kCreateTime1,
                                       content::PROCESS_TYPE_BROWSER);
 
@@ -587,7 +595,7 @@
   EXPECT_FALSE(module_database()->IsIdle());
 
   // Can't fast forward to idle because a module load event is needed.
-  FastForwardToModuleDatabaseIdle();
+  FastForwardToIdleTimer();
   EXPECT_FALSE(module_database()->IsIdle());
 
   // A load module event starts the timer.
@@ -595,14 +603,14 @@
                                   kGoodAddress1);
   EXPECT_FALSE(module_database()->IsIdle());
 
-  FastForwardToModuleDatabaseIdle();
+  FastForwardToIdleTimer();
   EXPECT_TRUE(module_database()->IsIdle());
 
   // A new shell extension resets the timer.
   module_database()->OnShellExtensionEnumerated(dll1_, kSize1, kTime1);
   EXPECT_FALSE(module_database()->IsIdle());
 
-  FastForwardToModuleDatabaseIdle();
+  FastForwardToIdleTimer();
   EXPECT_TRUE(module_database()->IsIdle());
 
   // Adding an observer while idle immediately calls OnModuleDatabaseIdle().
@@ -623,9 +631,48 @@
   EXPECT_FALSE(is_busy_observer.on_module_database_idle_called());
 
   // Fast forward will call OnModuleDatabaseIdle().
-  FastForwardToModuleDatabaseIdle();
+  FastForwardToIdleTimer();
   EXPECT_TRUE(module_database()->IsIdle());
   EXPECT_TRUE(is_busy_observer.on_module_database_idle_called());
 
   module_database()->RemoveObserver(&is_busy_observer);
 }
+
+// The ModuleDatabase waits until shell extensions and IMEs are enumerated
+// before notifying observers or going idle.
+TEST_F(ModuleDatabaseTest, WaitUntilRegisteredModulesEnumerated) {
+  module_database()->OnProcessStarted(kPid1, kCreateTime1,
+                                      content::PROCESS_TYPE_BROWSER);
+
+  // This observer is added before the first loaded module.
+  DummyObserver before_load_observer;
+  module_database()->AddObserver(&before_load_observer);
+  EXPECT_EQ(0, before_load_observer.new_module_count());
+
+  module_database()->OnModuleLoad(kPid1, kCreateTime1, dll1_, kSize1, kTime1,
+                                  kGoodAddress1);
+  FastForwardToIdleTimer();
+
+  // Idle state is prevented.
+  EXPECT_FALSE(module_database()->IsIdle());
+  EXPECT_EQ(0, before_load_observer.new_module_count());
+  EXPECT_FALSE(before_load_observer.on_module_database_idle_called());
+
+  // This observer is added after the first loaded module.
+  DummyObserver after_load_observer;
+  module_database()->AddObserver(&after_load_observer);
+  EXPECT_EQ(0, after_load_observer.new_module_count());
+  EXPECT_FALSE(after_load_observer.on_module_database_idle_called());
+
+  // Simulate the enumerations ending.
+  module_database()->OnImeEnumerationFinished();
+  module_database()->OnShellExtensionEnumerationFinished();
+
+  EXPECT_EQ(1, before_load_observer.new_module_count());
+  EXPECT_TRUE(before_load_observer.on_module_database_idle_called());
+  EXPECT_EQ(1, after_load_observer.new_module_count());
+  EXPECT_TRUE(after_load_observer.on_module_database_idle_called());
+
+  module_database()->RemoveObserver(&after_load_observer);
+  module_database()->RemoveObserver(&before_load_observer);
+}
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate_browsertest.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate_browsertest.cc
index 7867326..b385c03 100644
--- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate_browsertest.cc
+++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate_browsertest.cc
@@ -420,7 +420,8 @@
                           const std::string& headers) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // Ensure that a previous value is not overwritten.
-  EXPECT_FALSE(base::ContainsKey(*request_headers, url));
+  EXPECT_FALSE(base::ContainsKey(*request_headers, url))
+      << "URL: " << url << ", Headers: " << headers;
   (*request_headers)[url] = headers;
 }
 
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
index 0cf731de..0a3f29f 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -68,7 +68,7 @@
     const base::Optional<content::WebContents::CreateParams>& create_params,
     std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface)
     : content::WebContentsObserver(web_contents),
-      in_foreground_(create_params ? !create_params->initially_hidden : false),
+      in_foreground_(web_contents->IsVisible()),
       embedder_interface_(std::move(embedder_interface)),
       has_navigated_(false),
       page_load_metrics_binding_(web_contents, this) {
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
index a355a05a..710ade67 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
@@ -21,7 +21,20 @@
 
 const base::Feature kAdsFeature{"AdsMetrics", base::FEATURE_ENABLED_BY_DEFAULT};
 
-bool FrameIsAd(content::NavigationHandle* navigation_handle) {
+#define ADS_HISTOGRAM(suffix, hist_macro, ad_type, value)                  \
+  switch (ad_type) {                                                       \
+    case AdsPageLoadMetricsObserver::AD_TYPE_GOOGLE:                       \
+      hist_macro("PageLoad.Clients.Ads.Google." suffix, value);            \
+      break;                                                               \
+    case AdsPageLoadMetricsObserver::AD_TYPE_SUBRESOURCE_FILTER:           \
+      hist_macro("PageLoad.Clients.Ads.SubresourceFilter." suffix, value); \
+      break;                                                               \
+    case AdsPageLoadMetricsObserver::AD_TYPE_ALL:                          \
+      hist_macro("PageLoad.Clients.Ads.All." suffix, value);               \
+      break;                                                               \
+  }
+
+bool DetectGoogleAd(content::NavigationHandle* navigation_handle) {
   // Because sub-resource filtering isn't always enabled, and doesn't work
   // well in monitoring mode (no CSS enforcement), it's difficult to identify
   // ads. Google ads are prevalent and easy to track, so we'll start by
@@ -55,18 +68,22 @@
                           base::CompareCase::SENSITIVE);
 }
 
-void RecordParentExistsForSubFrame(bool parent_exists) {
-  UMA_HISTOGRAM_BOOLEAN("PageLoad.Clients.Ads.Google.ParentExistsForSubFrame",
-                        parent_exists);
+void RecordParentExistsForSubFrame(
+    bool parent_exists,
+    const AdsPageLoadMetricsObserver::AdTypes& ad_types) {
+  ADS_HISTOGRAM("ParentExistsForSubFrame", UMA_HISTOGRAM_BOOLEAN,
+                AdsPageLoadMetricsObserver::AD_TYPE_ALL, parent_exists);
 }
 
 }  // namespace
 
 AdsPageLoadMetricsObserver::AdFrameData::AdFrameData(
-    FrameTreeNodeId frame_tree_node_id)
+    FrameTreeNodeId frame_tree_node_id,
+    AdTypes ad_types)
     : frame_bytes(0u),
       frame_bytes_uncached(0u),
-      frame_tree_node_id(frame_tree_node_id) {}
+      frame_tree_node_id(frame_tree_node_id),
+      ad_types(ad_types) {}
 
 // static
 std::unique_ptr<AdsPageLoadMetricsObserver>
@@ -76,10 +93,27 @@
   return base::MakeUnique<AdsPageLoadMetricsObserver>();
 }
 
-AdsPageLoadMetricsObserver::AdsPageLoadMetricsObserver() = default;
+AdsPageLoadMetricsObserver::AdsPageLoadMetricsObserver()
+    : subresource_observer_(this) {}
+
 AdsPageLoadMetricsObserver::~AdsPageLoadMetricsObserver() = default;
 
 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+AdsPageLoadMetricsObserver::OnStart(
+    content::NavigationHandle* navigation_handle,
+    const GURL& currently_committed_url,
+    bool started_in_foreground) {
+  auto* observer_manager =
+      subresource_filter::SubresourceFilterObserverManager::FromWebContents(
+          navigation_handle->GetWebContents());
+  // |observer_manager| isn't constructed if the feature for subresource
+  // filtering isn't enabled.
+  if (observer_manager)
+    subresource_observer_.Add(observer_manager);
+  return CONTINUE_OBSERVING;
+}
+
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
 AdsPageLoadMetricsObserver::OnCommit(
     content::NavigationHandle* navigation_handle,
     ukm::SourceId source_id) {
@@ -103,6 +137,8 @@
   content::RenderFrameHost* parent_frame_host =
       navigation_handle->GetParentFrame();
 
+  AdTypes ad_types = DetectAds(navigation_handle);
+
   const auto& id_and_data = ad_frames_data_.find(frame_tree_node_id);
   if (id_and_data != ad_frames_data_.end()) {
     // An existing subframe is navigating again.
@@ -112,17 +148,15 @@
 
       if (frame_tree_node_id == id_and_data->second->frame_tree_node_id) {
         // This is the top-most frame in the ad.
-        UMA_HISTOGRAM_BOOLEAN(
-            "PageLoad.Clients.Ads.Google.Navigations.AdFrameRenavigatedToAd",
-            FrameIsAd(navigation_handle));
+        ADS_HISTOGRAM("Navigations.AdFrameRenavigatedToAd",
+                      UMA_HISTOGRAM_BOOLEAN, AD_TYPE_ALL, ad_types.any());
       }
       return;
     }
     // This frame was previously not an ad, process it as usual. If it had
     // any child frames that were ads, those will still be recorded.
-    UMA_HISTOGRAM_BOOLEAN(
-        "PageLoad.Clients.Ads.Google.Navigations.NonAdFrameRenavigatedToAd",
-        FrameIsAd(navigation_handle));
+    ADS_HISTOGRAM("Navigations.NonAdFrameRenavigatedToAd",
+                  UMA_HISTOGRAM_BOOLEAN, AD_TYPE_ALL, ad_types.any());
   }
 
   // Determine who the parent frame's ad ancestor is.
@@ -131,17 +165,16 @@
   if (parent_id_and_data == ad_frames_data_.end()) {
     // We don't know who the parent for this frame is. One possibility is that
     // it's a frame from a previous navigation.
-    RecordParentExistsForSubFrame(false /* parent_exists */);
-
+    RecordParentExistsForSubFrame(false /* parent_exists */, ad_types);
     return;
   }
-  RecordParentExistsForSubFrame(true /* parent_exists */);
+  RecordParentExistsForSubFrame(true /* parent_exists */, ad_types);
 
   AdFrameData* ad_data = parent_id_and_data->second;
 
-  if (!ad_data && FrameIsAd(navigation_handle)) {
+  if (!ad_data && ad_types.any()) {
     // This frame is not nested within an ad frame but is itself an ad.
-    ad_frames_data_storage_.emplace_back(frame_tree_node_id);
+    ad_frames_data_storage_.emplace_back(frame_tree_node_id, ad_types);
     ad_data = &ad_frames_data_storage_.back();
   }
 
@@ -173,6 +206,40 @@
   RecordHistograms();
 }
 
+void AdsPageLoadMetricsObserver::OnSubframeNavigationEvaluated(
+    content::NavigationHandle* navigation_handle,
+    subresource_filter::LoadPolicy load_policy) {
+  // We don't track DISALLOW frames because their resources won't be loaded
+  // and therefore would provide bad histogram data. Note that WOULD_DISALLOW
+  // is only seen in dry runs.
+  if (load_policy == subresource_filter::LoadPolicy::WOULD_DISALLOW) {
+    unfinished_subresource_ad_frames_.insert(
+        navigation_handle->GetFrameTreeNodeId());
+  }
+}
+
+void AdsPageLoadMetricsObserver::OnSubresourceFilterGoingAway() {
+  subresource_observer_.RemoveAll();
+}
+
+bool AdsPageLoadMetricsObserver::DetectSubresourceFilterAd(
+    FrameTreeNodeId frame_tree_node_id) {
+  return unfinished_subresource_ad_frames_.erase(frame_tree_node_id);
+}
+
+AdsPageLoadMetricsObserver::AdTypes AdsPageLoadMetricsObserver::DetectAds(
+    content::NavigationHandle* navigation_handle) {
+  AdTypes ad_types;
+
+  if (DetectGoogleAd(navigation_handle))
+    ad_types.set(AD_TYPE_GOOGLE);
+
+  if (DetectSubresourceFilterAd(navigation_handle->GetFrameTreeNodeId()))
+    ad_types.set(AD_TYPE_SUBRESOURCE_FILTER);
+
+  return ad_types;
+}
+
 void AdsPageLoadMetricsObserver::ProcessLoadedResource(
     const page_load_metrics::ExtraRequestCompleteInfo& extra_request_info) {
   const auto& id_and_data =
@@ -201,7 +268,7 @@
     }
     if (committed_) {
       UMA_HISTOGRAM_ENUMERATION(
-          "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound",
+          "PageLoad.Clients.Ads.All.ResourceTypeWhenNoFrameFound",
           extra_request_info.resource_type, content::RESOURCE_TYPE_LAST_TYPE);
     }
 
@@ -225,6 +292,12 @@
 }
 
 void AdsPageLoadMetricsObserver::RecordHistograms() {
+  RecordHistogramsForType(AD_TYPE_GOOGLE);
+  RecordHistogramsForType(AD_TYPE_SUBRESOURCE_FILTER);
+  RecordHistogramsForType(AD_TYPE_ALL);
+}
+
+void AdsPageLoadMetricsObserver::RecordHistogramsForType(int ad_type) {
   if (page_bytes_ == 0)
     return;
 
@@ -236,59 +309,58 @@
     if (ad_frame_data.frame_bytes == 0)
       continue;
 
+    // If this isn't the type of ad we're looking for, move on to the next.
+    if (ad_type != AD_TYPE_ALL && !ad_frame_data.ad_types.test(ad_type))
+      continue;
+
     non_zero_ad_frames += 1;
     total_ad_frame_bytes += ad_frame_data.frame_bytes;
-    uncached_ad_frame_bytes += ad_frame_data.frame_bytes_uncached;
 
-    PAGE_BYTES_HISTOGRAM(
-        "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Total",
-        ad_frame_data.frame_bytes);
-    PAGE_BYTES_HISTOGRAM(
-        "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Network",
-        ad_frame_data.frame_bytes_uncached);
-    UMA_HISTOGRAM_PERCENTAGE(
-        "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.PercentNetwork",
+    uncached_ad_frame_bytes += ad_frame_data.frame_bytes_uncached;
+    ADS_HISTOGRAM("Bytes.AdFrames.PerFrame.Total", PAGE_BYTES_HISTOGRAM,
+                  ad_type, ad_frame_data.frame_bytes);
+    ADS_HISTOGRAM("Bytes.AdFrames.PerFrame.Network", PAGE_BYTES_HISTOGRAM,
+                  ad_type, ad_frame_data.frame_bytes_uncached);
+    ADS_HISTOGRAM(
+        "Bytes.AdFrames.PerFrame.PercentNetwork", UMA_HISTOGRAM_PERCENTAGE,
+        ad_type,
         ad_frame_data.frame_bytes_uncached * 100 / ad_frame_data.frame_bytes);
   }
 
-  UMA_HISTOGRAM_COUNTS_1000(
-      "PageLoad.Clients.Ads.Google.FrameCounts.AnyParentFrame.AdFrames",
-      non_zero_ad_frames);
+  ADS_HISTOGRAM("FrameCounts.AnyParentFrame.AdFrames",
+                UMA_HISTOGRAM_COUNTS_1000, ad_type, non_zero_ad_frames);
 
   // Don't post UMA for pages that don't have ads.
   if (non_zero_ad_frames == 0)
     return;
 
-  PAGE_BYTES_HISTOGRAM(
-      "PageLoad.Clients.Ads.Google.Bytes.NonAdFrames.Aggregate.Total",
-      page_bytes_ - total_ad_frame_bytes);
+  ADS_HISTOGRAM("Bytes.NonAdFrames.Aggregate.Total", PAGE_BYTES_HISTOGRAM,
+                ad_type, page_bytes_ - total_ad_frame_bytes);
 
-  PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Google.Bytes.FullPage.Total",
-                       page_bytes_);
-  PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Google.Bytes.FullPage.Network",
-                       uncached_page_bytes_);
+  ADS_HISTOGRAM("Bytes.FullPage.Total", PAGE_BYTES_HISTOGRAM, ad_type,
+                page_bytes_);
+  ADS_HISTOGRAM("Bytes.FullPage.Network", PAGE_BYTES_HISTOGRAM, ad_type,
+                uncached_page_bytes_);
+
   if (page_bytes_) {
-    UMA_HISTOGRAM_PERCENTAGE(
-        "PageLoad.Clients.Ads.Google.Bytes.FullPage.Total.PercentAds",
-        total_ad_frame_bytes * 100 / page_bytes_);
+    ADS_HISTOGRAM("Bytes.FullPage.Total.PercentAds", UMA_HISTOGRAM_PERCENTAGE,
+                  ad_type, total_ad_frame_bytes * 100 / page_bytes_);
   }
   if (uncached_page_bytes_ > 0) {
-    UMA_HISTOGRAM_PERCENTAGE(
-        "PageLoad.Clients.Ads.Google.Bytes.FullPage.Network.PercentAds",
-        uncached_ad_frame_bytes * 100 / uncached_page_bytes_);
+    ADS_HISTOGRAM("Bytes.FullPage.Network.PercentAds", UMA_HISTOGRAM_PERCENTAGE,
+                  ad_type,
+                  uncached_ad_frame_bytes * 100 / uncached_page_bytes_);
   }
 
-  PAGE_BYTES_HISTOGRAM(
-      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Total",
-      total_ad_frame_bytes);
-  PAGE_BYTES_HISTOGRAM(
-      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Network",
-      uncached_ad_frame_bytes);
+  ADS_HISTOGRAM("Bytes.AdFrames.Aggregate.Total", PAGE_BYTES_HISTOGRAM, ad_type,
+                total_ad_frame_bytes);
+  ADS_HISTOGRAM("Bytes.AdFrames.Aggregate.Network", PAGE_BYTES_HISTOGRAM,
+                ad_type, uncached_ad_frame_bytes);
 
   if (total_ad_frame_bytes) {
-    UMA_HISTOGRAM_PERCENTAGE(
-        "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.PercentNetwork",
-        uncached_ad_frame_bytes * 100 / total_ad_frame_bytes);
+    ADS_HISTOGRAM("Bytes.AdFrames.Aggregate.PercentNetwork",
+                  UMA_HISTOGRAM_PERCENTAGE, ad_type,
+                  uncached_ad_frame_bytes * 100 / total_ad_frame_bytes);
   }
 }
 
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h
index 3e42a42e..b48fb40 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h
@@ -5,20 +5,36 @@
 #ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_ADS_PAGE_LOAD_METRICS_OBSERVER_H_
 #define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_ADS_PAGE_LOAD_METRICS_OBSERVER_H_
 
+#include <bitset>
 #include <list>
 #include <map>
 #include <memory>
 
 #include "base/macros.h"
+#include "base/scoped_observer.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
+#include "components/subresource_filter/content/browser/subresource_filter_observer.h"
+#include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h"
+#include "components/subresource_filter/core/common/load_policy.h"
 #include "components/ukm/ukm_source.h"
 #include "net/http/http_response_info.h"
 
 // This observer labels each sub-frame as an ad or not, and keeps track of
 // relevant per-frame and whole-page byte statistics.
 class AdsPageLoadMetricsObserver
-    : public page_load_metrics::PageLoadMetricsObserver {
+    : public page_load_metrics::PageLoadMetricsObserver,
+      public subresource_filter::SubresourceFilterObserver {
  public:
+  // The types of ads that one can filter on.
+  enum AdType {
+    AD_TYPE_GOOGLE = 0,
+    AD_TYPE_SUBRESOURCE_FILTER = 1,
+    AD_TYPE_ALL = 2,
+    AD_TYPE_MAX = AD_TYPE_ALL
+  };
+
+  using AdTypes = std::bitset<AD_TYPE_MAX>;
+
   // Returns a new AdsPageLoadMetricObserver. If the feature is disabled it
   // returns nullptr.
   static std::unique_ptr<AdsPageLoadMetricsObserver> CreateIfNeeded();
@@ -27,6 +43,9 @@
   ~AdsPageLoadMetricsObserver() override;
 
   // page_load_metrics::PageLoadMetricsObserver
+  ObservePolicy OnStart(content::NavigationHandle* navigation_handle,
+                        const GURL& currently_committed_url,
+                        bool started_in_foreground) override;
   ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
                          ukm::SourceId source_id) override;
   void OnDidFinishSubFrameNavigation(
@@ -41,15 +60,33 @@
 
  private:
   struct AdFrameData {
-    explicit AdFrameData(FrameTreeNodeId frame_tree_node_id);
+    AdFrameData(FrameTreeNodeId frame_tree_node_id, AdTypes ad_types);
     size_t frame_bytes;
     size_t frame_bytes_uncached;
     const FrameTreeNodeId frame_tree_node_id;
+    AdTypes ad_types;
   };
 
+  // subresource_filter::SubresourceFilterObserver:
+  void OnSubframeNavigationEvaluated(
+      content::NavigationHandle* navigation_handle,
+      subresource_filter::LoadPolicy load_policy) override;
+  void OnSubresourceFilterGoingAway() override;
+
+  // Determines if the URL of a frame matches the SubresourceFilter block
+  // list. Should only be called once per frame navigation.
+  bool DetectSubresourceFilterAd(FrameTreeNodeId frame_tree_node_id);
+
+  // This should only be called once per frame navigation, as the
+  // SubresourceFilter detector clears its state about detected frames after
+  // each call in order to free up memory.
+  AdTypes DetectAds(content::NavigationHandle* navigation_handle);
+
   void ProcessLoadedResource(
       const page_load_metrics::ExtraRequestCompleteInfo& extra_request_info);
+
   void RecordHistograms();
+  void RecordHistogramsForType(int ad_type);
 
   // Checks to see if a resource is waiting for a navigation with the given
   // |frame_tree_node_id| to commit before it can be processed. If so, call
@@ -67,6 +104,11 @@
   // nullptr.
   std::map<FrameTreeNodeId, AdFrameData*> ad_frames_data_;
 
+  // The set of frames that have yet to finish but that the SubresourceFilter
+  // has reported are ads. Once DetectSubresourceFilterAd is called the id is
+  // removed from the set.
+  std::set<FrameTreeNodeId> unfinished_subresource_ad_frames_;
+
   // When the observer receives report of a document resource loading for a
   // sub-frame before the sub-frame commit occurs, hold onto the resource
   // request info (delay it) until the sub-frame commits.
@@ -77,6 +119,10 @@
   size_t uncached_page_bytes_ = 0u;
   bool committed_ = false;
 
+  ScopedObserver<subresource_filter::SubresourceFilterObserverManager,
+                 subresource_filter::SubresourceFilterObserver>
+      subresource_observer_;
+
   DISALLOW_COPY_AND_ASSIGN(AdsPageLoadMetricsObserver);
 };
 
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc
index 08ae49f..73b94614 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc
@@ -7,11 +7,14 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/strings/stringprintf.h"
 #include "base/test/histogram_tester.h"
 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h"
 #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/page_load_tracker.h"
+#include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h"
+#include "components/subresource_filter/core/common/load_policy.h"
 #include "content/public/browser/global_request_id.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
@@ -36,10 +39,14 @@
   size_t uncached_kb;
 };
 
+enum class AdType { GOOGLE = 0, SUBRESOURCE_FILTER = 1, ALL = 2 };
 enum class ResourceCached { NOT_CACHED, CACHED };
 enum class FrameType { AD = 0, NON_AD };
 
 const char kAdUrl[] = "https://tpc.googlesyndication.com/safeframe/1";
+const char kSubresourceFilterWouldDisallowAdUrl[] = "https://ad.example.com/";
+const char kSubresourceFilterDisallowAdUrl[] =
+    "https://ad.example.com/disallow";
 const char kNonAdUrl[] = "https://foo.com/";
 const char kNonAdUrl2[] = "https://bar.com/";
 
@@ -117,13 +124,32 @@
   DISALLOW_COPY_AND_ASSIGN(DelayWillProcessResponseObserver);
 };
 
+std::string AdTypeToString(AdType ad_type) {
+  switch (ad_type) {
+    case AdType::GOOGLE:
+      return "Google";
+    case AdType::SUBRESOURCE_FILTER:
+      return "SubresourceFilter";
+    case AdType::ALL:
+      return "All";
+  }
+  ADD_FAILURE();
+  return "";
+}
+
+std::string TypedHistogram(const std::string& suffix, AdType ad_type) {
+  return base::StringPrintf("PageLoad.Clients.Ads.%s.%s",
+                            AdTypeToString(ad_type).c_str(), suffix.c_str());
+}
+
 // Verifies that the histograms match what is expected given |google_ad_frames|
 // ad frame byte counts and non-ad counts (|other_cached_kb| and
 // |other_uncached_kb|).
 void TestHistograms(const base::HistogramTester& histograms,
                     const std::vector<ExpectedFrameBytes>& google_ad_frames,
                     size_t non_ad_cached_kb,
-                    size_t non_ad_uncached_kb) {
+                    size_t non_ad_uncached_kb,
+                    AdType ad_type) {
   size_t total_ad_cached_kb = 0;
   size_t total_ad_uncached_kb = 0;
   size_t total_ad_kb = 0;
@@ -155,7 +181,7 @@
 
   // Test the histograms.
   histograms.ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.FrameCounts.AnyParentFrame.AdFrames",
+      TypedHistogram("FrameCounts.AnyParentFrame.AdFrames", ad_type),
       ad_frame_count, 1);
 
   if (ad_frame_count == 0)
@@ -163,46 +189,46 @@
 
   for (const auto& total_bytes_and_count : frames_with_total_byte_count) {
     histograms.ExpectBucketCount(
-        "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Total",
+        TypedHistogram("Bytes.AdFrames.PerFrame.Total", ad_type),
         total_bytes_and_count.first, total_bytes_and_count.second);
   }
   for (const auto& network_bytes_and_count : frames_with_network_byte_count) {
     histograms.ExpectBucketCount(
-        "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Network",
+        TypedHistogram("Bytes.AdFrames.PerFrame.Network", ad_type),
         network_bytes_and_count.first, network_bytes_and_count.second);
   }
   for (const auto& percent_network_and_count :
        frames_with_percent_network_count) {
     histograms.ExpectBucketCount(
-        "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.PercentNetwork",
+        TypedHistogram("Bytes.AdFrames.PerFrame.PercentNetwork", ad_type),
         percent_network_and_count.first, percent_network_and_count.second);
   }
 
   histograms.ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Total", total_ad_kb,
+      TypedHistogram("Bytes.AdFrames.Aggregate.Total", ad_type), total_ad_kb,
       1);
   histograms.ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Network",
+      TypedHistogram("Bytes.AdFrames.Aggregate.Network", ad_type),
       total_ad_uncached_kb, 1);
   histograms.ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Total",
+      TypedHistogram("Bytes.FullPage.Total", ad_type),
       non_ad_cached_kb + non_ad_uncached_kb + total_ad_kb, 1);
   histograms.ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Network",
+      TypedHistogram("Bytes.FullPage.Network", ad_type),
       non_ad_uncached_kb + total_ad_uncached_kb, 1);
   histograms.ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.NonAdFrames.Aggregate.Total",
+      TypedHistogram("Bytes.NonAdFrames.Aggregate.Total", ad_type),
       non_ad_cached_kb + non_ad_uncached_kb, 1);
   histograms.ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Total.PercentAds",
+      TypedHistogram("Bytes.FullPage.Total.PercentAds", ad_type),
       (total_ad_kb * 100) /
           (total_ad_kb + non_ad_cached_kb + non_ad_uncached_kb),
       1);
   histograms.ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.PercentNetwork",
+      TypedHistogram("Bytes.AdFrames.Aggregate.PercentNetwork", ad_type),
       ((total_ad_uncached_kb * 100) / total_ad_kb), 1);
   histograms.ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Network.PercentAds",
+      TypedHistogram("Bytes.FullPage.Network.PercentAds", ad_type),
       (total_ad_uncached_kb * 100) /
           (total_ad_uncached_kb + non_ad_uncached_kb),
       1);
@@ -215,6 +241,15 @@
  public:
   AdsPageLoadMetricsObserverTest() {}
 
+  void SetUp() override {
+    page_load_metrics::PageLoadMetricsObserverTestHarness::SetUp();
+    subresource_filter::SubresourceFilterObserverManager::CreateForWebContents(
+        web_contents());
+    subresource_observer_manager_ =
+        subresource_filter::SubresourceFilterObserverManager::FromWebContents(
+            web_contents());
+  }
+
   // Returns the final RenderFrameHost after navigation commits.
   RenderFrameHost* NavigateFrame(const std::string& url,
                                  content::RenderFrameHost* frame) {
@@ -237,6 +272,22 @@
         RenderFrameHostTester::For(parent)->AppendChild(frame_name);
     auto navigation_simulator =
         NavigationSimulator::CreateRendererInitiated(GURL(url), subframe);
+    navigation_simulator->Start();
+
+    // Simulate subresource filter evaluation.
+    content::NavigationHandle* handle =
+        navigation_simulator->GetNavigationHandle();
+    if (url == kSubresourceFilterWouldDisallowAdUrl) {
+      subresource_observer_manager_->NotifySubframeNavigationEvaluated(
+          handle, subresource_filter::LoadPolicy::WOULD_DISALLOW);
+    } else if (url == kSubresourceFilterDisallowAdUrl) {
+      subresource_observer_manager_->NotifySubframeNavigationEvaluated(
+          handle, subresource_filter::LoadPolicy::DISALLOW);
+    } else {
+      subresource_observer_manager_->NotifySubframeNavigationEvaluated(
+          handle, subresource_filter::LoadPolicy::ALLOW);
+    }
+
     navigation_simulator->Commit();
     return navigation_simulator->GetFinalRenderFrameHost();
   }
@@ -252,11 +303,11 @@
 
     if (frame_type == FrameType::AD) {
       tester.ExpectUniqueSample(
-          "PageLoad.Clients.Ads.Google.Navigations.AdFrameRenavigatedToAd",
-          bucket, 1);
+          "PageLoad.Clients.Ads.All.Navigations.AdFrameRenavigatedToAd", bucket,
+          1);
     } else {
       tester.ExpectUniqueSample(
-          "PageLoad.Clients.Ads.Google.Navigations.NonAdFrameRenavigatedToAd",
+          "PageLoad.Clients.Ads.All.Navigations.NonAdFrameRenavigatedToAd",
           bucket, 1);
     }
 
@@ -281,6 +332,8 @@
   }
 
  private:
+  subresource_filter::SubresourceFilterObserverManager*
+      subresource_observer_manager_ = nullptr;
   DISALLOW_COPY_AND_ASSIGN(AdsPageLoadMetricsObserverTest);
 };
 
@@ -298,7 +351,8 @@
   NavigateFrame(kNonAdUrl, main_frame);
 
   TestHistograms(histogram_tester(), std::vector<ExpectedFrameBytes>(),
-                 0 /* non_ad_cached_kb */, 30 /* non_ad_uncached_kb */);
+                 0 /* non_ad_cached_kb */, 30 /* non_ad_uncached_kb */,
+                 AdType::GOOGLE);
 
   // Verify that other UMA wasn't written.
   histogram_tester().ExpectTotalCount(
@@ -327,10 +381,10 @@
   NavigateFrame(kNonAdUrl, main_frame);
 
   TestHistograms(histogram_tester(), {{0, 10}}, 0 /* non_ad_cached_kb */,
-                 10 /*non_ad_uncached_kb*/);
+                 10 /*non_ad_uncached_kb*/, AdType::GOOGLE);
 }
 
-TEST_F(AdsPageLoadMetricsObserverTest, PageWithAdFrames) {
+TEST_F(AdsPageLoadMetricsObserverTest, AllAdTypesInPage) {
   RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
   RenderFrameHost* non_ad_frame =
       CreateAndNavigateSubFrame(kNonAdUrl, kNonAdName, main_frame);
@@ -339,40 +393,54 @@
   // nested ad frame doesn't get counted separately (but that its bytes are
   // still counted). Also verify that the various ad signals (urls and names)
   // are properly detected.
-  RenderFrameHost* ad_frame1 =
+  RenderFrameHost* google_frame1 =
       CreateAndNavigateSubFrame(kNonAdUrl, "google_ads_iframe_1", main_frame);
-  RenderFrameHost* ad_frame2 =
-      CreateAndNavigateSubFrame(kNonAdUrl, "google_ads_frame_2", main_frame);
-  RenderFrameHost* ad_frame3 = CreateAndNavigateSubFrame(
-      "https://tpc.googlesyndication.com/safeframe/", "", main_frame);
-  RenderFrameHost* ad_frame4 = CreateAndNavigateSubFrame(
-      "https://tpc.googlesyndication.com/safeframe/1", "", main_frame);
-  RenderFrameHost* nested_ad_frame4 = CreateAndNavigateSubFrame(
-      "https://tpc.googlesyndication.com/safeframe/2", "", ad_frame4);
+  RenderFrameHost* google_frame2 =
+      CreateAndNavigateSubFrame(kAdUrl, kNonAdName, main_frame);
+  RenderFrameHost* srf_frame1 = CreateAndNavigateSubFrame(
+      kSubresourceFilterWouldDisallowAdUrl, kNonAdName, main_frame);
+  RenderFrameHost* srf_frame2 = CreateAndNavigateSubFrame(
+      kSubresourceFilterWouldDisallowAdUrl, kNonAdName, main_frame);
+  RenderFrameHost* nested_srf_frame3 = CreateAndNavigateSubFrame(
+      kSubresourceFilterWouldDisallowAdUrl, kNonAdName, srf_frame2);
+
+  // This frame should return DISALLOW by the SubresourceFilter so it won't
+  // count as an ad.
+  RenderFrameHost* disallowed_srf_frame = CreateAndNavigateSubFrame(
+      kSubresourceFilterDisallowAdUrl, kNonAdName, main_frame);
 
   // Create an addditional ad frame without content. It shouldn't be counted
   // as an ad frame.
-  CreateAndNavigateSubFrame(kAdUrl, kNonAdName, main_frame);
+  CreateAndNavigateSubFrame(kSubresourceFilterWouldDisallowAdUrl, kNonAdName,
+                            main_frame);
 
   // 70KB total in page, 50 from ads, 40 from network, and 30 of those
   // are from ads.
   LoadResource(main_frame, ResourceCached::NOT_CACHED, 10);
   LoadResource(non_ad_frame, ResourceCached::CACHED, 10);
-  LoadResource(ad_frame1, ResourceCached::CACHED, 10);
-  LoadResource(ad_frame2, ResourceCached::NOT_CACHED, 10);
-  LoadResource(ad_frame3, ResourceCached::NOT_CACHED, 10);
-  LoadResource(ad_frame4, ResourceCached::NOT_CACHED, 10);
-  LoadResource(nested_ad_frame4, ResourceCached::CACHED, 10);
+  LoadResource(google_frame1, ResourceCached::CACHED, 10);
+  LoadResource(google_frame2, ResourceCached::NOT_CACHED, 10);
+  LoadResource(srf_frame1, ResourceCached::NOT_CACHED, 10);
+  LoadResource(srf_frame2, ResourceCached::NOT_CACHED, 10);
+  LoadResource(nested_srf_frame3, ResourceCached::CACHED, 10);
+  LoadResource(disallowed_srf_frame, ResourceCached::CACHED, 10);
 
   // Navigate again to trigger histograms.
   NavigateFrame(kNonAdUrl, main_frame);
 
+  TestHistograms(histogram_tester(), {{10, 0}, {0, 10}},
+                 30 /* non_ad_cached_kb */, 30 /* non_ad_uncached_kb */,
+                 AdType::GOOGLE);
+  TestHistograms(histogram_tester(), {{0, 10}, {10, 10}},
+                 30 /* non_ad_cached_kb */, 20 /* non_ad_uncached_kb */,
+                 AdType::SUBRESOURCE_FILTER);
   TestHistograms(histogram_tester(), {{10, 0}, {0, 10}, {0, 10}, {10, 10}},
-                 10 /* non_ad_cached_kb */, 10 /* non_ad_uncached_kb */);
+                 20 /* non_ad_cached_kb */, 10 /* non_ad_uncached_kb */,
+                 AdType::ALL);
   histogram_tester().ExpectBucketCount(
-      "PageLoad.Clients.Ads.Google.ParentExistsForSubFrame", 0, 0);
+      "PageLoad.Clients.Ads.All.ParentExistsForSubFrame", 0, 0);
   histogram_tester().ExpectTotalCount(
-      "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound", 0);
+      "PageLoad.Clients.Ads.All.ResourceTypeWhenNoFrameFound", 0);
 }
 
 TEST_F(AdsPageLoadMetricsObserverTest, PageLoadSubFrameRenavigationMetrics) {
@@ -410,7 +478,7 @@
   base::HistogramTester tester;
   ad_sub_sub_frame = NavigateFrame(kNonAdUrl2, ad_sub_sub_frame);
   tester.ExpectTotalCount(
-      "PageLoad.Clients.Ads.Google.Navigations.AdFrameRenavigatedToAd", 0);
+      "PageLoad.Clients.Ads.All.Navigations.AdFrameRenavigatedToAd", 0);
 }
 
 TEST_F(AdsPageLoadMetricsObserverTest, PageWithAdFrameThatRenavigates) {
@@ -431,11 +499,11 @@
   NavigateFrame(kNonAdUrl, main_frame);
 
   TestHistograms(histogram_tester(), {{0, 20}}, 0 /* non_ad_cached_kb */,
-                 10 /* non_ad_uncached_kb */);
+                 10 /* non_ad_uncached_kb */, AdType::GOOGLE);
   histogram_tester().ExpectBucketCount(
-      "PageLoad.Clients.Ads.Google.ParentExistsForSubFrame", 0, 0);
+      "PageLoad.Clients.Ads.All.ParentExistsForSubFrame", 0, 0);
   histogram_tester().ExpectTotalCount(
-      "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound", 0);
+      "PageLoad.Clients.Ads.All.ResourceTypeWhenNoFrameFound", 0);
 }
 
 TEST_F(AdsPageLoadMetricsObserverTest, PageWithNonAdFrameThatRenavigatesToAd) {
@@ -466,11 +534,12 @@
   NavigateFrame(kNonAdUrl, main_frame);
 
   TestHistograms(histogram_tester(), {{0, 10}, {0, 10}},
-                 0 /* non_ad_cached_kb */, 20 /* non_ad_uncached_kb */);
+                 0 /* non_ad_cached_kb */, 20 /* non_ad_uncached_kb */,
+                 AdType::GOOGLE);
   histogram_tester().ExpectBucketCount(
-      "PageLoad.Clients.Ads.Google.ParentExistsForSubFrame", 0, 0);
+      "PageLoad.Clients.Ads.All.ParentExistsForSubFrame", 0, 0);
   histogram_tester().ExpectTotalCount(
-      "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound", 0);
+      "PageLoad.Clients.Ads.All.ResourceTypeWhenNoFrameFound", 0);
 }
 
 TEST_F(AdsPageLoadMetricsObserverTest, CountAbortedNavigation) {
@@ -497,7 +566,7 @@
   NavigateFrame(kNonAdUrl, main_frame);
 
   TestHistograms(histogram_tester(), {{0, 20}}, 0 /* non_ad_cached_kb */,
-                 10 /* non_ad_uncached_kb */);
+                 10 /* non_ad_uncached_kb */, AdType::GOOGLE);
 }
 
 TEST_F(AdsPageLoadMetricsObserverTest, CountAbortedSecondNavigationForFrame) {
@@ -526,7 +595,7 @@
   NavigateFrame(kNonAdUrl, main_frame);
 
   TestHistograms(histogram_tester(), {{0, 20}}, 0 /* non_ad_cached_kb */,
-                 20 /* non_ad_uncached_kb */);
+                 20 /* non_ad_uncached_kb */, AdType::GOOGLE);
 }
 
 TEST_F(AdsPageLoadMetricsObserverTest, TwoResourceLoadsBeforeCommit) {
@@ -561,12 +630,11 @@
   NavigateFrame(kNonAdUrl, main_frame);
 
   TestHistograms(histogram_tester(), {{0, 20}}, 0 /* non_ad_cached_kb */,
-                 10 /* non_ad_uncached_kb */);
-
+                 10 /* non_ad_uncached_kb */, AdType::GOOGLE);
   histogram_tester().ExpectBucketCount(
-      "PageLoad.Clients.Ads.Google.ParentExistsForSubFrame", 0, 0);
+      "PageLoad.Clients.Ads.All.ParentExistsForSubFrame", 0, 0);
   histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound",
+      "PageLoad.Clients.Ads.All.ResourceTypeWhenNoFrameFound",
       content::RESOURCE_TYPE_SUB_FRAME, 1);
 }
 
@@ -580,7 +648,7 @@
       CreateAndNavigateSubFrame(kNonAdUrl, kNonAdName, main_frame);
 
   histogram_tester().ExpectBucketCount(
-      "PageLoad.Clients.Ads.Google.ParentExistsForSubFrame", 0, 0);
+      "PageLoad.Clients.Ads.All.ParentExistsForSubFrame", 0, 0);
 
   // Renavigate the child, but, while navigating, the main frame renavigates.
   RenderFrameHost* child_of_subframe =
@@ -596,15 +664,15 @@
   navigation_simulator->Commit();
   child_of_subframe = navigation_simulator->GetFinalRenderFrameHost();
   histogram_tester().ExpectBucketCount(
-      "PageLoad.Clients.Ads.Google.ParentExistsForSubFrame", 0, 1);
+      "PageLoad.Clients.Ads.All.ParentExistsForSubFrame", 0, 1);
 
   // Test that a resource loaded into an unknown frame doesn't cause any
   // issues.
   histogram_tester().ExpectTotalCount(
-      "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound", 0);
+      "PageLoad.Clients.Ads.All.ResourceTypeWhenNoFrameFound", 0);
   LoadResource(child_of_subframe, ResourceCached::NOT_CACHED, 10);
   histogram_tester().ExpectBucketCount(
-      "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound",
+      "PageLoad.Clients.Ads.All.ResourceTypeWhenNoFrameFound",
       content::RESOURCE_TYPE_SUB_FRAME, 1);
 }
 
@@ -668,6 +736,6 @@
 
   // There shouldn't be any histograms for an aborted main frame.
   EXPECT_EQ(0u, histogram_tester()
-                    .GetTotalCountsForPrefix("PageLoad.Clients.Ads.")
+                    .GetTotalCountsForPrefix("PageLoad.Clients.Ads.Google.")
                     .size());
 }
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index c81c149..66e12c4 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -11,16 +11,23 @@
 #include "base/test/histogram_tester.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
+#include "chrome/browser/lifetime/keep_alive_types.h"
+#include "chrome/browser/lifetime/scoped_keep_alive.h"
 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h"
 #include "chrome/browser/page_load_metrics/observers/aborts_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/no_state_prefetch_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/page_load_tracker.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/prerender/prerender_histograms.h"
 #include "chrome/browser/prerender/prerender_origin.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sessions/session_service_factory.h"
+#include "chrome/browser/sessions/session_service_test_helper.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_features.h"
@@ -1070,3 +1077,95 @@
 
   histogram_tester_.ExpectUniqueSample(internal::kHistogramTotalBytes, 0, 1);
 }
+
+class SessionRestorePageLoadMetricsBrowserTest
+    : public PageLoadMetricsBrowserTest {
+ public:
+  SessionRestorePageLoadMetricsBrowserTest() {}
+
+  // PageLoadMetricsBrowserTest:
+  void SetUpOnMainThread() override {
+    PageLoadMetricsBrowserTest::SetUpOnMainThread();
+    SessionStartupPref::SetStartupPref(
+        browser()->profile(), SessionStartupPref(SessionStartupPref::LAST));
+    ASSERT_TRUE(embedded_test_server()->Start());
+#if defined(OS_CHROMEOS)
+    SessionServiceTestHelper helper(
+        SessionServiceFactory::GetForProfile(browser()->profile()));
+    helper.SetForceBrowserNotAliveWithNoWindows(true);
+    helper.ReleaseService();
+#endif
+  }
+
+  Browser* QuitBrowserAndRestore(Browser* browser) {
+    Profile* profile = browser->profile();
+
+    std::unique_ptr<ScopedKeepAlive> keep_alive(new ScopedKeepAlive(
+        KeepAliveOrigin::SESSION_RESTORE, KeepAliveRestartOption::DISABLED));
+    CloseBrowserSynchronously(browser);
+
+    // Create a new window, which should trigger session restore.
+    chrome::NewEmptyWindow(profile);
+    ui_test_utils::BrowserAddedObserver window_observer;
+    return window_observer.WaitForSingleNewBrowser();
+  }
+
+  void WaitForTabsToLoad(Browser* browser) {
+    for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
+      content::WebContents* contents =
+          browser->tab_strip_model()->GetWebContentsAt(i);
+      contents->GetController().LoadIfNecessary();
+      content::WaitForLoadStop(contents);
+    }
+  }
+
+  GURL GetTestURL() const {
+    return embedded_test_server()->GetURL("/title1.html");
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SessionRestorePageLoadMetricsBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
+                       InitialVisibilityOfSingleRestoredTab) {
+  ui_test_utils::NavigateToURL(browser(), GetTestURL());
+  histogram_tester_.ExpectTotalCount(
+      page_load_metrics::internal::kPageLoadStartedInForeground, 1);
+  histogram_tester_.ExpectBucketCount(
+      page_load_metrics::internal::kPageLoadStartedInForeground, true, 1);
+
+  Browser* new_browser = QuitBrowserAndRestore(browser());
+  WaitForTabsToLoad(new_browser);
+
+  histogram_tester_.ExpectTotalCount(
+      page_load_metrics::internal::kPageLoadStartedInForeground, 2);
+  histogram_tester_.ExpectBucketCount(
+      page_load_metrics::internal::kPageLoadStartedInForeground, true, 2);
+}
+
+IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest,
+                       InitialVisibilityOfMultipleRestoredTabs) {
+  ui_test_utils::NavigateToURL(browser(), GetTestURL());
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), GetTestURL(), WindowOpenDisposition::NEW_BACKGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+  histogram_tester_.ExpectTotalCount(
+      page_load_metrics::internal::kPageLoadStartedInForeground, 2);
+  histogram_tester_.ExpectBucketCount(
+      page_load_metrics::internal::kPageLoadStartedInForeground, false, 1);
+
+  Browser* new_browser = QuitBrowserAndRestore(browser());
+  WaitForTabsToLoad(new_browser);
+
+  TabStripModel* tab_strip = new_browser->tab_strip_model();
+  ASSERT_TRUE(tab_strip);
+  ASSERT_EQ(2, tab_strip->count());
+
+  histogram_tester_.ExpectTotalCount(
+      page_load_metrics::internal::kPageLoadStartedInForeground, 4);
+  histogram_tester_.ExpectBucketCount(
+      page_load_metrics::internal::kPageLoadStartedInForeground, true, 2);
+  histogram_tester_.ExpectBucketCount(
+      page_load_metrics::internal::kPageLoadStartedInForeground, false, 2);
+}
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.h b/chrome/browser/page_load_metrics/page_load_tracker.h
index f8185b0..6146a09 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.h
+++ b/chrome/browser/page_load_metrics/page_load_tracker.h
@@ -44,6 +44,7 @@
 extern const char kAbortChainSizeNoCommit[];
 extern const char kAbortChainSizeSameURL[];
 extern const char kPageLoadCompletedAfterAppBackground[];
+extern const char kPageLoadStartedInForeground[];
 
 }  // namespace internal
 
diff --git a/chrome/browser/plugins/flash_permission_browsertest.cc b/chrome/browser/plugins/flash_permission_browsertest.cc
index 508190b..d8f1dee 100644
--- a/chrome/browser/plugins/flash_permission_browsertest.cc
+++ b/chrome/browser/plugins/flash_permission_browsertest.cc
@@ -2,21 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/permissions/permissions_browsertest.h"
 #include "chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/variations/variations_switches.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/ppapi_test_utils.h"
+#include "content/public/test/test_utils.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
 #include "url/gurl.h"
 
@@ -55,13 +55,9 @@
 
     // Set a high engagement threshhold so it doesn't interfere with testing the
     // permission.
-    command_line->AppendSwitchASCII(switches::kEnableFeatures,
-                                    "PreferHtmlOverPlugins<Study1");
-    command_line->AppendSwitchASCII(switches::kForceFieldTrials,
-                                    "Study1/Enabled/");
-    command_line->AppendSwitchASCII(
-        variations::switches::kForceFieldTrialParams,
-        "Study1.Enabled:engagement_threshold_for_flash/100");
+    content::EnableFeatureWithParam(features::kPreferHtmlOverPlugins,
+                                    "engagement_threshold_for_flash", "100",
+                                    command_line);
   }
 
   void TriggerPrompt() override {
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index fb5062f1..15be438 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "ash/accelerators/accelerator_controller_delegate_aura.h"
-#include "base/base_switches.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
@@ -33,7 +32,6 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/test_file_util.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
@@ -132,7 +130,6 @@
 #include "components/update_client/url_request_post_interceptor.h"
 #include "components/user_prefs/user_prefs.h"
 #include "components/variations/service/variations_service.h"
-#include "components/variations/variations_switches.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
@@ -4384,21 +4381,9 @@
 class NetworkTimePolicyTest : public PolicyTest {
  public:
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitchASCII(
-        switches::kForceFieldTrials,
-        "SSLNetworkTimeBrowserTestFieldTrial/Enabled/");
-    command_line->AppendSwitchASCII(
-        variations::switches::kForceFieldTrialParams,
-        "SSLNetworkTimeBrowserTestFieldTrial.Enabled:FetchBehavior/"
-        "on-demand-only");
-  }
-
-  void SetUpOnMainThread() override {
-    PolicyTest::SetUpOnMainThread();
-    scoped_feature_list_.InitFromCommandLine(
-        std::string(network_time::kNetworkTimeServiceQuerying.name) +
-            "<SSLNetworkTimeBrowserTestFieldTrial",
-        std::string());
+    content::EnableFeatureWithParam(network_time::kNetworkTimeServiceQuerying,
+                                    "FetchBehavior", "on-demand-only",
+                                    command_line);
   }
 
   // A request handler that returns a dummy response and counts the number of
@@ -4421,7 +4406,6 @@
 
  private:
   uint32_t num_requests_ = 0;
-  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 IN_PROC_BROWSER_TEST_F(NetworkTimePolicyTest, NetworkTimeQueriesDisabled) {
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
index 3915695..4ee5055c 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
@@ -23,6 +23,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/browsing_data_remover.h"
+#include "content/public/test/test_utils.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/url_util.h"
 #include "net/dns/mock_host_resolver.h"
@@ -321,13 +322,9 @@
   using URLRequestSummary = URLRequestSummary;
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitchASCII("force-fieldtrials", "trial/group");
-    std::string parameter = base::StringPrintf(
-        "trial.group:%s/%s", kModeParamName, kExternalPrefetchingMode);
-    command_line->AppendSwitchASCII("force-fieldtrial-params", parameter);
-    std::string enabled_feature = base::StringPrintf(
-        "%s<trial", kSpeculativeResourcePrefetchingFeatureName);
-    command_line->AppendSwitchASCII("enable-features", enabled_feature);
+    content::EnableFeatureWithParam(kSpeculativeResourcePrefetchingFeature,
+                                    kModeParamName, kExternalPrefetchingMode,
+                                    command_line);
   }
 
   void SetUpOnMainThread() override {
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
index 2cccb4b..a04c9a79 100644
--- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
+++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
@@ -86,8 +86,10 @@
         'on-printer-discovered', this.onPrinterDiscovered_.bind(this));
     this.addWebUIListener(
         'on-printer-discovery-done', this.onPrinterDiscoveryDone_.bind(this));
-    this.addWebUIListener(
-        'on-printer-discovery-failed', this.onPrinterDiscoveryDone_.bind(this));
+  },
+
+  close: function() {
+    this.$$('add-printer-dialog').close();
   },
 
   /**
@@ -108,7 +110,10 @@
   onPrinterDiscoveryDone_: function() {
     this.discovering_ = false;
     this.$$('add-printer-list').style.maxHeight = kPrinterListFullHeight + 'px';
-    this.$.noPrinterMessage.hidden = !!this.discoveredPrinters;
+    this.$.noPrinterMessage.hidden = !!this.discoveredPrinters.length;
+
+    if (!this.discoveredPrinters.length)
+      this.fire('no-detected-printer');
   },
 
   /** @private */
@@ -380,6 +385,7 @@
     'open-configuring-printer-dialog': 'openConfiguringPrinterDialog_',
     'open-discovery-printers-dialog': 'openDiscoveryPrintersDialog_',
     'open-manufacturer-model-dialog': 'openManufacturerModelDialog_',
+    'no-detected-printer': 'onNoDetectedPrinter_',
   },
 
   /** @override */
@@ -512,6 +518,17 @@
     }
   },
 
+  /** @private */
+  onNoDetectedPrinter_: function() {
+    // If there is no detected printer, automatically open manually-add-printer
+    // dialog only when the user opens the discovery-dialog through the
+    // "ADD PRINTER" button.
+    if (!this.previousDialog_) {
+      this.$$('add-printer-discovery-dialog').close();
+      this.openManuallyAddPrinterDialog_();
+    }
+  },
+
   /**
    * Switch dialog from |fromDialog| to |toDialog|.
    * @param {string} fromDialog
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc b/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
index 468c1e69..89d6b6a 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/safe_browsing/certificate_reporting_service.h"
 
-#include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/test/histogram_tester.h"
@@ -25,7 +24,7 @@
 #include "components/certificate_reporting/error_report.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
-#include "components/variations/variations_switches.h"
+#include "components/variations/variations_params_manager.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
@@ -108,13 +107,10 @@
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitchASCII(
-        switches::kForceFieldTrials,
-        "ReportCertificateErrors/ShowAndPossiblySend/");
     // Setting the sending threshold to 1.0 ensures reporting is enabled.
-    command_line->AppendSwitchASCII(
-        variations::switches::kForceFieldTrialParams,
-        "ReportCertificateErrors.ShowAndPossiblySend:sendingThreshold/1.0");
+    variations::testing::VariationParamsManager::AppendVariationParams(
+        "ReportCertificateErrors", "ShowAndPossiblySend",
+        {{"sendingThreshold", "1.0"}}, command_line);
   }
 
   CertificateReportingServiceTestHelper* test_helper() { return &test_helper_; }
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
index b0f2d24..9777cb9 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
@@ -157,11 +157,6 @@
       base::BindOnce(&OnChromeCleanerFetched, base::Passed(&fetched_callback)));
 }
 
-bool ChromeCleanerControllerDelegate::
-    SafeBrowsingExtendedReportingScoutEnabled() {
-  return safe_browsing::SafeBrowsingExtendedReportingScoutEnabled();
-}
-
 bool ChromeCleanerControllerDelegate::IsMetricsAndCrashReportingEnabled() {
   return ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
 }
@@ -404,14 +399,8 @@
           ? ChromeCleanerRunner::ChromeMetricsStatus::kEnabled
           : ChromeCleanerRunner::ChromeMetricsStatus::kDisabled;
 
-  ChromeCleanerRunner::CleanerLogsStatus cleaner_logs_status =
-      delegate_->SafeBrowsingExtendedReportingScoutEnabled()
-          ? ChromeCleanerRunner::CleanerLogsStatus::kUploadEnabled
-          : ChromeCleanerRunner::CleanerLogsStatus::kUploadDisabled;
-
   ChromeCleanerRunner::RunChromeCleanerAndReplyWithExitCode(
       executable_path, *reporter_invocation_, metrics_status,
-      cleaner_logs_status,
       base::Bind(&ChromeCleanerController::WeakOnPromptUser,
                  weak_factory_.GetWeakPtr()),
       base::Bind(&ChromeCleanerController::OnConnectionClosed,
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
index 8ed8f3b..3715aa17 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
@@ -50,7 +50,6 @@
   // extension. If the operation fails, the file name passed to
   // |fecthed_callback| will be empty.
   virtual void FetchAndVerifyChromeCleaner(FetchedCallback fetched_callback);
-  virtual bool SafeBrowsingExtendedReportingScoutEnabled();
   virtual bool IsMetricsAndCrashReportingEnabled();
 
   // Auxiliary methods for tagging and resetting open profiles.
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win_unittest.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win_unittest.cc
index d63a48c..95eb6dbc 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win_unittest.cc
@@ -84,11 +84,6 @@
   kDisabled,
 };
 
-enum class ScoutStatus {
-  kEnabled,
-  kDisabled,
-};
-
 // Simple test fixture that passes an invalid process handle back to the
 // ChromeCleanerRunner class and is intended for testing simple things like
 // command line flags that Chrome sends to the Chrome Cleaner process.
@@ -96,10 +91,8 @@
 // Parameters:
 // - metrics_status (MetricsStatus): whether Chrome metrics reporting is
 //   enabled.
-// - scout_status (ScoutStatus): whether logs upload in the Cleaner process
-//   should be enabled.
 class ChromeCleanerControllerSimpleTest
-    : public testing::TestWithParam<std::tuple<MetricsStatus, ScoutStatus>>,
+    : public testing::TestWithParam<MetricsStatus>,
       public ChromeCleanerRunnerTestDelegate,
       public ChromeCleanerControllerDelegate {
  public:
@@ -109,12 +102,9 @@
   ~ChromeCleanerControllerSimpleTest() override {}
 
   void SetUp() override {
-    MetricsStatus metrics_status;
-    ScoutStatus scout_status;
-    std::tie(metrics_status, scout_status) = GetParam();
+    MetricsStatus metrics_status = GetParam();
 
     metrics_enabled_ = metrics_status == MetricsStatus::kEnabled;
-    scout_enabled_ = scout_status == ScoutStatus::kEnabled;
 
     SetChromeCleanerRunnerTestDelegateForTesting(this);
     ChromeCleanerController::ResetInstanceForTesting();
@@ -136,10 +126,6 @@
         .Run(base::FilePath(FILE_PATH_LITERAL("chrome_cleaner.exe")));
   }
 
-  bool SafeBrowsingExtendedReportingScoutEnabled() override {
-    return scout_enabled_;
-  }
-
   bool IsMetricsAndCrashReportingEnabled() override { return metrics_enabled_; }
 
   void TagForResetting(Profile* profile) override {
@@ -174,7 +160,6 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 
   bool metrics_enabled_;
-  bool scout_enabled_;
   base::CommandLine command_line_;
 
   StrictMock<MockChromeCleanerControllerObserver> mock_observer_;
@@ -212,17 +197,14 @@
             command_line_.HasSwitch(chrome_cleaner::kUmaUserSwitch));
   EXPECT_EQ(metrics_enabled_, command_line_.HasSwitch(
                                   chrome_cleaner::kEnableCrashReportingSwitch));
-  EXPECT_EQ(scout_enabled_, command_line_.HasSwitch(
-                                chrome_cleaner::kEnableCleanerLoggingSwitch));
 
   controller->RemoveObserver(&mock_observer_);
 }
 
-INSTANTIATE_TEST_CASE_P(
-    All,
-    ChromeCleanerControllerSimpleTest,
-    Combine(Values(MetricsStatus::kDisabled, MetricsStatus::kEnabled),
-            Values(ScoutStatus::kDisabled, ScoutStatus::kEnabled)));
+INSTANTIATE_TEST_CASE_P(All,
+                        ChromeCleanerControllerSimpleTest,
+                        Values(MetricsStatus::kDisabled,
+                               MetricsStatus::kEnabled));
 
 enum class CleanerProcessStatus {
   kFetchFailure,
@@ -290,12 +272,6 @@
                 : base::FilePath()));
   }
 
-  bool SafeBrowsingExtendedReportingScoutEnabled() override {
-    // Returning an arbitrary value since this is not being tested in this
-    // fixture.
-    return false;
-  }
-
   bool IsMetricsAndCrashReportingEnabled() override {
     // Returning an arbitrary value since this is not being tested in this
     // fixture.
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc
index 8724e44..e5066b4 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc
@@ -51,16 +51,14 @@
     const base::FilePath& cleaner_executable_path,
     const SwReporterInvocation& reporter_invocation,
     ChromeMetricsStatus metrics_status,
-    CleanerLogsStatus cleaner_logs_status,
     ChromePromptImpl::OnPromptUser on_prompt_user,
     base::OnceClosure on_connection_closed,
     ChromeCleanerRunner::ProcessDoneCallback on_process_done,
     scoped_refptr<base::SequencedTaskRunner> task_runner) {
   auto cleaner_runner = make_scoped_refptr(new ChromeCleanerRunner(
       cleaner_executable_path, reporter_invocation, metrics_status,
-      cleaner_logs_status, std::move(on_prompt_user),
-      std::move(on_connection_closed), std::move(on_process_done),
-      std::move(task_runner)));
+      std::move(on_prompt_user), std::move(on_connection_closed),
+      std::move(on_process_done), std::move(task_runner)));
   auto launch_and_wait = base::BindOnce(
       &ChromeCleanerRunner::LaunchAndWaitForExitOnBackgroundThread,
       cleaner_runner);
@@ -80,7 +78,6 @@
     const base::FilePath& cleaner_executable_path,
     const SwReporterInvocation& reporter_invocation,
     ChromeMetricsStatus metrics_status,
-    CleanerLogsStatus cleaner_logs_status,
     ChromePromptImpl::OnPromptUser on_prompt_user,
     base::OnceClosure on_connection_closed,
     ProcessDoneCallback on_process_done,
@@ -133,12 +130,6 @@
     cleaner_command_line_.AppendSwitch(
         chrome_cleaner::kEnableCrashReportingSwitch);
   }
-
-  // Enable logs upload for users who have opted into safe browsing extended
-  // reporting v2.
-  if (cleaner_logs_status == CleanerLogsStatus::kUploadEnabled)
-    cleaner_command_line_.AppendSwitch(
-        chrome_cleaner::kEnableCleanerLoggingSwitch);
 }
 
 ChromeCleanerRunner::ProcessStatus
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.h
index 7e92607d..86985d1 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.h
@@ -54,11 +54,6 @@
     kDisabled,
   };
 
-  enum class CleanerLogsStatus {
-    kUploadEnabled,
-    kUploadDisabled,
-  };
-
   enum class LaunchStatus {
     // Got an invalid process when attempting to launch the Chrome Cleaner
     // process. As a result, the Mojo pipe was never set up and the
@@ -94,11 +89,11 @@
   //
   // This function will pass command line flags to the Chrome Cleaner executable
   // as appropriate based on the flags in |reporter_invocation| and the
-  // |metrics_status| and |cleaner_logs_status| parameters. The Cleaner process
-  // will communicate with Chrome via a Mojo IPC interface and any IPC requests
-  // or notifications are passed to the caller via the |on_prompt_user| and
-  // |on_connection_closed| callbacks. Finally, when the Chrome Cleaner process
-  // terminates, a ProcessStatus is passed along to |on_process_done|.
+  // |metrics_status| parameters The Cleaner process will communicate with
+  // Chrome via a Mojo IPC interface and any IPC requests or notifications are
+  // passed to the caller via the |on_prompt_user| and |on_connection_closed|
+  // callbacks. Finally, when the Chrome Cleaner process terminates, a
+  // ProcessStatus is passed along to |on_process_done|.
   //
   // The details of the mojo interface are documented in
   // "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h".
@@ -106,7 +101,6 @@
       const base::FilePath& cleaner_executable_path,
       const SwReporterInvocation& reporter_invocation,
       ChromeMetricsStatus metrics_status,
-      CleanerLogsStatus cleaner_logs_status,
       ChromePromptImpl::OnPromptUser on_prompt_user,
       base::OnceClosure on_connection_closed,
       ChromeCleanerRunner::ProcessDoneCallback on_process_done,
@@ -120,7 +114,6 @@
   ChromeCleanerRunner(const base::FilePath& cleaner_executable_path,
                       const SwReporterInvocation& reporter_invocation,
                       ChromeMetricsStatus metrics_status,
-                      CleanerLogsStatus cleaner_logs_status,
                       ChromePromptImpl::OnPromptUser on_prompt_user,
                       base::OnceClosure on_connection_closed,
                       ChromeCleanerRunner::ProcessDoneCallback on_process_done,
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win_unittest.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win_unittest.cc
index 93f3539e..9a066ce 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win_unittest.cc
@@ -38,7 +38,6 @@
 using ::testing::Combine;
 using ::testing::Values;
 using ChromeMetricsStatus = ChromeCleanerRunner::ChromeMetricsStatus;
-using CleanerLogsStatus = ChromeCleanerRunner::CleanerLogsStatus;
 
 enum class ReporterEngine {
   kUnspecified,
@@ -55,14 +54,11 @@
 // Parameters:
 // - metrics_status (ChromeMetricsStatus): whether Chrome metrics reporting is
 //       enabled
-// - logs_upload_status (CleanerLogsStatus): whether logs upload in the Cleaner
-//       process should be enabled.
 // - reporter_engine (ReporterEngine): the type of Cleaner engine specified in
 //       the SwReporterInvocation.
 class ChromeCleanerRunnerSimpleTest
     : public testing::TestWithParam<
           std::tuple<ChromeCleanerRunner::ChromeMetricsStatus,
-                     ChromeCleanerRunner::CleanerLogsStatus,
                      ReporterEngine>>,
       public ChromeCleanerRunnerTestDelegate {
  public:
@@ -70,8 +66,7 @@
       : command_line_(base::CommandLine::NO_PROGRAM) {}
 
   void SetUp() override {
-    std::tie(metrics_status_, logs_upload_status_, reporter_engine_) =
-        GetParam();
+    std::tie(metrics_status_, reporter_engine_) = GetParam();
 
     SetChromeCleanerRunnerTestDelegateForTesting(this);
     scoped_feature_list_.InitAndEnableFeature(kInBrowserCleanerUIFeature);
@@ -95,7 +90,7 @@
 
     ChromeCleanerRunner::RunChromeCleanerAndReplyWithExitCode(
         base::FilePath(FILE_PATH_LITERAL("cleaner.exe")), reporter_invocation,
-        metrics_status_, logs_upload_status_,
+        metrics_status_,
         base::BindOnce(&ChromeCleanerRunnerSimpleTest::OnPromptUser,
                        base::Unretained(this)),
         base::BindOnce(&ChromeCleanerRunnerSimpleTest::OnConnectionClosed,
@@ -137,7 +132,6 @@
 
   // Test fixture parameters.
   ChromeCleanerRunner::ChromeMetricsStatus metrics_status_;
-  ChromeCleanerRunner::CleanerLogsStatus logs_upload_status_;
   ReporterEngine reporter_engine_;
 
   // Set by LaunchTestProcess.
@@ -179,10 +173,6 @@
   EXPECT_EQ(
       metrics_status_ == ChromeMetricsStatus::kEnabled,
       command_line_.HasSwitch(chrome_cleaner::kEnableCrashReportingSwitch));
-
-  EXPECT_EQ(
-      logs_upload_status_ == CleanerLogsStatus::kUploadEnabled,
-      command_line_.HasSwitch(chrome_cleaner::kEnableCleanerLoggingSwitch));
 }
 
 INSTANTIATE_TEST_CASE_P(
@@ -190,8 +180,6 @@
     ChromeCleanerRunnerSimpleTest,
     Combine(Values(ChromeCleanerRunner::ChromeMetricsStatus::kEnabled,
                    ChromeCleanerRunner::ChromeMetricsStatus::kDisabled),
-            Values(ChromeCleanerRunner::CleanerLogsStatus::kUploadEnabled,
-                   ChromeCleanerRunner::CleanerLogsStatus::kUploadDisabled),
             Values(ReporterEngine::kUnspecified,
                    ReporterEngine::kOldEngine,
                    ReporterEngine::kNewEngine)));
@@ -250,7 +238,6 @@
     ChromeCleanerRunner::RunChromeCleanerAndReplyWithExitCode(
         base::FilePath(FILE_PATH_LITERAL("cleaner.exe")),
         SwReporterInvocation(), ChromeMetricsStatus::kDisabled,
-        CleanerLogsStatus::kUploadDisabled,
         base::BindOnce(&ChromeCleanerRunnerTest::OnPromptUser,
                        base::Unretained(this)),
         base::BindOnce(&ChromeCleanerRunnerTest::OnConnectionClosed,
diff --git a/chrome/browser/safe_browsing/test_safe_browsing_blocking_page_quiet.cc b/chrome/browser/safe_browsing/test_safe_browsing_blocking_page_quiet.cc
index 1cc4321..26626ea5 100644
--- a/chrome/browser/safe_browsing/test_safe_browsing_blocking_page_quiet.cc
+++ b/chrome/browser/safe_browsing/test_safe_browsing_blocking_page_quiet.cc
@@ -20,13 +20,15 @@
     const UnsafeResourceList& unsafe_resources,
     const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options,
     bool is_giant_webview)
-    : BaseBlockingPage(
-          ui_manager,
-          web_contents,
-          main_frame_url,
-          unsafe_resources,
-          CreateControllerClient(web_contents, unsafe_resources, ui_manager),
-          display_options),
+    : BaseBlockingPage(ui_manager,
+                       web_contents,
+                       main_frame_url,
+                       unsafe_resources,
+                       CreateControllerClient(web_contents,
+                                              unsafe_resources,
+                                              ui_manager,
+                                              nullptr),
+                       display_options),
       sb_error_ui_(unsafe_resources[0].url,
                    main_frame_url,
                    GetInterstitialReason(unsafe_resources),
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index b8bf25a4..8d64156 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -613,13 +613,12 @@
 
     WebContents* web_contents = chrome::AddRestoredTab(
         browser, tab.navigations, tab_index, selected_index,
-        tab.extension_app_id,
-        false,  // select
-        tab.pinned, true, session_storage_namespace.get(),
-        tab.user_agent_override);
-    // Regression check: check that the tab didn't start loading right away. The
+        tab.extension_app_id, is_selected_tab, tab.pinned, true,
+        session_storage_namespace.get(), tab.user_agent_override);
+    // Regression check: if the current tab |is_selected_tab|, it should load
+    // immediately, otherwise, tabs should not start loading right away. The
     // focused tab will be loaded by Browser, and TabLoader will load the rest.
-    DCHECK(web_contents->GetController().NeedsReload());
+    DCHECK(is_selected_tab || web_contents->GetController().NeedsReload());
 
     return web_contents;
   }
diff --git a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
index de48f66..e2c1259771 100644
--- a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
+++ b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
@@ -198,8 +198,8 @@
       ++minimized_count;
   }
   EXPECT_EQ(2u, total_count);
-  // Chrome OS always activates the last browser window on login, which results
-  // in one window being restored. This seems reasonable as it reminds users
-  // they have a browser running instead of just showing them an empty desktop.
-  EXPECT_EQ(1u, minimized_count);
+  // Chrome OS always activates the last browser windows on login to remind
+  // users they have a browser running instead of just showing them an empty
+  // desktop.
+  EXPECT_EQ(0u, minimized_count);
 }
diff --git a/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc b/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
index e7f3115..e49edc877 100644
--- a/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
+++ b/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
@@ -7,7 +7,6 @@
 #include <string>
 #include <utility>
 
-#include "base/base_switches.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/command_line.h"
@@ -28,7 +27,7 @@
 #include "components/captive_portal/captive_portal_detector.h"
 #include "components/prefs/pref_service.h"
 #include "components/security_state/core/security_state.h"
-#include "components/variations/variations_switches.h"
+#include "components/variations/variations_params_manager.h"
 #include "content/public/browser/interstitial_page.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
@@ -100,13 +99,10 @@
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitchASCII(
-        switches::kForceFieldTrials,
-        "ReportCertificateErrors/ShowAndPossiblySend/");
     // Setting the sending threshold to 1.0 ensures reporting is enabled.
-    command_line->AppendSwitchASCII(
-        variations::switches::kForceFieldTrialParams,
-        "ReportCertificateErrors.ShowAndPossiblySend:sendingThreshold/1.0");
+    variations::testing::VariationParamsManager::AppendVariationParams(
+        "ReportCertificateErrors", "ShowAndPossiblySend",
+        {{"sendingThreshold", "1.0"}}, command_line);
   }
 
   void TestInterstitial(bool is_wifi_connection,
diff --git a/chrome/browser/ssl/cert_report_helper.cc b/chrome/browser/ssl/cert_report_helper.cc
index 923ee3d..02c67fb 100644
--- a/chrome/browser/ssl/cert_report_helper.cc
+++ b/chrome/browser/ssl/cert_report_helper.cc
@@ -28,6 +28,12 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#elif defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#endif
+
 namespace {
 
 // Certificate reports are only sent from official builds, but this flag can be
@@ -128,6 +134,14 @@
 
   report.AddChromeChannel(chrome::GetChannel());
 
+#if defined(OS_WIN)
+  report.SetIsEnterpriseManaged(base::win::IsEnterpriseManaged());
+#elif defined(OS_CHROMEOS)
+  report.SetIsEnterpriseManaged(g_browser_process->platform_part()
+                                    ->browser_policy_connector_chromeos()
+                                    ->IsEnterpriseManaged());
+#endif
+
   report.SetInterstitialInfo(
       interstitial_reason_, user_proceeded,
       overridable_
diff --git a/chrome/browser/tracing/chrome_tracing_delegate_browsertest.cc b/chrome/browser/tracing/chrome_tracing_delegate_browsertest.cc
index 7b4504cf..17a1177 100644
--- a/chrome/browser/tracing/chrome_tracing_delegate_browsertest.cc
+++ b/chrome/browser/tracing/chrome_tracing_delegate_browsertest.cc
@@ -4,7 +4,6 @@
 
 #include <utility>
 
-#include "base/base_switches.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "build/build_config.h"
@@ -17,7 +16,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/metrics/metrics_pref_names.h"
 #include "components/prefs/pref_service.h"
-#include "components/variations/variations_switches.h"
+#include "components/variations/variations_params_manager.h"
 #include "content/public/browser/background_tracing_config.h"
 #include "content/public/browser/background_tracing_manager.h"
 #include "content/public/browser/browser_thread.h"
@@ -251,11 +250,9 @@
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-        switches::kForceFieldTrials, "BackgroundTracing/TestGroup/");
-    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-        variations::switches::kForceFieldTrialParams,
-        "BackgroundTracing.TestGroup:config/default_config_for_testing");
+    variations::testing::VariationParamsManager::AppendVariationParams(
+        "BackgroundTracing", "TestGroup",
+        {{"config", "default_config_for_testing"}}, command_line);
 
     tracing::SetConfigTextFilterForTesting(&FieldTrialConfigTextFilter);
   }
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
index e8de4cb..34631a1 100644
--- a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
@@ -71,6 +71,7 @@
   web_contents_->SetDelegate(this);
   web_view_->set_owned_by_client();
   web_view_->SetWebContents(web_contents_.get());
+  web_view_->SetResizeBackgroundColor(SK_ColorTRANSPARENT);
 
   // Make the webview transparent since it's going to be shown on top of a
   // highlightable button.
diff --git a/chrome/browser/ui/ash/DEPS b/chrome/browser/ui/ash/DEPS
index 367f2d98..86434f62 100644
--- a/chrome/browser/ui/ash/DEPS
+++ b/chrome/browser/ui/ash/DEPS
@@ -11,13 +11,3 @@
   "+mash/shelf/public/interfaces",
   "+media",
 ]
-specific_include_rules = {
-  # Allow ash::SessionStateDelegate for SessionStateDelegateChromeOS.
-  # SessionStateDelegate is deprecated. Chrome code should not use it anymore.
-  # Instead, SessionManager/UserManager/SessionControllerClient should be used.
-  # This is temporary rule before SessionStateDelegate(ChromeOS) can be fully
-  # removed.
-  "session_state_delegate_chromeos\.(cc|h)": [
-    "+ash/session",
-  ]
-}
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index 93c22f4..9768baf3 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
+#include "chrome/browser/vr/vr_tab_helper.h"
 #include "chrome/browser/web_data_service_factory.h"
 #include "chrome/common/url_constants.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
@@ -405,4 +406,12 @@
       false /* is_renderer_initiated */));
 }
 
+bool ChromeAutofillClient::IsAutofillSupported() {
+  // VR browsing does not support popups at the moment.
+  if (vr::VrTabHelper::IsInVr(web_contents()))
+    return false;
+
+  return true;
+}
+
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h
index 0e9dd28..e3c2042 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.h
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -90,6 +90,7 @@
   bool ShouldShowSigninPromo() override;
   void StartSigninFlow() override;
   void ShowHttpNotSecureExplanation() override;
+  bool IsAutofillSupported() override;
 
   // content::WebContentsObserver implementation.
   void MainFrameWasResized(bool width_changed) override;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 37094f1..37240d2 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1973,9 +1973,14 @@
   if (!widget)
     return;
 
-  if (!initialized_ && details.is_add) {
+  bool init = !initialized_ && details.is_add;
+  if (init) {
     InitViews();
     initialized_ = true;
+  }
+
+#if defined(USE_AURA)
+  if (init) {
     if (base::CommandLine::ForCurrentProcess()->HasSwitch(
             switches::kEnableExperimentalFullscreenExitUI)) {
       widget->GetNativeView()->AddPreTargetHandler(GetFullscreenControlHost());
@@ -1985,6 +1990,7 @@
     if (native_view)
       native_view->RemovePreTargetHandler(fullscreen_control_host_.get());
   }
+#endif
 }
 
 void BrowserView::PaintChildren(const ui::PaintContext& context) {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index cfceb1c5a..cf44149 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -138,6 +138,7 @@
     "//components/sync_sessions:test_support",
     "//components/toolbar:test_support",
     "//components/update_client:test_support",
+    "//components/variations:test_support",
     "//components/web_resource:test_support",
     "//content/public/app:both",
     "//content/public/child",
@@ -3488,7 +3489,6 @@
     "//components/sync:test_support_driver",
     "//components/sync:test_support_model",
     "//components/sync_sessions:test_support",
-    "//components/variations:test_support",
     "//components/version_info:generate_version_info",
     "//components/webdata_services:test_support",
     "//content/app/resources",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 8220260..a0a7ef24 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -63,9 +63,6 @@
     "javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java",
     "javatests/src/org/chromium/chrome/test/util/OmniboxTestUtils.java",
     "javatests/src/org/chromium/chrome/test/util/OverviewModeBehaviorWatcher.java",
-    "javatests/src/org/chromium/chrome/test/util/parameters/AddFakeAccountToAppParameter.java",
-    "javatests/src/org/chromium/chrome/test/util/parameters/AddFakeAccountToOsParameter.java",
-    "javatests/src/org/chromium/chrome/test/util/parameters/AddGoogleAccountToOsParameter.java",
     "javatests/src/org/chromium/chrome/test/util/PrerenderTestHelper.java",
     "javatests/src/org/chromium/chrome/test/util/RenderTestRule.java",
     "javatests/src/org/chromium/chrome/test/util/TabStripUtils.java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
index 60899e8..84d146a 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
@@ -12,7 +12,6 @@
 
 import org.chromium.base.test.BaseActivityInstrumentationTestCase;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.parameter.BaseParameter;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.infobar.InfoBar;
@@ -21,14 +20,10 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeActivityTestCommon.ChromeTestCommonCallback;
 import org.chromium.chrome.test.util.ApplicationTestUtils;
-import org.chromium.chrome.test.util.parameters.AddFakeAccountToAppParameter;
-import org.chromium.chrome.test.util.parameters.AddFakeAccountToOsParameter;
-import org.chromium.chrome.test.util.parameters.AddGoogleAccountToOsParameter;
 import org.chromium.content.browser.test.util.TestTouchUtils;
 import org.chromium.content.browser.test.util.TouchCommon;
 
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.TimeoutException;
 
 /**
@@ -376,18 +371,6 @@
         return mTestCommon.runJavaScriptCodeInCurrentTab(code);
     }
 
-    @Override
-    protected Map<String, BaseParameter> createAvailableParameters() {
-        Map<String, BaseParameter> availableParameters = super.createAvailableParameters();
-        availableParameters.put(AddFakeAccountToAppParameter.PARAMETER_TAG,
-                new AddFakeAccountToAppParameter(getParameterReader(), getInstrumentation()));
-        availableParameters.put(AddFakeAccountToOsParameter.PARAMETER_TAG,
-                new AddFakeAccountToOsParameter(getParameterReader(), getInstrumentation()));
-        availableParameters.put(AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                new AddGoogleAccountToOsParameter(getParameterReader(), getInstrumentation()));
-        return availableParameters;
-    }
-
     /**
      * Waits till the ContentViewCore receives the expected page scale factor
      * from the compositor and asserts that this happens.
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestBase.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestBase.java
index 0b22331a..f2a2e966 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestBase.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/MultiActivityTestBase.java
@@ -8,32 +8,18 @@
 import android.test.InstrumentationTestCase;
 
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.parameter.BaseParameter;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.base.test.util.parameter.Parameterizable;
-import org.chromium.base.test.util.parameter.parameters.MethodParameter;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.test.util.browser.tabmodel.document.MockStorageDelegate;
-import org.chromium.chrome.test.util.parameters.AddFakeAccountToAppParameter;
-import org.chromium.chrome.test.util.parameters.AddFakeAccountToOsParameter;
-import org.chromium.chrome.test.util.parameters.AddGoogleAccountToOsParameter;
-
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * Base for testing and interacting with multiple Activities (e.g. Document or Webapp Activities).
  */
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public abstract class MultiActivityTestBase extends InstrumentationTestCase
-        implements Parameterizable, MultiActivityTestCommon.MultiActivityTestCommonCallback {
+        implements MultiActivityTestCommon.MultiActivityTestCommonCallback {
     private final MultiActivityTestCommon mTestCommon;
 
-    private Parameter.Reader mParameterReader;
-
-    private Map<String, BaseParameter> mAvailableParameters;
-
     public MultiActivityTestBase() {
         mTestCommon = new MultiActivityTestCommon(this);
     }
@@ -73,66 +59,4 @@
             boolean waitLongerForLoad) {
         mTestCommon.waitForFullLoad(activity, expectedTitle, waitLongerForLoad);
     }
-
-    /**
-     * Creates the {@link Map} of available parameters for the test to use.
-     *
-     * @return a {@link Map} of {@link BaseParameter} objects.
-     */
-    protected Map<String, BaseParameter> createAvailableParameters() {
-        Map<String, BaseParameter> availableParameters = new HashMap<>();
-        availableParameters
-                .put(MethodParameter.PARAMETER_TAG, new MethodParameter(getParameterReader()));
-        availableParameters.put(AddFakeAccountToAppParameter.PARAMETER_TAG,
-                new AddFakeAccountToAppParameter(getParameterReader(), getInstrumentation()));
-        availableParameters.put(AddFakeAccountToOsParameter.PARAMETER_TAG,
-                new AddFakeAccountToOsParameter(getParameterReader(), getInstrumentation()));
-        availableParameters.put(AddGoogleAccountToOsParameter.PARAMETER_TAG,
-                new AddGoogleAccountToOsParameter(getParameterReader(), getInstrumentation()));
-        return availableParameters;
-    }
-
-    /**
-     * Gets the {@link Map} of available parameters that inherited classes can use.
-     *
-     * @return a {@link Map} of {@link BaseParameter} objects to set as the available parameters.
-     */
-    @Override
-    public Map<String, BaseParameter> getAvailableParameters() {
-        return mAvailableParameters;
-    }
-
-    /**
-     * Gets a specific parameter from the current test.
-     *
-     * @param parameterTag a string with the name of the {@link BaseParameter} we want.
-     * @return a parameter that extends {@link BaseParameter} that has the matching parameterTag.
-     */
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T extends BaseParameter> T getAvailableParameter(String parameterTag) {
-        return (T) mAvailableParameters.get(parameterTag);
-    }
-
-    /**
-     * Setter method for {@link Parameter.Reader}.
-     *
-     * @param parameterReader the {@link Parameter.Reader} to set.
-     */
-    @Override
-    public void setParameterReader(Parameter.Reader parameterReader) {
-        mParameterReader = parameterReader;
-        mAvailableParameters = createAvailableParameters();
-    }
-
-    /**
-     * Getter method for {@link Parameter.Reader} object to be used by test cases reading the
-     * parameter.
-     *
-     * @return the {@link Parameter.Reader} for the current {@link
-     * org.chromium.base.test.util.parameter.ParameterizedTest} being run.
-     */
-    protected Parameter.Reader getParameterReader() {
-        return mParameterReader;
-    }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/parameters/AddFakeAccountToAppParameter.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/parameters/AddFakeAccountToAppParameter.java
deleted file mode 100644
index afd656c3c..0000000
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/parameters/AddFakeAccountToAppParameter.java
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.test.util.parameters;
-
-import android.app.Instrumentation;
-
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.test.util.parameter.BaseParameter;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.chrome.browser.init.ProcessInitializationHandler;
-import org.chromium.chrome.test.util.ChromeSigninUtils;
-import org.chromium.components.signin.ChromeSigninController;
-
-/**
- * Adds a fake account to app when this parameter is used.
- */
-public class AddFakeAccountToAppParameter extends BaseParameter {
-    /** Adds a fake test account to app to run test as signed into the app. */
-    public static final String PARAMETER_TAG = "add-fake-account-to-app-parameter";
-
-    /** The {@Parameter.Argument#name()} value. */
-    public static final class ARGUMENT {
-        public static final String USERNAME = "username";
-        private static final class DEFAULT {
-            private static final String USERNAME = "test@google.com";
-        }
-    }
-
-    private ChromeSigninController mSigninController;
-    private ChromeSigninUtils mSigninUtil;
-
-    public AddFakeAccountToAppParameter(Parameter.Reader parameterReader,
-            Instrumentation instrumentation) {
-        super(PARAMETER_TAG, parameterReader);
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                ProcessInitializationHandler.getInstance().initializePreNative();
-            }
-        });
-        mSigninController = ChromeSigninController.get();
-        mSigninUtil = new ChromeSigninUtils(instrumentation);
-    }
-
-    @Override
-    public void setUp() {
-        String username = getStringArgument(ARGUMENT.USERNAME, ARGUMENT.DEFAULT.USERNAME);
-
-        mSigninController.setSignedInAccountName(null);
-        mSigninUtil.addAccountToApp(username);
-    }
-
-    @Override
-    public void tearDown() {
-        mSigninController.setSignedInAccountName(null);
-    }
-
-    /**
-     * Only affects Java tests.
-     *
-     * @return {@code true} if an account is on the app, {@code false} otherwise.
-     */
-    public boolean isSignedIn() {
-        return mSigninController.isSignedIn();
-    }
-}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/parameters/AddFakeAccountToOsParameter.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/parameters/AddFakeAccountToOsParameter.java
deleted file mode 100644
index 2d09beb5..0000000
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/parameters/AddFakeAccountToOsParameter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.test.util.parameters;
-
-import android.app.Instrumentation;
-
-import org.chromium.base.test.util.parameter.BaseParameter;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.chrome.test.util.ChromeSigninUtils;
-
-/**
- * Adds a fake account to OS when this parameter is used.
- */
-public class AddFakeAccountToOsParameter extends BaseParameter {
-    /** Adds a fake test account to OS to run test as signed into the OS. */
-    public static final String PARAMETER_TAG = "add-fake-account-to-os-parameter";
-
-    /** The {@Parameter.Argument#name()} value. */
-    public static final class ARGUMENT {
-        public static final String USERNAME = "username";
-        public static final String PASSWORD = "password";
-        private static final class DEFAULT {
-            private static final String USERNAME = "test@google.com";
-            private static final String PASSWORD = "$3cr3t";
-        }
-    }
-
-    private ChromeSigninUtils mSigninUtil;
-
-    public AddFakeAccountToOsParameter(Parameter.Reader parameterReader,
-            Instrumentation instrumentation) {
-        super(PARAMETER_TAG, parameterReader);
-        mSigninUtil = new ChromeSigninUtils(instrumentation);
-    }
-
-    @Override
-    public void setUp() {
-        String username = getStringArgument(ARGUMENT.USERNAME, ARGUMENT.DEFAULT.USERNAME);
-        String password = getStringArgument(ARGUMENT.PASSWORD, ARGUMENT.DEFAULT.PASSWORD);
-
-        mSigninUtil.removeAllFakeAccountsFromOs();
-        mSigninUtil.addFakeAccountToOs(username, password);
-    }
-
-    @Override
-    public void tearDown() {
-        mSigninUtil.removeAllFakeAccountsFromOs();
-    }
-
-    public boolean isSignedIn() {
-        return isSignedIn(ARGUMENT.DEFAULT.USERNAME);
-    }
-
-    public boolean isSignedIn(String username) {
-        return mSigninUtil.isExistingFakeAccountOnOs(username);
-    }
-}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/parameters/AddGoogleAccountToOsParameter.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/parameters/AddGoogleAccountToOsParameter.java
deleted file mode 100644
index 34a3597..0000000
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/parameters/AddGoogleAccountToOsParameter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.test.util.parameters;
-
-import android.app.Instrumentation;
-
-import org.chromium.base.test.util.parameter.BaseParameter;
-import org.chromium.base.test.util.parameter.Parameter;
-import org.chromium.chrome.test.util.ChromeSigninUtils;
-
-/**
- * Adds a Google account to OS when this parameter is used.
- */
-public class AddGoogleAccountToOsParameter extends BaseParameter {
-    /** Adds a Google account to OS to run test as signed into the OS. */
-    public static final String PARAMETER_TAG = "add-google-account-to-os-parameter";
-
-    /** The {@Parameter.Argument#name()} value. */
-    public static final class ARGUMENT {
-        public static final String USERNAME = "username";
-        public static final String PASSWORD = "password";
-        public static final String TYPE = "type";
-        private static final class DEFAULT {
-            private static final String TYPE = "mail";
-        }
-    }
-
-    private ChromeSigninUtils mSigninUtil;
-
-    public AddGoogleAccountToOsParameter(Parameter.Reader parameterReader,
-            Instrumentation instrumentation) {
-        super(PARAMETER_TAG, parameterReader);
-        mSigninUtil = new ChromeSigninUtils(instrumentation);
-    }
-
-    @Override
-    public void setUp() {
-        String username = getStringArgument(ARGUMENT.USERNAME);
-        String password = getStringArgument(ARGUMENT.PASSWORD);
-        String type = getStringArgument(ARGUMENT.TYPE, ARGUMENT.DEFAULT.TYPE);
-
-        mSigninUtil.removeAllGoogleAccountsFromOs();
-        mSigninUtil.addGoogleAccountToOs(username, password, type);
-    }
-
-    @Override
-    public void tearDown() {
-        mSigninUtil.removeAllGoogleAccountsFromOs();
-    }
-
-    public boolean isSignedIn(String username) {
-        return mSigninUtil.isExistingGoogleAccountOnOs(username);
-    }
-}
diff --git a/chrome/test/chromedriver/chrome/adb_impl.cc b/chrome/test/chromedriver/chrome/adb_impl.cc
index c592328..221c8a7 100644
--- a/chrome/test/chromedriver/chrome/adb_impl.cc
+++ b/chrome/test/chromedriver/chrome/adb_impl.cc
@@ -72,6 +72,17 @@
       base::Bind(&ResponseBuffer::OnResponse, response_buffer));
 }
 
+void SendFileOnIOThread(const std::string& device_serial,
+                        const std::string& filename,
+                        const std::string& content,
+                        scoped_refptr<ResponseBuffer> response_buffer,
+                        int port) {
+  CHECK(base::MessageLoopForIO::IsCurrent());
+  AdbClientSocket::SendFile(
+      port, device_serial, filename, content,
+      base::Bind(&ResponseBuffer::OnResponse, response_buffer));
+}
+
 }  // namespace
 
 AdbImpl::AdbImpl(
@@ -122,20 +133,16 @@
                                    const std::string& exec_name,
                                    const std::string& args) {
   std::string response;
-  std::string quoted_command =
-      base::GetQuotedJSONString(exec_name + " " + args);
-  Status status = ExecuteHostShellCommand(
-      device_serial,
-      base::StringPrintf("echo %s > %s; echo $?",
-                         quoted_command.c_str(),
-                         command_line_file.c_str()),
-      &response);
-  if (!status.IsOk())
-    return status;
-  if (response.find("0") == std::string::npos)
-    return Status(kUnknownError, "Failed to set command line file " +
-                  command_line_file + " on device " + device_serial);
-  return Status(kOk);
+  std::string command(exec_name + " " + args + "\n");
+  scoped_refptr<ResponseBuffer> response_buffer = new ResponseBuffer;
+  VLOG(1) << "Sending command line file: " << command_line_file;
+  io_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&SendFileOnIOThread, device_serial, command_line_file,
+                     command, response_buffer, port_));
+  Status status =
+      response_buffer->GetResponse(&response, base::TimeDelta::FromSeconds(30));
+  return status;
 }
 
 Status AdbImpl::CheckAppInstalled(
diff --git a/chrome/test/chromedriver/net/adb_client_socket.cc b/chrome/test/chromedriver/net/adb_client_socket.cc
index 3d5ea5e6..448378f 100644
--- a/chrome/test/chromedriver/net/adb_client_socket.cc
+++ b/chrome/test/chromedriver/net/adb_client_socket.cc
@@ -23,9 +23,14 @@
 namespace {
 
 const int kBufferSize = 16 * 1024;
+const size_t kAdbDataChunkSize = 32 * 1024;
 const char kOkayResponse[] = "OKAY";
 const char kHostTransportCommand[] = "host:transport:%s";
 const char kLocalAbstractCommand[] = "localabstract:%s";
+const char kSyncCommand[] = "sync:";
+const char kSendCommand[] = "SEND";
+const char kDataCommand[] = "DATA";
+const char kDoneCommand[] = "DONE";
 
 typedef base::Callback<void(int, const std::string&)> CommandCallback;
 typedef base::Callback<void(int, net::StreamSocket*)> SocketCallback;
@@ -301,6 +306,129 @@
   CommandCallback callback_;
 };
 
+// Implement the ADB protocol to send a file to the device.
+// The protocol consists of the following steps:
+// * Send "host:transport" command with device serial
+// * Send "sync:" command to initialize file transfer
+// * Send "SEND" command with name and mode of the file
+// * Send "DATA" command one or more times for the file content
+// * Send "DONE" command to indicate end of file transfer
+// The first two commands use normal ADB command format implemented by
+// AdbClientSocket::SendCommand. The remaining commands use a special
+// format implemented by AdbSendFileSocket::SendPayload.
+class AdbSendFileSocket : AdbClientSocket {
+ public:
+  AdbSendFileSocket(int port,
+                    const std::string& serial,
+                    const std::string& filename,
+                    const std::string& content,
+                    const CommandCallback& callback)
+      : AdbClientSocket(port),
+        serial_(serial),
+        filename_(filename),
+        content_(content),
+        current_offset_(0),
+        callback_(callback) {
+    Connect(
+        base::Bind(&AdbSendFileSocket::SendTransport, base::Unretained(this)));
+  }
+
+ private:
+  ~AdbSendFileSocket() {}
+
+  void SendTransport(int result) {
+    if (!CheckNetResultOrDie(result))
+      return;
+    SendCommand(
+        base::StringPrintf(kHostTransportCommand, serial_.c_str()), true, true,
+        base::Bind(&AdbSendFileSocket::SendSync, base::Unretained(this)));
+  }
+
+  void SendSync(int result, const std::string& response) {
+    if (!CheckNetResultOrDie(result))
+      return;
+    SendCommand(
+        kSyncCommand, true, true,
+        base::Bind(&AdbSendFileSocket::SendSend, base::Unretained(this)));
+  }
+
+  void SendSend(int result, const std::string& response) {
+    if (!CheckNetResultOrDie(result))
+      return;
+    // File mode. The following value is equivalent to S_IRUSR | S_IWUSR.
+    // Can't use the symbolic names since they are not available on Windows.
+    int mode = 0600;
+    std::string payload = base::StringPrintf("%s,%d", filename_.c_str(), mode);
+    SendPayload(
+        kSendCommand, payload.length(), payload.c_str(), payload.length(),
+        base::Bind(&AdbSendFileSocket::SendContent, base::Unretained(this)));
+  }
+
+  void SendContent(int result) {
+    if (!CheckNetResultOrDie(result))
+      return;
+    if (current_offset_ >= content_.length()) {
+      SendDone();
+      return;
+    }
+    size_t offset = current_offset_;
+    size_t length = std::min(content_.length() - offset, kAdbDataChunkSize);
+    current_offset_ += length;
+    SendPayload(
+        kDataCommand, length, content_.c_str() + offset, length,
+        base::Bind(&AdbSendFileSocket::SendContent, base::Unretained(this)));
+  }
+
+  void SendDone() {
+    int data = time(NULL);
+    SendPayload(kDoneCommand, data, nullptr, 0,
+                base::Bind(&AdbSendFileSocket::ReadFinalResponse,
+                           base::Unretained(this)));
+  }
+
+  void ReadFinalResponse(int result) {
+    ReadResponse(callback_, true, false, result);
+  }
+
+  // Send a special payload command ("SEND", "DATA", or "DONE").
+  // Each command consists of a command line, followed by a 4-byte integer
+  // sent in raw little-endian format, followed by an optional payload.
+  void SendPayload(const char* command,
+                   int data,
+                   const char* payload,
+                   size_t payloadLength,
+                   const net::CompletionCallback& callback) {
+    std::string buffer(command);
+    for (int i = 0; i < 4; i++) {
+      buffer.append(1, static_cast<char>(data & 0xff));
+      data >>= 8;
+    }
+    if (payloadLength > 0)
+      buffer.append(payload, payloadLength);
+
+    scoped_refptr<net::StringIOBuffer> request_buffer =
+        new net::StringIOBuffer(buffer);
+    int result =
+        socket_->Write(request_buffer.get(), request_buffer->size(), callback);
+    if (result != net::ERR_IO_PENDING)
+      callback.Run(result);
+  }
+
+  bool CheckNetResultOrDie(int result) {
+    if (result >= 0)
+      return true;
+    callback_.Run(result, NULL);
+    delete this;
+    return false;
+  }
+
+  std::string serial_;
+  std::string filename_;
+  std::string content_;
+  size_t current_offset_;
+  CommandCallback callback_;
+};
+
 }  // namespace
 
 // static
@@ -310,6 +438,15 @@
   new AdbQuerySocket(port, query, callback);
 }
 
+// static
+void AdbClientSocket::SendFile(int port,
+                               const std::string& serial,
+                               const std::string& filename,
+                               const std::string& content,
+                               const CommandCallback& callback) {
+  new AdbSendFileSocket(port, serial, filename, content, callback);
+}
+
 #if BUILDFLAG(DEBUG_DEVTOOLS)
 static void UseTransportQueryForDesktop(const SocketCallback& callback,
                                         net::StreamSocket* socket,
diff --git a/chrome/test/chromedriver/net/adb_client_socket.h b/chrome/test/chromedriver/net/adb_client_socket.h
index 183f0f8e..2430d98 100644
--- a/chrome/test/chromedriver/net/adb_client_socket.h
+++ b/chrome/test/chromedriver/net/adb_client_socket.h
@@ -37,6 +37,12 @@
                         const std::string& request,
                         const SocketCallback& callback);
 
+  static void SendFile(int port,
+                       const std::string& serial,
+                       const std::string& filename,
+                       const std::string& content,
+                       const CommandCallback& callback);
+
   explicit AdbClientSocket(int port);
   ~AdbClientSocket();
 
@@ -50,12 +56,12 @@
 
   std::unique_ptr<net::StreamSocket> socket_;
 
- private:
   void ReadResponse(const CommandCallback& callback,
                     bool is_void,
                     bool has_length,
                     int result);
 
+ private:
   void OnResponseStatus(const CommandCallback& callback,
                         bool is_void,
                         bool has_length,
diff --git a/chromeos/components/tether/fake_notification_presenter.cc b/chromeos/components/tether/fake_notification_presenter.cc
index 5106769..e08b1e42 100644
--- a/chromeos/components/tether/fake_notification_presenter.cc
+++ b/chromeos/components/tether/fake_notification_presenter.cc
@@ -29,7 +29,8 @@
 }
 
 void FakeNotificationPresenter::NotifyPotentialHotspotNearby(
-    const cryptauth::RemoteDevice& remote_device) {
+    const cryptauth::RemoteDevice& remote_device,
+    int signal_strength) {
   potential_hotspot_state_ =
       PotentialHotspotNotificationState::SINGLE_HOTSPOT_NEARBY_SHOWN;
   potential_hotspot_remote_device_ = remote_device;
diff --git a/chromeos/components/tether/fake_notification_presenter.h b/chromeos/components/tether/fake_notification_presenter.h
index cf985f91..68e34db 100644
--- a/chromeos/components/tether/fake_notification_presenter.h
+++ b/chromeos/components/tether/fake_notification_presenter.h
@@ -44,7 +44,8 @@
 
   // NotificationPresenter:
   void NotifyPotentialHotspotNearby(
-      const cryptauth::RemoteDevice& remote_device) override;
+      const cryptauth::RemoteDevice& remote_device,
+      int signal_strength) override;
   void NotifyMultiplePotentialHotspotsNearby() override;
   void RemovePotentialHotspotNotification() override;
   void NotifySetupRequired(const std::string& device_name) override;
diff --git a/chromeos/components/tether/host_scanner.cc b/chromeos/components/tether/host_scanner.cc
index 13af4f28..60cc1228b 100644
--- a/chromeos/components/tether/host_scanner.cc
+++ b/chromeos/components/tether/host_scanner.cc
@@ -93,8 +93,14 @@
     }
 
     if (scanned_device_list_so_far.size() == 1) {
-      notification_presenter_->NotifyPotentialHotspotNearby(
-          scanned_device_list_so_far.at(0).remote_device);
+      const cryptauth::RemoteDevice& remote_device =
+          scanned_device_list_so_far.at(0).remote_device;
+      int32_t signal_strength;
+      NormalizeDeviceStatus(scanned_device_list_so_far.at(0).device_status,
+                            nullptr /* carrier */,
+                            nullptr /* battery_percentage */, &signal_strength);
+      notification_presenter_->NotifyPotentialHotspotNearby(remote_device,
+                                                            signal_strength);
     } else {
       notification_presenter_->NotifyMultiplePotentialHotspotsNearby();
     }
diff --git a/chromeos/components/tether/notification_presenter.h b/chromeos/components/tether/notification_presenter.h
index f59bd24..53045b8 100644
--- a/chromeos/components/tether/notification_presenter.h
+++ b/chromeos/components/tether/notification_presenter.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "base/observer_list.h"
+#include "chromeos/network/network_state.h"
 #include "components/cryptauth/remote_device.h"
 
 namespace chromeos {
@@ -19,9 +20,10 @@
   virtual ~NotificationPresenter() {}
 
   // Notifies the user that a nearby device can potentially provide a tether
-  // hotspot.
+  // hotspot, and shows the signal strength with a blue icon.
   virtual void NotifyPotentialHotspotNearby(
-      const cryptauth::RemoteDevice& remote_device) = 0;
+      const cryptauth::RemoteDevice& remote_device,
+      int signal_strength) = 0;
 
   // Notifies the user that multiple nearby devices can potentially provide
   // tether hotspots.
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h
index 9084f772..149b668 100644
--- a/components/autofill/core/browser/autofill_client.h
+++ b/components/autofill/core/browser/autofill_client.h
@@ -199,6 +199,10 @@
 
   // Shows the explanation of http not secure warning message.
   virtual void ShowHttpNotSecureExplanation() = 0;
+
+  // Whether Autofill is currently supported by the client. If false, all
+  // features of Autofill are disabled, including Autocomplete.
+  virtual bool IsAutofillSupported() = 0;
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index a63c720..3784b4da 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -1165,7 +1165,8 @@
 }
 
 bool AutofillManager::IsAutofillEnabled() const {
-  return ::autofill::IsAutofillEnabled(client_->GetPrefs());
+  return ::autofill::IsAutofillEnabled(client_->GetPrefs()) &&
+         client_->IsAutofillSupported();
 }
 
 bool AutofillManager::IsCreditCardUploadEnabled() {
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index 5efc4bc..f24f885 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -190,7 +190,8 @@
                      const std::vector<base::string16>& labels) override;
   void Reset() override;
 
-  // Returns the value of the AutofillEnabled pref.
+  // Returns true if the value of the AutofillEnabled pref is true and the
+  // client supports Autofill.
   virtual bool IsAutofillEnabled() const;
 
   // Returns true if all the conditions for enabling the upload of credit card
diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc
index 61d05df..8dde20e85 100644
--- a/components/autofill/core/browser/test_autofill_client.cc
+++ b/components/autofill/core/browser/test_autofill_client.cc
@@ -145,4 +145,8 @@
 
 void TestAutofillClient::ShowHttpNotSecureExplanation() {}
 
+bool TestAutofillClient::IsAutofillSupported() {
+  return true;
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h
index 965023d..a0bd9cb 100644
--- a/components/autofill/core/browser/test_autofill_client.h
+++ b/components/autofill/core/browser/test_autofill_client.h
@@ -77,6 +77,7 @@
   bool ShouldShowSigninPromo() override;
   void StartSigninFlow() override;
   void ShowHttpNotSecureExplanation() override;
+  bool IsAutofillSupported() override;
 
   void SetPrefs(std::unique_ptr<PrefService> prefs) {
     prefs_ = std::move(prefs);
diff --git a/components/certificate_reporting/cert_logger.proto b/components/certificate_reporting/cert_logger.proto
index e28b3b9..8a3538f 100644
--- a/components/certificate_reporting/cert_logger.proto
+++ b/components/certificate_reporting/cert_logger.proto
@@ -160,4 +160,8 @@
 
   // The Chrome channel that this error occurred on.
   optional ChromeChannel chrome_channel = 12;
+
+  // True if the machine is enterprise managed. Currently only available for
+  // Windows and ChromeOS clients.
+  optional bool is_enterprise_managed = 13;
 };
diff --git a/components/certificate_reporting/error_report.cc b/components/certificate_reporting/error_report.cc
index e988ffc..a0e3a57 100644
--- a/components/certificate_reporting/error_report.cc
+++ b/components/certificate_reporting/error_report.cc
@@ -200,6 +200,10 @@
   }
 }
 
+void ErrorReport::SetIsEnterpriseManaged(bool is_enterprise_managed) {
+  cert_report_->set_is_enterprise_managed(is_enterprise_managed);
+}
+
 void ErrorReport::SetIsRetryUpload(bool is_retry_upload) {
   cert_report_->set_is_retry_upload(is_retry_upload);
 }
@@ -212,6 +216,10 @@
   return cert_report_->chrome_channel();
 }
 
+bool ErrorReport::is_enterprise_managed() const {
+  return cert_report_->is_enterprise_managed();
+}
+
 bool ErrorReport::is_retry_upload() const {
   return cert_report_->is_retry_upload();
 }
diff --git a/components/certificate_reporting/error_report.h b/components/certificate_reporting/error_report.h
index 801e75e..6c30f60 100644
--- a/components/certificate_reporting/error_report.h
+++ b/components/certificate_reporting/error_report.h
@@ -78,6 +78,8 @@
 
   void AddChromeChannel(version_info::Channel channel);
 
+  void SetIsEnterpriseManaged(bool is_enterprise_managed);
+
   // Sets is_retry_upload field of the protobuf to |is_retry_upload|.
   void SetIsRetryUpload(bool is_retry_upload);
 
@@ -87,6 +89,9 @@
   // Gets the Chrome channel attached to this report.
   CertLoggerRequest::ChromeChannel chrome_channel() const;
 
+  // Returns true if the device that issued the report is a managed device.
+  bool is_enterprise_managed() const;
+
   // Returns true if the report has been retried.
   bool is_retry_upload() const;
 
diff --git a/components/certificate_reporting/error_report_unittest.cc b/components/certificate_reporting/error_report_unittest.cc
index 5818625..ab51025 100644
--- a/components/certificate_reporting/error_report_unittest.cc
+++ b/components/certificate_reporting/error_report_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/threading/thread.h"
 #include "base/time/default_clock.h"
 #include "base/time/default_tick_clock.h"
+#include "build/build_config.h"
 #include "components/certificate_reporting/cert_logger.pb.h"
 #include "components/network_time/network_time_test_utils.h"
 #include "components/prefs/testing_pref_service.h"
@@ -279,6 +280,28 @@
   }
 }
 
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+// Tests that the SetIsEnterpriseManaged() function populates
+// is_enterprise_managed correctly on Windows, and that value is correctly
+// extracted from the parsed report.
+// These tests are OS specific because SetIsEnterpriseManaged is called only
+// on the Windows and ChromeOS OS.
+TEST(ErrorReportTest, TestIsEnterpriseManagedPopulatedOnWindows) {
+  SSLInfo ssl_info;
+  ASSERT_NO_FATAL_FAILURE(
+      GetTestSSLInfo(INCLUDE_UNVERIFIED_CERT_CHAIN, &ssl_info, kCertStatus));
+  ErrorReport report(kDummyHostname, ssl_info);
+
+  report.SetIsEnterpriseManaged(true);
+  std::string serialized_report;
+  ASSERT_TRUE(report.Serialize(&serialized_report));
+
+  CertLoggerRequest parsed;
+  ASSERT_TRUE(parsed.ParseFromString(serialized_report));
+  EXPECT_EQ(true, parsed.is_enterprise_managed());
+}
+#endif
+
 #if defined(OS_ANDROID)
 // Tests that information about the Android AIA fetching feature is included in
 // the report.
diff --git a/components/chrome_cleaner/public/constants/constants.cc b/components/chrome_cleaner/public/constants/constants.cc
index 2457c6f..3837e21f 100644
--- a/components/chrome_cleaner/public/constants/constants.cc
+++ b/components/chrome_cleaner/public/constants/constants.cc
@@ -13,7 +13,6 @@
 const char kChromePromptSwitch[] = "chrome-prompt";
 const char kChromeSystemInstallSwitch[] = "chrome-system-install";
 const char kChromeVersionSwitch[] = "chrome-version";
-const char kEnableCleanerLoggingSwitch[] = "enable-cleaner-logging";
 const char kEnableCrashReportingSwitch[] = "enable-crash-reporting";
 const char kEngineExperimentGroupSwitch[] = "engine-experiment-group";
 const char kEngineSwitch[] = "engine";
diff --git a/components/chrome_cleaner/public/constants/constants.h b/components/chrome_cleaner/public/constants/constants.h
index 4b4ed44..d28e875 100644
--- a/components/chrome_cleaner/public/constants/constants.h
+++ b/components/chrome_cleaner/public/constants/constants.h
@@ -33,10 +33,6 @@
 // The Chrome version string.
 extern const char kChromeVersionSwitch[];
 
-// Indicates whether logs upload is enabled in the cleaner process.
-// Takes effect only if execution mode is ExecutionMode::kCleanup.
-extern const char kEnableCleanerLoggingSwitch[];
-
 // Indicates that crash reporting is enabled for the current user.
 extern const char kEnableCrashReportingSwitch[];
 
@@ -116,9 +112,12 @@
   // The cleaner will run in scanning mode. No UI will be shown to the user
   // (UI handled by Chrome) and logs will not be uploaded.
   kScanning = 1,
-  // The cleaner will run in cleanup mode only. No UI will be shown to the
-  // user (UI handled by Chrome) and logs should only be uploaded if
-  // |kEnableCleanerLoggingSwitch| is set.
+  // The cleaner will run in cleaning mode. No UI will be shown to the user
+  // (UI handled by Chrome) and logs will be uploaded if the user did not opt
+  // out of logs collection when it was offered by the Chrome UI.
+  // Chrome should not try to launch the Chrome Cleanup Tool with |kCleanup|.
+  // It should instead communicate through IPC with the cleaner launched with
+  // |kScanning| to ask it to start cleanup.
   kCleanup = 2,
 
   // Auxiliary enumerator for range checking.
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index a496d19d..8a712ba 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -183,6 +183,8 @@
     "//ash/test:test_support_without_content",
     "//base",
     "//base/test:test_support",
+    "//cc:test_support",
+    "//components/viz/test:test_support",
     "//device/gamepad:test_helpers",
     "//mojo/edk/embedder:headers",
     "//testing/gtest",
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc
index f9cd7b56..dd901d8 100644
--- a/components/exo/buffer.cc
+++ b/components/exo/buffer.cc
@@ -411,7 +411,6 @@
 
 bool Buffer::ProduceTransferableResource(
     LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder,
-    cc::ResourceId resource_id,
     bool secure_output_only,
     bool client_usage,
     cc::TransferableResource* resource) {
@@ -439,7 +438,7 @@
     return false;
   }
 
-  resource->id = resource_id;
+  resource->id = layer_tree_frame_sink_holder->AllocateResourceId();
   resource->format = viz::RGBA_8888;
   resource->filter = GL_LINEAR;
   resource->size = gpu_memory_buffer_->GetSize();
@@ -473,7 +472,7 @@
     // The contents texture will be released when no longer used by the
     // compositor.
     layer_tree_frame_sink_holder->SetResourceReleaseCallback(
-        resource_id,
+        resource->id,
         base::Bind(&Buffer::Texture::ReleaseTexImage,
                    base::Unretained(contents_texture),
                    base::Bind(&Buffer::ReleaseContentsTexture, AsWeakPtr(),
@@ -503,7 +502,7 @@
   // The mailbox texture will be released when no longer used by the
   // compositor.
   layer_tree_frame_sink_holder->SetResourceReleaseCallback(
-      resource_id,
+      resource->id,
       base::Bind(&Buffer::Texture::Release, base::Unretained(texture),
                  base::Bind(&Buffer::ReleaseTexture, AsWeakPtr(),
                             base::Passed(&texture_))));
diff --git a/components/exo/buffer.h b/components/exo/buffer.h
index 890edf4..f347582 100644
--- a/components/exo/buffer.h
+++ b/components/exo/buffer.h
@@ -54,7 +54,6 @@
   // |non_client_usage| is true.
   bool ProduceTransferableResource(
       LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder,
-      cc::ResourceId resource_id,
       bool secure_output_only,
       bool client_usage,
       cc::TransferableResource* resource);
diff --git a/components/exo/buffer_unittest.cc b/components/exo/buffer_unittest.cc
index 32c78ea..d5ce3d2 100644
--- a/components/exo/buffer_unittest.cc
+++ b/components/exo/buffer_unittest.cc
@@ -8,7 +8,7 @@
 #include "cc/output/context_provider.h"
 #include "cc/resources/single_release_callback.h"
 #include "components/exo/buffer.h"
-#include "components/exo/surface.h"
+#include "components/exo/surface_tree_host.h"
 #include "components/exo/test/exo_test_base.h"
 #include "components/exo/test/exo_test_helper.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
@@ -29,12 +29,12 @@
 
 TEST_F(BufferTest, ReleaseCallback) {
   gfx::Size buffer_size(256, 256);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface);
-  const viz::FrameSinkId arbitrary_frame_sink_id(1, 1);
-  LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder =
-      surface->layer_tree_frame_sink_holder();
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  auto surface_tree_host =
+      base::MakeUnique<SurfaceTreeHost>("BufferTest", nullptr);
+  LayerTreeFrameSinkHolder* frame_sink_holder =
+      surface_tree_host->layer_tree_frame_sink_holder();
 
   // Set the release callback.
   int release_call_count = 0;
@@ -44,8 +44,8 @@
   buffer->OnAttach();
   cc::TransferableResource resource;
   // Produce a transferable resource for the contents of the buffer.
-  bool rv = buffer->ProduceTransferableResource(layer_tree_frame_sink_holder, 0,
-                                                false, true, &resource);
+  bool rv = buffer->ProduceTransferableResource(frame_sink_holder, false, true,
+                                                &resource);
   ASSERT_TRUE(rv);
 
   // Release buffer.
@@ -54,7 +54,7 @@
   returned_resource.sync_token = resource.mailbox_holder.sync_token;
   returned_resource.lost = false;
   std::vector<cc::ReturnedResource> resources = {returned_resource};
-  layer_tree_frame_sink_holder->ReclaimResources(resources);
+  frame_sink_holder->ReclaimResources(resources);
 
   RunAllPendingInMessageLoop();
   ASSERT_EQ(release_call_count, 0);
@@ -67,19 +67,18 @@
 
 TEST_F(BufferTest, IsLost) {
   gfx::Size buffer_size(256, 256);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  const viz::FrameSinkId arbitrary_frame_sink_id(1, 1);
-  std::unique_ptr<Surface> surface(new Surface);
-  LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder =
-      surface->layer_tree_frame_sink_holder();
-  cc::ResourceId resource_id = 0;
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  auto surface_tree_host =
+      base::MakeUnique<SurfaceTreeHost>("BufferTest", nullptr);
+  LayerTreeFrameSinkHolder* frame_sink_holder =
+      surface_tree_host->layer_tree_frame_sink_holder();
 
   buffer->OnAttach();
   // Acquire a texture transferable resource for the contents of the buffer.
   cc::TransferableResource resource;
-  bool rv = buffer->ProduceTransferableResource(
-      layer_tree_frame_sink_holder, resource_id, false, true, &resource);
+  bool rv = buffer->ProduceTransferableResource(frame_sink_holder, false, true,
+                                                &resource);
   ASSERT_TRUE(rv);
 
   scoped_refptr<cc::ContextProvider> context_provider =
@@ -95,28 +94,27 @@
   // Release buffer.
   bool is_lost = true;
   cc::ReturnedResource returned_resource;
-  returned_resource.id = resource_id;
+  returned_resource.id = resource.id;
   returned_resource.sync_token = gpu::SyncToken();
   returned_resource.lost = is_lost;
   std::vector<cc::ReturnedResource> resources = {returned_resource};
-  layer_tree_frame_sink_holder->ReclaimResources(resources);
+  frame_sink_holder->ReclaimResources(resources);
   RunAllPendingInMessageLoop();
 
   // Producing a new texture transferable resource for the contents of the
   // buffer.
-  ++resource_id;
   cc::TransferableResource new_resource;
-  rv = buffer->ProduceTransferableResource(
-      layer_tree_frame_sink_holder, resource_id, false, false, &new_resource);
+  rv = buffer->ProduceTransferableResource(frame_sink_holder, false, false,
+                                           &new_resource);
   ASSERT_TRUE(rv);
   buffer->OnDetach();
 
   cc::ReturnedResource returned_resource2;
-  returned_resource2.id = resource_id;
+  returned_resource2.id = new_resource.id;
   returned_resource2.sync_token = gpu::SyncToken();
   returned_resource2.lost = false;
   std::vector<cc::ReturnedResource> resources2 = {returned_resource2};
-  layer_tree_frame_sink_holder->ReclaimResources(resources2);
+  frame_sink_holder->ReclaimResources(resources2);
   RunAllPendingInMessageLoop();
 }
 
diff --git a/components/exo/layer_tree_frame_sink_holder.cc b/components/exo/layer_tree_frame_sink_holder.cc
index a750192d..fa4b2cf 100644
--- a/components/exo/layer_tree_frame_sink_holder.cc
+++ b/components/exo/layer_tree_frame_sink_holder.cc
@@ -6,7 +6,7 @@
 
 #include "cc/output/layer_tree_frame_sink.h"
 #include "cc/resources/returned_resource.h"
-#include "components/exo/surface.h"
+#include "components/exo/surface_tree_host.h"
 
 namespace exo {
 
@@ -14,19 +14,16 @@
 // LayerTreeFrameSinkHolder, public:
 
 LayerTreeFrameSinkHolder::LayerTreeFrameSinkHolder(
-    Surface* surface,
+    SurfaceTreeHost* surface_tree_host,
     std::unique_ptr<cc::LayerTreeFrameSink> frame_sink)
-    : surface_(surface),
+    : surface_tree_host_(surface_tree_host),
       frame_sink_(std::move(frame_sink)),
       weak_factory_(this) {
-  surface_->AddSurfaceObserver(this);
   frame_sink_->BindToClient(this);
 }
 
 LayerTreeFrameSinkHolder::~LayerTreeFrameSinkHolder() {
   frame_sink_->DetachFromClient();
-  if (surface_)
-    surface_->RemoveSurfaceObserver(this);
 
   // Release all resources which aren't returned from LayerTreeFrameSink.
   for (auto& callback : release_callbacks_)
@@ -58,8 +55,7 @@
 
 void LayerTreeFrameSinkHolder::SetBeginFrameSource(
     cc::BeginFrameSource* source) {
-  if (surface_)
-    surface_->SetBeginFrameSource(source);
+  surface_tree_host_->SetBeginFrameSource(source);
 }
 
 void LayerTreeFrameSinkHolder::ReclaimResources(
@@ -75,16 +71,7 @@
 }
 
 void LayerTreeFrameSinkHolder::DidReceiveCompositorFrameAck() {
-  if (surface_)
-    surface_->DidReceiveCompositorFrameAck();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// SurfaceObserver overrides:
-
-void LayerTreeFrameSinkHolder::OnSurfaceDestroying(Surface* surface) {
-  surface_->RemoveSurfaceObserver(this);
-  surface_ = nullptr;
+  surface_tree_host_->DidReceiveCompositorFrameAck();
 }
 
 }  // namespace exo
diff --git a/components/exo/layer_tree_frame_sink_holder.h b/components/exo/layer_tree_frame_sink_holder.h
index 12b0c45..2fb9b9a 100644
--- a/components/exo/layer_tree_frame_sink_holder.h
+++ b/components/exo/layer_tree_frame_sink_holder.h
@@ -10,23 +10,19 @@
 #include "base/containers/flat_map.h"
 #include "cc/output/layer_tree_frame_sink_client.h"
 #include "cc/resources/release_callback.h"
-#include "components/exo/surface_observer.h"
 
 namespace cc {
 class LayerTreeFrameSink;
 }
 
 namespace exo {
-class Surface;
+class SurfaceTreeHost;
 
 // This class talks to CompositorFrameSink and keeps track of references to
-// the contents of Buffers. It's keeped alive by references from
-// release_callbacks_. It's destroyed when its owning Surface is destroyed and
-// the last outstanding release callback is called.
-class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient,
-                                 public SurfaceObserver {
+// the contents of Buffers.
+class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient {
  public:
-  LayerTreeFrameSinkHolder(Surface* surface,
+  LayerTreeFrameSinkHolder(SurfaceTreeHost* surface_tree_host,
                            std::unique_ptr<cc::LayerTreeFrameSink> frame_sink);
   ~LayerTreeFrameSinkHolder() override;
 
@@ -53,15 +49,12 @@
       const gfx::Rect& viewport_rect,
       const gfx::Transform& transform) override {}
 
-  // Overridden from SurfaceObserver:
-  void OnSurfaceDestroying(Surface* surface) override;
-
  private:
   // A collection of callbacks used to release resources.
   using ResourceReleaseCallbackMap = base::flat_map<int, cc::ReleaseCallback>;
   ResourceReleaseCallbackMap release_callbacks_;
 
-  Surface* surface_;
+  SurfaceTreeHost* surface_tree_host_;
   std::unique_ptr<cc::LayerTreeFrameSink> frame_sink_;
 
   // The next resource id the buffer is attached to.
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 3b32f0b..c44cf39 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -956,6 +956,9 @@
 void ShellSurface::OnWindowBoundsChanged(aura::Window* window,
                                          const gfx::Rect& old_bounds,
                                          const gfx::Rect& new_bounds) {
+  if (window == host_window())
+    return;
+
   // TODO(domlaskowski): For BoundsMode::CLIENT, the configure callback does not
   // yet support resizing. See crbug.com/699746.
   if (bounds_mode_ == BoundsMode::CLIENT)
@@ -987,7 +990,23 @@
   }
 }
 
+void ShellSurface::OnWindowAddedToRootWindow(aura::Window* window) {
+  if (window == host_window())
+    SurfaceTreeHost::OnWindowAddedToRootWindow(window);
+}
+
+void ShellSurface::OnWindowRemovingFromRootWindow(aura::Window* window,
+                                                  aura::Window* new_root) {
+  if (window == host_window())
+    SurfaceTreeHost::OnWindowRemovingFromRootWindow(window, new_root);
+}
+
 void ShellSurface::OnWindowDestroying(aura::Window* window) {
+  if (window == host_window()) {
+    SurfaceTreeHost::OnWindowDestroying(window);
+    return;
+  }
+
   if (window == parent_) {
     parent_ = nullptr;
     // |parent_| being set to null effects the ability to maximize the window.
diff --git a/components/exo/shell_surface.h b/components/exo/shell_surface.h
index ab05c116..fc96631d 100644
--- a/components/exo/shell_surface.h
+++ b/components/exo/shell_surface.h
@@ -16,7 +16,6 @@
 #include "components/exo/surface_observer.h"
 #include "components/exo/surface_tree_host.h"
 #include "components/exo/wm_helper.h"
-#include "ui/aura/window_observer.h"
 #include "ui/base/hit_test.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
@@ -47,7 +46,6 @@
                      public views::WidgetDelegate,
                      public views::View,
                      public ash::wm::WindowStateObserver,
-                     public aura::WindowObserver,
                      public WMHelper::ActivationObserver,
                      public WMHelper::DisplayConfigurationObserver {
  public:
@@ -258,6 +256,9 @@
   void OnWindowBoundsChanged(aura::Window* window,
                              const gfx::Rect& old_bounds,
                              const gfx::Rect& new_bounds) override;
+  void OnWindowAddedToRootWindow(aura::Window* window) override;
+  void OnWindowRemovingFromRootWindow(aura::Window* window,
+                                      aura::Window* new_root) override;
   void OnWindowDestroying(aura::Window* window) override;
 
   // Overridden from WMHelper::ActivationObserver:
diff --git a/components/exo/sub_surface.cc b/components/exo/sub_surface.cc
index 1f8e2f30..f170dae 100644
--- a/components/exo/sub_surface.cc
+++ b/components/exo/sub_surface.cc
@@ -96,7 +96,8 @@
   if (IsSurfaceSynchronized())
     return;
 
-  surface_->CommitSurfaceHierarchy();
+  // TODO(penghuang): http://crbug.com/740110 Support async mode.
+  NOTIMPLEMENTED() << "Async subsurface is not supported!";
 }
 
 bool SubSurface::IsSurfaceSynchronized() const {
diff --git a/components/exo/sub_surface_unittest.cc b/components/exo/sub_surface_unittest.cc
index 1132dec..c569753 100644
--- a/components/exo/sub_surface_unittest.cc
+++ b/components/exo/sub_surface_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/exo/sub_surface.h"
 
 #include "base/memory/ptr_util.h"
+#include "components/exo/shell_surface.h"
 #include "components/exo/surface.h"
 #include "components/exo/test/exo_test_base.h"
 #include "components/exo/test/exo_test_helper.h"
@@ -16,10 +17,10 @@
 using SubSurfaceTest = test::ExoTestBase;
 
 TEST_F(SubSurfaceTest, SetPosition) {
-  std::unique_ptr<Surface> parent(new Surface);
-  std::unique_ptr<Surface> surface(new Surface);
-  std::unique_ptr<SubSurface> sub_surface(
-      new SubSurface(surface.get(), parent.get()));
+  auto parent = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(parent.get());
+  auto surface = base::MakeUnique<Surface>();
+  auto sub_surface = base::MakeUnique<SubSurface>(surface.get(), parent.get());
 
   // Initial position is at the origin.
   EXPECT_EQ(gfx::Point().ToString(),
@@ -49,14 +50,15 @@
 }
 
 TEST_F(SubSurfaceTest, PlaceAbove) {
-  std::unique_ptr<Surface> parent(new Surface);
-  std::unique_ptr<Surface> surface1(new Surface);
-  std::unique_ptr<Surface> surface2(new Surface);
-  std::unique_ptr<Surface> non_sibling_surface(new Surface);
-  std::unique_ptr<SubSurface> sub_surface1(
-      new SubSurface(surface1.get(), parent.get()));
-  std::unique_ptr<SubSurface> sub_surface2(
-      new SubSurface(surface2.get(), parent.get()));
+  auto parent = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(parent.get());
+  auto surface1 = base::MakeUnique<Surface>();
+  auto surface2 = base::MakeUnique<Surface>();
+  auto non_sibling_surface = base::MakeUnique<Surface>();
+  auto sub_surface1 =
+      base::MakeUnique<SubSurface>(surface1.get(), parent.get());
+  auto sub_surface2 =
+      base::MakeUnique<SubSurface>(surface2.get(), parent.get());
 
   ASSERT_EQ(2u, parent->window()->children().size());
   EXPECT_EQ(surface1->window(), parent->window()->children()[0]);
@@ -80,14 +82,15 @@
 }
 
 TEST_F(SubSurfaceTest, PlaceBelow) {
-  std::unique_ptr<Surface> parent(new Surface);
-  std::unique_ptr<Surface> surface1(new Surface);
-  std::unique_ptr<Surface> surface2(new Surface);
-  std::unique_ptr<Surface> non_sibling_surface(new Surface);
-  std::unique_ptr<SubSurface> sub_surface1(
-      new SubSurface(surface1.get(), parent.get()));
-  std::unique_ptr<SubSurface> sub_surface2(
-      new SubSurface(surface2.get(), parent.get()));
+  auto parent = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(parent.get());
+  auto surface1 = base::MakeUnique<Surface>();
+  auto surface2 = base::MakeUnique<Surface>();
+  auto non_sibling_surface = base::MakeUnique<Surface>();
+  auto sub_surface1 =
+      base::MakeUnique<SubSurface>(surface1.get(), parent.get());
+  auto sub_surface2 =
+      base::MakeUnique<SubSurface>(surface2.get(), parent.get());
 
   ASSERT_EQ(2u, parent->window()->children().size());
   EXPECT_EQ(surface1->window(), parent->window()->children()[0]);
@@ -111,13 +114,14 @@
 }
 
 TEST_F(SubSurfaceTest, SetCommitBehavior) {
-  std::unique_ptr<Surface> parent(new Surface);
-  std::unique_ptr<Surface> child(new Surface);
-  std::unique_ptr<Surface> grandchild(new Surface);
-  std::unique_ptr<SubSurface> child_sub_surface(
-      new SubSurface(child.get(), parent.get()));
-  std::unique_ptr<SubSurface> grandchild_sub_surface(
-      new SubSurface(grandchild.get(), child.get()));
+  auto parent = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(parent.get());
+  auto child = base::MakeUnique<Surface>();
+  auto grandchild = base::MakeUnique<Surface>();
+  auto child_sub_surface =
+      base::MakeUnique<SubSurface>(child.get(), parent.get());
+  auto grandchild_sub_surface =
+      base::MakeUnique<SubSurface>(grandchild.get(), child.get());
 
   // Initial position is at the origin.
   EXPECT_EQ(gfx::Point().ToString(),
@@ -141,19 +145,20 @@
   EXPECT_EQ(position1.ToString(),
             grandchild->window()->bounds().origin().ToString());
 
+  // TODO(penghuang): http://crbug.com/740110 Support async mode.
   // Disable synchronous commit behavior.
-  bool synchronized = false;
-  child_sub_surface->SetCommitBehavior(synchronized);
+  // bool synchronized = false;
+  // child_sub_surface->SetCommitBehavior(synchronized);
 
   // Set position to 20, 20.
-  gfx::Point position2(20, 20);
-  grandchild_sub_surface->SetPosition(position2);
-  child->Commit();
+  // gfx::Point position2(20, 20);
+  // grandchild_sub_surface->SetPosition(position2);
+  // child->Commit();
 
   // A Commit() call on child should be sufficient for the position of
   // grandchild to take effect when synchronous is disabled.
-  EXPECT_EQ(position2.ToString(),
-            grandchild->window()->bounds().origin().ToString());
+  // EXPECT_EQ(position2.ToString(),
+  //           grandchild->window()->bounds().origin().ToString());
 }
 
 }  // namespace
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 40a23ab..9e711ab1 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/callback_helpers.h"
+#include "base/containers/adapters.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -27,7 +28,6 @@
 #include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
 #include "third_party/khronos/GLES2/gl2.h"
 #include "ui/aura/client/aura_constants.h"
-#include "ui/aura/env.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/aura/window_targeter.h"
 #include "ui/base/class_property.h"
@@ -189,42 +189,23 @@
   window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
   window_->SetName("ExoSurface");
   window_->SetProperty(kSurfaceKey, this);
-  window_->Init(ui::LAYER_SOLID_COLOR);
+  window_->Init(ui::LAYER_NOT_DRAWN);
   window_->SetEventTargeter(base::WrapUnique(new CustomWindowTargeter));
   window_->set_owned_by_parent(false);
-  window_->AddObserver(this);
-  aura::Env::GetInstance()->context_factory()->AddObserver(this);
-  layer_tree_frame_sink_holder_ = base::MakeUnique<LayerTreeFrameSinkHolder>(
-      this, window_->CreateLayerTreeFrameSink());
 }
 
 Surface::~Surface() {
-  aura::Env::GetInstance()->context_factory()->RemoveObserver(this);
   for (SurfaceObserver& observer : observers_)
     observer.OnSurfaceDestroying(this);
 
-  window_->RemoveObserver(this);
-  if (window_->layer()->GetCompositor())
-    window_->layer()->GetCompositor()->vsync_manager()->RemoveObserver(this);
-  window_->layer()->SetShowSolidColorContent();
-
-  frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_);
-  active_frame_callbacks_.splice(active_frame_callbacks_.end(),
-                                 frame_callbacks_);
   // Call all frame callbacks with a null frame time to indicate that they
   // have been cancelled.
-  for (const auto& frame_callback : active_frame_callbacks_)
+  for (const auto& frame_callback : pending_frame_callbacks_)
     frame_callback.Run(base::TimeTicks());
 
-  presentation_callbacks_.splice(presentation_callbacks_.end(),
-                                 pending_presentation_callbacks_);
-  swapping_presentation_callbacks_.splice(
-      swapping_presentation_callbacks_.end(), presentation_callbacks_);
-  swapped_presentation_callbacks_.splice(swapped_presentation_callbacks_.end(),
-                                         swapping_presentation_callbacks_);
   // Call all presentation callbacks with a null presentation time to indicate
   // that they have been cancelled.
-  for (const auto& presentation_callback : swapped_presentation_callbacks_)
+  for (const auto& presentation_callback : pending_presentation_callbacks_)
     presentation_callback.Run(base::TimeTicks(), base::TimeDelta());
 }
 
@@ -233,10 +214,6 @@
   return window->GetProperty(kSurfaceKey);
 }
 
-viz::SurfaceId Surface::GetSurfaceId() const {
-  return window_->GetSurfaceId();
-}
-
 void Surface::Attach(Buffer* buffer) {
   TRACE_EVENT1("exo", "Surface::Attach", "buffer",
                buffer ? buffer->GetSize().ToString() : "null");
@@ -290,11 +267,13 @@
 
   DCHECK(!sub_surface->window()->parent());
   DCHECK(!sub_surface->window()->IsVisible());
+  sub_surface->window()->SetBounds(
+      gfx::Rect(sub_surface->window()->bounds().size()));
   window_->AddChild(sub_surface->window());
 
   DCHECK(!ListContainsEntry(pending_sub_surfaces_, sub_surface));
   pending_sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point()));
-  has_pending_layer_changes_ = true;
+  sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point()));
 }
 
 void Surface::RemoveSubSurface(Surface* sub_surface) {
@@ -308,7 +287,8 @@
   DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
   pending_sub_surfaces_.erase(
       FindListEntry(pending_sub_surfaces_, sub_surface));
-  has_pending_layer_changes_ = true;
+  DCHECK(ListContainsEntry(sub_surfaces_, sub_surface));
+  sub_surfaces_.erase(FindListEntry(sub_surfaces_, sub_surface));
 }
 
 void Surface::SetSubSurfacePosition(Surface* sub_surface,
@@ -321,7 +301,7 @@
   if (it->second == position)
     return;
   it->second = position;
-  has_pending_layer_changes_ = true;
+  sub_surfaces_changed_ = true;
 }
 
 void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) {
@@ -353,7 +333,7 @@
   if (it == position_it)
     return;
   pending_sub_surfaces_.splice(position_it, pending_sub_surfaces_, it);
-  has_pending_layer_changes_ = true;
+  sub_surfaces_changed_ = true;
 }
 
 void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) {
@@ -378,7 +358,7 @@
   if (it == sibling_it)
     return;
   pending_sub_surfaces_.splice(sibling_it, pending_sub_surfaces_, it);
-  has_pending_layer_changes_ = true;
+  sub_surfaces_changed_ = true;
 }
 
 void Surface::SetViewport(const gfx::Size& viewport) {
@@ -421,108 +401,87 @@
   TRACE_EVENT0("exo", "Surface::Commit");
 
   needs_commit_surface_hierarchy_ = true;
-
-  if (state_ != pending_state_)
-    has_pending_layer_changes_ = true;
-
-  if (has_pending_contents_) {
-    if (pending_buffer_.buffer()) {
-      if (current_resource_.size != pending_buffer_.buffer()->GetSize())
-        has_pending_layer_changes_ = true;
-      // Whether layer fills bounds opaquely or not might have changed.
-      if (current_resource_has_alpha_ !=
-          FormatHasAlpha(pending_buffer_.buffer()->GetFormat()))
-        has_pending_layer_changes_ = true;
-    } else if (!current_resource_.size.IsEmpty()) {
-      has_pending_layer_changes_ = true;
-    }
-  }
-
-  if (delegate_) {
+  if (delegate_)
     delegate_->OnSurfaceCommit();
-  } else {
-    CommitSurfaceHierarchy();
-  }
-
-  if (current_begin_frame_ack_.sequence_number !=
-      cc::BeginFrameArgs::kInvalidFrameNumber) {
-    if (!current_begin_frame_ack_.has_damage) {
-      layer_tree_frame_sink_holder_->frame_sink()->DidNotProduceFrame(
-          current_begin_frame_ack_);
-    }
-    current_begin_frame_ack_.sequence_number =
-        cc::BeginFrameArgs::kInvalidFrameNumber;
-    if (begin_frame_source_)
-      begin_frame_source_->DidFinishFrame(this);
-  }
 }
 
-void Surface::CommitSurfaceHierarchy() {
-  DCHECK(needs_commit_surface_hierarchy_);
-  needs_commit_surface_hierarchy_ = false;
-  has_pending_layer_changes_ = false;
+void Surface::CommitSurfaceHierarchy(
+    const gfx::Point& origin,
+    FrameType frame_type,
+    LayerTreeFrameSinkHolder* frame_sink_holder,
+    cc::CompositorFrame* frame,
+    std::list<FrameCallback>* frame_callbacks,
+    std::list<PresentationCallback>* presentation_callbacks) {
+  bool needs_commit =
+      frame_type == FRAME_TYPE_COMMIT && needs_commit_surface_hierarchy_;
+  if (needs_commit) {
+    needs_commit_surface_hierarchy_ = false;
 
-  state_ = pending_state_;
-  pending_state_.only_visible_on_secure_output = false;
+    state_ = pending_state_;
+    pending_state_.only_visible_on_secure_output = false;
 
-  // We update contents if Attach() has been called since last commit.
-  if (has_pending_contents_) {
-    has_pending_contents_ = false;
+    // We update contents if Attach() has been called since last commit.
+    if (has_pending_contents_) {
+      has_pending_contents_ = false;
 
-    current_buffer_ = std::move(pending_buffer_);
+      current_buffer_ = std::move(pending_buffer_);
 
-    UpdateResource(true);
+      UpdateResource(frame_sink_holder, true);
+    }
+
+    // Move pending frame callbacks to the end of frame_callbacks.
+    frame_callbacks->splice(frame_callbacks->end(), pending_frame_callbacks_);
+
+    // Move pending presentation callbacks to the end of presentation_callbacks.
+    presentation_callbacks->splice(presentation_callbacks->end(),
+                                   pending_presentation_callbacks_);
+
+    UpdateContentSize();
+
+    // Synchronize window hierarchy. This will position and update the stacking
+    // order of all sub-surfaces after committing all pending state of
+    // sub-surface descendants.
+    if (sub_surfaces_changed_) {
+      sub_surfaces_.clear();
+      aura::Window* stacking_target = nullptr;
+      for (const auto& sub_surface_entry : pending_sub_surfaces_) {
+        Surface* sub_surface = sub_surface_entry.first;
+        sub_surfaces_.push_back(sub_surface_entry);
+        // Move sub-surface to its new position in the stack.
+        if (stacking_target)
+          window_->StackChildAbove(sub_surface->window(), stacking_target);
+
+        // Stack next sub-surface above this sub-surface.
+        stacking_target = sub_surface->window();
+
+        // Update sub-surface position relative to surface origin.
+        sub_surface->window()->SetBounds(gfx::Rect(
+            sub_surface_entry.second, sub_surface->window()->bounds().size()));
+      }
+      sub_surfaces_changed_ = false;
+    }
   }
 
-  // Move pending frame callbacks to the end of frame_callbacks_.
-  frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_);
-
-  // Move pending presentation callbacks to the end of presentation_callbacks_.
-  presentation_callbacks_.splice(presentation_callbacks_.end(),
-                                 pending_presentation_callbacks_);
-
-  UpdateSurface(false);
-
-  window_->layer()->SetFillsBoundsOpaquely(
-      !current_resource_has_alpha_ || state_.blend_mode == SkBlendMode::kSrc ||
-      state_.opaque_region.contains(
-          gfx::RectToSkIRect(gfx::Rect(content_size_))));
-
-  // Reset damage.
-  pending_damage_.setEmpty();
-  DCHECK(!current_resource_.id ||
-         layer_tree_frame_sink_holder_->HasReleaseCallbackForResource(
-             current_resource_.id));
-
-  // Synchronize window hierarchy. This will position and update the stacking
-  // order of all sub-surfaces after committing all pending state of sub-surface
-  // descendants.
-  aura::Window* stacking_target = nullptr;
-  for (auto& sub_surface_entry : pending_sub_surfaces_) {
-    Surface* sub_surface = sub_surface_entry.first;
-
+  // The top most sub-surface is at the front of the RenderPass's quad_list,
+  // so we need composite sub-surface in reversed order.
+  for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
+    auto* sub_surface = sub_surface_entry.first;
     // Synchronsouly commit all pending state of the sub-surface and its
     // decendents.
-    if (sub_surface->needs_commit_surface_hierarchy())
-      sub_surface->CommitSurfaceHierarchy();
-
-    // Enable/disable sub-surface based on if it has contents.
-    if (sub_surface->has_contents())
-      sub_surface->window()->Show();
-    else
-      sub_surface->window()->Hide();
-
-    // Move sub-surface to its new position in the stack.
-    if (stacking_target)
-      window_->StackChildAbove(sub_surface->window(), stacking_target);
-
-    // Stack next sub-surface above this sub-surface.
-    stacking_target = sub_surface->window();
-
-    // Update sub-surface position relative to surface origin.
-    sub_surface->window()->SetBounds(
-        gfx::Rect(sub_surface_entry.second, sub_surface->content_size_));
+    sub_surface->CommitSurfaceHierarchy(
+        origin + sub_surface_entry.second.OffsetFromOrigin(), frame_type,
+        frame_sink_holder, frame, frame_callbacks, presentation_callbacks);
   }
+
+  AppendContentsToFrame(origin, frame_type, frame);
+
+  // Reset damage.
+  if (needs_commit)
+    pending_damage_.setEmpty();
+
+  DCHECK(
+      !current_resource_.id ||
+      frame_sink_holder->HasReleaseCallbackForResource(current_resource_.id));
 }
 
 bool Surface::IsSynchronized() const {
@@ -599,49 +558,6 @@
   return value;
 }
 
-void Surface::DidReceiveCompositorFrameAck() {
-  active_frame_callbacks_.splice(active_frame_callbacks_.end(),
-                                 frame_callbacks_);
-  swapping_presentation_callbacks_.splice(
-      swapping_presentation_callbacks_.end(), presentation_callbacks_);
-  UpdateNeedsBeginFrame();
-}
-
-void Surface::SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) {
-  if (needs_begin_frame_) {
-    DCHECK(begin_frame_source_);
-    begin_frame_source_->RemoveObserver(this);
-    needs_begin_frame_ = false;
-  }
-  begin_frame_source_ = begin_frame_source;
-  UpdateNeedsBeginFrame();
-}
-
-void Surface::UpdateNeedsBeginFrame() {
-  if (!begin_frame_source_)
-    return;
-
-  bool needs_begin_frame = !active_frame_callbacks_.empty();
-  if (needs_begin_frame == needs_begin_frame_)
-    return;
-
-  needs_begin_frame_ = needs_begin_frame;
-  if (needs_begin_frame_)
-    begin_frame_source_->AddObserver(this);
-  else
-    begin_frame_source_->RemoveObserver(this);
-}
-
-bool Surface::OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) {
-  current_begin_frame_ack_ =
-      cc::BeginFrameAck(args.source_id, args.sequence_number, false);
-  while (!active_frame_callbacks_.empty()) {
-    active_frame_callbacks_.front().Run(args.frame_time);
-    active_frame_callbacks_.pop_front();
-  }
-  return true;
-}
-
 bool Surface::IsStylusOnly() {
   return window_->GetProperty(kStylusOnlyKey);
 }
@@ -650,48 +566,17 @@
   window_->SetProperty(kStylusOnlyKey, true);
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// ui::ContextFactoryObserver overrides:
-
-void Surface::OnLostResources() {
-  if (!window_->GetSurfaceId().is_valid())
-    return;
-  UpdateResource(false);
-  UpdateSurface(true);
+void Surface::RecreateResources(LayerTreeFrameSinkHolder* frame_sink_holder) {
+  UpdateResource(frame_sink_holder, false);
+  for (const auto& sub_surface : sub_surfaces_)
+    sub_surface.first->RecreateResources(frame_sink_holder);
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// aura::WindowObserver overrides:
-
-void Surface::OnWindowAddedToRootWindow(aura::Window* window) {
-  window->layer()->GetCompositor()->vsync_manager()->AddObserver(this);
-}
-
-void Surface::OnWindowRemovingFromRootWindow(aura::Window* window,
-                                             aura::Window* new_root) {
-  window->layer()->GetCompositor()->vsync_manager()->RemoveObserver(this);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ui::CompositorVSyncManager::Observer overrides:
-
-void Surface::OnUpdateVSyncParameters(base::TimeTicks timebase,
-                                      base::TimeDelta interval) {
-  // Use current time if platform doesn't provide an accurate timebase.
-  if (timebase.is_null())
-    timebase = base::TimeTicks::Now();
-
-  while (!swapped_presentation_callbacks_.empty()) {
-    swapped_presentation_callbacks_.front().Run(timebase, interval);
-    swapped_presentation_callbacks_.pop_front();
-  }
-
-  // VSync parameters updates are generated at the start of a new swap. Move
-  // the swapping presentation callbacks to swapped callbacks so they fire
-  // at the next VSync parameters update as that will contain the presentation
-  // time for the previous frame.
-  swapped_presentation_callbacks_.splice(swapped_presentation_callbacks_.end(),
-                                         swapping_presentation_callbacks_);
+bool Surface::FillsBoundsOpaquely() const {
+  return !current_resource_has_alpha_ ||
+         state_.blend_mode == SkBlendMode::kSrc ||
+         state_.opaque_region.contains(
+             gfx::RectToSkIRect(gfx::Rect(content_size_)));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -741,12 +626,11 @@
   buffer_ = buffer;
 }
 
-void Surface::UpdateResource(bool client_usage) {
+void Surface::UpdateResource(LayerTreeFrameSinkHolder* frame_sink_holder,
+                             bool client_usage) {
   if (current_buffer_.buffer() &&
       current_buffer_.buffer()->ProduceTransferableResource(
-          layer_tree_frame_sink_holder_.get(),
-          layer_tree_frame_sink_holder_->AllocateResourceId(),
-          state_.only_visible_on_secure_output, client_usage,
+          frame_sink_holder, state_.only_visible_on_secure_output, client_usage,
           &current_resource_)) {
     current_resource_has_alpha_ =
         FormatHasAlpha(current_buffer_.buffer()->GetFormat());
@@ -757,80 +641,47 @@
   }
 }
 
-void Surface::UpdateSurface(bool full_damage) {
-  gfx::Size buffer_size = current_resource_.size;
-  gfx::SizeF scaled_buffer_size(
-      gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / state_.buffer_scale));
-
-  gfx::Size layer_size;  // Size of the output layer, in DIP.
-  if (!state_.viewport.IsEmpty()) {
-    layer_size = state_.viewport;
-  } else if (!state_.crop.IsEmpty()) {
-    DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) ||
-                         !gfx::IsExpressibleAsInt(state_.crop.height()))
-        << "Crop rectangle size (" << state_.crop.size().ToString()
-        << ") most be expressible using integers when viewport is not set";
-    layer_size = gfx::ToCeiledSize(state_.crop.size());
-  } else {
-    layer_size = gfx::ToCeiledSize(scaled_buffer_size);
-  }
-
-  content_size_ = layer_size;
-  // We need update window_'s bounds with content size, because the
-  // LayerTreeFrameSink may not update the window's size base the size of
-  // the lastest submitted CompositorFrame.
-  window_->SetBounds(gfx::Rect(window_->bounds().origin(), content_size_));
-  // TODO(jbauman): Figure out how this interacts with the pixel size of
-  // CopyOutputRequests on the layer.
-  gfx::Size contents_surface_size = layer_size;
-
-  gfx::PointF uv_top_left(0.f, 0.f);
-  gfx::PointF uv_bottom_right(1.f, 1.f);
-  if (!state_.crop.IsEmpty()) {
-    uv_top_left = state_.crop.origin();
-
-    uv_top_left.Scale(1.f / scaled_buffer_size.width(),
-                      1.f / scaled_buffer_size.height());
-    uv_bottom_right = state_.crop.bottom_right();
-    uv_bottom_right.Scale(1.f / scaled_buffer_size.width(),
-                          1.f / scaled_buffer_size.height());
-  }
-
-  gfx::Rect damage_rect;
-  gfx::Rect output_rect = gfx::Rect(contents_surface_size);
-  if (full_damage) {
-    damage_rect = output_rect;
-  } else {
-    // pending_damage_ is in Surface coordinates.
-    damage_rect = gfx::SkIRectToRect(pending_damage_.getBounds());
-    damage_rect.Intersect(output_rect);
-  }
-
-  const int kRenderPassId = 1;
-  std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
-  render_pass->SetNew(kRenderPassId, output_rect, damage_rect,
-                      gfx::Transform());
-
+void Surface::AppendContentsToFrame(const gfx::Point& origin,
+                                    FrameType frame_type,
+                                    cc::CompositorFrame* frame) {
+  const std::unique_ptr<cc::RenderPass>& render_pass =
+      frame->render_pass_list.back();
+  gfx::Rect output_rect = gfx::Rect(origin, content_size_);
   gfx::Rect quad_rect = output_rect;
+  gfx::Rect damage_rect;
+  switch (frame_type) {
+    case FRAME_TYPE_COMMIT:
+      // pending_damage_ is in Surface coordinates.
+      damage_rect = gfx::SkIRectToRect(pending_damage_.getBounds());
+      damage_rect.set_origin(origin);
+      damage_rect.Intersect(output_rect);
+      break;
+    case FRAME_TYPE_RECREATED_RESOURCES:
+      damage_rect = output_rect;
+      break;
+  }
+
+  render_pass->damage_rect.Union(damage_rect);
   cc::SharedQuadState* quad_state =
       render_pass->CreateAndAppendSharedQuadState();
-  quad_state->quad_layer_rect = gfx::Rect(contents_surface_size);
+  quad_state->quad_layer_rect = gfx::Rect(content_size_);
   quad_state->visible_quad_layer_rect = quad_rect;
   quad_state->opacity = state_.alpha;
 
-  cc::CompositorFrame frame;
-  // If we commit while we don't have an active BeginFrame, we acknowledge a
-  // manual one.
-  if (current_begin_frame_ack_.sequence_number ==
-      cc::BeginFrameArgs::kInvalidFrameNumber) {
-    current_begin_frame_ack_ = cc::BeginFrameAck::CreateManualAckWithDamage();
-  } else {
-    current_begin_frame_ack_.has_damage = true;
-  }
-  frame.metadata.begin_frame_ack = current_begin_frame_ack_;
-  frame.metadata.device_scale_factor = device_scale_factor_;
-
   if (current_resource_.id) {
+    gfx::PointF uv_top_left(0.f, 0.f);
+    gfx::PointF uv_bottom_right(1.f, 1.f);
+    if (!state_.crop.IsEmpty()) {
+      gfx::SizeF scaled_buffer_size(gfx::ScaleSize(
+          gfx::SizeF(current_resource_.size), 1.0f / state_.buffer_scale));
+      uv_top_left = state_.crop.origin();
+
+      uv_top_left.Scale(1.f / scaled_buffer_size.width(),
+                        1.f / scaled_buffer_size.height());
+      uv_bottom_right = state_.crop.bottom_right();
+      uv_bottom_right.Scale(1.f / scaled_buffer_size.width(),
+                            1.f / scaled_buffer_size.height());
+    }
     // Texture quad is only needed if buffer is not fully transparent.
     if (state_.alpha) {
       cc::TextureDrawQuad* texture_quad =
@@ -845,23 +696,46 @@
         opaque_rect = gfx::SkIRectToRect(state_.opaque_region.getBounds());
       }
 
-      texture_quad->SetNew(quad_state, quad_rect, opaque_rect, quad_rect,
-                           current_resource_.id, true, uv_top_left,
-                           uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity,
-                           false, false, state_.only_visible_on_secure_output);
+      texture_quad->SetNew(
+          quad_state, quad_rect, opaque_rect, quad_rect, current_resource_.id,
+          true /* premultiplied_alpha */, uv_top_left, uv_bottom_right,
+          SK_ColorTRANSPARENT /* background_color */, vertex_opacity,
+          false /* y_flipped */, false /* nearest_neighbor */,
+          state_.only_visible_on_secure_output);
       if (current_resource_.is_overlay_candidate)
         texture_quad->set_resource_size_in_pixels(current_resource_.size);
-      frame.resource_list.push_back(current_resource_);
+      frame->resource_list.push_back(current_resource_);
     }
   } else {
     cc::SolidColorDrawQuad* solid_quad =
         render_pass->CreateAndAppendDrawQuad<cc::SolidColorDrawQuad>();
-    solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK, false);
+    solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK,
+                       false /* force_anti_aliasing_off */);
   }
+}
 
-  frame.render_pass_list.push_back(std::move(render_pass));
-  layer_tree_frame_sink_holder_->frame_sink()->SubmitCompositorFrame(
-      std::move(frame));
+void Surface::UpdateContentSize() {
+  gfx::Size buffer_size = current_resource_.size;
+  gfx::SizeF scaled_buffer_size(
+      gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / state_.buffer_scale));
+  if (!state_.viewport.IsEmpty()) {
+    content_size_ = state_.viewport;
+  } else if (!state_.crop.IsEmpty()) {
+    DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) ||
+                         !gfx::IsExpressibleAsInt(state_.crop.height()))
+        << "Crop rectangle size (" << state_.crop.size().ToString()
+        << ") most be expressible using integers when viewport is not set";
+    content_size_ = gfx::ToCeiledSize(state_.crop.size());
+  } else {
+    content_size_ = gfx::ToCeiledSize(scaled_buffer_size);
+  }
+  window_->SetBounds(gfx::Rect(window_->bounds().origin(), content_size_));
+
+  // Enable/disable sub-surface based on if it has contents.
+  if (has_contents())
+    window_->Show();
+  else
+    window_->Hide();
 }
 
 }  // namespace exo
diff --git a/components/exo/surface.h b/components/exo/surface.h
index ae16873..5047d16 100644
--- a/components/exo/surface.h
+++ b/components/exo/surface.h
@@ -15,13 +15,10 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "cc/resources/transferable_resource.h"
-#include "cc/scheduler/begin_frame_source.h"
 #include "components/exo/layer_tree_frame_sink_holder.h"
 #include "third_party/skia/include/core/SkBlendMode.h"
 #include "third_party/skia/include/core/SkRegion.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
-#include "ui/compositor/compositor_vsync_manager.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
 
@@ -31,12 +28,17 @@
 }
 }
 
+namespace cc {
+class CompositorFrame;
+}
+
 namespace gfx {
 class Path;
 }
 
 namespace exo {
 class Buffer;
+class LayerTreeFrameSinkHolder;
 class Pointer;
 class SurfaceDelegate;
 class SurfaceObserver;
@@ -52,28 +54,18 @@
 
 // This class represents a rectangular area that is displayed on the screen.
 // It has a location, size and pixel contents.
-class Surface : public ui::ContextFactoryObserver,
-                public aura::WindowObserver,
-                public ui::PropertyHandler,
-                public ui::CompositorVSyncManager::Observer,
-                public cc::BeginFrameObserverBase {
+class Surface : public ui::PropertyHandler {
  public:
   using PropertyDeallocator = void (*)(int64_t value);
 
   Surface();
-  ~Surface() override;
+  ~Surface();
 
   // Type-checking downcast routine.
   static Surface* AsSurface(const aura::Window* window);
 
   aura::Window* window() { return window_.get(); }
 
-  viz::SurfaceId GetSurfaceId() const;
-
-  LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder() {
-    return layer_tree_frame_sink_holder_.get();
-  }
-
   // Set a buffer as the content of this surface. A buffer can only be attached
   // to one surface at a time.
   void Attach(Buffer* buffer);
@@ -144,7 +136,17 @@
   // This will synchronously commit all pending state of the surface and its
   // descendants by recursively calling CommitSurfaceHierarchy() for each
   // sub-surface with pending state.
-  void CommitSurfaceHierarchy();
+  enum FrameType {
+    FRAME_TYPE_COMMIT,
+    FRAME_TYPE_RECREATED_RESOURCES,
+  };
+  void CommitSurfaceHierarchy(
+      const gfx::Point& origin,
+      FrameType frame_type,
+      LayerTreeFrameSinkHolder* frame_sink_holder,
+      cc::CompositorFrame* frame,
+      std::list<FrameCallback>* frame_callbacks,
+      std::list<PresentationCallback>* presentation_callbacks);
 
   // Returns true if surface is in synchronized mode.
   bool IsSynchronized() const;
@@ -186,10 +188,6 @@
   // Returns a trace value representing the state of the surface.
   std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const;
 
-  // Call this to indicate that the previous CompositorFrame is processed and
-  // the surface is being scheduled for a draw.
-  void DidReceiveCompositorFrameAck();
-
   // Called when the begin frame source has changed.
   void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source);
 
@@ -202,26 +200,16 @@
   // Enables 'stylus-only' mode for the associated window.
   void SetStylusOnly();
 
-  // Overridden from ui::ContextFactoryObserver:
-  void OnLostResources() override;
+  // Recreates resources for the surface and sub surfaces.
+  void RecreateResources(LayerTreeFrameSinkHolder* frame_sink_holder);
 
-  // Overridden from aura::WindowObserver:
-  void OnWindowAddedToRootWindow(aura::Window* window) override;
-  void OnWindowRemovingFromRootWindow(aura::Window* window,
-                                      aura::Window* new_root) override;
-
-  // Overridden from ui::CompositorVSyncManager::Observer:
-  void OnUpdateVSyncParameters(base::TimeTicks timebase,
-                               base::TimeDelta interval) override;
+  // Returns true if the surface's bounds should be filled opaquely.
+  bool FillsBoundsOpaquely() const;
 
   bool HasPendingDamageForTesting(const gfx::Rect& damage) const {
     return pending_damage_.contains(gfx::RectToSkIRect(damage));
   }
 
-  // Overridden from cc::BeginFrameObserverBase:
-  bool OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) override;
-  void OnBeginFrameSourcePausedChanged(bool paused) override {}
-
  private:
   struct State {
     State();
@@ -269,14 +257,16 @@
   // contents of the attached buffer (or id 0, if no buffer is attached).
   // UpdateSurface must be called afterwards to ensure the release callback
   // will be called.
-  void UpdateResource(bool client_usage);
+  void UpdateResource(LayerTreeFrameSinkHolder* frame_sink_holder,
+                      bool client_usage);
 
-  // Updates the current Surface with a new frame referring to the resource in
-  // current_resource_.
-  void UpdateSurface(bool full_damage);
+  // Puts the current surface into a draw quad, and appends the draw quads into
+  // the |frame|.
+  void AppendContentsToFrame(const gfx::Point& origin,
+                             FrameType frame_type,
+                             cc::CompositorFrame* frame);
 
-  // Adds/Removes begin frame observer based on state.
-  void UpdateNeedsBeginFrame();
+  void UpdateContentSize();
 
   // This returns true when the surface has some contents assigned to it.
   bool has_contents() const { return !!current_buffer_.buffer(); }
@@ -284,10 +274,8 @@
   // This window has the layer which contains the Surface contents.
   std::unique_ptr<aura::Window> window_;
 
-  // This is true if it's possible that the layer properties (size, opacity,
-  // etc.) may have been modified since the last commit. Attaching a new
-  // buffer with the same size as the old shouldn't set this to true.
-  bool has_pending_layer_changes_ = true;
+  // This true, if sub_surfaces_ has changes (order, position, etc).
+  bool sub_surfaces_changed_ = false;
 
   // This is the size of the last committed contents.
   gfx::Size content_size_;
@@ -302,8 +290,6 @@
   // The device scale factor sent in CompositorFrames.
   float device_scale_factor_ = 1.0f;
 
-  std::unique_ptr<LayerTreeFrameSinkHolder> layer_tree_frame_sink_holder_;
-
   // The damage region to schedule paint for when Commit() is called.
   SkRegion pending_damage_;
 
@@ -313,8 +299,6 @@
   // |active_frame_callbacks_| when the effect of the Commit() is scheduled to
   // be drawn. They fire at the first begin frame notification after this.
   std::list<FrameCallback> pending_frame_callbacks_;
-  std::list<FrameCallback> frame_callbacks_;
-  std::list<FrameCallback> active_frame_callbacks_;
 
   // These lists contains the callbacks to notify the client when surface
   // contents have been presented. These callbacks move to
@@ -324,9 +308,6 @@
   // after receiving VSync parameters update for the previous frame. They fire
   // at the next VSync parameters update after that.
   std::list<PresentationCallback> pending_presentation_callbacks_;
-  std::list<PresentationCallback> presentation_callbacks_;
-  std::list<PresentationCallback> swapping_presentation_callbacks_;
-  std::list<PresentationCallback> swapped_presentation_callbacks_;
 
   // This is the state that has yet to be committed.
   State pending_state_;
@@ -340,6 +321,7 @@
   using SubSurfaceEntry = std::pair<Surface*, gfx::Point>;
   using SubSurfaceEntryList = std::list<SubSurfaceEntry>;
   SubSurfaceEntryList pending_sub_surfaces_;
+  SubSurfaceEntryList sub_surfaces_;
 
   // The buffer that is currently set as content of surface.
   BufferAttachment current_buffer_;
@@ -369,11 +351,6 @@
   // Surface observer list. Surface does not own the observers.
   base::ObserverList<SurfaceObserver, true> observers_;
 
-  // The begin frame source being observed.
-  cc::BeginFrameSource* begin_frame_source_ = nullptr;
-  bool needs_begin_frame_ = false;
-  cc::BeginFrameAck current_begin_frame_ack_;
-
   DISALLOW_COPY_AND_ASSIGN(Surface);
 };
 
diff --git a/components/exo/surface_tree_host.cc b/components/exo/surface_tree_host.cc
index 36442f58..24dff7f 100644
--- a/components/exo/surface_tree_host.cc
+++ b/components/exo/surface_tree_host.cc
@@ -8,7 +8,11 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "cc/output/compositor_frame.h"
+#include "cc/output/layer_tree_frame_sink.h"
+#include "components/exo/layer_tree_frame_sink_holder.h"
 #include "components/exo/surface.h"
+#include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -73,15 +77,20 @@
   host_window_ = base::MakeUnique<aura::Window>(window_delegate);
   host_window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
   host_window_->SetName(window_name);
-  host_window_->Init(ui::LAYER_NOT_DRAWN);
+  host_window_->Init(ui::LAYER_SOLID_COLOR);
   host_window_->set_owned_by_parent(false);
   host_window_->SetEventTargeter(base::MakeUnique<CustomWindowTargeter>(this));
+  layer_tree_frame_sink_holder_ = base::MakeUnique<LayerTreeFrameSinkHolder>(
+      this, host_window_->CreateLayerTreeFrameSink());
+  aura::Env::GetInstance()->context_factory()->AddObserver(this);
 }
 
 SurfaceTreeHost::~SurfaceTreeHost() {
-  if (root_surface_) {
-    root_surface_->window()->Hide();
-    root_surface_->SetSurfaceDelegate(nullptr);
+  aura::Env::GetInstance()->context_factory()->RemoveObserver(this);
+  SetRootSurface(nullptr);
+  if (host_window_->layer()->GetCompositor()) {
+    host_window_->layer()->GetCompositor()->vsync_manager()->RemoveObserver(
+        this);
   }
 }
 
@@ -96,6 +105,28 @@
         gfx::Rect(host_window_->bounds().origin(), gfx::Size()));
     root_surface_->SetSurfaceDelegate(nullptr);
     root_surface_ = nullptr;
+
+    active_frame_callbacks_.splice(active_frame_callbacks_.end(),
+                                   frame_callbacks_);
+    // Call all frame callbacks with a null frame time to indicate that they
+    // have been cancelled.
+    while (!active_frame_callbacks_.empty()) {
+      active_frame_callbacks_.front().Run(base::TimeTicks());
+      active_frame_callbacks_.pop_front();
+    }
+
+    swapping_presentation_callbacks_.splice(
+        swapping_presentation_callbacks_.end(), presentation_callbacks_);
+    swapped_presentation_callbacks_.splice(
+        swapped_presentation_callbacks_.end(),
+        swapping_presentation_callbacks_);
+    // Call all presentation callbacks with a null presentation time to indicate
+    // that they have been cancelled.
+    while (!swapped_presentation_callbacks_.empty()) {
+      swapped_presentation_callbacks_.front().Run(base::TimeTicks(),
+                                                  base::TimeDelta());
+      swapped_presentation_callbacks_.pop_front();
+    }
   }
 
   if (root_surface) {
@@ -125,14 +156,43 @@
   return root_surface_ ? root_surface_->GetCursor() : ui::CursorType::kNull;
 }
 
+void SurfaceTreeHost::DidReceiveCompositorFrameAck() {
+  active_frame_callbacks_.splice(active_frame_callbacks_.end(),
+                                 frame_callbacks_);
+  swapping_presentation_callbacks_.splice(
+      swapping_presentation_callbacks_.end(), presentation_callbacks_);
+  UpdateNeedsBeginFrame();
+}
+
+void SurfaceTreeHost::SetBeginFrameSource(
+    cc::BeginFrameSource* begin_frame_source) {
+  if (needs_begin_frame_) {
+    DCHECK(begin_frame_source_);
+    begin_frame_source_->RemoveObserver(this);
+    needs_begin_frame_ = false;
+  }
+  begin_frame_source_ = begin_frame_source;
+  UpdateNeedsBeginFrame();
+}
+
+void SurfaceTreeHost::UpdateNeedsBeginFrame() {
+  if (!begin_frame_source_)
+    return;
+  bool needs_begin_frame = !active_frame_callbacks_.empty();
+  if (needs_begin_frame == needs_begin_frame_)
+    return;
+  needs_begin_frame_ = needs_begin_frame;
+  if (needs_begin_frame_)
+    begin_frame_source_->AddObserver(this);
+  else
+    begin_frame_source_->RemoveObserver(this);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // SurfaceDelegate overrides:
 
 void SurfaceTreeHost::OnSurfaceCommit() {
-  DCHECK(root_surface_);
-  root_surface_->CommitSurfaceHierarchy();
-  host_window_->SetBounds(gfx::Rect(host_window_->bounds().origin(),
-                                    root_surface_->content_size()));
+  SubmitCompositorFrame(Surface::FRAME_TYPE_COMMIT);
 }
 
 bool SurfaceTreeHost::IsSurfaceSynchronized() const {
@@ -141,4 +201,111 @@
   return false;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// aura::WindowObserver overrides:
+
+void SurfaceTreeHost::OnWindowAddedToRootWindow(aura::Window* window) {
+  DCHECK_EQ(window, host_window());
+  window->layer()->GetCompositor()->vsync_manager()->AddObserver(this);
+}
+
+void SurfaceTreeHost::OnWindowRemovingFromRootWindow(aura::Window* window,
+                                                     aura::Window* new_root) {
+  DCHECK_EQ(window, host_window());
+  window->layer()->GetCompositor()->vsync_manager()->RemoveObserver(this);
+}
+
+void SurfaceTreeHost::OnWindowDestroying(aura::Window* window) {
+  DCHECK_EQ(window, host_window());
+  window->RemoveObserver(this);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// cc::BeginFrameObserverBase overrides:
+
+bool SurfaceTreeHost::OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) {
+  current_begin_frame_ack_ =
+      cc::BeginFrameAck(args.source_id, args.sequence_number, false);
+  while (!active_frame_callbacks_.empty()) {
+    active_frame_callbacks_.front().Run(args.frame_time);
+    active_frame_callbacks_.pop_front();
+  }
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ui::CompositorVSyncManager::Observer overrides:
+
+void SurfaceTreeHost::OnUpdateVSyncParameters(base::TimeTicks timebase,
+                                              base::TimeDelta interval) {
+  // Use current time if platform doesn't provide an accurate timebase.
+  if (timebase.is_null())
+    timebase = base::TimeTicks::Now();
+  while (!swapped_presentation_callbacks_.empty()) {
+    swapped_presentation_callbacks_.front().Run(timebase, interval);
+    swapped_presentation_callbacks_.pop_front();
+  }
+  // VSync parameters updates are generated at the start of a new swap. Move
+  // the swapping presentation callbacks to swapped callbacks so they fire
+  // at the next VSync parameters update as that will contain the presentation
+  // time for the previous frame.
+  swapped_presentation_callbacks_.splice(swapped_presentation_callbacks_.end(),
+                                         swapping_presentation_callbacks_);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ui::ContextFactoryObserver overrides:
+
+void SurfaceTreeHost::OnLostResources() {
+  if (!host_window_->GetSurfaceId().is_valid())
+    return;
+  root_surface_->RecreateResources(layer_tree_frame_sink_holder_.get());
+  SubmitCompositorFrame(Surface::FRAME_TYPE_RECREATED_RESOURCES);
+}
+
+void SurfaceTreeHost::SubmitCompositorFrame(Surface::FrameType frame_type) {
+  DCHECK(root_surface_);
+  cc::CompositorFrame frame;
+  // If we commit while we don't have an active BeginFrame, we acknowledge a
+  // manual one.
+  if (current_begin_frame_ack_.sequence_number ==
+      cc::BeginFrameArgs::kInvalidFrameNumber) {
+    current_begin_frame_ack_ = cc::BeginFrameAck::CreateManualAckWithDamage();
+  } else {
+    current_begin_frame_ack_.has_damage = true;
+  }
+
+  frame.metadata.begin_frame_ack = current_begin_frame_ack_;
+  frame.metadata.device_scale_factor =
+      host_window_->layer()->device_scale_factor();
+  const int kRenderPassId = 1;
+  std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
+  render_pass->SetNew(kRenderPassId, gfx::Rect(), gfx::Rect(),
+                      gfx::Transform());
+  frame.render_pass_list.push_back(std::move(render_pass));
+  root_surface_->CommitSurfaceHierarchy(
+      gfx::Point(), frame_type, layer_tree_frame_sink_holder_.get(), &frame,
+      &frame_callbacks_, &presentation_callbacks_);
+  frame.render_pass_list.back()->output_rect =
+      gfx::Rect(root_surface_->content_size());
+  layer_tree_frame_sink_holder_->frame_sink()->SubmitCompositorFrame(
+      std::move(frame));
+  host_window_->SetBounds(gfx::Rect(host_window_->bounds().origin(),
+                                    root_surface_->content_size()));
+  host_window_->layer()->SetFillsBoundsOpaquely(
+      root_surface_->FillsBoundsOpaquely());
+
+  if (current_begin_frame_ack_.sequence_number !=
+      cc::BeginFrameArgs::kInvalidFrameNumber) {
+    if (!current_begin_frame_ack_.has_damage) {
+      layer_tree_frame_sink_holder_->frame_sink()->DidNotProduceFrame(
+          current_begin_frame_ack_);
+    }
+    current_begin_frame_ack_.sequence_number =
+        cc::BeginFrameArgs::kInvalidFrameNumber;
+    if (begin_frame_source_)
+      begin_frame_source_->DidFinishFrame(this);
+  }
+}
+
 }  // namespace exo
diff --git a/components/exo/surface_tree_host.h b/components/exo/surface_tree_host.h
index c92a434..e102766a 100644
--- a/components/exo/surface_tree_host.h
+++ b/components/exo/surface_tree_host.h
@@ -8,8 +8,12 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "cc/scheduler/begin_frame_source.h"
+#include "components/exo/layer_tree_frame_sink_holder.h"
 #include "components/exo/surface.h"
 #include "components/exo/surface_delegate.h"
+#include "ui/aura/window_observer.h"
+#include "ui/compositor/compositor_vsync_manager.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace aura {
@@ -17,15 +21,24 @@
 class WindowDelegate;
 }  // namespace aura
 
+namespace cc {
+class BeginFrameSource;
+}  // namespace cc
+
 namespace gfx {
 class Path;
 }  // namespace gfx
 
 namespace exo {
+class LayerTreeFrameSinkHolder;
 
 // This class provides functionality for hosting a surface tree. The surface
 // tree is hosted in the |host_window_|.
-class SurfaceTreeHost : public SurfaceDelegate {
+class SurfaceTreeHost : public SurfaceDelegate,
+                        public aura::WindowObserver,
+                        public cc::BeginFrameObserverBase,
+                        public ui::CompositorVSyncManager::Observer,
+                        public ui::ContextFactoryObserver {
  public:
   SurfaceTreeHost(const std::string& window_name,
                   aura::WindowDelegate* window_delegate);
@@ -48,19 +61,77 @@
   // registered then CursorType::kNull is returned.
   gfx::NativeCursor GetCursor(const gfx::Point& point) const;
 
+  // Call this to indicate that the previous CompositorFrame is processed and
+  // the surface is being scheduled for a draw.
+  void DidReceiveCompositorFrameAck();
+
+  // Called when the begin frame source has changed.
+  void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source);
+
+  // Adds/Removes begin frame observer based on state.
+  void UpdateNeedsBeginFrame();
+
   aura::Window* host_window() { return host_window_.get(); }
   const aura::Window* host_window() const { return host_window_.get(); }
 
   Surface* root_surface() { return root_surface_; }
   const Surface* root_surface() const { return root_surface_; }
 
+  LayerTreeFrameSinkHolder* layer_tree_frame_sink_holder() {
+    return layer_tree_frame_sink_holder_.get();
+  }
+
   // Overridden from SurfaceDelegate:
   void OnSurfaceCommit() override;
   bool IsSurfaceSynchronized() const override;
 
+  // Overridden from aura::WindowObserver:
+  void OnWindowAddedToRootWindow(aura::Window* window) override;
+  void OnWindowRemovingFromRootWindow(aura::Window* window,
+                                      aura::Window* new_root) override;
+  void OnWindowDestroying(aura::Window* window) override;
+
+  // Overridden from cc::BeginFrameObserverBase:
+  bool OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) override;
+  void OnBeginFrameSourcePausedChanged(bool paused) override {}
+
+  // Overridden from ui::CompositorVSyncManager::Observer:
+  void OnUpdateVSyncParameters(base::TimeTicks timebase,
+                               base::TimeDelta interval) override;
+
+  // Overridden from ui::ContextFactoryObserver:
+  void OnLostResources() override;
+
  private:
+  void SubmitCompositorFrame(Surface::FrameType frame_type);
+
   Surface* root_surface_ = nullptr;
   std::unique_ptr<aura::Window> host_window_;
+  std::unique_ptr<LayerTreeFrameSinkHolder> layer_tree_frame_sink_holder_;
+
+  // The begin frame source being observed.
+  cc::BeginFrameSource* begin_frame_source_ = nullptr;
+  bool needs_begin_frame_ = false;
+  cc::BeginFrameAck current_begin_frame_ack_;
+
+  // These lists contain the callbacks to notify the client when it is a good
+  // time to start producing a new frame. These callbacks move to
+  // |frame_callbacks_| when Commit() is called. Later they are moved to
+  // |active_frame_callbacks_| when the effect of the Commit() is scheduled to
+  // be drawn. They fire at the first begin frame notification after this.
+  std::list<Surface::FrameCallback> frame_callbacks_;
+  std::list<Surface::FrameCallback> active_frame_callbacks_;
+
+  // These lists contains the callbacks to notify the client when surface
+  // contents have been presented. These callbacks move to
+  // |presentation_callbacks_| when Commit() is called. Later they are moved to
+  // |swapping_presentation_callbacks_| when the effect of the Commit() is
+  // scheduled to be drawn and then moved to |swapped_presentation_callbacks_|
+  // after receiving VSync parameters update for the previous frame. They fire
+  // at the next VSync parameters update after that.
+  std::list<Surface::PresentationCallback> presentation_callbacks_;
+  std::list<Surface::PresentationCallback> swapping_presentation_callbacks_;
+  std::list<Surface::PresentationCallback> swapped_presentation_callbacks_;
 
   DISALLOW_COPY_AND_ASSIGN(SurfaceTreeHost);
 };
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc
index d638abc..d8f7f63 100644
--- a/components/exo/surface_unittest.cc
+++ b/components/exo/surface_unittest.cc
@@ -9,11 +9,13 @@
 #include "cc/test/begin_frame_args_test.h"
 #include "cc/test/fake_external_begin_frame_source.h"
 #include "components/exo/buffer.h"
+#include "components/exo/shell_surface.h"
 #include "components/exo/surface.h"
 #include "components/exo/test/exo_test_base.h"
 #include "components/exo/test/exo_test_helper.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/khronos/GLES2/gl2.h"
 #include "ui/aura/env.h"
 #include "ui/compositor/layer_tree_owner.h"
 #include "ui/gfx/gpu_memory_buffer.h"
@@ -99,8 +101,8 @@
   EXPECT_TRUE(frame_time.is_null());
 }
 
-const cc::CompositorFrame& GetFrameFromSurface(Surface* surface) {
-  viz::SurfaceId surface_id = surface->GetSurfaceId();
+const cc::CompositorFrame& GetFrameFromSurface(ShellSurface* shell_surface) {
+  viz::SurfaceId surface_id = shell_surface->host_window()->GetSurfaceId();
   cc::SurfaceManager* surface_manager = aura::Env::GetInstance()
                                             ->context_factory_private()
                                             ->GetFrameSinkManager()
@@ -112,9 +114,10 @@
 
 TEST_F(SurfaceTest, SetOpaqueRegion) {
   gfx::Size buffer_size(1, 1);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface);
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  auto surface = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
 
   // Attaching a buffer with alpha channel.
   surface->Attach(buffer.get());
@@ -126,7 +129,7 @@
   RunAllPendingInMessageLoop();
 
   {
-    const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get());
+    const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
     ASSERT_EQ(1u, frame.render_pass_list.size());
     ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
     EXPECT_FALSE(frame.render_pass_list.back()
@@ -140,7 +143,7 @@
   RunAllPendingInMessageLoop();
 
   {
-    const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get());
+    const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
     ASSERT_EQ(1u, frame.render_pass_list.size());
     ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
     EXPECT_TRUE(frame.render_pass_list.back()
@@ -159,7 +162,7 @@
   RunAllPendingInMessageLoop();
 
   {
-    const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get());
+    const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
     ASSERT_EQ(1u, frame.render_pass_list.size());
     ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
     EXPECT_FALSE(frame.render_pass_list.back()
@@ -180,9 +183,10 @@
 
 TEST_F(SurfaceTest, SetBufferScale) {
   gfx::Size buffer_size(512, 512);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface);
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  auto surface = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
 
   // This will update the bounds of the surface and take the buffer scale into
   // account.
@@ -200,9 +204,10 @@
 
 TEST_F(SurfaceTest, MirrorLayers) {
   gfx::Size buffer_size(512, 512);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface);
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  auto surface = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
 
   surface->Attach(buffer.get());
   surface->Commit();
@@ -210,19 +215,20 @@
   EXPECT_EQ(buffer_size, surface->window()->bounds().size());
   EXPECT_EQ(buffer_size, surface->window()->layer()->bounds().size());
   std::unique_ptr<ui::LayerTreeOwner> old_layer_owner =
-      ::wm::MirrorLayers(surface->window(), false /* sync_bounds */);
+      ::wm::MirrorLayers(shell_surface->host_window(), false /* sync_bounds */);
   EXPECT_EQ(buffer_size, surface->window()->bounds().size());
   EXPECT_EQ(buffer_size, surface->window()->layer()->bounds().size());
   EXPECT_EQ(buffer_size, old_layer_owner->root()->bounds().size());
-  EXPECT_TRUE(surface->window()->layer()->has_external_content());
+  EXPECT_TRUE(shell_surface->host_window()->layer()->has_external_content());
   EXPECT_TRUE(old_layer_owner->root()->has_external_content());
 }
 
 TEST_F(SurfaceTest, SetViewport) {
   gfx::Size buffer_size(1, 1);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface);
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  auto surface = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
 
   // This will update the bounds of the surface and take the viewport into
   // account.
@@ -244,9 +250,10 @@
 
 TEST_F(SurfaceTest, SetCrop) {
   gfx::Size buffer_size(16, 16);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface);
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  auto surface = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
 
   surface->Attach(buffer.get());
   gfx::Size crop_size(12, 12);
@@ -259,16 +266,17 @@
 
 TEST_F(SurfaceTest, SetBlendMode) {
   gfx::Size buffer_size(1, 1);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface);
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  auto surface = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
 
   surface->Attach(buffer.get());
   surface->SetBlendMode(SkBlendMode::kSrc);
   surface->Commit();
   RunAllPendingInMessageLoop();
 
-  const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get());
+  const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
   ASSERT_EQ(1u, frame.render_pass_list.size());
   ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
   EXPECT_FALSE(frame.render_pass_list.back()
@@ -278,15 +286,17 @@
 
 TEST_F(SurfaceTest, OverlayCandidate) {
   gfx::Size buffer_size(1, 1);
-  std::unique_ptr<Buffer> buffer(new Buffer(
-      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), 0, 0, true, true));
-  std::unique_ptr<Surface> surface(new Surface);
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
+      true, true);
+  auto surface = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
 
   surface->Attach(buffer.get());
   surface->Commit();
   RunAllPendingInMessageLoop();
 
-  const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get());
+  const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
   ASSERT_EQ(1u, frame.render_pass_list.size());
   ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
   cc::DrawQuad* draw_quad = frame.render_pass_list.back()->quad_list.back();
@@ -299,9 +309,11 @@
 
 TEST_F(SurfaceTest, SetAlpha) {
   gfx::Size buffer_size(1, 1);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface);
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
+      true, true);
+  auto surface = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
 
   surface->Attach(buffer.get());
   surface->SetAlpha(0.5f);
@@ -318,10 +330,12 @@
 TEST_F(SurfaceTest, SendsBeginFrameAcks) {
   cc::FakeExternalBeginFrameSource source(0.f, false);
   gfx::Size buffer_size(1, 1);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface);
-  surface->SetBeginFrameSource(&source);
+  auto buffer = base::MakeUnique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
+      true, true);
+  auto surface = base::MakeUnique<Surface>();
+  auto shell_surface = base::MakeUnique<ShellSurface>(surface.get());
+  shell_surface->SetBeginFrameSource(&source);
   surface->Attach(buffer.get());
 
   // Request a frame callback so that Surface now needs BeginFrames.
@@ -333,7 +347,7 @@
 
   // Surface should add itself as observer during
   // DidReceiveCompositorFrameAck().
-  surface->DidReceiveCompositorFrameAck();
+  shell_surface->DidReceiveCompositorFrameAck();
   EXPECT_EQ(1u, source.num_observers());
 
   cc::BeginFrameArgs args(source.CreateBeginFrameArgs(BEGINFRAME_FROM_HERE));
@@ -344,7 +358,7 @@
   surface->Commit();  // Acknowledges the BeginFrame via CompositorFrame.
   RunAllPendingInMessageLoop();
 
-  const cc::CompositorFrame& frame = GetFrameFromSurface(surface.get());
+  const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
   cc::BeginFrameAck expected_ack(args.source_id, args.sequence_number, true);
   EXPECT_EQ(expected_ack, frame.metadata.begin_frame_ack);
 
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h
index f0c0fac..1405106 100644
--- a/components/infobars/core/infobar_delegate.h
+++ b/components/infobars/core/infobar_delegate.h
@@ -122,9 +122,9 @@
     AUTOFILL_CC_INFOBAR_DELEGATE = 49,
     TRANSLATE_INFOBAR_DELEGATE = 50,
     IOS_CHROME_SAVE_PASSWORD_INFOBAR_DELEGATE = 51,
-    NATIVE_APP_INSTALLER_INFOBAR_DELEGATE = 52,
-    NATIVE_APP_LAUNCHER_INFOBAR_DELEGATE = 53,
-    NATIVE_APP_OPEN_POLICY_INFOBAR_DELEGATE = 54,
+    // Removed: NATIVE_APP_INSTALLER_INFOBAR_DELEGATE = 52,
+    // Removed: NATIVE_APP_LAUNCHER_INFOBAR_DELEGATE = 53,
+    // Removed: NATIVE_APP_OPEN_POLICY_INFOBAR_DELEGATE = 54,
     RE_SIGN_IN_INFOBAR_DELEGATE = 55,
     SHOW_PASSKIT_INFOBAR_ERROR_DELEGATE = 56,
     READER_MODE_INFOBAR_DELEGATE_IOS = 57,
diff --git a/components/neterror/resources/neterror.css b/components/neterror/resources/neterror.css
index 7ead318..c7cd42e 100644
--- a/components/neterror/resources/neterror.css
+++ b/components/neterror/resources/neterror.css
@@ -531,7 +531,6 @@
   left: 0;
   margin: auto;
   right: 0;
-  top: 0;
   transform-origin: top center;
   transition: transform 250ms cubic-bezier(0.4, 0.0, 1, 1) .4s;
   z-index: 2;
diff --git a/components/neterror/resources/offline.js b/components/neterror/resources/offline.js
index e89c25d..f7235b3 100644
--- a/components/neterror/resources/offline.js
+++ b/components/neterror/resources/offline.js
@@ -125,6 +125,7 @@
   RESOURCE_TEMPLATE_ID: 'audio-resources',
   SPEED: 6,
   SPEED_DROP_COEFFICIENT: 3,
+  ARCADE_MODE_INITIAL_TOP_POSITION: 35,
   ARCADE_MODE_TOP_POSITION_PERCENT: 0.1
 };
 
@@ -865,7 +866,8 @@
     var scaledCanvasHeight = this.dimensions.HEIGHT * scale;
     // Positions the game container at 10% of the available vertical window
     // height minus the game container height.
-    var translateY = Math.max(0, (windowHeight - scaledCanvasHeight) *
+    var translateY = Math.max(0, (windowHeight - scaledCanvasHeight -
+        Runner.config.ARCADE_MODE_INITIAL_TOP_POSITION) *
         Runner.config.ARCADE_MODE_TOP_POSITION_PERCENT);
     this.containerEl.style.transform = 'scale(' + scale + ') translateY(' +
         translateY + 'px)';
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder.cc b/components/password_manager/core/browser/password_form_metrics_recorder.cc
index 497b5fa..fc0bfed 100644
--- a/components/password_manager/core/browser/password_form_metrics_recorder.cc
+++ b/components/password_manager/core/browser/password_form_metrics_recorder.cc
@@ -237,6 +237,9 @@
       GetHistogramSampleForSuppressedAccounts(best_match),
       kMaxSuppressedAccountStats);
   RecordUkmMetric("SuppressedAccount.Manual.SameOrganizationName", best_match);
+
+  if (current_bubble_ != CurrentBubbleOfInterest::kNone)
+    RecordUIDismissalReason(metrics_util::NO_DIRECT_INTERACTION);
 }
 
 void PasswordFormMetricsRecorder::RecordPasswordBubbleShown(
@@ -244,6 +247,7 @@
     metrics_util::UIDisplayDisposition display_disposition) {
   if (credential_source_type == metrics_util::CredentialSourceType::kUnknown)
     return;
+  DCHECK_EQ(CurrentBubbleOfInterest::kNone, current_bubble_);
   BubbleTrigger automatic_trigger_type =
       credential_source_type ==
               metrics_util::CredentialSourceType::kPasswordManager
@@ -258,11 +262,13 @@
   switch (display_disposition) {
     // New credential cases:
     case metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING:
+      current_bubble_ = CurrentBubbleOfInterest::kSaveBubble;
       save_prompt_shown_ = true;
       RecordUkmMetric(kUkmSavingPromptTrigger,
                       static_cast<int64_t>(automatic_trigger_type));
       break;
     case metrics_util::MANUAL_WITH_PASSWORD_PENDING:
+      current_bubble_ = CurrentBubbleOfInterest::kSaveBubble;
       save_prompt_shown_ = true;
       RecordUkmMetric(kUkmSavingPromptTrigger,
                       static_cast<int64_t>(manual_trigger_type));
@@ -270,11 +276,13 @@
 
     // Update cases:
     case metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING_UPDATE:
+      current_bubble_ = CurrentBubbleOfInterest::kUpdateBubble;
       update_prompt_shown_ = true;
       RecordUkmMetric(kUkmUpdatingPromptTrigger,
                       static_cast<int64_t>(automatic_trigger_type));
       break;
     case metrics_util::MANUAL_WITH_PASSWORD_PENDING_UPDATE:
+      current_bubble_ = CurrentBubbleOfInterest::kUpdateBubble;
       update_prompt_shown_ = true;
       RecordUkmMetric(kUkmUpdatingPromptTrigger,
                       static_cast<int64_t>(manual_trigger_type));
@@ -298,11 +306,12 @@
 
 void PasswordFormMetricsRecorder::RecordUIDismissalReason(
     metrics_util::UIDismissalReason ui_dismissal_reason) {
-  DCHECK(!(update_prompt_shown_ && save_prompt_shown_));
-  if (!(update_prompt_shown_ || save_prompt_shown_))
+  if (current_bubble_ != CurrentBubbleOfInterest::kUpdateBubble &&
+      current_bubble_ != CurrentBubbleOfInterest::kSaveBubble)
     return;
-  const char* metric = update_prompt_shown_ ? kUkmUpdatingPromptInteraction
-                                            : kUkmSavingPromptInteraction;
+  const char* metric = current_bubble_ == CurrentBubbleOfInterest::kUpdateBubble
+                           ? kUkmUpdatingPromptInteraction
+                           : kUkmSavingPromptInteraction;
   switch (ui_dismissal_reason) {
     // Accepted by user.
     case metrics_util::CLICKED_SAVE:
@@ -340,6 +349,8 @@
       NOTREACHED();
       break;
   }
+
+  current_bubble_ = CurrentBubbleOfInterest::kNone;
 }
 
 void PasswordFormMetricsRecorder::RecordFillEvent(ManagerAutofillEvent event) {
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder.h b/components/password_manager/core/browser/password_form_metrics_recorder.h
index 9ea261a..00af1e6 100644
--- a/components/password_manager/core/browser/password_form_metrics_recorder.h
+++ b/components/password_manager/core/browser/password_form_metrics_recorder.h
@@ -265,6 +265,17 @@
  private:
   friend class base::RefCounted<PasswordFormMetricsRecorder>;
 
+  // Enum to track which password bubble is currently being displayed.
+  enum class CurrentBubbleOfInterest {
+    // This covers the cases that no password bubble is currently being
+    // displayed or the one displayed is none of the interesting cases.
+    kNone,
+    // The user is currently seeing a password save bubble.
+    kSaveBubble,
+    // The user is currently seeing a password update bubble.
+    kUpdateBubble,
+  };
+
   // Destructor reports a couple of UMA metrics as well as calls
   // RecordUkmMetric.
   ~PasswordFormMetricsRecorder();
@@ -309,6 +320,9 @@
   // Whether this form has an auto generated password.
   bool has_generated_password_ = false;
 
+  // Tracks which bubble is currently being displayed to the user.
+  CurrentBubbleOfInterest current_bubble_ = CurrentBubbleOfInterest::kNone;
+
   // Whether the user was shown a prompt to update a password.
   bool update_prompt_shown_ = false;
 
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc b/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
index 93f982c..6fdcd6b 100644
--- a/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
+++ b/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
@@ -522,4 +522,47 @@
   }
 }
 
+// Verify that it is ok to open and close the password bubble more than once
+// and still get accurate metrics.
+TEST(PasswordFormMetricsRecorder, SequencesOfBubbles) {
+  using BubbleDismissalReason =
+      PasswordFormMetricsRecorder::BubbleDismissalReason;
+  using BubbleTrigger = PasswordFormMetricsRecorder::BubbleTrigger;
+  ukm::TestUkmRecorder test_ukm_recorder;
+  {
+    auto recorder = base::MakeRefCounted<PasswordFormMetricsRecorder>(
+        true /*is_main_frame_secure*/,
+        CreateUkmEntryBuilder(&test_ukm_recorder));
+    // Open and confirm an automatically triggered saving prompt.
+    recorder->RecordPasswordBubbleShown(
+        metrics_util::CredentialSourceType::kPasswordManager,
+        metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING);
+    recorder->RecordUIDismissalReason(metrics_util::CLICKED_SAVE);
+    // Open and confirm a manually triggered update prompt.
+    recorder->RecordPasswordBubbleShown(
+        metrics_util::CredentialSourceType::kPasswordManager,
+        metrics_util::MANUAL_WITH_PASSWORD_PENDING_UPDATE);
+    recorder->RecordUIDismissalReason(metrics_util::CLICKED_SAVE);
+  }
+  // Verify recorded UKM data.
+  const ukm::UkmSource* source = test_ukm_recorder.GetSourceForUrl(kTestUrl);
+  ASSERT_TRUE(source);
+  test_ukm_recorder.ExpectMetric(
+      *source, "PasswordForm", kUkmSavingPromptInteraction,
+      static_cast<int64_t>(BubbleDismissalReason::kAccepted));
+  test_ukm_recorder.ExpectMetric(
+      *source, "PasswordForm", kUkmUpdatingPromptInteraction,
+      static_cast<int64_t>(BubbleDismissalReason::kAccepted));
+  test_ukm_recorder.ExpectMetric(*source, "PasswordForm",
+                                 kUkmUpdatingPromptShown, 1);
+  test_ukm_recorder.ExpectMetric(*source, "PasswordForm", kUkmSavingPromptShown,
+                                 1);
+  test_ukm_recorder.ExpectMetric(
+      *source, "PasswordForm", kUkmSavingPromptTrigger,
+      static_cast<int64_t>(BubbleTrigger::kPasswordManagerSuggestionAutomatic));
+  test_ukm_recorder.ExpectMetric(
+      *source, "PasswordForm", kUkmUpdatingPromptTrigger,
+      static_cast<int64_t>(BubbleTrigger::kPasswordManagerSuggestionManual));
+}
+
 }  // namespace password_manager
diff --git a/components/safe_browsing/base_blocking_page.cc b/components/safe_browsing/base_blocking_page.cc
index efecb26..6c16975 100644
--- a/components/safe_browsing/base_blocking_page.cc
+++ b/components/safe_browsing/base_blocking_page.cc
@@ -104,7 +104,8 @@
     BaseBlockingPage* blocking_page = new BaseBlockingPage(
         ui_manager, web_contents, entry ? entry->GetURL() : GURL(),
         unsafe_resources,
-        CreateControllerClient(web_contents, unsafe_resources, ui_manager),
+        CreateControllerClient(web_contents, unsafe_resources, ui_manager,
+                               nullptr),
         CreateDefaultDisplayOptions(unsafe_resources));
     blocking_page->Show();
   }
@@ -339,7 +340,8 @@
 BaseBlockingPage::CreateControllerClient(
     content::WebContents* web_contents,
     const UnsafeResourceList& unsafe_resources,
-    BaseUIManager* ui_manager) {
+    BaseUIManager* ui_manager,
+    PrefService* pref_service) {
   history::HistoryService* history_service =
       ui_manager->history_service(web_contents);
 
@@ -349,7 +351,7 @@
           history_service);
 
   return base::MakeUnique<SecurityInterstitialControllerClient>(
-      web_contents, std::move(metrics_helper), nullptr, /* prefs */
+      web_contents, std::move(metrics_helper), pref_service,
       ui_manager->app_locale(), ui_manager->default_safe_page());
 }
 
diff --git a/components/safe_browsing/base_blocking_page.h b/components/safe_browsing/base_blocking_page.h
index 1757d2e..837498b9 100644
--- a/components/safe_browsing/base_blocking_page.h
+++ b/components/safe_browsing/base_blocking_page.h
@@ -119,7 +119,8 @@
       security_interstitials::SecurityInterstitialControllerClient>
   CreateControllerClient(content::WebContents* web_contents,
                          const UnsafeResourceList& unsafe_resources,
-                         BaseUIManager* ui_manager);
+                         BaseUIManager* ui_manager,
+                         PrefService* pref_service);
 
   int GetHTMLTemplateId() override;
 
diff --git a/components/security_interstitials/core/controller_client.cc b/components/security_interstitials/core/controller_client.cc
index b1ab274..e146d72 100644
--- a/components/security_interstitials/core/controller_client.cc
+++ b/components/security_interstitials/core/controller_client.cc
@@ -35,6 +35,7 @@
 }
 
 void ControllerClient::SetReportingPreference(bool report) {
+  DCHECK(GetPrefService());
   GetPrefService()->SetBoolean(GetExtendedReportingPrefName(), report);
   metrics_helper_->RecordUserInteraction(
       report ? MetricsHelper::SET_EXTENDED_REPORTING_ENABLED
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn
index 3fb8f8d1..7e2458ad 100644
--- a/components/variations/BUILD.gn
+++ b/components/variations/BUILD.gn
@@ -111,6 +111,7 @@
   ]
 
   deps = [
+    "field_trial_config:field_trial_config",
     "//base/test:test_support",
   ]
 }
diff --git a/components/variations/field_trial_config/field_trial_util.cc b/components/variations/field_trial_config/field_trial_util.cc
index b77180dab..761ba237 100644
--- a/components/variations/field_trial_config/field_trial_util.cc
+++ b/components/variations/field_trial_config/field_trial_util.cc
@@ -21,7 +21,7 @@
 namespace variations {
 namespace {
 
-std::string EscapeValue(const std::string& value) {
+std::string UnescapeValue(const std::string& value) {
   return net::UnescapeURLComponent(
       value, net::UnescapeRule::PATH_SEPARATORS |
                  net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
@@ -83,6 +83,12 @@
 
 } // namespace
 
+std::string EscapeValue(const std::string& value) {
+  // This needs to be the inverse of UnescapeValue in the anonymous namespace
+  // above.
+  return net::EscapeQueryParamValue(value, true /* use_plus */);
+}
+
 bool AssociateParamsFromString(const std::string& varations_string) {
   // Format: Trial1.Group1:k1/v1/k2/v2,Trial2.Group2:k1/v1/k2/v2
   std::set<std::pair<std::string, std::string>> trial_groups;
@@ -109,8 +115,8 @@
       DLOG(ERROR) << "Param name and param value should be separated by '/'";
       return false;
     }
-    std::string trial = EscapeValue(group_parts[0]);
-    std::string group = EscapeValue(group_parts[1]);
+    std::string trial = UnescapeValue(group_parts[0]);
+    std::string group = UnescapeValue(group_parts[1]);
     auto trial_group = std::make_pair(trial, group);
     if (trial_groups.find(trial_group) != trial_groups.end()) {
       DLOG(ERROR) << base::StringPrintf(
@@ -121,8 +127,8 @@
     trial_groups.insert(trial_group);
     std::map<std::string, std::string> params;
     for (size_t i = 0; i < key_values.size(); i += 2) {
-      std::string key = EscapeValue(key_values[i]);
-      std::string value = EscapeValue(key_values[i + 1]);
+      std::string key = UnescapeValue(key_values[i]);
+      std::string value = UnescapeValue(key_values[i + 1]);
       params[key] = value;
     }
     AssociateVariationParams(trial, group, params);
diff --git a/components/variations/field_trial_config/field_trial_util.h b/components/variations/field_trial_config/field_trial_util.h
index e9487c4e..8bb44eded 100644
--- a/components/variations/field_trial_config/field_trial_util.h
+++ b/components/variations/field_trial_config/field_trial_util.h
@@ -15,6 +15,10 @@
 
 struct FieldTrialTestingConfig;
 
+// Escapes the trial name, or parameter name, or parameter value in a way that
+// makes it usable within variations::switches::kForceFieldTrialParams.
+std::string EscapeValue(const std::string& value);
+
 // Provides a mechanism to associate multiple set of params to multiple groups
 // with a formatted string specified from commandline. See
 // kForceFieldTrialParams in components/variations/variations_switches.cc for
diff --git a/components/variations/variations_params_manager.cc b/components/variations/variations_params_manager.cc
index 27204b0c..be71186 100644
--- a/components/variations/variations_params_manager.cc
+++ b/components/variations/variations_params_manager.cc
@@ -6,11 +6,14 @@
 
 #include <utility>
 
+#include "base/base_switches.h"
 #include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/test/scoped_feature_list.h"
+#include "components/variations/field_trial_config/field_trial_util.h"
 #include "components/variations/variations_associated_data.h"
+#include "components/variations/variations_switches.h"
 
 namespace variations {
 namespace testing {
@@ -91,5 +94,35 @@
   field_trial_list_ = base::MakeUnique<base::FieldTrialList>(nullptr);
 }
 
+// static
+void VariationParamsManager::AppendVariationParams(
+    const std::string& trial_name,
+    const std::string& trial_group_name,
+    const std::map<std::string, std::string>& param_values,
+    base::CommandLine* command_line) {
+  // Register the trial group.
+  command_line->AppendSwitchASCII(
+      ::switches::kForceFieldTrials,
+      EscapeValue(trial_name) + "/" + EscapeValue(trial_group_name));
+
+  // Associate |param_values| with the trial group.
+  std::string params_arg =
+      EscapeValue(trial_name) + "." + EscapeValue(trial_group_name) + ":";
+  bool first = true;
+  for (const auto& param : param_values) {
+    // Separate each |param|.
+    if (!first)
+      params_arg += "/";
+    first = false;
+
+    // Append each |param|.
+    const std::string& name = param.first;
+    const std::string& value = param.second;
+    params_arg += EscapeValue(name) + "/" + EscapeValue(value);
+  }
+  command_line->AppendSwitchASCII(variations::switches::kForceFieldTrialParams,
+                                  params_arg);
+}
+
 }  // namespace testing
 }  // namespace variations
diff --git a/components/variations/variations_params_manager.h b/components/variations/variations_params_manager.h
index 6a65e18..2c61c52 100644
--- a/components/variations/variations_params_manager.h
+++ b/components/variations/variations_params_manager.h
@@ -14,6 +14,7 @@
 #include "base/metrics/field_trial.h"
 
 namespace base {
+class CommandLine;
 class FieldTrialList;
 
 namespace test {
@@ -70,6 +71,19 @@
   // Clears all of the associated params.
   void ClearAllVariationParams();
 
+  // Appends command line switches to |command_line| in a way that mimics
+  // SetVariationParams.
+  //
+  // This static method is useful in situations where using
+  // VariationParamsManager directly would have resulted in initializing
+  // FieldTrialList twice (once from ChromeBrowserMainParts::SetupFieldTrials
+  // and once from VariationParamsManager).
+  static void AppendVariationParams(
+      const std::string& trial_name,
+      const std::string& trial_group_name,
+      const std::map<std::string, std::string>& param_values,
+      base::CommandLine* command_line);
+
  private:
   std::unique_ptr<base::FieldTrialList> field_trial_list_;
   std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 8a9cd856..a0f0dc8 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -67,6 +67,7 @@
     "gl_helper_unittest.cc",
     "resources/buffer_to_texture_target_map_unittest.cc",
     "resources/platform_color_unittest.cc",
+    "surfaces/surface_sequence_generator_unittest.cc",
     "yuv_readback_unittest.cc",
   ]
 
diff --git a/cc/surfaces/surface_sequence_generator_unittest.cc b/components/viz/common/surfaces/surface_sequence_generator_unittest.cc
similarity index 64%
rename from cc/surfaces/surface_sequence_generator_unittest.cc
rename to components/viz/common/surfaces/surface_sequence_generator_unittest.cc
index 828a38a76..5d1913cc 100644
--- a/cc/surfaces/surface_sequence_generator_unittest.cc
+++ b/components/viz/common/surfaces/surface_sequence_generator_unittest.cc
@@ -7,18 +7,18 @@
 #include "components/viz/common/surfaces/surface_sequence.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace cc {
+namespace viz {
 namespace {
 
-static constexpr viz::FrameSinkId kArbitraryFrameSinkId(1, 1);
+static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
 
 TEST(SurfaceSequenceGeneratorTest, Basic) {
-  viz::SurfaceSequenceGenerator generator;
+  SurfaceSequenceGenerator generator;
   generator.set_frame_sink_id(kArbitraryFrameSinkId);
-  viz::SurfaceSequence sequence1 = generator.CreateSurfaceSequence();
-  viz::SurfaceSequence sequence2 = generator.CreateSurfaceSequence();
+  SurfaceSequence sequence1 = generator.CreateSurfaceSequence();
+  SurfaceSequence sequence2 = generator.CreateSurfaceSequence();
   EXPECT_NE(sequence1, sequence2);
 }
 
 }  // namespace
-}  // namespace cc
+}  // namespace viz
diff --git a/components/viz/host/BUILD.gn b/components/viz/host/BUILD.gn
index 7995512..e5d833e 100644
--- a/components/viz/host/BUILD.gn
+++ b/components/viz/host/BUILD.gn
@@ -23,6 +23,10 @@
     "//gpu/ipc/client",
     "//gpu/ipc/common",
     "//services/ui/gpu/interfaces",
+
+    # TODO(kylechar): This is temporary and will be removed when all host to
+    # service communication is over Mojo.
+    "//components/viz/service",
   ]
 
   public_deps = [
@@ -50,5 +54,9 @@
     "//services/ui/gpu/interfaces",
     "//testing/gmock",
     "//testing/gtest",
+
+    # TODO(kylechar): This is temporary and will be removed when all host to
+    # service communication is over Mojo.
+    "//components/viz/service",
   ]
 }
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc
index 6b4e26b..d6af712 100644
--- a/components/viz/host/host_frame_sink_manager.cc
+++ b/components/viz/host/host_frame_sink_manager.cc
@@ -7,22 +7,38 @@
 #include <utility>
 
 #include "base/sequenced_task_runner.h"
-#include "cc/surfaces/surface_manager.h"
 #include "components/viz/common/surfaces/surface_info.h"
+#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
+#include "components/viz/service/frame_sinks/compositor_frame_sink_support_client.h"
+#include "components/viz/service/frame_sinks/frame_sink_manager.h"
+#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 
 namespace viz {
 
-HostFrameSinkManager::HostFrameSinkManager() : binding_(this) {}
+HostFrameSinkManager::HostFrameSinkManager()
+    : binding_(this), weak_ptr_factory_(this) {}
 
 HostFrameSinkManager::~HostFrameSinkManager() = default;
 
+void HostFrameSinkManager::SetLocalManager(
+    FrameSinkManagerImpl* frame_sink_manager_impl) {
+  DCHECK(!frame_sink_manager_ptr_);
+  frame_sink_manager_impl_ = frame_sink_manager_impl;
+
+  frame_sink_manager_ = frame_sink_manager_impl;
+}
+
 void HostFrameSinkManager::BindAndSetManager(
     cc::mojom::FrameSinkManagerClientRequest request,
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     cc::mojom::FrameSinkManagerPtr ptr) {
+  DCHECK(!frame_sink_manager_impl_);
   DCHECK(!binding_.is_bound());
+
   binding_.Bind(std::move(request), std::move(task_runner));
   frame_sink_manager_ptr_ = std::move(ptr);
+
+  frame_sink_manager_ = frame_sink_manager_ptr_.get();
 }
 
 void HostFrameSinkManager::AddObserver(FrameSinkObserver* observer) {
@@ -40,8 +56,9 @@
   DCHECK_EQ(frame_sink_data_map_.count(frame_sink_id), 0u);
 
   FrameSinkData& data = frame_sink_data_map_[frame_sink_id];
+  data.is_root = false;
 
-  frame_sink_manager_ptr_->CreateCompositorFrameSink(
+  frame_sink_manager_->CreateCompositorFrameSink(
       frame_sink_id, std::move(request),
       mojo::MakeRequest(&data.private_interface), std::move(client));
 }
@@ -62,9 +79,12 @@
 void HostFrameSinkManager::RegisterFrameSinkHierarchy(
     const FrameSinkId& parent_frame_sink_id,
     const FrameSinkId& child_frame_sink_id) {
-  // Register and store the parent.
-  frame_sink_manager_ptr_->RegisterFrameSinkHierarchy(parent_frame_sink_id,
-                                                      child_frame_sink_id);
+  DCHECK_EQ(frame_sink_data_map_.count(child_frame_sink_id), 1u);
+
+  // Register and store the parent, either directly or over Mojo.
+  frame_sink_manager_->RegisterFrameSinkHierarchy(parent_frame_sink_id,
+                                                  child_frame_sink_id);
+
   frame_sink_data_map_[child_frame_sink_id].parent = parent_frame_sink_id;
 }
 
@@ -77,15 +97,35 @@
   FrameSinkData& data = iter->second;
   DCHECK_EQ(data.parent.value(), parent_frame_sink_id);
 
-  // Unregister and clear the stored parent.
-  frame_sink_manager_ptr_->UnregisterFrameSinkHierarchy(parent_frame_sink_id,
-                                                        child_frame_sink_id);
-  data.parent.reset();
+  // Unregister and clear the stored parent, either directly or over Mojo.
+  frame_sink_manager_->UnregisterFrameSinkHierarchy(parent_frame_sink_id,
+                                                    child_frame_sink_id);
 
-  // If the client never called CreateCompositorFrameSink() then they won't
-  // call DestroyCompositorFrameSink() either, so cleanup map entry here.
-  if (!data.private_interface.is_bound())
-    frame_sink_data_map_.erase(iter);
+  data.parent.reset();
+}
+
+std::unique_ptr<CompositorFrameSinkSupport>
+HostFrameSinkManager::CreateCompositorFrameSinkSupport(
+    CompositorFrameSinkSupportClient* client,
+    const FrameSinkId& frame_sink_id,
+    bool is_root,
+    bool handles_frame_sink_id_invalidation,
+    bool needs_sync_points) {
+  DCHECK(frame_sink_manager_impl_);
+  DCHECK_EQ(frame_sink_data_map_.count(frame_sink_id), 0u);
+
+  auto support = CompositorFrameSinkSupport::Create(
+      client, frame_sink_manager_impl_->frame_sink_manager(), frame_sink_id,
+      is_root, handles_frame_sink_id_invalidation, needs_sync_points);
+  support->SetDestructionCallback(
+      base::BindOnce(&HostFrameSinkManager::DestroyCompositorFrameSink,
+                     weak_ptr_factory_.GetWeakPtr(), frame_sink_id));
+
+  FrameSinkData& data = frame_sink_data_map_[frame_sink_id];
+  data.support = support.get();
+  data.is_root = is_root;
+
+  return support;
 }
 
 void HostFrameSinkManager::OnSurfaceCreated(const SurfaceInfo& surface_info) {
diff --git a/components/viz/host/host_frame_sink_manager.h b/components/viz/host/host_frame_sink_manager.h
index ce09d0b5..db76c340 100644
--- a/components/viz/host/host_frame_sink_manager.h
+++ b/components/viz/host/host_frame_sink_manager.h
@@ -9,12 +9,14 @@
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/optional.h"
 #include "cc/ipc/frame_sink_manager.mojom.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/host/frame_sink_observer.h"
 #include "components/viz/host/viz_host_export.h"
+#include "components/viz/service/frame_sinks/compositor_frame_sink_support_manager.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace base {
@@ -23,19 +25,30 @@
 
 namespace cc {
 class SurfaceInfo;
-class SurfaceManager;
 }  // namespace cc
 
 namespace viz {
 
+class CompositorFrameSinkSupport;
+class CompositorFrameSinkSupportClient;
+class FrameSinkManagerImpl;
+
+namespace test {
+class HostFrameSinkManagerTest;
+}
+
 // Browser side wrapper of mojom::FrameSinkManager, to be used from the
 // UI thread. Manages frame sinks and is intended to replace SurfaceManager.
 class VIZ_HOST_EXPORT HostFrameSinkManager
-    : NON_EXPORTED_BASE(cc::mojom::FrameSinkManagerClient) {
+    : public NON_EXPORTED_BASE(cc::mojom::FrameSinkManagerClient),
+      public NON_EXPORTED_BASE(CompositorFrameSinkSupportManager) {
  public:
   HostFrameSinkManager();
   ~HostFrameSinkManager() override;
 
+  // Sets a local FrameSinkManagerImpl instance and connects directly to it.
+  void SetLocalManager(FrameSinkManagerImpl* frame_sink_manager_impl);
+
   // Binds |this| as a FrameSinkManagerClient for |request| on |task_runner|. On
   // Mac |task_runner| will be the resize helper task runner. May only be called
   // once.
@@ -70,21 +83,38 @@
   void UnregisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id,
                                     const FrameSinkId& child_frame_sink_id);
 
+  // CompositorFrameSinkSupportManager:
+  std::unique_ptr<CompositorFrameSinkSupport> CreateCompositorFrameSinkSupport(
+      CompositorFrameSinkSupportClient* client,
+      const FrameSinkId& frame_sink_id,
+      bool is_root,
+      bool handles_frame_sink_id_invalidation,
+      bool needs_sync_points) override;
+
  private:
+  friend class test::HostFrameSinkManagerTest;
+
   struct FrameSinkData {
     FrameSinkData();
     FrameSinkData(FrameSinkData&& other);
     ~FrameSinkData();
     FrameSinkData& operator=(FrameSinkData&& other);
 
+    // If the frame sink is a root that corresponds to a Display.
+    bool is_root = false;
+
     // The FrameSinkId registered as the parent in the BeginFrame hierarchy.
     // This mirrors state in viz.
     base::Optional<FrameSinkId> parent;
 
     // The private interface that gives the host control over the
-    // CompositorFrameSink connection between the client and viz.
+    // CompositorFrameSink connection between the client and viz. This will be
+    // unbound if not using Mojo.
     cc::mojom::CompositorFrameSinkPrivatePtr private_interface;
 
+    // This will be null if using Mojo.
+    CompositorFrameSinkSupport* support = nullptr;
+
    private:
     DISALLOW_COPY_AND_ASSIGN(FrameSinkData);
   };
@@ -93,18 +123,31 @@
   void OnSurfaceCreated(const SurfaceInfo& surface_info) override;
   void OnClientConnectionClosed(const FrameSinkId& frame_sink_id) override;
 
-  // Mojo connection to the FrameSinkManager.
+  // This will point to |frame_sink_manager_ptr_| if using Mojo or
+  // |frame_sink_manager_impl_| if directly connected. Use this to make function
+  // calls.
+  cc::mojom::FrameSinkManager* frame_sink_manager_ = nullptr;
+
+  // Mojo connection to the FrameSinkManager. If this is bound then
+  // |frame_sink_manager_impl_| must be null.
   cc::mojom::FrameSinkManagerPtr frame_sink_manager_ptr_;
 
   // Mojo connection back from the FrameSinkManager.
   mojo::Binding<cc::mojom::FrameSinkManagerClient> binding_;
 
+  // A direct connection to FrameSinkManagerImpl. If this is set then
+  // |frame_sink_manager_ptr_| must be unbound. For use in browser process only,
+  // viz process should not set this.
+  FrameSinkManagerImpl* frame_sink_manager_impl_ = nullptr;
+
   // Per CompositorFrameSink data.
   base::flat_map<FrameSinkId, FrameSinkData> frame_sink_data_map_;
 
   // Local observers to that receive OnSurfaceCreated() messages from IPC.
   base::ObserverList<FrameSinkObserver> observers_;
 
+  base::WeakPtrFactory<HostFrameSinkManager> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(HostFrameSinkManager);
 };
 
diff --git a/components/viz/host/host_frame_sink_manager_unittests.cc b/components/viz/host/host_frame_sink_manager_unittests.cc
index 1717515d..c4c6cbe6 100644
--- a/components/viz/host/host_frame_sink_manager_unittests.cc
+++ b/components/viz/host/host_frame_sink_manager_unittests.cc
@@ -12,6 +12,8 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "cc/ipc/frame_sink_manager.mojom.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
+#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -20,7 +22,7 @@
 namespace {
 
 constexpr FrameSinkId kFrameSinkId1(1, 1);
-constexpr FrameSinkId kFrameSinkId2(1, 1);
+constexpr FrameSinkId kFrameSinkId2(2, 1);
 
 ACTION_P(InvokeClosure, closure) {
   closure.Run();
@@ -53,42 +55,21 @@
 };
 
 // A mock implementation of mojom::FrameSinkManager.
-class MockFrameSinkManagerImpl : public cc::mojom::FrameSinkManager {
+class MockFrameSinkManagerImpl : public FrameSinkManagerImpl {
  public:
-  MockFrameSinkManagerImpl() : binding_(this) {}
+  MockFrameSinkManagerImpl() : FrameSinkManagerImpl(false, nullptr) {}
   ~MockFrameSinkManagerImpl() override = default;
 
-  void BindAndSetClient(cc::mojom::FrameSinkManagerRequest request,
-                        cc::mojom::FrameSinkManagerClientPtr client) {
-    binding_.Bind(std::move(request));
-    client_ = std::move(client);
-  }
-
   // cc::mojom::FrameSinkManager:
-  // TODO(kylechar): See if we can mock functions with InterfacePtrs parameters.
-  void CreateRootCompositorFrameSink(
-      const FrameSinkId& frame_sink_id,
-      gpu::SurfaceHandle surface_handle,
-      cc::mojom::CompositorFrameSinkAssociatedRequest request,
-      cc::mojom::CompositorFrameSinkPrivateRequest private_request,
-      cc::mojom::CompositorFrameSinkClientPtr client,
-      cc::mojom::DisplayPrivateAssociatedRequest display_private_request)
-      override {}
-  void CreateCompositorFrameSink(
-      const FrameSinkId& frame_sink_id,
-      cc::mojom::CompositorFrameSinkRequest request,
-      cc::mojom::CompositorFrameSinkPrivateRequest private_request,
-      cc::mojom::CompositorFrameSinkClientPtr client) override {}
   MOCK_METHOD2(RegisterFrameSinkHierarchy,
                void(const FrameSinkId& parent, const FrameSinkId& child));
   MOCK_METHOD2(UnregisterFrameSinkHierarchy,
                void(const FrameSinkId& parent, const FrameSinkId& child));
   MOCK_METHOD1(DropTemporaryReference, void(const SurfaceId& surface_id));
 
- private:
-  mojo::Binding<cc::mojom::FrameSinkManager> binding_;
-  cc::mojom::FrameSinkManagerClientPtr client_;
+  // TODO(kylechar): See if we can mock functions with InterfacePtr parameters.
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(MockFrameSinkManagerImpl);
 };
 
@@ -103,23 +84,17 @@
 
   MockFrameSinkManagerImpl& manager_impl() { return *manager_impl_; }
 
+  bool FrameSinkIdExists(const FrameSinkId& frame_sink_id) {
+    return host_manager_->frame_sink_data_map_.count(frame_sink_id) > 0;
+  }
+
   // testing::Test:
   void SetUp() override {
     manager_impl_ = base::MakeUnique<MockFrameSinkManagerImpl>();
     host_manager_ = base::MakeUnique<HostFrameSinkManager>();
 
-    // Connect HostFrameSinkManager and FrameSinkManagerImpl.
-    cc::mojom::FrameSinkManagerClientPtr host_mojo;
-    cc::mojom::FrameSinkManagerClientRequest host_mojo_request =
-        mojo::MakeRequest(&host_mojo);
-    cc::mojom::FrameSinkManagerPtr manager_mojo;
-    cc::mojom::FrameSinkManagerRequest manager_impl_request =
-        mojo::MakeRequest(&manager_mojo);
-    manager_impl_->BindAndSetClient(std::move(manager_impl_request),
-                                    std::move(host_mojo));
-    host_manager_->BindAndSetManager(std::move(host_mojo_request),
-                                     base::SequencedTaskRunnerHandle::Get(),
-                                     std::move(manager_mojo));
+    manager_impl_->SetLocalClient(host_manager_.get());
+    host_manager_->SetLocalManager(manager_impl_.get());
   }
 
  private:
@@ -132,7 +107,13 @@
 // Verify that when destroying a CompositorFrameSink with registered FrameSink
 // hierarchy, the hierarchy is automatically unregistered.
 TEST_F(HostFrameSinkManagerTest, UnregisterHierarchyOnDestroy) {
-  base::RunLoop run_loop;
+  // Register is called explicitly.
+  EXPECT_CALL(manager_impl(),
+              RegisterFrameSinkHierarchy(kFrameSinkId2, kFrameSinkId1));
+
+  // Unregister should be called when DestroyCompositorFrameSink() is called.
+  EXPECT_CALL(manager_impl(),
+              UnregisterFrameSinkHierarchy(kFrameSinkId2, kFrameSinkId1));
 
   cc::mojom::CompositorFrameSinkPtr frame_sink;
   StubCompositorFrameSinkClient frame_sink_client;
@@ -141,17 +122,19 @@
                                            frame_sink_client.GetInterfacePtr());
   host_manager().RegisterFrameSinkHierarchy(kFrameSinkId2, kFrameSinkId1);
   host_manager().DestroyCompositorFrameSink(kFrameSinkId1);
+}
 
-  // Register is called explicitly.
-  EXPECT_CALL(manager_impl(),
-              RegisterFrameSinkHierarchy(kFrameSinkId2, kFrameSinkId1));
+// Checks that creating a CompositorFrameSinkSupport registers it and destroying
+// the CompositorFrameSinkSupport unregisters it.
+TEST_F(HostFrameSinkManagerTest, CreateDestroyCompositorFrameSinkSupport) {
+  auto support = host_manager().CreateCompositorFrameSinkSupport(
+      nullptr /* client */, kFrameSinkId1, true /* is_root */,
+      true /* handles_frame_sink_id_invalidation */,
+      false /* needs_sync_points */);
+  EXPECT_TRUE(FrameSinkIdExists(support->frame_sink_id()));
 
-  // Unregister should be called when DestroyCompositorFrameSink() is called.
-  EXPECT_CALL(manager_impl(),
-              UnregisterFrameSinkHierarchy(kFrameSinkId2, kFrameSinkId1))
-      .WillOnce(InvokeClosure(run_loop.QuitClosure()));
-
-  run_loop.Run();
+  support.reset();
+  EXPECT_FALSE(FrameSinkIdExists(support->frame_sink_id()));
 }
 
 }  // namespace test
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 5d8e588..81c6075f 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -34,6 +34,7 @@
     "frame_sinks/compositor_frame_sink_support.cc",
     "frame_sinks/compositor_frame_sink_support.h",
     "frame_sinks/compositor_frame_sink_support_client.h",
+    "frame_sinks/compositor_frame_sink_support_manager.h",
     "frame_sinks/direct_layer_tree_frame_sink.cc",
     "frame_sinks/direct_layer_tree_frame_sink.h",
     "frame_sinks/frame_eviction_manager.cc",
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index 70ee3f77..7863532 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -35,6 +35,9 @@
 }
 
 CompositorFrameSinkSupport::~CompositorFrameSinkSupport() {
+  if (!destruction_callback_.is_null())
+    std::move(destruction_callback_).Run();
+
   // Unregister |this| as a cc::BeginFrameObserver so that the
   // cc::BeginFrameSource does not call into |this| after it's deleted.
   SetNeedsBeginFrame(false);
@@ -53,6 +56,11 @@
     frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_);
 }
 
+void CompositorFrameSinkSupport::SetDestructionCallback(
+    base::OnceCallback<void()> callback) {
+  destruction_callback_ = std::move(callback);
+}
+
 void CompositorFrameSinkSupport::OnSurfaceActivated(cc::Surface* surface) {
   DCHECK(surface->HasActiveFrame());
   const cc::CompositorFrame& frame = surface->GetActiveFrame();
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index 7c467c92..b77fa99 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -9,6 +9,7 @@
 #include <unordered_set>
 #include <vector>
 
+#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "cc/output/compositor_frame.h"
@@ -52,6 +53,8 @@
   FrameSinkManager* frame_sink_manager() { return frame_sink_manager_; }
   cc::SurfaceManager* surface_manager() { return surface_manager_; }
 
+  void SetDestructionCallback(base::OnceCallback<void()> callback);
+
   // SurfaceClient implementation.
   void OnSurfaceActivated(cc::Surface* surface) override;
   void RefResources(
@@ -157,6 +160,9 @@
   // goes away and we can remove this bool.
   const bool handles_frame_sink_id_invalidation_;
 
+  // A callback that will be run at the start of the destructor if set.
+  base::OnceCallback<void()> destruction_callback_;
+
   base::WeakPtrFactory<CompositorFrameSinkSupport> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(CompositorFrameSinkSupport);
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_manager.h b/components/viz/service/frame_sinks/compositor_frame_sink_support_manager.h
new file mode 100644
index 0000000..91a4e80
--- /dev/null
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_manager.h
@@ -0,0 +1,35 @@
+// 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 COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_MANAGER_H_
+#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_MANAGER_H_
+
+#include <memory>
+
+#include "base/callback.h"
+
+namespace viz {
+
+class CompositorFrameSinkSupport;
+class CompositorFrameSinkSupportClient;
+class FrameSinkId;
+
+// This inteface provides a way for DirectLayerTreeFrameSink to create a
+// CompositorFrameSinkSupport.
+class CompositorFrameSinkSupportManager {
+ public:
+  virtual std::unique_ptr<CompositorFrameSinkSupport>
+  CreateCompositorFrameSinkSupport(CompositorFrameSinkSupportClient* client,
+                                   const FrameSinkId& frame_sink_id,
+                                   bool is_root,
+                                   bool handles_frame_sink_id_invalidation,
+                                   bool needs_sync_points) = 0;
+
+ protected:
+  virtual ~CompositorFrameSinkSupportManager() {}
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_MANAGER_H_
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
index 8d5c797..4c6b389 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -11,12 +11,14 @@
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/common/surfaces/local_surface_id_allocator.h"
 #include "components/viz/service/display/display.h"
+#include "components/viz/service/frame_sinks/compositor_frame_sink_support_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager.h"
 
 namespace viz {
 
 DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
     const FrameSinkId& frame_sink_id,
+    CompositorFrameSinkSupportManager* support_manager,
     FrameSinkManager* frame_sink_manager,
     Display* display,
     scoped_refptr<cc::ContextProvider> context_provider,
@@ -28,6 +30,7 @@
                          gpu_memory_buffer_manager,
                          shared_bitmap_manager),
       frame_sink_id_(frame_sink_id),
+      support_manager_(support_manager),
       frame_sink_manager_(frame_sink_manager),
       display_(display) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -39,11 +42,13 @@
 
 DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
     const FrameSinkId& frame_sink_id,
+    CompositorFrameSinkSupportManager* support_manager,
     FrameSinkManager* frame_sink_manager,
     Display* display,
     scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider)
     : LayerTreeFrameSink(std::move(vulkan_context_provider)),
       frame_sink_id_(frame_sink_id),
+      support_manager_(support_manager),
       frame_sink_manager_(frame_sink_manager),
       display_(display) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -69,9 +74,8 @@
 
   constexpr bool is_root = true;
   constexpr bool handles_frame_sink_id_invalidation = false;
-  support_ = CompositorFrameSinkSupport::Create(
-      this, frame_sink_manager_, frame_sink_id_, is_root,
-      handles_frame_sink_id_invalidation,
+  support_ = support_manager_->CreateCompositorFrameSinkSupport(
+      this, frame_sink_id_, is_root, handles_frame_sink_id_invalidation,
       capabilities_.delegated_sync_points_required);
   begin_frame_source_ = base::MakeUnique<cc::ExternalBeginFrameSource>(this);
   client_->SetBeginFrameSource(begin_frame_source_.get());
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
index ab38247..30391ff 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
@@ -21,6 +21,7 @@
 }  // namespace cc
 
 namespace viz {
+class CompositorFrameSinkSupportManager;
 class Display;
 
 // This class submits compositor frames to an in-process Display, with the
@@ -35,6 +36,7 @@
   // outlive this class.
   DirectLayerTreeFrameSink(
       const FrameSinkId& frame_sink_id,
+      CompositorFrameSinkSupportManager* support_manager,
       FrameSinkManager* frame_sink_manager,
       Display* display,
       scoped_refptr<cc::ContextProvider> context_provider,
@@ -43,6 +45,7 @@
       SharedBitmapManager* shared_bitmap_manager);
   DirectLayerTreeFrameSink(
       const FrameSinkId& frame_sink_id,
+      CompositorFrameSinkSupportManager* support_manager,
       FrameSinkManager* frame_sink_manager,
       Display* display,
       scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider);
@@ -81,6 +84,7 @@
 
   const FrameSinkId frame_sink_id_;
   LocalSurfaceId local_surface_id_;
+  CompositorFrameSinkSupportManager* const support_manager_;
   FrameSinkManager* frame_sink_manager_;
   LocalSurfaceIdAllocator local_surface_id_allocator_;
   Display* display_;
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
index 6d96600..fc5fd11d 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
@@ -23,6 +23,7 @@
 #include "components/viz/common/surfaces/local_surface_id_allocator.h"
 #include "components/viz/service/display/display.h"
 #include "components/viz/service/display/display_scheduler.h"
+#include "components/viz/service/frame_sinks/compositor_frame_sink_support_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -38,6 +39,31 @@
   CompositorFrameSinkSupport* support() const { return support_.get(); }
 };
 
+class TestCompositorFrameSinkSupportManager
+    : public CompositorFrameSinkSupportManager {
+ public:
+  explicit TestCompositorFrameSinkSupportManager(
+      FrameSinkManager* frame_sink_manager)
+      : frame_sink_manager_(frame_sink_manager) {}
+  ~TestCompositorFrameSinkSupportManager() override = default;
+
+  std::unique_ptr<CompositorFrameSinkSupport> CreateCompositorFrameSinkSupport(
+      CompositorFrameSinkSupportClient* client,
+      const FrameSinkId& frame_sink_id,
+      bool is_root,
+      bool handles_frame_sink_id_invalidation,
+      bool needs_sync_points) override {
+    return CompositorFrameSinkSupport::Create(
+        client, frame_sink_manager_, frame_sink_id, is_root,
+        handles_frame_sink_id_invalidation, needs_sync_points);
+  }
+
+ private:
+  FrameSinkManager* const frame_sink_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestCompositorFrameSinkSupportManager);
+};
+
 class DirectLayerTreeFrameSinkTest : public testing::Test {
  public:
   DirectLayerTreeFrameSinkTest()
@@ -45,6 +71,7 @@
         task_runner_(new cc::OrderedSimpleTaskRunner(now_src_.get(), true)),
         display_size_(1920, 1080),
         display_rect_(display_size_),
+        support_manager_(&frame_sink_manager_),
         context_provider_(cc::TestContextProvider::Create()) {
     frame_sink_manager_.RegisterFrameSinkId(kArbitraryFrameSinkId);
 
@@ -64,8 +91,8 @@
         std::move(scheduler),
         base::MakeUnique<cc::TextureMailboxDeleter>(task_runner_.get())));
     layer_tree_frame_sink_ = base::MakeUnique<TestDirectLayerTreeFrameSink>(
-        kArbitraryFrameSinkId, &frame_sink_manager_, display_.get(),
-        context_provider_, nullptr, &gpu_memory_buffer_manager_,
+        kArbitraryFrameSinkId, &support_manager_, &frame_sink_manager_,
+        display_.get(), context_provider_, nullptr, &gpu_memory_buffer_manager_,
         &bitmap_manager_);
 
     layer_tree_frame_sink_->BindToClient(&layer_tree_frame_sink_client_);
@@ -107,6 +134,7 @@
   const gfx::Size display_size_;
   const gfx::Rect display_rect_;
   FrameSinkManager frame_sink_manager_;
+  TestCompositorFrameSinkSupportManager support_manager_;
   cc::TestSharedBitmapManager bitmap_manager_;
   cc::TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
 
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
index 7b3de665..61a6ceb 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -37,9 +37,19 @@
     cc::mojom::FrameSinkManagerRequest request,
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     cc::mojom::FrameSinkManagerClientPtr client) {
+  DCHECK(!client_);
   DCHECK(!binding_.is_bound());
   binding_.Bind(std::move(request), std::move(task_runner));
-  client_ = std::move(client);
+  client_ptr_ = std::move(client);
+
+  client_ = client_ptr_.get();
+}
+
+void FrameSinkManagerImpl::SetLocalClient(
+    cc::mojom::FrameSinkManagerClient* client) {
+  DCHECK(!client_ptr_);
+
+  client_ = client;
 }
 
 void FrameSinkManagerImpl::CreateRootCompositorFrameSink(
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
index b97f905d..5dd3b25 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -56,6 +56,9 @@
                         scoped_refptr<base::SequencedTaskRunner> task_runner,
                         cc::mojom::FrameSinkManagerClientPtr client);
 
+  // Sets up a direction connection to |client| without using Mojo.
+  void SetLocalClient(cc::mojom::FrameSinkManagerClient* client);
+
   // cc::mojom::FrameSinkManager implementation:
   void CreateRootCompositorFrameSink(
       const FrameSinkId& frame_sink_id,
@@ -115,7 +118,11 @@
 
   THREAD_CHECKER(thread_checker_);
 
-  cc::mojom::FrameSinkManagerClientPtr client_;
+  // This will point to |client_ptr_| if using Mojo or a provided client if
+  // directly connected. Use this to make function calls.
+  cc::mojom::FrameSinkManagerClient* client_ = nullptr;
+
+  cc::mojom::FrameSinkManagerClientPtr client_ptr_;
   mojo::Binding<cc::mojom::FrameSinkManager> binding_;
 
   DISALLOW_COPY_AND_ASSIGN(FrameSinkManagerImpl);
diff --git a/content/DEPS b/content/DEPS
index fd8706d..b34a6f4 100644
--- a/content/DEPS
+++ b/content/DEPS
@@ -118,10 +118,20 @@
   "+jni",
 ]
 
-# content -> content/shell dependency is not allowed, except for browser tests.
 specific_include_rules = {
   ".*_browsertest[a-z_]*\.(cc|h)": [
+    # content -> content/shell dependency is disallowed, except browser tests.
     "+content/shell/browser",
     "+content/shell/common",
+
+    # components/variations/variations_params_manager.h is allowed from tests
+    # (it is part of //components/variations:test_support target).
+    "+components/variations/variations_params_manager.h",
+  ],
+
+  "test_utils\.cc": [
+    # components/variations/variations_params_manager.h is allowed from tests
+    # (it is part of //components/variations:test_support target).
+    "+components/variations/variations_params_manager.h",
   ],
 }
diff --git a/content/browser/browser_associated_interface_unittest.cc b/content/browser/browser_associated_interface_unittest.cc
index d653010e..504474e 100644
--- a/content/browser/browser_associated_interface_unittest.cc
+++ b/content/browser/browser_associated_interface_unittest.cc
@@ -92,6 +92,12 @@
     return true;
   }
 
+  void OnFilterRemoved() override {
+    // Check that the bindings are cleared by
+    // BrowserAssociatedInterface::ClearBindings() callbacks.
+    EXPECT_FALSE(internal_state_->bindings_.get());
+  }
+
   // mojom::BrowserAssociatedInterfaceTestDriver:
   void ExpectString(const std::string& expected) override {
     next_expected_string_ = expected;
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index c2db985f..5d8124c 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -1471,9 +1471,8 @@
 
     // TODO(danakj): Don't make a FrameSinkManagerImpl when display is in the
     // Gpu process, instead get the mojo pointer from the Gpu process.
-    surface_utils::ConnectWithInProcessFrameSinkManager(
-        host_frame_sink_manager_.get(), frame_sink_manager_impl_.get(),
-        GetResizeTaskRunner());
+    surface_utils::ConnectWithLocalFrameSinkManager(
+        host_frame_sink_manager_.get(), frame_sink_manager_impl_.get());
   }
 #endif
 
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index c12b2aeb..2e19825 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -619,13 +619,13 @@
   auto layer_tree_frame_sink =
       vulkan_context_provider
           ? base::MakeUnique<viz::DirectLayerTreeFrameSink>(
-                compositor->frame_sink_id(), GetFrameSinkManager(),
-                data->display.get(),
+                compositor->frame_sink_id(), GetHostFrameSinkManager(),
+                GetFrameSinkManager(), data->display.get(),
                 static_cast<scoped_refptr<cc::VulkanContextProvider>>(
                     vulkan_context_provider))
           : base::MakeUnique<viz::DirectLayerTreeFrameSink>(
-                compositor->frame_sink_id(), GetFrameSinkManager(),
-                data->display.get(), context_provider,
+                compositor->frame_sink_id(), GetHostFrameSinkManager(),
+                GetFrameSinkManager(), data->display.get(), context_provider,
                 shared_worker_context_provider_, GetGpuMemoryBufferManager(),
                 viz::ServerSharedBitmapManager::current());
   data->display->Resize(compositor->size());
diff --git a/content/browser/compositor/surface_utils.cc b/content/browser/compositor/surface_utils.cc
index ee1d844..e70b74fe 100644
--- a/content/browser/compositor/surface_utils.cc
+++ b/content/browser/compositor/surface_utils.cc
@@ -169,7 +169,7 @@
   return CompositorImpl::GetFrameSinkManager();
 #else
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
-  if (factory == NULL)
+  if (!factory)
     return nullptr;
   return factory->GetContextFactoryPrivate()->GetFrameSinkManager();
 #endif
@@ -179,7 +179,10 @@
 #if defined(OS_ANDROID)
   return CompositorImpl::GetHostFrameSinkManager();
 #else
-  return BrowserMainLoop::GetInstance()->host_frame_sink_manager();
+  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+  if (!factory)
+    return nullptr;
+  return factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
 #endif
 }
 
@@ -237,6 +240,13 @@
                           std::move(manager_mojo));
 }
 
+void ConnectWithLocalFrameSinkManager(
+    viz::HostFrameSinkManager* host_frame_sink_manager,
+    viz::FrameSinkManagerImpl* frame_sink_manager_impl) {
+  host_frame_sink_manager->SetLocalManager(frame_sink_manager_impl);
+  frame_sink_manager_impl->SetLocalClient(host_frame_sink_manager);
+}
+
 }  // namespace surface_utils
 
 }  // namespace content
diff --git a/content/browser/compositor/surface_utils.h b/content/browser/compositor/surface_utils.h
index 1662845..997edaf6 100644
--- a/content/browser/compositor/surface_utils.h
+++ b/content/browser/compositor/surface_utils.h
@@ -44,9 +44,15 @@
 
 namespace surface_utils {
 
+// Directly connects HostFrameSinkManager to FrameSinkManagerImpl without Mojo.
+CONTENT_EXPORT void ConnectWithLocalFrameSinkManager(
+    viz::HostFrameSinkManager* host_frame_sink_manager,
+    viz::FrameSinkManagerImpl* frame_sink_manager_impl);
+
+// Connects HostFrameSinkManager to FrameSinkManagerImpl using in process Mojo.
 CONTENT_EXPORT void ConnectWithInProcessFrameSinkManager(
-    viz::HostFrameSinkManager* host,
-    viz::FrameSinkManagerImpl* manager,
+    viz::HostFrameSinkManager* host_frame_sink_manager,
+    viz::FrameSinkManagerImpl* frame_sink_manager_impl,
     scoped_refptr<base::SequencedTaskRunner> task_runner);
 
 }  // namespace surface_utils
diff --git a/content/browser/compositor/test/no_transport_image_transport_factory.cc b/content/browser/compositor/test/no_transport_image_transport_factory.cc
index 2d1ac5e0..cc12f63 100644
--- a/content/browser/compositor/test/no_transport_image_transport_factory.cc
+++ b/content/browser/compositor/test/no_transport_image_transport_factory.cc
@@ -22,9 +22,8 @@
     : frame_sink_manager_(false /* use surface references */, nullptr),
       context_factory_(&host_frame_sink_manager_,
                        frame_sink_manager_.frame_sink_manager()) {
-  surface_utils::ConnectWithInProcessFrameSinkManager(
-      &host_frame_sink_manager_, &frame_sink_manager_,
-      base::ThreadTaskRunnerHandle::Get());
+  surface_utils::ConnectWithLocalFrameSinkManager(&host_frame_sink_manager_,
+                                                  &frame_sink_manager_);
 
   // The context factory created here is for unit tests, thus using a higher
   // refresh rate to spend less time waiting for BeginFrames.
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc
index 804d5ef..7e78825 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -823,7 +823,7 @@
 
 viz::SurfaceId RenderWidgetHostViewChildFrame::SurfaceIdForTesting() const {
   return viz::SurfaceId(frame_sink_id_, local_surface_id_);
-};
+}
 
 void RenderWidgetHostViewChildFrame::CreateCompositorFrameSinkSupport() {
   if (service_manager::ServiceManagerIsRemote())
@@ -833,9 +833,9 @@
   constexpr bool is_root = false;
   constexpr bool handles_frame_sink_id_invalidation = false;
   constexpr bool needs_sync_points = true;
-  support_ = viz::CompositorFrameSinkSupport::Create(
-      this, GetFrameSinkManager(), frame_sink_id_, is_root,
-      handles_frame_sink_id_invalidation, needs_sync_points);
+  support_ = GetHostFrameSinkManager()->CreateCompositorFrameSinkSupport(
+      this, frame_sink_id_, is_root, handles_frame_sink_id_invalidation,
+      needs_sync_points);
   if (parent_frame_sink_id_.is_valid()) {
     GetFrameSinkManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_,
                                                       frame_sink_id_);
diff --git a/content/browser/memory/DEPS b/content/browser/memory/DEPS
deleted file mode 100644
index 80f6f90..0000000
--- a/content/browser/memory/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+components/variations",
-]
diff --git a/content/browser/memory/memory_condition_observer.cc b/content/browser/memory/memory_condition_observer.cc
index a1ae7adc..e80d4b36 100644
--- a/content/browser/memory/memory_condition_observer.cc
+++ b/content/browser/memory/memory_condition_observer.cc
@@ -6,7 +6,6 @@
 
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
-#include "components/variations/variations_associated_data.h"
 #include "content/browser/memory/memory_monitor.h"
 
 namespace content {
diff --git a/content/browser/renderer_host/DEPS b/content/browser/renderer_host/DEPS
index ab29198..ecc46881 100644
--- a/content/browser/renderer_host/DEPS
+++ b/content/browser/renderer_host/DEPS
@@ -3,7 +3,6 @@
   "+components/viz/common",
   "+components/viz/host",
   "+components/viz/service",
-  "+components/variations",
   "+services/ui/public",
   "+third_party/zlib",
   "+ui/latency",
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 43a11663..ae765ed 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -104,9 +104,8 @@
     // Gpu process, instead get the mojo pointer from the Gpu process.
     frame_sink_manager_impl =
         base::MakeUnique<viz::FrameSinkManagerImpl>(false, nullptr);
-    surface_utils::ConnectWithInProcessFrameSinkManager(
-        &host_frame_sink_manager, frame_sink_manager_impl.get(),
-        base::ThreadTaskRunnerHandle::Get());
+    surface_utils::ConnectWithLocalFrameSinkManager(
+        &host_frame_sink_manager, frame_sink_manager_impl.get());
   }
 
   SingleThreadTaskGraphRunner task_graph_runner;
@@ -837,10 +836,11 @@
   auto layer_tree_frame_sink =
       vulkan_context_provider
           ? base::MakeUnique<viz::DirectLayerTreeFrameSink>(
-                frame_sink_id_, manager, display_.get(),
-                vulkan_context_provider)
+                frame_sink_id_, GetHostFrameSinkManager(), manager,
+                display_.get(), vulkan_context_provider)
           : base::MakeUnique<viz::DirectLayerTreeFrameSink>(
-                frame_sink_id_, manager, display_.get(), context_provider,
+                frame_sink_id_, GetHostFrameSinkManager(), manager,
+                display_.get(), context_provider,
                 nullptr /* worker_context_provider */,
                 gpu_memory_buffer_manager,
                 viz::ServerSharedBitmapManager::current());
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
index 7805e3e..a27268b 100644
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -21,6 +21,7 @@
 #include "cc/surfaces/surface_hittest.h"
 #include "components/viz/common/gl_helper.h"
 #include "components/viz/common/quads/texture_mailbox.h"
+#include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager.h"
 #include "content/browser/compositor/surface_utils.h"
@@ -831,10 +832,11 @@
   constexpr bool handles_frame_sink_id_invalidation = false;
   constexpr bool needs_sync_points = true;
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
-  support_ = viz::CompositorFrameSinkSupport::Create(
-      this, factory->GetContextFactoryPrivate()->GetFrameSinkManager(),
-      frame_sink_id_, is_root, handles_frame_sink_id_invalidation,
-      needs_sync_points);
+  support_ = factory->GetContextFactoryPrivate()
+                 ->GetHostFrameSinkManager()
+                 ->CreateCompositorFrameSinkSupport(
+                     this, frame_sink_id_, is_root,
+                     handles_frame_sink_id_invalidation, needs_sync_points);
   if (compositor_)
     compositor_->AddFrameSink(frame_sink_id_);
   if (needs_begin_frame_)
diff --git a/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc b/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
index 2127ef35..628fc5d8 100644
--- a/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
+++ b/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
@@ -154,9 +154,8 @@
     // The FrameSinkManager implementation is in-process here for tests.
     frame_sink_manager_ =
         base::MakeUnique<viz::FrameSinkManagerImpl>(false, nullptr);
-    surface_utils::ConnectWithInProcessFrameSinkManager(
-        host_frame_sink_manager_.get(), frame_sink_manager_.get(),
-        message_loop_.task_runner());
+    surface_utils::ConnectWithLocalFrameSinkManager(
+        host_frame_sink_manager_.get(), frame_sink_manager_.get());
 
     provider_ = base::MakeUnique<OffscreenCanvasProviderImpl>(
         host_frame_sink_manager_.get(), kRendererClientId);
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index f6b12ff8..7218c7f 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -29,7 +29,6 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "cc/base/switches.h"
-#include "components/variations/variations_associated_data.h"
 #include "content/browser/bad_message.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 46bd35b..0082320 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -478,7 +478,8 @@
     viz::FrameSinkId frame_sink_id =
         host_->AllocateFrameSinkId(false /* is_guest_view_hack */);
     delegated_frame_host_.reset(new ui::DelegatedFrameHostAndroid(
-        &view_, CompositorImpl::GetFrameSinkManager(), this, frame_sink_id));
+        &view_, CompositorImpl::GetHostFrameSinkManager(),
+        CompositorImpl::GetFrameSinkManager(), this, frame_sink_id));
 
     // Let the page-level input event router know about our frame sink ID
     // for surface-based hit testing.
diff --git a/content/ppapi_plugin/DEPS b/content/ppapi_plugin/DEPS
index 0e09ed9..644ecee 100644
--- a/content/ppapi_plugin/DEPS
+++ b/content/ppapi_plugin/DEPS
@@ -1,6 +1,6 @@
 include_rules = [
   "+components/discardable_memory/client",
-  "+components/variations",
+  "+components/variations/child_process_field_trial_syncer.h",
   "+content/child",
   "+gin/public/isolate_holder.h",
   "+gin/v8_initializer.h",
diff --git a/content/public/browser/browser_associated_interface.h b/content/public/browser/browser_associated_interface.h
index f804998..2b86e21 100644
--- a/content/public/browser/browser_associated_interface.h
+++ b/content/public/browser/browser_associated_interface.h
@@ -58,14 +58,15 @@
     internal_state_->Initialize();
     filter->AddAssociatedInterface(
         Interface::Name_,
-        base::Bind(&InternalState::BindRequest, internal_state_));
+        base::Bind(&InternalState::BindRequest, internal_state_),
+        base::BindOnce(&InternalState::ClearBindings, internal_state_));
   }
 
-  ~BrowserAssociatedInterface() {
-    internal_state_->ShutDown();
-  }
+  ~BrowserAssociatedInterface() { internal_state_->ClearBindings(); }
 
  private:
+  friend class TestDriverMessageFilter;
+
   class InternalState : public base::RefCountedThreadSafe<InternalState> {
    public:
     explicit InternalState(Interface* impl) : impl_(impl) {}
@@ -79,10 +80,11 @@
       bindings_.reset(new mojo::AssociatedBindingSet<Interface>);
     }
 
-    void ShutDown() {
+    void ClearBindings() {
       if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
-        BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                                base::Bind(&InternalState::ShutDown, this));
+        BrowserThread::PostTask(
+            BrowserThread::IO, FROM_HERE,
+            base::Bind(&InternalState::ClearBindings, this));
         return;
       }
       bindings_.reset();
@@ -99,6 +101,7 @@
 
    private:
     friend class base::RefCountedThreadSafe<InternalState>;
+    friend class TestDriverMessageFilter;
 
     ~InternalState() {}
 
diff --git a/content/public/browser/browser_message_filter.cc b/content/public/browser/browser_message_filter.cc
index c44bea6..fd4096e6 100644
--- a/content/public/browser/browser_message_filter.cc
+++ b/content/public/browser/browser_message_filter.cc
@@ -37,7 +37,12 @@
     filter_->OnFilterAdded(channel);
   }
 
-  void OnFilterRemoved() override { filter_->OnFilterRemoved(); }
+  void OnFilterRemoved() override {
+    for (auto& callback : filter_->filter_removed_callbacks_)
+      std::move(callback).Run();
+    filter_->filter_removed_callbacks_.clear();
+    filter_->OnFilterRemoved();
+  }
 
   void OnChannelClosing() override {
     filter_->sender_ = nullptr;
@@ -112,8 +117,10 @@
 
 void BrowserMessageFilter::AddAssociatedInterface(
     const std::string& name,
-    const IPC::ChannelProxy::GenericAssociatedInterfaceFactory& factory) {
+    const IPC::ChannelProxy::GenericAssociatedInterfaceFactory& factory,
+    base::OnceClosure filter_removed_callback) {
   associated_interfaces_.emplace_back(name, factory);
+  filter_removed_callbacks_.emplace_back(std::move(filter_removed_callback));
 }
 
 base::ProcessHandle BrowserMessageFilter::PeerHandle() {
diff --git a/content/public/browser/browser_message_filter.h b/content/public/browser/browser_message_filter.h
index d112276..84b6cd5 100644
--- a/content/public/browser/browser_message_filter.h
+++ b/content/public/browser/browser_message_filter.h
@@ -85,9 +85,13 @@
 
   // Adds an associated interface factory to this filter. Must be called before
   // RegisterAssociatedInterfaces().
+  //
+  // |filter_removed_callback| is called on the IO thread when this filter is
+  // removed.
   void AddAssociatedInterface(
       const std::string& name,
-      const IPC::ChannelProxy::GenericAssociatedInterfaceFactory& factory);
+      const IPC::ChannelProxy::GenericAssociatedInterfaceFactory& factory,
+      const base::OnceClosure filter_removed_callback);
 
   // Can be called on any thread, after OnChannelConnected is called.
   base::ProcessHandle PeerHandle();
@@ -142,6 +146,9 @@
   std::vector<std::pair<std::string,
                         IPC::ChannelProxy::GenericAssociatedInterfaceFactory>>
       associated_interfaces_;
+
+  // Callbacks to be called in OnFilterRemoved().
+  std::vector<base::OnceClosure> filter_removed_callbacks_;
 };
 
 struct BrowserMessageFilterTraits {
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc
index a50cc6c..cb8a3b0 100644
--- a/content/public/test/test_utils.cc
+++ b/content/public/test/test_utils.cc
@@ -19,6 +19,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "components/variations/variations_params_manager.h"
 #include "content/common/site_isolation_policy.h"
 #include "content/common/url_schemes.h"
 #include "content/public/browser/browser_child_process_host_iterator.h"
@@ -212,6 +213,23 @@
   url::Initialize();
 }
 
+void EnableFeatureWithParam(const base::Feature& feature,
+                            const std::string& param_name,
+                            const std::string& param_value,
+                            base::CommandLine* command_line) {
+  static const char kFakeTrialName[] = "TrialNameForTesting";
+  static const char kFakeTrialGroupName[] = "TrialGroupForTesting";
+
+  // Enable all the |feature|, associating them with |trial_name|.
+  command_line->AppendSwitchASCII(
+      switches::kEnableFeatures,
+      std::string(feature.name) + "<" + kFakeTrialName);
+
+  std::map<std::string, std::string> param_values = {{param_name, param_value}};
+  variations::testing::VariationParamsManager::AppendVariationParams(
+      kFakeTrialName, kFakeTrialGroupName, param_values, command_line);
+}
+
 #if defined(OS_ANDROID)
 // Registers content/browser and mojo JNI bindings necessary for some types of
 // tests.
diff --git a/content/public/test/test_utils.h b/content/public/test/test_utils.h
index f8afeece..330210f 100644
--- a/content/public/test/test_utils.h
+++ b/content/public/test/test_utils.h
@@ -26,8 +26,9 @@
 #endif
 
 namespace base {
-class Value;
 class CommandLine;
+class Value;
+struct Feature;
 }  // namespace base
 
 // A collection of functions designed for use with unit and browser tests.
@@ -87,6 +88,17 @@
 // Resets the internal secure schemes/origins whitelist.
 void ResetSchemesAndOriginsWhitelist();
 
+// Appends command line switches to |command_line| to enable the |feature| and
+// to set field trial params associated with the feature as specified by
+// |param_name| and |param_value|.
+//
+// Note that a dummy trial and trial group will be registered behind the scenes.
+// See also variations::testing::VariationsParamsManager class.
+void EnableFeatureWithParam(const base::Feature& feature,
+                            const std::string& param_name,
+                            const std::string& param_value,
+                            base::CommandLine* command_line);
+
 #if defined(OS_ANDROID)
 // Registers content/browser JNI bindings necessary for some types of tests.
 bool RegisterJniForTesting(JNIEnv* env);
diff --git a/content/renderer/DEPS b/content/renderer/DEPS
index b803a5a..a77566d 100644
--- a/content/renderer/DEPS
+++ b/content/renderer/DEPS
@@ -7,7 +7,7 @@
   "+components/payments",
   "+components/scheduler",
   "+components/url_formatter",
-  "+components/variations",
+  "+components/variations/child_process_field_trial_syncer.h",
   "+components/viz/client",
   "+components/viz/common",
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 65c23fb..ac1e5a06 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -234,6 +234,7 @@
   ]
 
   public_deps = [
+    "//components/variations:test_support",
     "//content/public/app:both",
     "//content/public/browser",
     "//content/public/common",
diff --git a/docs/adding_to_third_party.md b/docs/adding_to_third_party.md
index 512c621..2f5d235 100644
--- a/docs/adding_to_third_party.md
+++ b/docs/adding_to_third_party.md
@@ -67,10 +67,6 @@
   about:credits page in Google Chrome builds.
 * `src/tools/checklicenses/checklicenses.py` - See below for info on how to
   handle possible failures.
-* If you are adding code that will be present in the content layer, please make
-  sure that the license used is compliant with Android tree requirements because
-  this code will also be used in Android WebView. You need to run
-  `src/android_webview/tools/webview_licenses.py scan`
 
 See the ["Odds n' Ends"](adding_to_third_party.md#Odds-n_Ends) Section below if
 you run into any failures running these.
@@ -187,16 +183,3 @@
       resulting binaries can't use GPL code. Ideally we just shouldn't have
       those files at all in the tree. If in doubt, please ask mal@chromium.org
 
-### Handling `webview_licenses.py` failures
-
-__If the failure looks like ...   ... the right action is to ... __
-
-* Missing license file
-    * Make sure that the license file is present. It should be called 'LICENSE',
-      or otherwise README.chromium file must point to it explicitly.
-* The following files contain a third-party license but are not in a listed
-  third-party directory...
-    * Check if it's a false positive (e.g. 'copyright' word used in a string
-      literal), if so, update
-      [src/tools/copyright_scanner/third_party_files_whitelist.txt](https://code.google.com/p/chromium/codesearch#chromium/src/tools/copyright_scanner/third_party_files_whitelist.txt)
-      file. Otherwise, please move the code into third_party.
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index c4f49c6..e914c07 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -49,12 +49,7 @@
       builders { name: "chromeos_daisy_chromium_compile_only_ng" }
       builders { name: "chromium_presubmit" }
       builders { name: "linux_chromium_asan_rel_ng" }
-      # TODO(dpranke): reenable ASAP; see crbug.com/669297.
-      #builders { name: "linux_chromium_chromeos_compile_dbg_ng" }
-      builders { name: "linux_chromium_chromeos_ozone_rel_ng" }
       builders { name: "linux_chromium_chromeos_rel_ng" }
-      # TODO(dpranke): reenable ASAP; see crbug.com/669297.
-      #builders { name: "linux_chromium_clobber_rel_ng" }
       builders { name: "linux_chromium_compile_dbg_ng" }
       builders { name: "linux_chromium_headless_rel" }
       builders { name: "linux_chromium_tsan_rel_ng" }
diff --git a/ios/build/xcode_install_wrapper.py b/ios/build/xcode_install_wrapper.py
new file mode 100755
index 0000000..b7b53fcb
--- /dev/null
+++ b/ios/build/xcode_install_wrapper.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""Wrapper script to install Xcode. For use on the bots.
+
+Installing Xcode requires sudo. This script will be whitelisted in /etc/sudoers
+so that we can easily update Xcode on our bots.
+"""
+
+import argparse
+import hashlib
+import logging
+import os
+import subprocess
+import sys
+
+
+# List of sha256 hashes of Xcode package file
+# Contents/Resources/Packages/XcodeSystemResources.pkg
+WHITELISTED_PACKAGES = [
+  # Xcode versions 8A218a-1, 8A218a-2
+  '3d948c4bd7c8941478a60aece3cb98ef936a57a4cc1c8f8d5f7eef70d0ebbad1',
+  # Xcode versions 8B62-1, 8C1002-1
+  '21ed3271af2ac7d67c6c09a9481a1fd5bb886950990365bb936dde7585e09061',
+  # Xcode versions 8E2002-1
+  'ff2377d3976f7acf2adfe5ca91c2e6cc59dd112647efa0bf39e9d9decd2ee1b3',
+  # Xcode versions 9M136h-1
+  '2ec798b123bcfa7f8c0e5618c193ecd26ddce87f2e27f6b5d2fb0720926e5464',
+  # Xcode versions 9M137d-1
+  '6c5f4a2fd6dc477f8f06ccd6f6119da540dd5fe3a6036357dbe9c13d611fc366',
+]
+
+def main():
+  logging.basicConfig(level=logging.DEBUG)
+
+  parser = argparse.ArgumentParser(
+      description='Wrapper script to install Xcode.')
+  parser.add_argument(
+      '--package-path',
+      help='Path to Xcode package to install.',
+      required=True)
+  args = parser.parse_args()
+
+  if not os.path.isfile(args.package_path):
+    logging.critical('Path %s is not a file.' % args.package_path)
+    return 1
+
+  sha256 = hashlib.sha256()
+  with open(args.package_path, 'rb') as f:
+    for chunk in iter(lambda: f.read(8192), b''):
+      sha256.update(chunk)
+  sha256_hash = sha256.hexdigest()
+
+  if sha256_hash not in WHITELISTED_PACKAGES:
+    logging.critical('Attempted to install a non-whitelisted Xcode package.')
+    return 1
+
+  pipe = subprocess.Popen(
+      ['/usr/sbin/installer', '-pkg', args.package_path, '-target', '/'],
+      stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+  stdout, stderr = pipe.communicate()
+
+  for line in stdout.splitlines():
+    logging.debug(line)
+  for line in stderr.splitlines():
+    logging.error(line)
+
+  return pipe.returncode
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 55bab02e..e2da779 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -195,24 +195,9 @@
       <message name="IDS_IOS_APPLICATION_SHORTCUT_VOICE_SEARCH_TITLE" desc="Message when opening a Voice Search from springboard force touch static shortcuts. [Length: unlimited] [iOS only]." meaning="3D Touch entry to trigger a voice search.">
         Voice Search
       </message>
-      <message name="IDS_IOS_APP_LAUNCHER_INSTALL_APP_BUTTON_LABEL" desc="Label of a button to install an application. [Length: 10em] [iOS only]">
-        Install
-      </message>
-      <message name="IDS_IOS_APP_LAUNCHER_OPEN_ALWAYS_BUTTON" desc="Label of a button to choose to launch an application always, as opposed to once. [Length: 12em] [iOS only]">
-        Always
-      </message>
       <message name="IDS_IOS_APP_LAUNCHER_OPEN_APP_BUTTON_LABEL" desc="Label of a button to open an application. [Length: 10em] [iOS only]">
         Open
       </message>
-      <message name="IDS_IOS_APP_LAUNCHER_OPEN_IN_APP_QUESTION_MESSAGE" desc="Message in the infobar asking the user if they want to open the current page in an external app. [Length: 40em] [iOS only]">
-        Open this page in the <ph name="APP_NAME">$1<ex>Google Maps</ex></ph> app?
-      </message>
-      <message name="IDS_IOS_APP_LAUNCHER_OPEN_IN_LABEL" desc="Label in the infobar to launch an application. [Length: 20em] [iOS only]">
-        Open in <ph name="APP_NAME">$1<ex>Google Maps</ex></ph>
-      </message>
-      <message name="IDS_IOS_APP_LAUNCHER_OPEN_ONCE_BUTTON" desc="Label of a button to choose to launch an application once, as opposed to always. [Length: 12em] [iOS only]">
-          Just once
-      </message>
       <message name="IDS_IOS_AUTOFILL" desc="Title for the view in Settings for enabling/disabling Autofill. [Length: 15em] [iOS only]">
         Autofill Forms
       </message>
diff --git a/ios/chrome/browser/native_app_launcher/BUILD.gn b/ios/chrome/browser/native_app_launcher/BUILD.gn
index 39eebc79..aa2afa9 100644
--- a/ios/chrome/browser/native_app_launcher/BUILD.gn
+++ b/ios/chrome/browser/native_app_launcher/BUILD.gn
@@ -7,45 +7,5 @@
   sources = [
     "ios_appstore_ids.h",
     "ios_appstore_ids.mm",
-    "native_app_infobar_controller.h",
-    "native_app_infobar_controller.mm",
-    "native_app_infobar_delegate.h",
-    "native_app_infobar_delegate.mm",
-    "native_app_navigation_controller_protocol.h",
-  ]
-  deps = [
-    "//base",
-    "//components/infobars/core",
-    "//ios/chrome/app/strings",
-    "//ios/chrome/browser/infobars",
-    "//ios/chrome/browser/ui/infobars",
-    "//ios/public/provider/chrome/browser/native_app_launcher",
-    "//ui/base",
-    "//url",
-  ]
-}
-
-source_set("unit_tests") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  testonly = true
-  sources = [
-    "native_app_infobar_controller_unittest.mm",
-    "native_app_infobar_delegate_unittest.mm",
-  ]
-  deps = [
-    ":native_app_launcher",
-    "//base",
-    "//base/test:test_support",
-    "//components/infobars/core",
-    "//ios/chrome/browser",
-    "//ios/chrome/test:test_support",
-    "//ios/public/provider/chrome/browser",
-    "//ios/public/provider/chrome/browser:test_support",
-    "//ios/public/provider/chrome/browser/native_app_launcher",
-    "//ios/web",
-    "//net:test_support",
-    "//testing/gmock",
-    "//testing/gtest",
-    "//url",
   ]
 }
diff --git a/ios/chrome/browser/native_app_launcher/native_app_infobar_controller.h b/ios/chrome/browser/native_app_launcher/native_app_infobar_controller.h
deleted file mode 100644
index 873f2cd..0000000
--- a/ios/chrome/browser/native_app_launcher/native_app_infobar_controller.h
+++ /dev/null
@@ -1,13 +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 IOS_CHROME_BROWSER_NATIVE_APP_LAUNCHER_NATIVE_APP_INFOBAR_CONTROLLER_H_
-#define IOS_CHROME_BROWSER_NATIVE_APP_LAUNCHER_NATIVE_APP_INFOBAR_CONTROLLER_H_
-
-#include "ios/chrome/browser/infobars/infobar_controller.h"
-
-@interface NativeAppInfoBarController : InfoBarController
-@end
-
-#endif  // IOS_CHROME_BROWSER_NATIVE_APP_LAUNCHER_NATIVE_APP_INFOBAR_CONTROLLER_H_
diff --git a/ios/chrome/browser/native_app_launcher/native_app_infobar_controller.mm b/ios/chrome/browser/native_app_launcher/native_app_infobar_controller.mm
deleted file mode 100644
index ae68f8c..0000000
--- a/ios/chrome/browser/native_app_launcher/native_app_infobar_controller.mm
+++ /dev/null
@@ -1,129 +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 "ios/chrome/browser/native_app_launcher/native_app_infobar_controller.h"
-
-#include "base/logging.h"
-#include "base/strings/sys_string_conversions.h"
-#include "ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h"
-#import "ios/chrome/browser/ui/infobars/infobar_view.h"
-#include "ios/chrome/browser/ui/infobars/infobar_view.h"
-#include "ios/chrome/grit/ios_strings.h"
-#import "ios/public/provider/chrome/browser/native_app_launcher/native_app_types.h"
-#include "ui/base/l10n/l10n_util.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface NativeAppInfoBarController ()
-
-// Action for any of the user defined buttons.
-- (void)infoBarButtonDidPress:(UIButton*)button;
-
-// Notifies the delegate of which action the user took.
-- (void)userPerformedAction:(NativeAppActionType)userAction;
-
-// For testing.
-// Sets the infobar delegate.
-- (void)setInfoBarDelegate:(NativeAppInfoBarDelegate*)delegate;
-
-@end
-
-@implementation NativeAppInfoBarController {
-  NativeAppInfoBarDelegate* nativeAppInfoBarDelegate_;  // weak
-}
-
-#pragma mark - InfoBarController
-
-- (InfoBarView*)viewForDelegate:(infobars::InfoBarDelegate*)delegate
-                          frame:(CGRect)frame {
-  InfoBarView* infoBarView;
-  nativeAppInfoBarDelegate_ = static_cast<NativeAppInfoBarDelegate*>(delegate);
-  DCHECK(nativeAppInfoBarDelegate_);
-  infoBarView =
-      [[InfoBarView alloc] initWithFrame:frame delegate:self.delegate];
-
-  // Lays out widgets common to all NativeAppInfobars.
-  [infoBarView
-      addPlaceholderTransparentIcon:native_app_infobar::kSmallIconSize];
-  nativeAppInfoBarDelegate_->FetchSmallAppIcon(^(UIImage* image) {
-    [infoBarView addLeftIconWithRoundedCornersAndShadow:image];
-  });
-  [infoBarView addCloseButtonWithTag:NATIVE_APP_ACTION_DISMISS
-                              target:self
-                              action:@selector(infoBarButtonDidPress:)];
-
-  auto type = nativeAppInfoBarDelegate_->GetControllerType();
-  switch (type) {
-    case NATIVE_APP_INSTALLER_CONTROLLER: {
-      NSString* buttonMsg =
-          l10n_util::GetNSString(IDS_IOS_APP_LAUNCHER_INSTALL_APP_BUTTON_LABEL);
-      [infoBarView addButton:buttonMsg
-                         tag:NATIVE_APP_ACTION_CLICK_INSTALL
-                      target:self
-                      action:@selector(infoBarButtonDidPress:)];
-      DCHECK(nativeAppInfoBarDelegate_->GetInstallText().length());
-      [infoBarView addLabel:base::SysUTF16ToNSString(
-                                nativeAppInfoBarDelegate_->GetInstallText())];
-      break;
-    }
-    case NATIVE_APP_LAUNCHER_CONTROLLER: {
-      NSString* buttonMsg =
-          l10n_util::GetNSString(IDS_IOS_APP_LAUNCHER_OPEN_APP_BUTTON_LABEL);
-      [infoBarView addButton:buttonMsg
-                         tag:NATIVE_APP_ACTION_CLICK_LAUNCH
-                      target:self
-                      action:@selector(infoBarButtonDidPress:)];
-      DCHECK(nativeAppInfoBarDelegate_->GetLaunchText().length());
-      [infoBarView addLabel:base::SysUTF16ToNSString(
-                                nativeAppInfoBarDelegate_->GetLaunchText())];
-      break;
-    }
-    case NATIVE_APP_OPEN_POLICY_CONTROLLER: {
-      NSString* labelMsg = base::SysUTF16ToNSString(
-          nativeAppInfoBarDelegate_->GetOpenPolicyText());
-      DCHECK(nativeAppInfoBarDelegate_->GetOpenPolicyText().length());
-      NSString* buttonOnceString = base::SysUTF16ToNSString(
-          nativeAppInfoBarDelegate_->GetOpenOnceText());
-      NSString* buttonAlwaysString = base::SysUTF16ToNSString(
-          nativeAppInfoBarDelegate_->GetOpenAlwaysText());
-      [infoBarView addLabel:labelMsg];
-      [infoBarView addButton1:buttonOnceString
-                         tag1:NATIVE_APP_ACTION_CLICK_ONCE
-                      button2:buttonAlwaysString
-                         tag2:NATIVE_APP_ACTION_CLICK_ALWAYS
-                       target:self
-                       action:@selector(infoBarButtonDidPress:)];
-      break;
-    }
-  }
-  return infoBarView;
-}
-
-- (void)infoBarButtonDidPress:(UIButton*)button {
-  DCHECK(nativeAppInfoBarDelegate_);
-  DCHECK([button isKindOfClass:[UIButton class]]);
-  // This press might have occurred after the user has already pressed a button,
-  // in which case the view has been detached from the delegate and this press
-  // should be ignored.
-  if (!self.delegate) {
-    return;
-  }
-  self.delegate->InfoBarDidCancel();
-  NativeAppActionType action = static_cast<NativeAppActionType>([button tag]);
-  [self userPerformedAction:action];
-}
-
-- (void)userPerformedAction:(NativeAppActionType)userAction {
-  nativeAppInfoBarDelegate_->UserPerformedAction(userAction);
-}
-
-#pragma mark - Testing
-
-- (void)setInfoBarDelegate:(NativeAppInfoBarDelegate*)delegate {
-  nativeAppInfoBarDelegate_ = delegate;
-}
-
-@end
diff --git a/ios/chrome/browser/native_app_launcher/native_app_infobar_controller_unittest.mm b/ios/chrome/browser/native_app_launcher/native_app_infobar_controller_unittest.mm
deleted file mode 100644
index 5676ce2..0000000
--- a/ios/chrome/browser/native_app_launcher/native_app_infobar_controller_unittest.mm
+++ /dev/null
@@ -1,105 +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 "ios/chrome/browser/native_app_launcher/native_app_infobar_controller.h"
-
-#include <memory>
-
-#include "base/mac/scoped_nsobject.h"
-#import "ios/public/provider/chrome/browser/native_app_launcher/native_app_types.h"
-#include "ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h"
-#import "ios/chrome/browser/native_app_launcher/native_app_navigation_controller_protocol.h"
-#include "testing/platform_test.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface NativeAppInfoBarController (Testing)
-- (void)infoBarButtonDidPress:(UIButton*)button;
-- (void)setInfoBarDelegate:(NativeAppInfoBarDelegate*)delegate;
-@end
-
-namespace {
-
-class NativeAppInfoBarControllerTest : public PlatformTest {
-  class MockNativeAppInfoBarDelegate : public NativeAppInfoBarDelegate {
-   public:
-    MockNativeAppInfoBarDelegate(NativeAppControllerType type)
-        : NativeAppInfoBarDelegate(nil, GURL(), type),
-          performedActionCount_(0),
-          userAction_(NATIVE_APP_ACTION_COUNT){};
-
-    void CheckIfPerformedActionIsCorrectAndResetCounter() {
-      EXPECT_EQ(expectedUserAction_, userAction_);
-      EXPECT_EQ(performedActionCount_, 1);
-      performedActionCount_ = 0;
-    }
-
-    void UserPerformedAction(NativeAppActionType userAction) override {
-      userAction_ = userAction;
-      performedActionCount_++;
-    };
-
-    void SetExpectedUserAction(const NativeAppActionType expectedUserAction) {
-      expectedUserAction_ = expectedUserAction;
-    };
-
-   private:
-    int performedActionCount_;
-    NativeAppActionType userAction_;
-    NativeAppActionType expectedUserAction_;
-  };
-
-  class MockInfobarViewDelegate : public InfoBarViewDelegate {
-   public:
-    void SetInfoBarTargetHeight(int height) override {}
-    void InfoBarDidCancel() override {}
-    void InfoBarButtonDidPress(NSUInteger button_id) override {}
-  };
-
- protected:
-  void SetUpWithType(NativeAppControllerType type) {
-    mockDelegate_.reset(new MockNativeAppInfoBarDelegate(type));
-    mockInfoBarViewDelegate_.reset(new MockInfobarViewDelegate());
-    infobarController_.reset([[NativeAppInfoBarController alloc]
-        initWithDelegate:mockInfoBarViewDelegate_.get()]);
-    [infobarController_ setInfoBarDelegate:mockDelegate_.get()];
-  };
-
-  // Checks -userPerformedAction: for calls to the delegate's
-  // UserPerformedAction member function.
-  void ExpectUserPerformedAction(NativeAppActionType performedAction) {
-    mockDelegate_->SetExpectedUserAction(performedAction);
-    UIButton* mockButton = [UIButton buttonWithType:UIButtonTypeCustom];
-    mockButton.tag = performedAction;
-    [infobarController_ infoBarButtonDidPress:mockButton];
-    mockDelegate_->CheckIfPerformedActionIsCorrectAndResetCounter();
-  };
-
-  base::scoped_nsobject<NativeAppInfoBarController> infobarController_;
-  std::unique_ptr<MockNativeAppInfoBarDelegate> mockDelegate_;
-  std::unique_ptr<MockInfobarViewDelegate> mockInfoBarViewDelegate_;
-};
-
-TEST_F(NativeAppInfoBarControllerTest, TestActionsWithInstallInfoBar) {
-  SetUpWithType(NATIVE_APP_INSTALLER_CONTROLLER);
-  ExpectUserPerformedAction(NATIVE_APP_ACTION_CLICK_INSTALL);
-  ExpectUserPerformedAction(NATIVE_APP_ACTION_DISMISS);
-}
-
-TEST_F(NativeAppInfoBarControllerTest, TestActionsWithLaunchInfoBar) {
-  SetUpWithType(NATIVE_APP_LAUNCHER_CONTROLLER);
-  ExpectUserPerformedAction(NATIVE_APP_ACTION_CLICK_LAUNCH);
-  ExpectUserPerformedAction(NATIVE_APP_ACTION_DISMISS);
-}
-
-TEST_F(NativeAppInfoBarControllerTest, TestActionsWithOpenPolicyInfoBar) {
-  SetUpWithType(NATIVE_APP_OPEN_POLICY_CONTROLLER);
-  ExpectUserPerformedAction(NATIVE_APP_ACTION_CLICK_ONCE);
-  ExpectUserPerformedAction(NATIVE_APP_ACTION_CLICK_ALWAYS);
-  ExpectUserPerformedAction(NATIVE_APP_ACTION_DISMISS);
-}
-
-}  // namespace
diff --git a/ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h b/ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h
deleted file mode 100644
index 179d16d..0000000
--- a/ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h
+++ /dev/null
@@ -1,74 +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 IOS_CHROME_BROWSER_NATIVE_APP_LAUNCHER_NATIVE_APP_INFOBAR_DELEGATE_H_
-#define IOS_CHROME_BROWSER_NATIVE_APP_LAUNCHER_NATIVE_APP_INFOBAR_DELEGATE_H_
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "components/infobars/core/infobar_delegate.h"
-#include "ios/chrome/browser/infobars/infobar.h"
-#import "ios/public/provider/chrome/browser/native_app_launcher/native_app_types.h"
-#include "url/gurl.h"
-
-@class NativeAppNavigationController;
-@protocol NativeAppNavigationControllerProtocol;
-@class NSString;
-@class UIImage;
-
-namespace infobars {
-class InfoBarManager;
-}  // namespace infobars
-
-namespace net {
-class URLRequestContextGetter;
-}  // namespace net
-
-namespace native_app_infobar {
-extern const CGSize kSmallIconSize;
-}  // namespace native_app_infobar
-
-// The delegate contains the information to create a
-// NativeAppInstallerInfoBarView, a NativeAppLauncherInfoBarView or a
-// NativeAppOpenPolicyInfoBarView.
-class NativeAppInfoBarDelegate : public infobars::InfoBarDelegate {
- public:
-  NativeAppInfoBarDelegate(id<NativeAppNavigationControllerProtocol> controller,
-                           const GURL& page_url,
-                           NativeAppControllerType type);
-  ~NativeAppInfoBarDelegate() override;
-
-  // Creates and adds a native app info bar to |manager|.
-  static bool Create(infobars::InfoBarManager* manager,
-                     id<NativeAppNavigationControllerProtocol> controller,
-                     const GURL& page_url,
-                     NativeAppControllerType type);
-
-  NativeAppInfoBarDelegate* AsNativeAppInfoBarDelegate() override;
-  base::string16 GetInstallText() const;
-  base::string16 GetLaunchText() const;
-  base::string16 GetOpenPolicyText() const;
-  base::string16 GetOpenOnceText() const;
-  base::string16 GetOpenAlwaysText() const;
-  const GURL& GetIconURL() const;
-  NSString* GetAppId() const;
-  infobars::InfoBarDelegate::Type GetInfoBarType() const override;
-  InfoBarIdentifier GetIdentifier() const override;
-  bool EqualsDelegate(infobars::InfoBarDelegate* delegate) const override;
-  net::URLRequestContextGetter* GetRequestContextGetter();
-  void FetchSmallAppIcon(void (^block)(UIImage*));
-  // This function is made virtual for tests.
-  virtual void UserPerformedAction(NativeAppActionType userAction);
-  NativeAppControllerType GetControllerType() const;
-
- private:
-  bool ShouldExpire(const NavigationDetails& details) const override;
-  __weak id<NativeAppNavigationControllerProtocol> controller_;
-  net::URLRequestContextGetter* requestContextGetter_;
-  GURL page_url_;
-  NativeAppControllerType type_;
-  DISALLOW_COPY_AND_ASSIGN(NativeAppInfoBarDelegate);
-};
-
-#endif  // IOS_CHROME_BROWSER_NATIVE_APP_LAUNCHER_NATIVE_APP_INFOBAR_DELEGATE_H_
diff --git a/ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.mm b/ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.mm
deleted file mode 100644
index 9e75ac9..0000000
--- a/ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.mm
+++ /dev/null
@@ -1,152 +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 "ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h"
-
-#import <Foundation/Foundation.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "components/infobars/core/infobar_manager.h"
-#import "ios/chrome/browser/native_app_launcher/native_app_infobar_controller.h"
-#import "ios/chrome/browser/native_app_launcher/native_app_navigation_controller_protocol.h"
-#include "ios/chrome/grit/ios_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace native_app_infobar {
-const CGSize kSmallIconSize = {29.0, 29.0};
-}  // namespace native_app_infobar
-
-NativeAppInfoBarDelegate::NativeAppInfoBarDelegate(
-    id<NativeAppNavigationControllerProtocol> controller,
-    const GURL& page_url,
-    NativeAppControllerType type)
-    : controller_(controller), page_url_(page_url), type_(type) {}
-
-NativeAppInfoBarDelegate::~NativeAppInfoBarDelegate() {}
-
-// static
-bool NativeAppInfoBarDelegate::Create(
-    infobars::InfoBarManager* manager,
-    id<NativeAppNavigationControllerProtocol> controller_protocol,
-    const GURL& page_url,
-    NativeAppControllerType type) {
-  DCHECK(manager);
-  auto infobar =
-      base::MakeUnique<InfoBarIOS>(base::MakeUnique<NativeAppInfoBarDelegate>(
-          controller_protocol, page_url, type));
-  NativeAppInfoBarController* controller =
-      [[NativeAppInfoBarController alloc] initWithDelegate:infobar.get()];
-  infobar->SetController(controller);
-  return !!manager->AddInfoBar(std::move(infobar));
-}
-
-bool NativeAppInfoBarDelegate::ShouldExpire(
-    const NavigationDetails& details) const {
-  return details.is_navigation_to_different_page;
-}
-
-NativeAppInfoBarDelegate*
-NativeAppInfoBarDelegate::AsNativeAppInfoBarDelegate() {
-  return this;
-}
-
-base::string16 NativeAppInfoBarDelegate::GetInstallText() const {
-  return l10n_util::GetStringFUTF16(
-      IDS_IOS_APP_LAUNCHER_OPEN_IN_APP_QUESTION_MESSAGE,
-      base::SysNSStringToUTF16([controller_ appName]));
-}
-
-base::string16 NativeAppInfoBarDelegate::GetLaunchText() const {
-  return l10n_util::GetStringFUTF16(
-      IDS_IOS_APP_LAUNCHER_OPEN_IN_APP_QUESTION_MESSAGE,
-      base::SysNSStringToUTF16([controller_ appName]));
-}
-
-base::string16 NativeAppInfoBarDelegate::GetOpenPolicyText() const {
-  return l10n_util::GetStringFUTF16(
-      IDS_IOS_APP_LAUNCHER_OPEN_IN_LABEL,
-      base::SysNSStringToUTF16([controller_ appName]));
-}
-
-base::string16 NativeAppInfoBarDelegate::GetOpenOnceText() const {
-  return l10n_util::GetStringUTF16(IDS_IOS_APP_LAUNCHER_OPEN_ONCE_BUTTON);
-}
-
-base::string16 NativeAppInfoBarDelegate::GetOpenAlwaysText() const {
-  return l10n_util::GetStringUTF16(IDS_IOS_APP_LAUNCHER_OPEN_ALWAYS_BUTTON);
-}
-
-NSString* NativeAppInfoBarDelegate::GetAppId() const {
-  return [controller_ appId];
-}
-
-infobars::InfoBarDelegate::Type NativeAppInfoBarDelegate::GetInfoBarType()
-    const {
-  return PAGE_ACTION_TYPE;
-}
-
-infobars::InfoBarDelegate::InfoBarIdentifier
-NativeAppInfoBarDelegate::GetIdentifier() const {
-  switch (type_) {
-    case NATIVE_APP_INSTALLER_CONTROLLER:
-      return NATIVE_APP_INSTALLER_INFOBAR_DELEGATE;
-    case NATIVE_APP_LAUNCHER_CONTROLLER:
-      return NATIVE_APP_LAUNCHER_INFOBAR_DELEGATE;
-    case NATIVE_APP_OPEN_POLICY_CONTROLLER:
-      return NATIVE_APP_OPEN_POLICY_INFOBAR_DELEGATE;
-  }
-}
-
-bool NativeAppInfoBarDelegate::EqualsDelegate(
-    infobars::InfoBarDelegate* delegate) const {
-  NativeAppInfoBarDelegate* nativeAppInfoBarDelegate =
-      delegate->AsNativeAppInfoBarDelegate();
-  return nativeAppInfoBarDelegate &&
-         [nativeAppInfoBarDelegate->GetAppId() isEqualToString:GetAppId()];
-}
-
-void NativeAppInfoBarDelegate::FetchSmallAppIcon(void (^block)(UIImage*)) {
-  [controller_ fetchSmallIconWithCompletionBlock:block];
-}
-
-void NativeAppInfoBarDelegate::UserPerformedAction(
-    NativeAppActionType userAction) {
-  [controller_ updateMetadataWithUserAction:userAction];
-  switch (userAction) {
-    case NATIVE_APP_ACTION_CLICK_INSTALL:
-      DCHECK(type_ == NATIVE_APP_INSTALLER_CONTROLLER);
-      [controller_ openStore];
-      break;
-    case NATIVE_APP_ACTION_CLICK_LAUNCH:
-      DCHECK(type_ == NATIVE_APP_LAUNCHER_CONTROLLER);
-      [controller_ launchApp:page_url_];
-      break;
-    case NATIVE_APP_ACTION_CLICK_ONCE:
-      DCHECK(type_ == NATIVE_APP_OPEN_POLICY_CONTROLLER);
-      [controller_ launchApp:page_url_];
-      break;
-    case NATIVE_APP_ACTION_CLICK_ALWAYS:
-      DCHECK(type_ == NATIVE_APP_OPEN_POLICY_CONTROLLER);
-      [controller_ launchApp:page_url_];
-      break;
-    case NATIVE_APP_ACTION_DISMISS:
-      break;
-    case NATIVE_APP_ACTION_IGNORE:
-    case NATIVE_APP_ACTION_COUNT:
-      NOTREACHED();
-      break;
-  }
-}
-
-NativeAppControllerType NativeAppInfoBarDelegate::GetControllerType() const {
-  return type_;
-}
diff --git a/ios/chrome/browser/native_app_launcher/native_app_infobar_delegate_unittest.mm b/ios/chrome/browser/native_app_launcher/native_app_infobar_delegate_unittest.mm
deleted file mode 100644
index 72b31ac..0000000
--- a/ios/chrome/browser/native_app_launcher/native_app_infobar_delegate_unittest.mm
+++ /dev/null
@@ -1,44 +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 "ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h"
-
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-#import "ios/public/provider/chrome/browser/native_app_launcher/native_app_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-class NativeAppInfoBarDelegateTest : public PlatformTest {};
-
-TEST_F(NativeAppInfoBarDelegateTest, TestIdentifiers) {
-  std::unique_ptr<NativeAppInfoBarDelegate> delegate;
-
-  delegate = base::MakeUnique<NativeAppInfoBarDelegate>(
-      nil, GURL(), NATIVE_APP_INSTALLER_CONTROLLER);
-  EXPECT_EQ(infobars::InfoBarDelegate::InfoBarIdentifier::
-                NATIVE_APP_INSTALLER_INFOBAR_DELEGATE,
-            delegate->GetIdentifier());
-
-  delegate = base::MakeUnique<NativeAppInfoBarDelegate>(
-      nil, GURL(), NATIVE_APP_LAUNCHER_CONTROLLER);
-  EXPECT_EQ(infobars::InfoBarDelegate::InfoBarIdentifier::
-                NATIVE_APP_LAUNCHER_INFOBAR_DELEGATE,
-            delegate->GetIdentifier());
-
-  delegate = base::MakeUnique<NativeAppInfoBarDelegate>(
-      nil, GURL(), NATIVE_APP_OPEN_POLICY_CONTROLLER);
-  EXPECT_EQ(infobars::InfoBarDelegate::InfoBarIdentifier::
-                NATIVE_APP_OPEN_POLICY_INFOBAR_DELEGATE,
-            delegate->GetIdentifier());
-}
-
-}  // namespace
diff --git a/ios/chrome/browser/native_app_launcher/native_app_navigation_controller_protocol.h b/ios/chrome/browser/native_app_launcher/native_app_navigation_controller_protocol.h
deleted file mode 100644
index c006f28..0000000
--- a/ios/chrome/browser/native_app_launcher/native_app_navigation_controller_protocol.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 IOS_CHROME_BROWSER_NATIVE_APP_LAUNCHER_NATIVE_APP_NAVIGATION_CONTROLLER_PROTOCOL_H_
-#define IOS_CHROME_BROWSER_NATIVE_APP_LAUNCHER_NATIVE_APP_NAVIGATION_CONTROLLER_PROTOCOL_H_
-
-#import "ios/public/provider/chrome/browser/native_app_launcher/native_app_types.h"
-
-class GURL;
-@class NSString;
-@class UIImage;
-
-// Protocol required for a controller to create a Native App Launcher infobar.
-@protocol NativeAppNavigationControllerProtocol
-// Returns app ID used to offer the installation of the application
-- (NSString*)appId;
-// Returns app name displayed in the infobar.
-- (NSString*)appName;
-// Asynchronously fetches icon and calls |block| when done.
-- (void)fetchSmallIconWithCompletionBlock:(void (^)(UIImage*))block;
-// Launches the application from the information extracted from |url|.
-- (void)launchApp:(const GURL&)url;
-// Opens store for the installation of the application.
-- (void)openStore;
-// Update metadata based on what the user did with the infobar.
-- (void)updateMetadataWithUserAction:(NativeAppActionType)userAction;
-@end
-
-#endif  // IOS_CHROME_BROWSER_NATIVE_APP_LAUNCHER_NATIVE_APP_NAVIGATION_CONTROLLER_PROTOCOL_H_
diff --git a/ios/chrome/browser/ui/autofill/autofill_client_ios.h b/ios/chrome/browser/ui/autofill/autofill_client_ios.h
index cb1a283..cb6b43ba 100644
--- a/ios/chrome/browser/ui/autofill/autofill_client_ios.h
+++ b/ios/chrome/browser/ui/autofill/autofill_client_ios.h
@@ -99,6 +99,7 @@
   bool ShouldShowSigninPromo() override;
   void StartSigninFlow() override;
   void ShowHttpNotSecureExplanation() override;
+  bool IsAutofillSupported() override;
 
  private:
   ios::ChromeBrowserState* browser_state_;
diff --git a/ios/chrome/browser/ui/autofill/autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
index 196df901..c938a2f 100644
--- a/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
+++ b/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
@@ -226,4 +226,8 @@
   NOTIMPLEMENTED();
 }
 
+bool AutofillClientIOS::IsAutofillSupported() {
+  return true;
+}
+
 }  // namespace autofill
diff --git a/ios/chrome/browser/ui/infobars/infobar_view.h b/ios/chrome/browser/ui/infobars/infobar_view.h
index 583552f3..8550e31 100644
--- a/ios/chrome/browser/ui/infobars/infobar_view.h
+++ b/ios/chrome/browser/ui/infobars/infobar_view.h
@@ -35,13 +35,6 @@
 // Adds icon subview.
 - (void)addLeftIcon:(UIImage*)image;
 
-// Adds transparent icon of size |imageSize| as placeholder during the time when
-// the icon is being downloaded.
-- (void)addPlaceholderTransparentIcon:(CGSize const&)imageSize;
-
-// Adds an icon subview with rounded corners and a shadow.
-- (void)addLeftIconWithRoundedCornersAndShadow:(UIImage*)image;
-
 // Creates a new string from |string| that is interpreted as a link by
 // |addLabel:|. |tag| must not be 0.
 + (NSString*)stringAsLink:(NSString*)string tag:(NSUInteger)tag;
diff --git a/ios/chrome/browser/ui/infobars/infobar_view.mm b/ios/chrome/browser/ui/infobars/infobar_view.mm
index d4b54623..9eb48b3 100644
--- a/ios/chrome/browser/ui/infobars/infobar_view.mm
+++ b/ios/chrome/browser/ui/infobars/infobar_view.mm
@@ -33,13 +33,6 @@
 
 const char kChromeInfobarURL[] = "chromeinternal://infobar/";
 
-// UX configuration constants for the shadow/rounded corners on the icon.
-const CGFloat kBaseSizeForEffects = 57.0;
-const CGFloat kCornerRadius = 10.0;
-const CGFloat kShadowVerticalOffset = 1.0;
-const CGFloat kShadowOpacity = 0.5;
-const CGFloat kShadowRadius = 0.8;
-
 // UX configuration for the layout of items.
 const CGFloat kLeftMarginOnFirstLineWhenIconAbsent = 20.0;
 const CGFloat kMinimumSpaceBetweenRightAndLeftAlignedWidgets = 30.0;
@@ -689,31 +682,6 @@
   [imageViewContainer_ addSubview:imageView_];
 }
 
-- (void)addPlaceholderTransparentIcon:(CGSize const&)imageSize {
-  UIGraphicsBeginImageContext(imageSize);
-  UIImage* placeholder = UIGraphicsGetImageFromCurrentImageContext();
-  UIGraphicsEndImageContext();
-  [self addLeftIcon:placeholder];
-}
-
-// Since shadows & rounded corners cannot be applied simultaneously to a
-// UIView, this method adds rounded corners to the UIImageView and then adds
-// drop shadow to the UIView containing the UIImageView.
-- (void)addLeftIconWithRoundedCornersAndShadow:(UIImage*)image {
-  CGFloat effectScaleFactor = image.size.width / kBaseSizeForEffects;
-  [self addLeftIcon:image];
-  CALayer* layer = [imageView_ layer];
-  [layer setMasksToBounds:YES];
-  [layer setCornerRadius:kCornerRadius * effectScaleFactor];
-  layer = [imageViewContainer_ layer];
-  [layer setShadowColor:[UIColor blackColor].CGColor];
-  [layer
-      setShadowOffset:CGSizeMake(0, kShadowVerticalOffset * effectScaleFactor)];
-  [layer setShadowOpacity:kShadowOpacity];
-  [layer setShadowRadius:kShadowRadius * effectScaleFactor];
-  [imageViewContainer_ setClipsToBounds:NO];
-}
-
 - (NSString*)stripMarkersFromString:(NSString*)string {
   linkRanges_.clear();
   for (;;) {
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
index 4e48fa85..5cb9352 100644
--- a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
@@ -56,12 +56,6 @@
 
 - (void)start {
   self.editViewController = [[PaymentRequestEditViewController alloc] init];
-  // TODO(crbug.com/602666): Title varies depending on what field is missing.
-  // e.g., Add Email vs. Add Phone Number.
-  NSString* title = self.address
-                        ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_ADDRESS)
-                        : l10n_util::GetNSString(IDS_PAYMENTS_ADD_ADDRESS);
-  [self.editViewController setTitle:title];
   [self.editViewController setDelegate:self];
   [self.editViewController setValidatorDelegate:self];
   self.mediator =
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator.mm b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
index 0a2ae33..99cb37e 100644
--- a/ios/chrome/browser/ui/payments/address_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
@@ -111,6 +111,13 @@
 
 #pragma mark - CreditCardEditViewControllerDataSource
 
+- (NSString*)title {
+  // TODO(crbug.com/602666): Title varies depending on what field is missing.
+  // e.g., Add Email vs. Add Phone Number.
+  return self.address ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_ADDRESS)
+                      : l10n_util::GetNSString(IDS_PAYMENTS_ADD_ADDRESS);
+}
+
 - (CollectionViewItem*)headerItem {
   return nil;
 }
diff --git a/ios/chrome/browser/ui/payments/billing_address_selection_coordinator.mm b/ios/chrome/browser/ui/payments/billing_address_selection_coordinator.mm
index 3335c86..3298c233 100644
--- a/ios/chrome/browser/ui/payments/billing_address_selection_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/billing_address_selection_coordinator.mm
@@ -61,8 +61,6 @@
       selectedBillingProfile:self.selectedBillingProfile];
 
   self.viewController = [[PaymentRequestSelectorViewController alloc] init];
-  self.viewController.title =
-      l10n_util::GetNSString(IDS_PAYMENTS_BILLING_ADDRESS);
   self.viewController.delegate = self;
   self.viewController.dataSource = self.mediator;
   [self.viewController loadModel];
diff --git a/ios/chrome/browser/ui/payments/billing_address_selection_mediator.mm b/ios/chrome/browser/ui/payments/billing_address_selection_mediator.mm
index 62df00f..f304761 100644
--- a/ios/chrome/browser/ui/payments/billing_address_selection_mediator.mm
+++ b/ios/chrome/browser/ui/payments/billing_address_selection_mediator.mm
@@ -72,6 +72,10 @@
   return YES;
 }
 
+- (NSString*)title {
+  return l10n_util::GetNSString(IDS_PAYMENTS_BILLING_ADDRESS);
+}
+
 - (CollectionViewItem*)headerItem {
   return nil;
 }
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
index ee359bf1..01642f2 100644
--- a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
@@ -51,13 +51,6 @@
 
 - (void)start {
   self.editViewController = [[PaymentRequestEditViewController alloc] init];
-  // TODO(crbug.com/602666): Title varies depending on what field is missing.
-  // e.g., Add Email vs. Add Phone Number.
-  NSString* title =
-      self.profile
-          ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_CONTACT_DETAILS_LABEL)
-          : l10n_util::GetNSString(IDS_PAYMENTS_ADD_CONTACT_DETAILS_LABEL);
-  [self.editViewController setTitle:title];
   [self.editViewController setDelegate:self];
   [self.editViewController setValidatorDelegate:self];
   self.mediator = [[ContactInfoEditMediator alloc]
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
index af5c782..a6f2686 100644
--- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
@@ -67,6 +67,14 @@
 
 #pragma mark - PaymentRequestEditViewControllerDataSource
 
+- (NSString*)title {
+  // TODO(crbug.com/602666): Title varies depending on what field is missing.
+  // e.g., Add Email vs. Add Phone Number.
+  return self.profile
+             ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_CONTACT_DETAILS_LABEL)
+             : l10n_util::GetNSString(IDS_PAYMENTS_ADD_CONTACT_DETAILS_LABEL);
+}
+
 - (CollectionViewItem*)headerItem {
   return nil;
 }
diff --git a/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.mm b/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.mm
index e73228e..f80cc9e 100644
--- a/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/contact_info_selection_coordinator.mm
@@ -63,8 +63,6 @@
       initWithPaymentRequest:self.paymentRequest];
 
   self.viewController = [[PaymentRequestSelectorViewController alloc] init];
-  self.viewController.title =
-      l10n_util::GetNSString(IDS_PAYMENT_REQUEST_CONTACT_INFO_SECTION_NAME);
   self.viewController.delegate = self;
   self.viewController.dataSource = self.mediator;
   [self.viewController loadModel];
diff --git a/ios/chrome/browser/ui/payments/contact_info_selection_mediator.mm b/ios/chrome/browser/ui/payments/contact_info_selection_mediator.mm
index 2e30016..082fb957 100644
--- a/ios/chrome/browser/ui/payments/contact_info_selection_mediator.mm
+++ b/ios/chrome/browser/ui/payments/contact_info_selection_mediator.mm
@@ -64,6 +64,10 @@
   return YES;
 }
 
+- (NSString*)title {
+  return l10n_util::GetNSString(IDS_PAYMENT_REQUEST_CONTACT_INFO_SECTION_NAME);
+}
+
 - (CollectionViewItem*)headerItem {
   return nil;
 }
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm
index 8ac85445..210b8984 100644
--- a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm
@@ -103,11 +103,6 @@
   _creditCard = _paymentMethod ? _paymentMethod->credit_card() : nil;
 
   _editViewController = [[PaymentRequestEditViewController alloc] init];
-  // TODO(crbug.com/602666): Title varies depending on the missing fields.
-  NSString* title = _creditCard
-                        ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_CARD)
-                        : l10n_util::GetNSString(IDS_PAYMENTS_ADD_CARD_LABEL);
-  [_editViewController setTitle:title];
   [_editViewController setDelegate:self];
   [_editViewController setValidatorDelegate:self];
   _mediator = [[CreditCardEditViewControllerMediator alloc]
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
index cf087c9d..1113cd3 100644
--- a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
@@ -103,6 +103,12 @@
 
 #pragma mark - PaymentRequestEditViewControllerDataSource
 
+- (NSString*)title {
+  // TODO(crbug.com/602666): Title varies depending on the missing fields.
+  return _creditCard ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_CARD)
+                     : l10n_util::GetNSString(IDS_PAYMENTS_ADD_CARD_LABEL);
+}
+
 - (CollectionViewItem*)headerItem {
   if (_creditCard && !autofill::IsCreditCardLocal(*_creditCard)) {
     // Return an item that identifies the server card being edited.
diff --git a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.mm b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.mm
index f4e2771..8e6f02b 100644
--- a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.mm
@@ -61,8 +61,6 @@
       initWithPaymentRequest:self.paymentRequest];
 
   self.viewController = [[PaymentRequestSelectorViewController alloc] init];
-  self.viewController.title =
-      l10n_util::GetNSString(IDS_PAYMENTS_METHOD_OF_PAYMENT_LABEL);
   self.viewController.delegate = self;
   self.viewController.dataSource = self.mediator;
   [self.viewController loadModel];
diff --git a/ios/chrome/browser/ui/payments/payment_method_selection_mediator.mm b/ios/chrome/browser/ui/payments/payment_method_selection_mediator.mm
index 3a202ea9..f1362e3a 100644
--- a/ios/chrome/browser/ui/payments/payment_method_selection_mediator.mm
+++ b/ios/chrome/browser/ui/payments/payment_method_selection_mediator.mm
@@ -69,6 +69,10 @@
   return YES;
 }
 
+- (NSString*)title {
+  return l10n_util::GetNSString(IDS_PAYMENTS_METHOD_OF_PAYMENT_LABEL);
+}
+
 - (CollectionViewItem*)headerItem {
   base::string16 headerText = payments::GetCardTypesAreAcceptedText(
       _paymentRequest->supported_card_types_set());
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
index 5b5acb4..bd7fac9 100644
--- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
@@ -226,6 +226,8 @@
   [super loadModel];
   CollectionViewModel* model = self.collectionViewModel;
 
+  self.title = [_dataSource title];
+
   [self.pickerViews removeAllObjects];
 
   CollectionViewItem* headerItem = [_dataSource headerItem];
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h
index 9393b6e..e6ade2bb 100644
--- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h
@@ -24,6 +24,9 @@
 // The current state of the view controller.
 @property(nonatomic, assign) EditViewControllerState state;
 
+// The title to display in the view controller.
+- (NSString*)title;
+
 // Returns the header item. May be nil.
 - (CollectionViewItem*)headerItem;
 
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_unittest.mm b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_unittest.mm
index b215901..d83a968a 100644
--- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_unittest.mm
@@ -22,6 +22,10 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+NSString* const kTestTitle = @"title";
+}  // namespace
+
 @interface TestPaymentRequestEditMediator
     : NSObject<PaymentRequestEditViewControllerDataSource>
 
@@ -34,6 +38,10 @@
 @synthesize state = _state;
 @synthesize consumer = _consumer;
 
+- (NSString*)title {
+  return kTestTitle;
+}
+
 - (CollectionViewItem*)headerItem {
   return [[CollectionViewTextItem alloc] init];
 }
@@ -101,6 +109,7 @@
   CheckController();
 
   [GetPaymentRequestEditViewController() loadModel];
+  CheckTitle(kTestTitle);
 
   // There is one section containing the header item, In addition to that, there
   // is one section for every form field (there are three fields in total) and
diff --git a/ios/chrome/browser/ui/payments/payment_request_selector_view_controller.mm b/ios/chrome/browser/ui/payments/payment_request_selector_view_controller.mm
index 0db5251..91fc0ff4 100644
--- a/ios/chrome/browser/ui/payments/payment_request_selector_view_controller.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_selector_view_controller.mm
@@ -115,6 +115,8 @@
   [super loadModel];
   CollectionViewModel* model = self.collectionViewModel;
 
+  self.title = [_dataSource title];
+
   // Set up trailing (edit or done) button.
   if (self.dataSource.state == PaymentRequestSelectorStateNormal &&
       [self.dataSource allowsEditMode]) {
diff --git a/ios/chrome/browser/ui/payments/payment_request_selector_view_controller_data_source.h b/ios/chrome/browser/ui/payments/payment_request_selector_view_controller_data_source.h
index 99a1acd..b2c24fe 100644
--- a/ios/chrome/browser/ui/payments/payment_request_selector_view_controller_data_source.h
+++ b/ios/chrome/browser/ui/payments/payment_request_selector_view_controller_data_source.h
@@ -35,6 +35,9 @@
 // Whether or not the view controller supports edit mode.
 - (BOOL)allowsEditMode;
 
+// The title to display in the view controller.
+- (NSString*)title;
+
 // The header item to display in the collection, if any.
 - (CollectionViewItem*)headerItem;
 
diff --git a/ios/chrome/browser/ui/payments/payment_request_selector_view_controller_unittest.mm b/ios/chrome/browser/ui/payments/payment_request_selector_view_controller_unittest.mm
index f0b8b26..3d0ff22 100644
--- a/ios/chrome/browser/ui/payments/payment_request_selector_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_selector_view_controller_unittest.mm
@@ -15,6 +15,10 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+NSString* const kTestTitle = @"title";
+}  // namespace
+
 @interface TestPaymentRequestSelectorMediator
     : NSObject<PaymentRequestSelectorViewControllerDataSource>
 
@@ -46,6 +50,10 @@
   return NO;
 }
 
+- (NSString*)title {
+  return kTestTitle;
+}
+
 - (CollectionViewItem*)headerItem {
   return [[CollectionViewItem alloc] init];
 }
@@ -89,6 +97,7 @@
   CheckController();
 
   [GetPaymentRequestSelectorViewController() loadModel];
+  CheckTitle(kTestTitle);
 
   ASSERT_EQ(1, NumberOfSections());
   // One header item, two selectable items, and one add button.
diff --git a/ios/chrome/browser/ui/payments/shipping_address_selection_coordinator.mm b/ios/chrome/browser/ui/payments/shipping_address_selection_coordinator.mm
index e25258d..001a03e 100644
--- a/ios/chrome/browser/ui/payments/shipping_address_selection_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/shipping_address_selection_coordinator.mm
@@ -9,7 +9,6 @@
 #include "base/logging.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/autofill/core/browser/autofill_profile.h"
-#include "components/payments/core/strings_util.h"
 #include "ios/chrome/browser/payments/payment_request.h"
 #import "ios/chrome/browser/payments/payment_request_util.h"
 #import "ios/chrome/browser/ui/payments/cells/autofill_profile_item.h"
@@ -21,10 +20,6 @@
 #endif
 
 namespace {
-using ::payment_request_util::GetShippingAddressSelectorErrorMessage;
-using ::payments::GetShippingAddressSectionString;
-using ::payments::GetShippingAddressSelectorInfoMessage;
-
 // The delay in nano seconds before notifying the delegate of the selection.
 const int64_t kDelegateNotificationDelayInNanoSeconds = 0.2 * NSEC_PER_SEC;
 }  // namespace
@@ -63,15 +58,8 @@
 - (void)start {
   self.mediator = [[ShippingAddressSelectionMediator alloc]
       initWithPaymentRequest:self.paymentRequest];
-  self.mediator.headerText =
-      self.paymentRequest->shipping_options().empty()
-          ? base::SysUTF16ToNSString(GetShippingAddressSelectorInfoMessage(
-                self.paymentRequest->shipping_type()))
-          : nil;
 
   self.viewController = [[PaymentRequestSelectorViewController alloc] init];
-  self.viewController.title = base::SysUTF16ToNSString(
-      GetShippingAddressSectionString(self.paymentRequest->shipping_type()));
   self.viewController.delegate = self;
   self.viewController.dataSource = self.mediator;
   [self.viewController loadModel];
@@ -96,8 +84,6 @@
   self.viewController.view.userInteractionEnabled = YES;
 
   DCHECK(self.paymentRequest);
-  self.mediator.headerText =
-      GetShippingAddressSelectorErrorMessage(*self.paymentRequest);
   self.mediator.state = PaymentRequestSelectorStateError;
   [self.viewController loadModel];
   [self.viewController.collectionView reloadData];
diff --git a/ios/chrome/browser/ui/payments/shipping_address_selection_mediator.h b/ios/chrome/browser/ui/payments/shipping_address_selection_mediator.h
index bcec5314..882b0f0 100644
--- a/ios/chrome/browser/ui/payments/shipping_address_selection_mediator.h
+++ b/ios/chrome/browser/ui/payments/shipping_address_selection_mediator.h
@@ -15,10 +15,6 @@
 @interface ShippingAddressSelectionMediator
     : NSObject<PaymentRequestSelectorViewControllerDataSource>
 
-// The text to display in the header item. If nil, the header item will also be
-// nil.
-@property(nonatomic, copy) NSString* headerText;
-
 // Redefined to be read-write.
 @property(nonatomic, readwrite, assign) PaymentRequestSelectorState state;
 
diff --git a/ios/chrome/browser/ui/payments/shipping_address_selection_mediator.mm b/ios/chrome/browser/ui/payments/shipping_address_selection_mediator.mm
index 086c2d3a..a2bbfc1 100644
--- a/ios/chrome/browser/ui/payments/shipping_address_selection_mediator.mm
+++ b/ios/chrome/browser/ui/payments/shipping_address_selection_mediator.mm
@@ -8,6 +8,7 @@
 
 #include "base/strings/sys_string_conversions.h"
 #include "components/autofill/core/browser/autofill_profile.h"
+#include "components/payments/core/strings_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/payments/payment_request.h"
 #import "ios/chrome/browser/payments/payment_request_util.h"
@@ -22,6 +23,9 @@
 #endif
 
 namespace {
+using ::payments::GetShippingAddressSectionString;
+using ::payments::GetShippingAddressSelectorInfoMessage;
+using ::payment_request_util::GetShippingAddressSelectorErrorMessage;
 using ::payment_request_util::GetAddressNotificationLabelFromAutofillProfile;
 using ::payment_request_util::GetNameLabelFromAutofillProfile;
 using ::payment_request_util::GetPhoneNumberLabelFromAutofillProfile;
@@ -42,7 +46,6 @@
 
 @implementation ShippingAddressSelectionMediator
 
-@synthesize headerText = _headerText;
 @synthesize state = _state;
 @synthesize selectedItemIndex = _selectedItemIndex;
 @synthesize paymentRequest = _paymentRequest;
@@ -59,18 +62,34 @@
   return self;
 }
 
+- (NSString*)getHeaderText {
+  if (self.state == PaymentRequestSelectorStateError) {
+    return GetShippingAddressSelectorErrorMessage(*self.paymentRequest);
+  } else {
+    return self.paymentRequest->shipping_options().empty()
+               ? base::SysUTF16ToNSString(GetShippingAddressSelectorInfoMessage(
+                     self.paymentRequest->shipping_type()))
+               : nil;
+  }
+}
+
 #pragma mark - PaymentRequestSelectorViewControllerDataSource
 
 - (BOOL)allowsEditMode {
   return YES;
 }
 
+- (NSString*)title {
+  return base::SysUTF16ToNSString(
+      GetShippingAddressSectionString(self.paymentRequest->shipping_type()));
+}
+
 - (CollectionViewItem*)headerItem {
-  if (!self.headerText.length)
+  if (![self getHeaderText].length)
     return nil;
 
   PaymentsTextItem* headerItem = [[PaymentsTextItem alloc] init];
-  headerItem.text = self.headerText;
+  headerItem.text = [self getHeaderText];
   if (self.state == PaymentRequestSelectorStateError)
     headerItem.image = NativeImage(IDR_IOS_PAYMENTS_WARNING);
   return headerItem;
diff --git a/ios/chrome/browser/ui/payments/shipping_option_selection_coordinator.mm b/ios/chrome/browser/ui/payments/shipping_option_selection_coordinator.mm
index d81b2af..9351689e 100644
--- a/ios/chrome/browser/ui/payments/shipping_option_selection_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/shipping_option_selection_coordinator.mm
@@ -6,7 +6,6 @@
 
 #include "base/logging.h"
 #include "base/strings/sys_string_conversions.h"
-#include "components/payments/core/strings_util.h"
 #include "ios/chrome/browser/payments/payment_request.h"
 #import "ios/chrome/browser/payments/payment_request_util.h"
 #include "ios/chrome/browser/ui/payments/shipping_option_selection_mediator.h"
@@ -18,7 +17,6 @@
 
 namespace {
 using ::payment_request_util::GetShippingOptionSelectorErrorMessage;
-using ::payments::GetShippingOptionSectionString;
 
 // The delay in nano seconds before notifying the delegate of the selection.
 const int64_t kDelegateNotificationDelayInNanoSeconds = 0.2 * NSEC_PER_SEC;
@@ -52,8 +50,6 @@
       initWithPaymentRequest:self.paymentRequest];
 
   self.viewController = [[PaymentRequestSelectorViewController alloc] init];
-  self.viewController.title = base::SysUTF16ToNSString(
-      GetShippingOptionSectionString(self.paymentRequest->shipping_type()));
   self.viewController.delegate = self;
   self.viewController.dataSource = self.mediator;
   [self.viewController loadModel];
diff --git a/ios/chrome/browser/ui/payments/shipping_option_selection_mediator.mm b/ios/chrome/browser/ui/payments/shipping_option_selection_mediator.mm
index e3bcaa20..cd59363 100644
--- a/ios/chrome/browser/ui/payments/shipping_option_selection_mediator.mm
+++ b/ios/chrome/browser/ui/payments/shipping_option_selection_mediator.mm
@@ -9,6 +9,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/payments/core/currency_formatter.h"
+#include "components/payments/core/strings_util.h"
 #include "ios/chrome/browser/payments/payment_request.h"
 #import "ios/chrome/browser/ui/payments/cells/payments_text_item.h"
 #include "ios/chrome/browser/ui/uikit_ui_util.h"
@@ -19,6 +20,10 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+using payments::GetShippingOptionSectionString;
+}  // namespace
+
 @interface ShippingOptionSelectionMediator ()
 
 // The PaymentRequest object owning an instance of web::PaymentRequest as
@@ -59,6 +64,11 @@
   return NO;
 }
 
+- (NSString*)title {
+  return base::SysUTF16ToNSString(
+      GetShippingOptionSectionString(self.paymentRequest->shipping_type()));
+}
+
 - (CollectionViewItem*)headerItem {
   if (!self.headerText.length)
     return nil;
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 4d7a12fc..a90c20f 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -143,7 +143,6 @@
     "//ios/chrome/browser/language:unit_tests",
     "//ios/chrome/browser/metrics:unit_tests",
     "//ios/chrome/browser/metrics:unit_tests_internal",
-    "//ios/chrome/browser/native_app_launcher:unit_tests",
     "//ios/chrome/browser/net:unit_tests",
     "//ios/chrome/browser/omaha:unit_tests",
     "//ios/chrome/browser/passwords:unit_tests",
diff --git a/ios/showcase/payments/sc_payments_editor_coordinator.mm b/ios/showcase/payments/sc_payments_editor_coordinator.mm
index 1d4ca68e..40a8c8ee 100644
--- a/ios/showcase/payments/sc_payments_editor_coordinator.mm
+++ b/ios/showcase/payments/sc_payments_editor_coordinator.mm
@@ -100,6 +100,10 @@
 
 #pragma mark - PaymentRequestEditViewControllerDataSource
 
+- (NSString*)title {
+  return nil;
+}
+
 - (CollectionViewItem*)headerItem {
   return nil;
 }
diff --git a/ios/showcase/payments/sc_payments_selector_coordinator.mm b/ios/showcase/payments/sc_payments_selector_coordinator.mm
index bcb25ce..c41441a5 100644
--- a/ios/showcase/payments/sc_payments_selector_coordinator.mm
+++ b/ios/showcase/payments/sc_payments_selector_coordinator.mm
@@ -74,6 +74,10 @@
   return NO;
 }
 
+- (NSString*)title {
+  return @"Title";
+}
+
 - (CollectionViewItem*)headerItem {
   return [self createItemWithText:@"Header item"];
 }
diff --git a/ios/web/web_state/navigation_callbacks_inttest.mm b/ios/web/web_state/navigation_callbacks_inttest.mm
index ec7867d..9df911e 100644
--- a/ios/web/web_state/navigation_callbacks_inttest.mm
+++ b/ios/web/web_state/navigation_callbacks_inttest.mm
@@ -87,15 +87,9 @@
   EXPECT_FALSE((*context)->GetError());
   ASSERT_FALSE((*context)->GetResponseHeaders());
   ASSERT_TRUE(web_state->IsLoading());
-  // TODO(crbug.com/676129): Reload does not create a pending item. Remove this
-  // workaround once the bug is fixed.
-  if (!ui::PageTransitionTypeIncludingQualifiersIs(
-          ui::PageTransition::PAGE_TRANSITION_RELOAD,
-          (*context)->GetPageTransition())) {
-    NavigationManager* navigation_manager = web_state->GetNavigationManager();
-    NavigationItem* item = navigation_manager->GetPendingItem();
-    EXPECT_EQ(url, item->GetURL());
-  }
+  NavigationManager* navigation_manager = web_state->GetNavigationManager();
+  NavigationItem* item = navigation_manager->GetPendingItem();
+  EXPECT_EQ(url, item->GetURL());
 }
 
 // Verifies correctness of |NavigationContext| (|arg0|) for navigations via POST
@@ -217,9 +211,8 @@
   EXPECT_FALSE((*context)->IsSameDocument());
   EXPECT_FALSE((*context)->GetError());
   EXPECT_FALSE((*context)->GetResponseHeaders());
-  // TODO(crbug.com/676129): Reload does not create a pending item. Check
-  // pending item once the bug is fixed.
-  EXPECT_FALSE(web_state->GetNavigationManager()->GetPendingItem());
+  EXPECT_EQ(web_state->GetNavigationManager()->GetPendingItem(),
+            web_state->GetNavigationManager()->GetLastCommittedItem());
 }
 
 // Verifies correctness of |NavigationContext| (|arg0|) for reload navigation
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index b08853ea..22cf740 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1520,11 +1520,18 @@
     // Typically on PAGE_TRANSITION_CLIENT_REDIRECT.
     [[self sessionController] updatePendingItem:requestURL];
   } else {
-    // A new session history entry needs to be created.
-    self.navigationManagerImpl->AddPendingItem(
-        requestURL, referrer, transition,
-        web::NavigationInitiationType::RENDERER_INITIATED,
-        web::NavigationManager::UserAgentOverrideOption::INHERIT);
+    // If this is a reload then there no need to create a new pending item,
+    // instead update the pending item to the last committed item.
+    if (PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD)) {
+      self.sessionController.pendingItemIndex =
+          self.sessionController.lastCommittedItemIndex;
+    } else {
+      // A new session history entry needs to be created.
+      self.navigationManagerImpl->AddPendingItem(
+          requestURL, referrer, transition,
+          web::NavigationInitiationType::RENDERER_INITIATED,
+          web::NavigationManager::UserAgentOverrideOption::INHERIT);
+    }
   }
   std::unique_ptr<web::NavigationContextImpl> context =
       web::NavigationContextImpl::CreateNavigationContext(
@@ -1979,6 +1986,11 @@
     BOOL isChromeScheme =
         web::GetWebClient()->IsAppSpecificURL(currentNavigationURL);
 
+    // Since this is implicit reload, no new pending item should be created, set
+    // the pending item index to the last committed item.
+    self.sessionController.pendingItemIndex =
+        self.sessionController.lastCommittedItemIndex;
+
     // Don't immediately load the web page if in overlay mode. Always load if
     // native.
     if (isChromeScheme || !_overlayPreviewMode) {
@@ -2020,6 +2032,10 @@
   _lastUserInteraction.reset();
   base::RecordAction(UserMetricsAction("Reload"));
   GURL url = self.currentNavItem->GetURL();
+  // Reloading shouldn't create create a new pending item, instead set the
+  // pending item index to the last committed item.
+  self.sessionController.pendingItemIndex =
+      self.sessionController.lastCommittedItemIndex;
   if ([self shouldLoadURLInNativeView:url]) {
     std::unique_ptr<web::NavigationContextImpl> navigationContext = [self
         registerLoadRequestForURL:url
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 9a2d752..c87d8e5 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -1112,9 +1112,6 @@
         NetLogEventType::SOCKET_POOL_REUSED_AN_EXISTING_SOCKET,
         NetLog::IntCallback("idle_ms",
                             static_cast<int>(idle_time.InMilliseconds())));
-
-    UMA_HISTOGRAM_COUNTS_1000("Net.Socket.IdleSocketReuseTime",
-                              idle_time.InSeconds());
   }
 
   if (reuse_type != ClientSocketHandle::UNUSED) {
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index f108173..45851ef5 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -268,18 +268,6 @@
         "test": "latency_unittests"
       },
       {
-        "args": [
-          "--ozone-platform=headless",
-          "--override-use-software-gl-for-tests",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mash.browser_tests.filter"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "hard_timeout": 900
-        },
-        "test": "mash_browser_tests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -509,6 +497,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "angle_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "app_list_presenter_unittests"
       },
       {
@@ -530,6 +524,30 @@
         "test": "ash_content_unittests"
       },
       {
+        "args": [
+          "--mash",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/ash_unittests_mash.filter"
+        ],
+        "name": "ash_unittests-mash",
+        "override_isolate_target": "ash_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ash_unittests"
+      },
+      {
+        "args": [
+          "--mus",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/ash_unittests_mus.filter"
+        ],
+        "name": "ash_unittests-mus",
+        "override_isolate_target": "ash_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ash_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -688,7 +706,8 @@
       },
       {
         "swarming": {
-          "can_use_on_swarming_builders": true
+          "can_use_on_swarming_builders": true,
+          "shards": 3
         },
         "test": "interactive_ui_tests"
       },
@@ -720,12 +739,24 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "mash_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_blink_unittests"
       },
       {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "media_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "media_unittests"
       },
       {
@@ -741,6 +772,18 @@
         "test": "midi_unittests"
       },
       {
+        "args": [
+          "--ozone-platform=headless",
+          "--override-use-software-gl-for-tests",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/mus.browser_tests.filter"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "hard_timeout": 900
+        },
+        "test": "mus_browser_tests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -765,6 +808,21 @@
         "test": "net_unittests"
       },
       {
+        "args": [
+          "--ozone-platform=headless"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ozone_gl_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "ozone_unittests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -780,6 +838,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "printing_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "remoting_unittests"
       },
       {
@@ -861,6 +925,18 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "views_mus_interactive_ui_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "views_mus_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "views_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index e6c0e68..ac5f7c6 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -4199,6 +4199,14 @@
       }
     ]
   },
+  "ClangToTLinux": {
+    "scripts": [
+      {
+        "name": "check_gn_headers",
+        "script": "check_gn_headers.py"
+      }
+    ]
+  },
   "ClangToTLinux tester": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 506864e..f591bd8 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -707,18 +707,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "ash_content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ash_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "aura_unittests"
       },
       {
@@ -729,13 +717,6 @@
       },
       {
         "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "cacheinvalidation_unittests"
@@ -844,13 +825,6 @@
       },
       {
         "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ipc_tests"
@@ -978,13 +952,6 @@
       },
       {
         "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "url_unittests"
diff --git a/testing/buildbot/filters/ash_unittests_mus.filter b/testing/buildbot/filters/ash_unittests_mus.filter
index dec585b..417488e 100644
--- a/testing/buildbot/filters/ash_unittests_mus.filter
+++ b/testing/buildbot/filters/ash_unittests_mus.filter
@@ -1,11 +1,3 @@
-# TODO: fix these. They all timeout. http://crbug.com/734811.
--ScreenRotationAnimatorSmoothAnimationTest.OverviewButtonTrayHideAnimationAlwaysCompletes
--ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalPrimaryDisplayBeforeSecondCopyCallback
--ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalPrimaryDisplayDuringAnimationChangedRootWindow
--ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalSecondaryDisplayBeforeSecondCopyCallback
--ScreenRotationAnimatorSmoothAnimationTest.RotatesToDifferentRotationWithCopyCallback
--ScreenRotationAnimatorSmoothAnimationTest.ShouldRotateAfterRecreateLayers
-
 # TODO: fix these. They fail because DeviceDataManager isn't created.
 # http://crbug.com/734812.
 -TrayIMETest.HidesOnA11yEnabled
diff --git a/testing/scripts/check_gn_headers.py b/testing/scripts/check_gn_headers.py
index cb2520c3..6530ada7 100755
--- a/testing/scripts/check_gn_headers.py
+++ b/testing/scripts/check_gn_headers.py
@@ -44,4 +44,4 @@
     'run': main_run,
     'compile_targets': main_compile_targets,
   }
-  sys.exit(common.run_script(sys.argv[1:], funcs))
+  common.run_script(sys.argv[1:], funcs)
diff --git a/testing/scripts/webview_licenses.py b/testing/scripts/webview_licenses.py
deleted file mode 100755
index 255c62e..0000000
--- a/testing/scripts/webview_licenses.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import json
-import os
-import sys
-
-
-import common
-
-
-def main_run(args):
-  with common.temporary_file() as tempfile_path:
-    rc = common.run_command([
-        os.path.join(common.SRC_DIR, 'android_webview', 'tools',
-                     'webview_licenses.py'),
-        'scan',
-        '--json', tempfile_path
-    ])
-
-    with open(tempfile_path) as f:
-      results = json.load(f)
-
-  json.dump({
-      'valid': True,
-      'failures': results,
-  }, args.output)
-
-  return rc
-
-
-def main_compile_targets(args):
-  json.dump([], args.output)
-
-
-if __name__ == '__main__':
-  funcs = {
-    'run': main_run,
-    'compile_targets': main_compile_targets,
-  }
-  sys.exit(common.run_script(sys.argv[1:], funcs))
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 7166869..6a8af3f 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -241,12 +241,6 @@
 crbug.com/711807 external/wpt/css/CSS2/normal-flow/replaced-intrinsic-002.xht [ Skip ]
 crbug.com/711807 external/wpt/css/CSS2/normal-flow/width-inherit-001.xht [ Skip ]
 
-#### third_party/WebKit/LayoutTests/external/wpt/css-paint-api
-#### Passed: 50
-#### Skipped: 2
-crbug.com/578252 external/wpt/css-paint-api/background-image-tiled.html [ Skip ]
-crbug.com/578252 external/wpt/css-paint-api/geometry-background-image-tiled-001.html [ Skip ]
-
 #### third_party/WebKit/LayoutTests/overflow
 crbug.com/724697 overflow/overflow-basic-002.html [ Failure ]
 crbug.com/724701 overflow/overflow-basic-004.html [ Failure ]
@@ -1660,6 +1654,9 @@
 crbug.com/646644 [ Mac10.9 ] http/tests/media/video-buffered-range-contains-currentTime.html [ Failure Timeout ]
 crbug.com/646644 [ Mac10.9 ] virtual/mojo-loading/http/tests/media/video-buffered-range-contains-currentTime.html [ Failure Timeout ]
 
+crbug.com/743068 [ Mac10.9 ] fast/forms/calendar-picker/calendar-picker-appearance-zoom125.html [ Pass Failure ]
+crbug.com/743068 [ Mac10.9 ] fast/forms/calendar-picker/calendar-picker-appearance-zoom200.html [ Pass Failure ]
+
 crbug.com/637930 http/tests/media/video-buffered.html [ Pass Failure ]
 crbug.com/637930 virtual/mojo-loading/http/tests/media/video-buffered.html [ Pass Failure ]
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-multiple-hashing-algorithms.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-multiple-hashing-algorithms.html
new file mode 100644
index 0000000..75ff342
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-multiple-hashing-algorithms.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Multiple policies with different hashing algorithms still work.</title>
+  <!-- nonces are here just to let all of our scripts run -->
+  <script nonce="abc" src='/resources/testharness.js'></script>
+  <script nonce="abc" src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+  <script nonce="abc">
+    var t = async_test("Test that script executes if allowed by proper hash values");
+    document.addEventListener("securitypolicyviolation", t.unreached_func("Should not have triggered a security event"));
+    var executed = false;
+  </script>
+
+  <!-- test will fail if this script is not allowed to run -->
+  <script>executed = true;</script>
+
+  <script nonce="abc">
+    t.step(function() {
+      assert_true(executed);
+      t.done();
+    });
+  </script>
+
+  <script nonce="abc" async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-multiple-hashing-algorithms.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-multiple-hashing-algorithms.html.sub.headers
new file mode 100644
index 0000000..36203b76
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-multiple-hashing-algorithms.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-multiple-policies-multiple-hashing-algorithms={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: script-src 'sha256-EpVP4fTImWaRzBRBw/wrdfLhGTe/1U+CaBP1LNeKUIE=' 'nonce-abc'; report-uri ../support/report.py?op=put&reportID={{$id}}
+Content-Security-Policy: script-src 'sha384-skw7BVxHbmE2umPGMd1kX+ye6qBeHAb875erPoD8ilKv1LkjKR+WFi7N85ORMdhS' 'nonce-abc'; report-uri ../support/report.py?op=put&reportID={{$id}}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-one-using-hashing-algorithms.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-one-using-hashing-algorithms.html
new file mode 100644
index 0000000..34fed6d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-one-using-hashing-algorithms.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Multiple policies some using hashes some not using hashes still work.</title>
+  <!-- nonces are here just to let all of our scripts run -->
+  <script nonce="abc" src='/resources/testharness.js'></script>
+  <script nonce="abc" src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+  <script nonce="abc">
+    var t = async_test("Test that script executes if allowed by proper hash values");
+    document.addEventListener("securitypolicyviolation", t.unreached_func("Should not have triggered a security event"));
+    var executed = false;
+  </script>
+
+  <!-- test will fail if this script is not allowed to run -->
+  <script>executed = true;</script>
+
+  <script nonce="abc">
+    t.step(function() {
+      assert_true(executed);
+      t.done();
+    });
+  </script>
+
+  <script nonce="abc" async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-one-using-hashing-algorithms.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-one-using-hashing-algorithms.html.sub.headers
new file mode 100644
index 0000000..114c560b2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-multiple-policies-one-using-hashing-algorithms.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-multiple-policies-multiple-hashing-algorithms-work={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: script-src 'sha256-EpVP4fTImWaRzBRBw/wrdfLhGTe/1U+CaBP1LNeKUIE=' 'nonce-abc'; report-uri ../support/report.py?op=put&reportID={{$id}}
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html
new file mode 100644
index 0000000..f0f7bcb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>A report-only policy that does not allow a script should not affect an enforcing policy using hashes.</title>
+  <!-- nonces are here just to let all of our scripts run -->
+  <script nonce="abc" src='/resources/testharness.js'></script>
+  <script nonce="abc" src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+  <script nonce="abc">
+    var externalRan = false;
+  </script>
+  <script src='./externalScript.js'
+          integrity="sha256-wIc3KtqOuTFEu6t17sIBuOswgkV406VJvhSk79Gw6U0="></script>
+  <script nonce="abc">
+    test(function() {
+      assert_true(externalRan, 'External script ran.');
+    }, 'External script in a script tag with matching SRI hash should run.');
+  </script>
+
+  <script nonce="abc" async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27nonce-abc%27'></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html.sub.headers
new file mode 100644
index 0000000..0ccfd50
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-report-only-policy-works-with-external-hash-policy={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: script-src 'sha256-wIc3KtqOuTFEu6t17sIBuOswgkV406VJvhSk79Gw6U0=' 'nonce-abc'
+Content-Security-Policy-Report-Only: script-src 'nonce-abc'; report-uri ../support/report.py?op=put&reportID={{$id}}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html
new file mode 100644
index 0000000..82a88791
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>A report-only policy that does not allow a script should not affect an enforcing policy using hashes.</title>
+  <!-- nonces are here just to let all of our scripts run -->
+  <script nonce="abc" src='/resources/testharness.js'></script>
+  <script nonce="abc" src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+  <script nonce="abc">
+    var t = async_test("Test that script executes if allowed by proper hash values");
+    var t_spv = async_test("Test that the securitypolicyviolation event is fired");
+    document.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) {
+      assert_equals(e.violatedDirective, "script-src");
+      assert_equals(e.disposition, "report");
+      assert_equals(e.blockedURI, "inline");
+    }));
+    var executed = false;
+  </script>
+
+  <!-- test will fail if this script is not allowed to run -->
+  <script>executed = true;</script>
+
+  <script nonce="abc">
+    t.step(function() {
+      assert_true(executed);
+      t.done();
+    });
+  </script>
+
+  <script nonce="abc" async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27nonce-abc%27'></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html.sub.headers
new file mode 100644
index 0000000..eaf175a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-report-only-policy-works-with-hash-policy={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: script-src 'sha256-EpVP4fTImWaRzBRBw/wrdfLhGTe/1U+CaBP1LNeKUIE=' 'nonce-abc'
+Content-Security-Policy-Report-Only: script-src 'nonce-abc'; report-uri ../support/report.py?op=put&reportID={{$id}}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/style-src/style-src-multiple-policies-multiple-hashing-algorithms.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/style-src/style-src-multiple-policies-multiple-hashing-algorithms.html
new file mode 100644
index 0000000..1575cd6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/style-src/style-src-multiple-policies-multiple-hashing-algorithms.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Multiple policies with different hashing algorithms still work.</title>
+  <script src='/resources/testharness.js'></script>
+  <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+  <script>
+    var t = async_test("Test that style loads if allowed by proper hash values");
+    document.addEventListener("securitypolicyviolation", t.unreached_func("Should not have triggered a security event"));
+  </script>
+
+  <!-- test will time out if this style is not allowed to load -->
+  <style onload="t.done();" onerror="t.unreached_func('Should have loaded the style');">p {color:blue;}</style>
+
+  <script async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/style-src/style-src-multiple-policies-multiple-hashing-algorithms.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/style-src/style-src-multiple-policies-multiple-hashing-algorithms.html.sub.headers
new file mode 100644
index 0000000..8d83a34
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/style-src/style-src-multiple-policies-multiple-hashing-algorithms.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: style-src-multiple-policies-multiple-hashing-algorithms={{$id:uuid()}}; Path=/content-security-policy/style-src/
+Content-Security-Policy: style-src 'sha256-rB6kiow2O3eFUeTNyyLeK3wV0+l7vNB90J1aqllKvjg='; script-src 'unsafe-inline' 'self'; report-uri ../support/report.py?op=put&reportID={{$id}}
+Content-Security-Policy: style-src 'sha384-DAShdG5sejEaOdWfT+TQMRP5mHssKiUNjFggNnElIvIoj048XQlacVRs+za2AM1a'; script-src 'unsafe-inline' 'self'; report-uri ../support/report.py?op=put&reportID={{$id}}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled-ref.html
index a0151d8..fe12f16 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled-ref.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled-ref.html
@@ -5,12 +5,9 @@
 <canvas id ="two" width="100" height="100"></canvas>
 <script>
 function drawCircle(ctx, geom) {
-    var x = geom.width / 2;
-    var y = geom.height / 2;
-
     ctx.fillStyle = 'green';
     ctx.beginPath();
-    ctx.ellipse(x, y, x - 1, y - 1, 0, 0, 2 * Math.PI);
+    ctx.rect(0, 0, geom.width, geom.height);
     ctx.fill();
 }
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled.html
index 95d8c12..0497acf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/background-image-tiled.html
@@ -29,12 +29,9 @@
 <script id="code" type="text/worklet">
 registerPaint('ellipse', class {
     paint(ctx, geom) {
-        var x = geom.width / 2;
-        var y = geom.height / 2;
-
         ctx.fillStyle = 'green';
         ctx.beginPath();
-        ctx.ellipse(x, y, x - 1, y - 1, 0, 0, 2 * Math.PI);
+        ctx.rect(0, 0, geom.width, geom.height);
         ctx.fill();
     }
 });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/geometry-background-image-tiled-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/geometry-background-image-tiled-001-ref.html
index 9f633a9..ce7988f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/geometry-background-image-tiled-001-ref.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/geometry-background-image-tiled-001-ref.html
@@ -8,10 +8,8 @@
 <script>
 var canvas = document.getElementById('canvas');
 var context = canvas.getContext("2d");
-context.strokeStyle = 'green';
-context.lineWidth = 4;
-context.strokeRect(0, 0, 50, 50);
-context.strokeRect(50, 0, 50, 50);
+context.fillStyle = 'green';
+context.fillRect(0, 0, 100, 50);
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/geometry-background-image-tiled-001.html b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/geometry-background-image-tiled-001.html
index d2b7e92..5cf8eb7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/geometry-background-image-tiled-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css-paint-api/geometry-background-image-tiled-001.html
@@ -21,9 +21,10 @@
 <script id="code" type="text/worklet">
 registerPaint('geometry', class {
     paint(ctx, geom) {
-        ctx.strokeStyle = 'green';
-        ctx.lineWidth = 4;
-        ctx.strokeRect(0, 0, geom.width, geom.height);
+        ctx.fillStyle = 'green';
+        ctx.beginPath();
+        ctx.rect(0, 0, geom.width, geom.height);
+        ctx.fill();
     }
 });
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_on_table_row-expected.html b/third_party/WebKit/LayoutTests/fast/table/backgr_on_table_row-expected.html
new file mode 100644
index 0000000..0d1ff60a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_on_table_row-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Tests background image render for TR</title>
+    <style>
+    .selected {
+      background-repeat: repeat-x;
+      background-position: top;
+      background: linear-gradient(to bottom, #C0C0FF, #FFFFFF);
+      color: black;
+    }
+    </style>
+  </head>
+  <body>
+    <table cellspacing="0" cellpadding="0">
+      <tr>
+        <td class="selected">Background set on row.</td>
+      </tr>
+      <tr>
+        <td class="selected">Background set on cell.</td>
+      </tr>
+    </table>
+    <p>
+      Background images should render the same whether set on the table
+      row or the table cell.
+    </p>
+    <p>
+      Test passes if backgrounds for the two rows above are identical.
+    </p>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_on_table_row.html b/third_party/WebKit/LayoutTests/fast/table/backgr_on_table_row.html
new file mode 100644
index 0000000..33540a5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_on_table_row.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Tests background image render for TR</title>
+    <style>
+    .selected {
+      background-repeat: repeat-x;
+      background-position: top;
+      background: linear-gradient(to bottom, #C0C0FF, #FFFFFF);
+      color: black;
+    }
+    </style>
+  </head>
+  <body>
+    <table cellspacing="0" cellpadding="0">
+      <tr class="selected">
+        <td>Background set on row.</td>
+      </tr>
+      <tr>
+        <td class="selected">Background set on cell.</td>
+      </tr>
+    </table>
+    <p>
+      Background images should render the same whether set on the table
+      row or the table cell.
+    </p>
+    <p>
+      Test passes if backgrounds for the two rows above are identical.
+    </p>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
index c37aea6..c6c6214 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
Binary files differ
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index 2087d79..ef3e81c 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1102,19 +1102,6 @@
   foreach(current, targets_generating_sources) {
     sources += get_target_outputs(current)
   }
-  jumbo_excluded_sources = [
-    # Same variables as HTMLElementFactory
-    "$blink_core_output_dir/SVGElementFactory.cpp",
-
-    # Same variables (stringpool_t, stringpool_contents) as CSSValueKeywords
-    "$blink_core_output_dir/CSSPropertyNames.cpp",
-
-    # Global "using namespace blink" and "using namespace XPath"
-    "$blink_core_output_dir/XPathGrammar.cpp",
-
-    # Using global "using namespace WTF"
-    "//third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp",
-  ]
   public_deps = [
     ":all_generators",
     "//third_party/WebKit/Source/bindings/core/v8:bindings_core_impl",
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index e5a9f5cf..a75f292 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -4166,7 +4166,7 @@
                                             ShadowRootType::kUserAgent) ||
              GetDocument().GetContentSecurityPolicy()->AllowInlineStyle(
                  this, GetDocument().Url(), String(), start_line_number,
-                 new_style_string)) {
+                 new_style_string, ContentSecurityPolicy::InlineType::kBlock)) {
     SetInlineStyleFromString(new_style_string);
   }
 
diff --git a/third_party/WebKit/Source/core/dom/MockScriptElementBase.h b/third_party/WebKit/Source/core/dom/MockScriptElementBase.h
index 828e5c2e..9c7ccdb 100644
--- a/third_party/WebKit/Source/core/dom/MockScriptElementBase.h
+++ b/third_party/WebKit/Source/core/dom/MockScriptElementBase.h
@@ -43,10 +43,11 @@
   MOCK_CONST_METHOD0(HasChildren, bool());
   MOCK_CONST_METHOD0(GetNonceForElement, const AtomicString&());
   MOCK_CONST_METHOD0(InitiatorName, AtomicString());
-  MOCK_METHOD3(AllowInlineScriptForCSP,
+  MOCK_METHOD4(AllowInlineScriptForCSP,
                bool(const AtomicString&,
                     const WTF::OrdinalNumber&,
-                    const String&));
+                    const String&,
+                    ContentSecurityPolicy::InlineType));
   MOCK_CONST_METHOD0(GetDocument, Document&());
   MOCK_METHOD1(SetScriptElementForBinding,
                void(HTMLScriptElementOrSVGScriptElement&));
diff --git a/third_party/WebKit/Source/core/dom/ScriptElementBase.h b/third_party/WebKit/Source/core/dom/ScriptElementBase.h
index 5b7a651..fd5a299 100644
--- a/third_party/WebKit/Source/core/dom/ScriptElementBase.h
+++ b/third_party/WebKit/Source/core/dom/ScriptElementBase.h
@@ -22,6 +22,7 @@
 #define ScriptElementBase_h
 
 #include "core/CoreExport.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
 #include "platform/heap/Handle.h"
 #include "platform/heap/Heap.h"
 #include "platform/wtf/text/AtomicString.h"
@@ -59,7 +60,8 @@
 
   virtual bool AllowInlineScriptForCSP(const AtomicString& nonce,
                                        const WTF::OrdinalNumber&,
-                                       const String& script_content) = 0;
+                                       const String& script_content,
+                                       ContentSecurityPolicy::InlineType) = 0;
   virtual Document& GetDocument() const = 0;
   virtual void SetScriptElementForBinding(
       HTMLScriptElementOrSVGScriptElement&) = 0;
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index 067b2a8e..43066d4 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -822,17 +822,14 @@
     return ExecuteScriptResult::kShouldFireNone;
 
   if (!is_external_script_) {
-    const ContentSecurityPolicy* csp =
-        element_document->GetContentSecurityPolicy();
     bool should_bypass_main_world_csp =
-        (frame->GetScriptController().ShouldBypassMainWorldCSP()) ||
-        csp->AllowScriptWithHash(script->InlineSourceTextForCSP(),
-                                 ContentSecurityPolicy::InlineType::kBlock);
+        (frame->GetScriptController().ShouldBypassMainWorldCSP());
 
     AtomicString nonce = element_->GetNonceForElement();
     if (!should_bypass_main_world_csp &&
-        !element_->AllowInlineScriptForCSP(nonce, start_line_number_,
-                                           script->InlineSourceTextForCSP())) {
+        !element_->AllowInlineScriptForCSP(
+            nonce, start_line_number_, script->InlineSourceTextForCSP(),
+            ContentSecurityPolicy::InlineType::kBlock)) {
       return ExecuteScriptResult::kShouldFireErrorEvent;
     }
   }
diff --git a/third_party/WebKit/Source/core/dom/StyleElement.cpp b/third_party/WebKit/Source/core/dom/StyleElement.cpp
index 8e883cf..6027697 100644
--- a/third_party/WebKit/Source/core/dom/StyleElement.cpp
+++ b/third_party/WebKit/Source/core/dom/StyleElement.cpp
@@ -139,10 +139,9 @@
   const ContentSecurityPolicy* csp = document.GetContentSecurityPolicy();
   bool passes_content_security_policy_checks =
       ShouldBypassMainWorldCSP(element) ||
-      csp->AllowStyleWithHash(text,
-                              ContentSecurityPolicy::InlineType::kBlock) ||
       csp->AllowInlineStyle(&element, document.Url(), element.nonce(),
-                            start_position_.line_, text);
+                            start_position_.line_, text,
+                            ContentSecurityPolicy::InlineType::kBlock);
 
   // Clearing the current sheet may remove the cache entry so create the new
   // sheet first
diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
index 4f1744f..8c35c32 100644
--- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
@@ -420,185 +420,11 @@
   return headers;
 }
 
-template <
-    bool (CSPDirectiveList::*allowed)(ScriptState* script_state,
-                                      SecurityViolationReportingPolicy,
-                                      ContentSecurityPolicy::ExceptionStatus,
-                                      const String& script_content) const>
-bool IsAllowedByAll(const CSPDirectiveListVector& policies,
-                    ScriptState* script_state,
-                    SecurityViolationReportingPolicy reporting_policy,
-                    ContentSecurityPolicy::ExceptionStatus exception_status,
-                    const String& script_content) {
-  bool is_allowed = true;
-  for (const auto& policy : policies) {
-    is_allowed &= (policy.Get()->*allowed)(script_state, reporting_policy,
-                                           exception_status, script_content);
-  }
-  return is_allowed;
-}
-
-template <bool (CSPDirectiveList::*allowed)(Element*,
-                                            const String&,
-                                            const String&,
-                                            const WTF::OrdinalNumber&,
-                                            SecurityViolationReportingPolicy)
-              const>
-bool IsAllowedByAll(const CSPDirectiveListVector& policies,
-                    Element* element,
-                    const String& source,
-                    const String& context_url,
-                    const WTF::OrdinalNumber& context_line,
-                    SecurityViolationReportingPolicy reporting_policy) {
-  bool is_allowed = true;
-  for (const auto& policy : policies) {
-    is_allowed &= (policy.Get()->*allowed)(element, source, context_url,
-                                           context_line, reporting_policy);
-  }
-  return is_allowed;
-}
-
-template <bool (CSPDirectiveList::*allowed)(Element*,
-                                            const String&,
-                                            const String&,
-                                            const WTF::OrdinalNumber&,
-                                            SecurityViolationReportingPolicy,
-                                            const String& content) const>
-bool IsAllowedByAll(const CSPDirectiveListVector& policies,
-                    Element* element,
-                    const String& context_url,
-                    const String& nonce,
-                    const WTF::OrdinalNumber& context_line,
-                    SecurityViolationReportingPolicy reporting_policy,
-                    const String& content) {
-  bool is_allowed = true;
-  for (const auto& policy : policies) {
-    is_allowed &= (policy.Get()->*allowed)(
-        element, context_url, nonce, context_line, reporting_policy, content);
-  }
-  return is_allowed;
-}
-
-template <bool (CSPDirectiveList::*allowed)(const CSPHashValue&,
-                                            ContentSecurityPolicy::InlineType)
-              const>
-bool IsAllowedByAll(const CSPDirectiveListVector& policies,
-                    const CSPHashValue& hash_value,
-                    ContentSecurityPolicy::InlineType type) {
-  bool is_allowed = true;
-  for (const auto& policy : policies)
-    is_allowed &= (policy.Get()->*allowed)(hash_value, type);
-  return is_allowed;
-}
-
-template <bool (CSPDirectiveList::*allowFromURL)(
-    const KURL&,
-    RedirectStatus,
-    SecurityViolationReportingPolicy) const>
-bool IsAllowedByAll(const CSPDirectiveListVector& policies,
-                    const KURL& url,
-                    RedirectStatus redirect_status,
-                    SecurityViolationReportingPolicy reporting_policy,
-                    ContentSecurityPolicy::CheckHeaderType check_header_type) {
-  if (ContentSecurityPolicy::ShouldBypassContentSecurityPolicy(url))
-    return true;
-
-  bool is_allowed = true;
-  for (const auto& policy : policies) {
-    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
-      continue;
-    is_allowed &=
-        (policy.Get()->*allowFromURL)(url, redirect_status, reporting_policy);
-  }
-
-  return is_allowed;
-}
-
-template <bool (CSPDirectiveList::*allowFromURLWithNonce)(
-    const KURL&,
-    const String& nonce,
-    RedirectStatus,
-    SecurityViolationReportingPolicy) const>
-bool IsAllowedByAll(const CSPDirectiveListVector& policies,
-                    const KURL& url,
-                    const String& nonce,
-                    RedirectStatus redirect_status,
-                    SecurityViolationReportingPolicy reporting_policy,
-                    ContentSecurityPolicy::CheckHeaderType check_header_type) {
-  if (ContentSecurityPolicy::ShouldBypassContentSecurityPolicy(url))
-    return true;
-
-  bool is_allowed = true;
-  for (const auto& policy : policies) {
-    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
-      continue;
-    is_allowed &= (policy.Get()->*allowFromURLWithNonce)(
-        url, nonce, redirect_status, reporting_policy);
-  }
-  return is_allowed;
-}
-
-template <bool (CSPDirectiveList::*allowFromURLWithNonceAndParser)(
-    const KURL&,
-    const String& nonce,
-    const IntegrityMetadataSet& hashes,
-    ParserDisposition parser_disposition,
-    RedirectStatus,
-    SecurityViolationReportingPolicy) const>
-bool IsAllowedByAll(const CSPDirectiveListVector& policies,
-                    const KURL& url,
-                    const String& nonce,
-                    const IntegrityMetadataSet& hashes,
-                    ParserDisposition parser_disposition,
-                    RedirectStatus redirect_status,
-                    SecurityViolationReportingPolicy reporting_policy,
-                    ContentSecurityPolicy::CheckHeaderType check_header_type) {
-  if (ContentSecurityPolicy::ShouldBypassContentSecurityPolicy(url)) {
-    // If we're running experimental features, bypass CSP only for
-    // non-parser-inserted resources whose scheme otherwise bypasses CSP. If
-    // we're not running experimental features, bypass CSP for all resources
-    // regardless of parser state. Once we have more data via the
-    // 'ScriptWithCSPBypassingScheme*' metrics, make a decision about what
-    // behavior to ship. https://crbug.com/653521
-    if (parser_disposition == kNotParserInserted ||
-        !RuntimeEnabledFeatures::
-            ExperimentalContentSecurityPolicyFeaturesEnabled()) {
-      return true;
-    }
-  }
-
-  bool is_allowed = true;
-  for (const auto& policy : policies) {
-    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
-      continue;
-    is_allowed &= (policy.Get()->*allowFromURLWithNonceAndParser)(
-        url, nonce, hashes, parser_disposition, redirect_status,
-        reporting_policy);
-  }
-  return is_allowed;
-}
-
-template <bool (CSPDirectiveList::*allowed)(LocalFrame*,
-                                            const KURL&,
-                                            SecurityViolationReportingPolicy)
-              const>
-bool IsAllowedByAll(const CSPDirectiveListVector& policies,
-                    LocalFrame* frame,
-                    const KURL& url,
-                    SecurityViolationReportingPolicy reporting_policy) {
-  bool is_allowed = true;
-  for (const auto& policy : policies)
-    is_allowed &= (policy.Get()->*allowed)(frame, url, reporting_policy);
-  return is_allowed;
-}
-
-template <bool (CSPDirectiveList::*allowed)(const CSPHashValue&,
-                                            ContentSecurityPolicy::InlineType)
-              const>
-bool CheckDigest(const String& source,
-                 ContentSecurityPolicy::InlineType type,
-                 uint8_t hash_algorithms_used,
-                 const CSPDirectiveListVector& policies) {
+// static
+void ContentSecurityPolicy::FillInCSPHashValues(
+    const String& source,
+    uint8_t hash_algorithms_used,
+    Vector<CSPHashValue>& csp_hash_values) {
   // Any additions or subtractions from this struct should also modify the
   // respective entries in the kSupportedPrefixes array in
   // SourceListDirective::parseHash().
@@ -614,7 +440,7 @@
   // Only bother normalizing the source/computing digests if there are any
   // checks to be done.
   if (hash_algorithms_used == kContentSecurityPolicyHashAlgorithmNone)
-    return false;
+    return;
 
   StringUTF8Adaptor utf8_source(source);
 
@@ -624,14 +450,37 @@
       bool digest_success =
           ComputeDigest(algorithm_map.algorithm, utf8_source.Data(),
                         utf8_source.length(), digest);
-      if (digest_success &&
-          IsAllowedByAll<allowed>(
-              policies, CSPHashValue(algorithm_map.csp_hash_algorithm, digest),
-              type))
-        return true;
+      if (digest_success) {
+        csp_hash_values.push_back(
+            CSPHashValue(algorithm_map.csp_hash_algorithm, digest));
+      }
     }
   }
+}
 
+// static
+bool ContentSecurityPolicy::CheckScriptHashAgainstPolicy(
+    Vector<CSPHashValue>& csp_hash_values,
+    const Member<CSPDirectiveList>& policy,
+    InlineType inline_type) {
+  for (const auto& csp_hash_value : csp_hash_values) {
+    if (policy->AllowScriptHash(csp_hash_value, inline_type)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// static
+bool ContentSecurityPolicy::CheckStyleHashAgainstPolicy(
+    Vector<CSPHashValue>& csp_hash_values,
+    const Member<CSPDirectiveList>& policy,
+    InlineType inline_type) {
+  for (const auto& csp_hash_value : csp_hash_values) {
+    if (policy->AllowStyleHash(csp_hash_value, inline_type)) {
+      return true;
+    }
+  }
   return false;
 }
 
@@ -641,8 +490,12 @@
     const String& context_url,
     const WTF::OrdinalNumber& context_line,
     SecurityViolationReportingPolicy reporting_policy) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowJavaScriptURLs>(
-      policies_, element, source, context_url, context_line, reporting_policy);
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    is_allowed &= policy->AllowJavaScriptURLs(element, source, context_url,
+                                              context_line, reporting_policy);
+  }
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowInlineEventHandler(
@@ -653,14 +506,20 @@
     SecurityViolationReportingPolicy reporting_policy) const {
   // Inline event handlers may be whitelisted by hash, if
   // 'unsafe-hash-attributes' is present in a policy. Check against the digest
-  // of the |source| first before proceeding on to checking whether inline
-  // script is allowed.
-  if (CheckDigest<&CSPDirectiveList::AllowScriptHash>(
-          source, InlineType::kAttribute, script_hash_algorithms_used_,
-          policies_))
-    return true;
-  return IsAllowedByAll<&CSPDirectiveList::AllowInlineEventHandlers>(
-      policies_, element, source, context_url, context_line, reporting_policy);
+  // of the |source| and also check whether inline script is allowed.
+  Vector<CSPHashValue> csp_hash_values;
+  FillInCSPHashValues(source, script_hash_algorithms_used_, csp_hash_values);
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    is_allowed &=
+        CheckScriptHashAgainstPolicy(csp_hash_values, policy,
+                                     InlineType::kAttribute) ||
+        policy->AllowInlineEventHandlers(element, source, context_url,
+                                         context_line, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowInlineScript(
@@ -669,11 +528,23 @@
     const String& nonce,
     const WTF::OrdinalNumber& context_line,
     const String& script_content,
+    InlineType inline_type,
     SecurityViolationReportingPolicy reporting_policy) const {
   DCHECK(element);
-  return IsAllowedByAll<&CSPDirectiveList::AllowInlineScript>(
-      policies_, element, context_url, nonce, context_line, reporting_policy,
-      script_content);
+
+  Vector<CSPHashValue> csp_hash_values;
+  FillInCSPHashValues(script_content, script_hash_algorithms_used_,
+                      csp_hash_values);
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    is_allowed &=
+        CheckScriptHashAgainstPolicy(csp_hash_values, policy, inline_type) ||
+        policy->AllowInlineScript(element, context_url, nonce, context_line,
+                                  reporting_policy, script_content);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowInlineStyle(
@@ -682,13 +553,26 @@
     const String& nonce,
     const WTF::OrdinalNumber& context_line,
     const String& style_content,
+    InlineType inline_type,
     SecurityViolationReportingPolicy reporting_policy) const {
   DCHECK(element);
+
   if (override_inline_style_allowed_)
     return true;
-  return IsAllowedByAll<&CSPDirectiveList::AllowInlineStyle>(
-      policies_, element, context_url, nonce, context_line, reporting_policy,
-      style_content);
+
+  Vector<CSPHashValue> csp_hash_values;
+  FillInCSPHashValues(style_content, style_hash_algorithms_used_,
+                      csp_hash_values);
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    is_allowed &=
+        CheckStyleHashAgainstPolicy(csp_hash_values, policy, inline_type) ||
+        policy->AllowInlineStyle(element, context_url, nonce, context_line,
+                                 reporting_policy, style_content);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowEval(
@@ -696,9 +580,12 @@
     SecurityViolationReportingPolicy reporting_policy,
     ContentSecurityPolicy::ExceptionStatus exception_status,
     const String& script_content) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowEval>(
-      policies_, script_state, reporting_policy, exception_status,
-      script_content);
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    is_allowed &= policy->AllowEval(script_state, reporting_policy,
+                                    exception_status, script_content);
+  }
+  return is_allowed;
 }
 
 String ContentSecurityPolicy::EvalDisabledErrorMessage() const {
@@ -767,22 +654,29 @@
         parser_disposition == kParserInserted
             ? WebFeature::kScriptWithCSPBypassingSchemeParserInserted
             : WebFeature::kScriptWithCSPBypassingSchemeNotParserInserted);
+
+    // If we're running experimental features, bypass CSP only for
+    // non-parser-inserted resources whose scheme otherwise bypasses CSP. If
+    // we're not running experimental features, bypass CSP for all resources
+    // regardless of parser state. Once we have more data via the
+    // 'ScriptWithCSPBypassingScheme*' metrics, make a decision about what
+    // behavior to ship. https://crbug.com/653521
+    if (parser_disposition == kNotParserInserted ||
+        !RuntimeEnabledFeatures::
+            ExperimentalContentSecurityPolicyFeaturesEnabled()) {
+      return true;
+    }
   }
-  return IsAllowedByAll<&CSPDirectiveList::AllowScriptFromSource>(
-      policies_, url, nonce, hashes, parser_disposition, redirect_status,
-      reporting_policy, check_header_type);
-}
 
-bool ContentSecurityPolicy::AllowScriptWithHash(const String& source,
-                                                InlineType type) const {
-  return CheckDigest<&CSPDirectiveList::AllowScriptHash>(
-      source, type, script_hash_algorithms_used_, policies_);
-}
-
-bool ContentSecurityPolicy::AllowStyleWithHash(const String& source,
-                                               InlineType type) const {
-  return CheckDigest<&CSPDirectiveList::AllowStyleHash>(
-      source, type, style_hash_algorithms_used_, policies_);
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowScriptFromSource(url, nonce, hashes, parser_disposition,
+                                      redirect_status, reporting_policy);
+  }
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowRequestWithoutIntegrity(
@@ -892,8 +786,18 @@
     RedirectStatus redirect_status,
     SecurityViolationReportingPolicy reporting_policy,
     CheckHeaderType check_header_type) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowObjectFromSource>(
-      policies_, url, redirect_status, reporting_policy, check_header_type);
+  if (ShouldBypassContentSecurityPolicy(url))
+    return true;
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowObjectFromSource(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowFrameFromSource(
@@ -901,8 +805,18 @@
     RedirectStatus redirect_status,
     SecurityViolationReportingPolicy reporting_policy,
     CheckHeaderType check_header_type) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowFrameFromSource>(
-      policies_, url, redirect_status, reporting_policy, check_header_type);
+  if (ShouldBypassContentSecurityPolicy(url))
+    return true;
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowFrameFromSource(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowImageFromSource(
@@ -912,8 +826,16 @@
     CheckHeaderType check_header_type) const {
   if (ShouldBypassContentSecurityPolicy(url, SchemeRegistry::kPolicyAreaImage))
     return true;
-  return IsAllowedByAll<&CSPDirectiveList::AllowImageFromSource>(
-      policies_, url, redirect_status, reporting_policy, check_header_type);
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowImageFromSource(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowStyleFromSource(
@@ -924,9 +846,15 @@
     CheckHeaderType check_header_type) const {
   if (ShouldBypassContentSecurityPolicy(url, SchemeRegistry::kPolicyAreaStyle))
     return true;
-  return IsAllowedByAll<&CSPDirectiveList::AllowStyleFromSource>(
-      policies_, url, nonce, redirect_status, reporting_policy,
-      check_header_type);
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &= policy->AllowStyleFromSource(url, nonce, redirect_status,
+                                               reporting_policy);
+  }
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowFontFromSource(
@@ -934,8 +862,18 @@
     RedirectStatus redirect_status,
     SecurityViolationReportingPolicy reporting_policy,
     CheckHeaderType check_header_type) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowFontFromSource>(
-      policies_, url, redirect_status, reporting_policy, check_header_type);
+  if (ShouldBypassContentSecurityPolicy(url))
+    return true;
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowFontFromSource(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowMediaFromSource(
@@ -943,8 +881,18 @@
     RedirectStatus redirect_status,
     SecurityViolationReportingPolicy reporting_policy,
     CheckHeaderType check_header_type) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowMediaFromSource>(
-      policies_, url, redirect_status, reporting_policy, check_header_type);
+  if (ShouldBypassContentSecurityPolicy(url))
+    return true;
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowMediaFromSource(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowConnectToSource(
@@ -952,8 +900,18 @@
     RedirectStatus redirect_status,
     SecurityViolationReportingPolicy reporting_policy,
     CheckHeaderType check_header_type) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowConnectToSource>(
-      policies_, url, redirect_status, reporting_policy, check_header_type);
+  if (ShouldBypassContentSecurityPolicy(url))
+    return true;
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowConnectToSource(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowFormAction(
@@ -961,8 +919,18 @@
     RedirectStatus redirect_status,
     SecurityViolationReportingPolicy reporting_policy,
     CheckHeaderType check_header_type) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowFormAction>(
-      policies_, url, redirect_status, reporting_policy, check_header_type);
+  if (ShouldBypassContentSecurityPolicy(url))
+    return true;
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowFormAction(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowBaseURI(
@@ -971,9 +939,18 @@
     SecurityViolationReportingPolicy reporting_policy) const {
   // `base-uri` isn't affected by 'upgrade-insecure-requests', so we'll check
   // both report-only and enforce headers here.
-  return IsAllowedByAll<&CSPDirectiveList::AllowBaseURI>(
-      policies_, url, redirect_status, reporting_policy,
-      ContentSecurityPolicy::CheckHeaderType::kCheckAll);
+  if (ShouldBypassContentSecurityPolicy(url))
+    return true;
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(CheckHeaderType::kCheckAll,
+                                policy->HeaderType()))
+      continue;
+    is_allowed &= policy->AllowBaseURI(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowWorkerContextFromSource(
@@ -986,22 +963,48 @@
   // TODO(mkwst): We reverted this.
   if (Document* document = this->GetDocument()) {
     UseCounter::Count(*document, WebFeature::kWorkerSubjectToCSP);
-    if (IsAllowedByAll<&CSPDirectiveList::AllowWorkerFromSource>(
-            policies_, url, redirect_status,
-            SecurityViolationReportingPolicy::kSuppressReporting,
-            check_header_type) &&
-        !IsAllowedByAll<&CSPDirectiveList::AllowScriptFromSource>(
-            policies_, url, AtomicString(), IntegrityMetadataSet(),
-            kNotParserInserted, redirect_status,
-            SecurityViolationReportingPolicy::kSuppressReporting,
-            check_header_type)) {
+    bool is_allowed_worker = true;
+    if (!ShouldBypassContentSecurityPolicy(url)) {
+      for (const auto& policy : policies_) {
+        if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+          continue;
+        is_allowed_worker &= policy->AllowWorkerFromSource(
+            url, redirect_status,
+            SecurityViolationReportingPolicy::kSuppressReporting);
+      }
+    }
+
+    bool is_allowed_script = true;
+
+    if (!ShouldBypassContentSecurityPolicy(url)) {
+      for (const auto& policy : policies_) {
+        if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+          continue;
+        is_allowed_script &= policy->AllowScriptFromSource(
+            url, AtomicString(), IntegrityMetadataSet(), kNotParserInserted,
+            redirect_status,
+            SecurityViolationReportingPolicy::kSuppressReporting);
+      }
+    }
+
+    if (is_allowed_worker && !is_allowed_script) {
       UseCounter::Count(*document,
                         WebFeature::kWorkerAllowedByChildBlockedByScript);
     }
   }
 
-  return IsAllowedByAll<&CSPDirectiveList::AllowWorkerFromSource>(
-      policies_, url, redirect_status, reporting_policy, check_header_type);
+  if (ShouldBypassContentSecurityPolicy(url))
+    return true;
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowWorkerFromSource(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowManifestFromSource(
@@ -1009,16 +1012,28 @@
     RedirectStatus redirect_status,
     SecurityViolationReportingPolicy reporting_policy,
     CheckHeaderType check_header_type) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowManifestFromSource>(
-      policies_, url, redirect_status, reporting_policy, check_header_type);
+  if (ShouldBypassContentSecurityPolicy(url))
+    return true;
+
+  bool is_allowed = true;
+  for (const auto& policy : policies_) {
+    if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType()))
+      continue;
+    is_allowed &=
+        policy->AllowManifestFromSource(url, redirect_status, reporting_policy);
+  }
+
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::AllowAncestors(
     LocalFrame* frame,
     const KURL& url,
     SecurityViolationReportingPolicy reporting_policy) const {
-  return IsAllowedByAll<&CSPDirectiveList::AllowAncestors>(
-      policies_, frame, url, reporting_policy);
+  bool is_allowed = true;
+  for (const auto& policy : policies_)
+    is_allowed &= policy->AllowAncestors(frame, url, reporting_policy);
+  return is_allowed;
 }
 
 bool ContentSecurityPolicy::IsFrameAncestorsEnforced() const {
diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h
index 2de91b11..beda3e9 100644
--- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h
+++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h
@@ -270,6 +270,7 @@
                          const String& nonce,
                          const WTF::OrdinalNumber& context_line,
                          const String& script_content,
+                         InlineType,
                          SecurityViolationReportingPolicy =
                              SecurityViolationReportingPolicy::kReport) const;
   bool AllowInlineStyle(Element*,
@@ -277,6 +278,7 @@
                         const String& nonce,
                         const WTF::OrdinalNumber& context_line,
                         const String& style_content,
+                        InlineType,
                         SecurityViolationReportingPolicy =
                             SecurityViolationReportingPolicy::kReport) const;
 
@@ -292,18 +294,6 @@
                           SecurityViolationReportingPolicy::kReport) const;
   bool IsFrameAncestorsEnforced() const;
 
-  // The hash allow functions are guaranteed to not have any side
-  // effects, including reporting.
-  // Hash functions check all policies relating to use of a script/style
-  // with the given hash and return true all CSP policies allow it.
-  // If these return true, callers can then process the content or
-  // issue a load and be safe disabling any further CSP checks.
-  //
-  // TODO(mkwst): Fold hashes into 'allow{Script,Style}' checks above, just
-  // as we've done with nonces. https://crbug.com/617065
-  bool AllowScriptWithHash(const String& source, InlineType) const;
-  bool AllowStyleWithHash(const String& source, InlineType) const;
-
   bool AllowRequestWithoutIntegrity(
       WebURLRequest::RequestContext,
       const KURL&,
@@ -467,6 +457,19 @@
                            LocalFrame*,
                            const Vector<String>& report_endpoints);
 
+  static void FillInCSPHashValues(const String& source,
+                                  uint8_t hash_algorithms_used,
+                                  Vector<CSPHashValue>& csp_hash_values);
+
+  // checks a vector of csp hashes against policy, probably a good idea
+  // to use in tandem with FillInCSPHashValues.
+  static bool CheckScriptHashAgainstPolicy(Vector<CSPHashValue>&,
+                                           const Member<CSPDirectiveList>&,
+                                           InlineType);
+  static bool CheckStyleHashAgainstPolicy(Vector<CSPHashValue>&,
+                                          const Member<CSPDirectiveList>&,
+                                          InlineType);
+
   Member<ExecutionContext> execution_context_;
   bool override_inline_style_allowed_;
   CSPDirectiveListVector policies_;
diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicyTest.cpp b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicyTest.cpp
index cc56529..974815ff 100644
--- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicyTest.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicyTest.cpp
@@ -737,9 +737,10 @@
     policy->DidReceiveHeader(String("script-src ") + test.policy,
                              kContentSecurityPolicyHeaderTypeEnforce,
                              kContentSecurityPolicyHeaderSourceHTTP);
-    EXPECT_EQ(test.allowed, policy->AllowInlineScript(element, context_url,
-                                                      String(test.nonce),
-                                                      context_line, content));
+    EXPECT_EQ(test.allowed,
+              policy->AllowInlineScript(
+                  element, context_url, String(test.nonce), context_line,
+                  content, ContentSecurityPolicy::InlineType::kBlock));
     EXPECT_EQ(expected_reports, policy->violation_reports_sent_.size());
 
     // Enforce 'style-src'
@@ -749,8 +750,9 @@
                              kContentSecurityPolicyHeaderTypeEnforce,
                              kContentSecurityPolicyHeaderSourceHTTP);
     EXPECT_EQ(test.allowed,
-              policy->AllowInlineStyle(element, context_url, String(test.nonce),
-                                       context_line, content));
+              policy->AllowInlineStyle(
+                  element, context_url, String(test.nonce), context_line,
+                  content, ContentSecurityPolicy::InlineType::kBlock));
     EXPECT_EQ(expected_reports, policy->violation_reports_sent_.size());
 
     // Report 'script-src'
@@ -760,7 +762,8 @@
                              kContentSecurityPolicyHeaderTypeReport,
                              kContentSecurityPolicyHeaderSourceHTTP);
     EXPECT_TRUE(policy->AllowInlineScript(
-        element, context_url, String(test.nonce), context_line, content));
+        element, context_url, String(test.nonce), context_line, content,
+        ContentSecurityPolicy::InlineType::kBlock));
     EXPECT_EQ(expected_reports, policy->violation_reports_sent_.size());
 
     // Report 'style-src'
@@ -770,7 +773,8 @@
                              kContentSecurityPolicyHeaderTypeReport,
                              kContentSecurityPolicyHeaderSourceHTTP);
     EXPECT_TRUE(policy->AllowInlineStyle(
-        element, context_url, String(test.nonce), context_line, content));
+        element, context_url, String(test.nonce), context_line, content,
+        ContentSecurityPolicy::InlineType::kBlock));
     EXPECT_EQ(expected_reports, policy->violation_reports_sent_.size());
   }
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp b/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp
index e8db754..2787cca 100644
--- a/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp
@@ -199,9 +199,11 @@
 bool HTMLScriptElement::AllowInlineScriptForCSP(
     const AtomicString& nonce,
     const WTF::OrdinalNumber& context_line,
-    const String& script_content) {
+    const String& script_content,
+    ContentSecurityPolicy::InlineType inline_type) {
   return GetDocument().GetContentSecurityPolicy()->AllowInlineScript(
-      this, GetDocument().Url(), nonce, context_line, script_content);
+      this, GetDocument().Url(), nonce, context_line, script_content,
+      inline_type);
 }
 
 AtomicString HTMLScriptElement::InitiatorName() const {
diff --git a/third_party/WebKit/Source/core/html/HTMLScriptElement.h b/third_party/WebKit/Source/core/html/HTMLScriptElement.h
index d9f1a4ca..119e7a5 100644
--- a/third_party/WebKit/Source/core/html/HTMLScriptElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLScriptElement.h
@@ -94,7 +94,8 @@
   const AtomicString& GetNonceForElement() const override;
   bool AllowInlineScriptForCSP(const AtomicString& nonce,
                                const WTF::OrdinalNumber&,
-                               const String& script_content) override;
+                               const String& script_content,
+                               ContentSecurityPolicy::InlineType) override;
   AtomicString InitiatorName() const override;
   void DispatchLoadEvent() override;
   void DispatchErrorEvent() override;
diff --git a/third_party/WebKit/Source/core/loader/HttpEquiv.cpp b/third_party/WebKit/Source/core/loader/HttpEquiv.cpp
index fe11fe2..01c58a1 100644
--- a/third_party/WebKit/Source/core/loader/HttpEquiv.cpp
+++ b/third_party/WebKit/Source/core/loader/HttpEquiv.cpp
@@ -108,6 +108,7 @@
   UseCounter::Count(document, WebFeature::kMetaRefresh);
   if (!document.GetContentSecurityPolicy()->AllowInlineScript(
           element, NullURL(), "", OrdinalNumber(), "",
+          ContentSecurityPolicy::InlineType::kBlock,
           SecurityViolationReportingPolicy::kSuppressReporting)) {
     UseCounter::Count(document,
                       WebFeature::kMetaRefreshWhenCSPBlocksInlineScript);
@@ -127,6 +128,7 @@
   UseCounter::Count(document, WebFeature::kMetaSetCookie);
   if (!document.GetContentSecurityPolicy()->AllowInlineScript(
           element, NullURL(), "", OrdinalNumber(), "",
+          ContentSecurityPolicy::InlineType::kBlock,
           SecurityViolationReportingPolicy::kSuppressReporting)) {
     UseCounter::Count(document,
                       WebFeature::kMetaSetCookieWhenCSPBlocksInlineScript);
diff --git a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
index 5b7a70d..d50de163 100644
--- a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
+++ b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
@@ -656,7 +656,7 @@
 }
 
 const ImageResourceObserver& BackgroundImageGeometry::ImageClient() const {
-  return box_;
+  return coordinate_offset_by_paint_rect_ ? box_ : positioning_box_;
 }
 
 const Document& BackgroundImageGeometry::ImageDocument() const {
diff --git a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
index dfce8152..41b555a 100644
--- a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
@@ -137,9 +137,11 @@
 bool SVGScriptElement::AllowInlineScriptForCSP(
     const AtomicString& nonce,
     const WTF::OrdinalNumber& context_line,
-    const String& script_content) {
+    const String& script_content,
+    ContentSecurityPolicy::InlineType inline_type) {
   return GetDocument().GetContentSecurityPolicy()->AllowInlineScript(
-      this, GetDocument().Url(), nonce, context_line, script_content);
+      this, GetDocument().Url(), nonce, context_line, script_content,
+      inline_type);
 }
 
 AtomicString SVGScriptElement::InitiatorName() const {
diff --git a/third_party/WebKit/Source/core/svg/SVGScriptElement.h b/third_party/WebKit/Source/core/svg/SVGScriptElement.h
index 64d66950..f5469ee3c 100644
--- a/third_party/WebKit/Source/core/svg/SVGScriptElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGScriptElement.h
@@ -88,7 +88,8 @@
   const AtomicString& GetNonceForElement() const override;
   bool AllowInlineScriptForCSP(const AtomicString& nonce,
                                const WTF::OrdinalNumber&,
-                               const String& script_content) override;
+                               const String& script_content,
+                               ContentSecurityPolicy::InlineType) override;
   AtomicString InitiatorName() const override;
   Document& GetDocument() const override;
   void DispatchLoadEvent() override;
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index fbd8d97..d1974c0e 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1842,6 +1842,7 @@
     "fonts/FontDescriptionTest.cpp",
     "fonts/FontPlatformDataTest.cpp",
     "fonts/FontTest.cpp",
+    "fonts/FontTestUtilities.cpp",
     "fonts/GenericFontFamilySettingsTest.cpp",
     "fonts/OrientationIteratorTest.cpp",
     "fonts/ScriptRunIteratorTest.cpp",
diff --git a/third_party/WebKit/Source/platform/fonts/FontTestUtilities.cpp b/third_party/WebKit/Source/platform/fonts/FontTestUtilities.cpp
new file mode 100644
index 0000000..2f61bb5
--- /dev/null
+++ b/third_party/WebKit/Source/platform/fonts/FontTestUtilities.cpp
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/fonts/FontTestUtilities.h"
+
+namespace blink {
+
+String To16Bit(const char* text, unsigned length) {
+  return String::Make16BitFrom8BitSource(reinterpret_cast<const LChar*>(text),
+                                         length);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontTestUtilities.h b/third_party/WebKit/Source/platform/fonts/FontTestUtilities.h
new file mode 100644
index 0000000..d2ac809
--- /dev/null
+++ b/third_party/WebKit/Source/platform/fonts/FontTestUtilities.h
@@ -0,0 +1,14 @@
+// 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 FontTestUtilities_h
+#define FontTestUtilities_h
+
+#include "platform/wtf/text/WTFString.h"
+
+namespace blink {
+String To16Bit(const char* text, unsigned length);
+}
+
+#endif  // FontTestUtilities_h
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp
index ef8cabe8..5082bf71 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp
@@ -9,6 +9,7 @@
 #include "build/build_config.h"
 #include "platform/fonts/Font.h"
 #include "platform/fonts/FontCache.h"
+#include "platform/fonts/FontTestUtilities.h"
 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h"
 #include "platform/fonts/shaping/ShapeResultTestInfo.h"
 #include "platform/text/TextBreakIterator.h"
@@ -41,11 +42,6 @@
   return static_cast<ShapeResultTestInfo*>(result.Get());
 }
 
-static inline String To16Bit(const char* text, unsigned length) {
-  return String::Make16BitFrom8BitSource(reinterpret_cast<const LChar*>(text),
-                                         length);
-}
-
 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLatin) {
   String latin_common = To16Bit("ABC DEF.", 8);
   HarfBuzzShaper shaper(latin_common.Characters16(), 8);
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreakerTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreakerTest.cpp
index c7bc639..cd53dea 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreakerTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreakerTest.cpp
@@ -7,6 +7,7 @@
 #include <unicode/uscript.h>
 #include "platform/fonts/Font.h"
 #include "platform/fonts/FontCache.h"
+#include "platform/fonts/FontTestUtilities.h"
 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h"
 #include "platform/fonts/shaping/ShapeResultTestInfo.h"
 #include "platform/text/TextBreakIterator.h"
@@ -34,11 +35,6 @@
   hb_script_t script = HB_SCRIPT_INVALID;
 };
 
-static inline String To16Bit(const char* text, unsigned length) {
-  return String::Make16BitFrom8BitSource(reinterpret_cast<const LChar*>(text),
-                                         length);
-}
-
 TEST_F(ShapingLineBreakerTest, ShapeLineLatin) {
   String string = To16Bit(
       "Test run with multiple words and breaking "
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index ec17c1a6d..efb5dd3d 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -633,10 +633,15 @@
                                     params.Options().initiator_info.name);
   }
 
-  // An URL with the "cid" scheme can only be handled by an MHTML Archive.
-  // Abort the request when there is none.
-  if (!archive_ && resource_request.Url().ProtocolIs(kContentIdScheme))
+  // A main resource request with the "cid" scheme can only be handled by an
+  // MHTML Archive. Abort the request when there is none.
+  // Note: There are some embedders of WebView that are using Content-ID
+  // URLs for sub-resources, even without any MHTMLArchive. Please see
+  // https://crbug.com/739658.
+  if (!archive_ && factory.GetType() == Resource::kMainResource &&
+      resource_request.Url().ProtocolIs(kContentIdScheme)) {
     return nullptr;
+  }
 
   bool is_data_url = resource_request.Url().ProtocolIsData();
   bool is_static_data = is_data_url || substitute_data.IsValid() || archive_;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp
index 5b9813cc..33c48fd5 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp
@@ -735,4 +735,38 @@
   EXPECT_EQ("text/testmimetype", resource->GetResponse().HttpContentType());
 }
 
+TEST_F(ResourceFetcherTest, ContentIdURL) {
+  KURL url(kParsedURLString, "cid:0123456789@example.com");
+  ResourceResponse response;
+  response.SetURL(url);
+  response.SetHTTPStatusCode(200);
+  RegisterMockedURLLoadWithCustomResponse(url, response);
+
+  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+
+  // Fetching a main resource with the Content-ID scheme must be canceled if
+  // there is no MHTMLArchive.
+  {
+    ResourceRequest resource_request(url);
+    resource_request.SetRequestContext(WebURLRequest::kRequestContextIframe);
+    resource_request.SetFrameType(WebURLRequest::kFrameTypeNested);
+    FetchParameters fetch_params(resource_request);
+    RawResource* resource =
+        RawResource::FetchMainResource(fetch_params, fetcher, SubstituteData());
+    EXPECT_EQ(nullptr, resource);
+  }
+
+  // For all the other resource type, it must not be canceled.
+  // Note: It is important not to cancel them because there are some embedders
+  // of WebView that are using Content-ID URLs for sub-resources, even without
+  // any MHTMLArchive. Please see https://crbug.com/739658.
+  {
+    ResourceRequest resource_request(url);
+    resource_request.SetRequestContext(WebURLRequest::kRequestContextVideo);
+    FetchParameters fetch_params(resource_request);
+    RawResource* resource = RawResource::FetchMedia(fetch_params, fetcher);
+    EXPECT_NE(nullptr, resource);
+  }
+}
+
 }  // namespace blink
diff --git a/tools/OWNERS b/tools/OWNERS
index f096352..945ca919 100644
--- a/tools/OWNERS
+++ b/tools/OWNERS
@@ -39,7 +39,9 @@
 
 per-file ipc_messages_log.py=yfriedman@chromium.org
 
-per-file licenses.py=file://tools/copyright_scanner/OWNERS
+per-file licenses.py=phajdan.jr@chromium.org
+per-file licenses.py=sgurun@chromium.org
+per-file licenses.py=torne@chromium.org
 
 per-file remove_stale_pyc_files.py=dtu@chromium.org
 
diff --git a/tools/copyright_scanner/PRESUBMIT.py b/tools/copyright_scanner/PRESUBMIT.py
deleted file mode 100644
index 455701ec..0000000
--- a/tools/copyright_scanner/PRESUBMIT.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2014 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.
-
-def CheckChangeOnUpload(input_api, output_api):
-  return _CommonChecks(input_api, output_api)
-
-def CheckChangeOnCommit(input_api, output_api):
-  return _CommonChecks(input_api, output_api)
-
-def _CommonChecks(input_api, output_api):
-  """Checks common to both upload and commit."""
-  results = []
-
-  would_affect_tests = [
-    'PRESUBMIT.py',
-    'copyright_scanner.py',
-    'copyright_scanner_unittest.py'
-  ]
-  need_to_run_unittests = False
-  for f in input_api.AffectedFiles():
-    if any(t for t in would_affect_tests if f.LocalPath().endswith(t)):
-      need_to_run_unittests = True
-      break
-  tests = [input_api.os_path.join(
-    input_api.PresubmitLocalPath(), 'copyright_scanner_unittest.py')]
-  results.extend(
-    input_api.canned_checks.RunUnitTests(input_api, output_api, tests))
-  return results
diff --git a/tools/copyright_scanner/__init__.py b/tools/copyright_scanner/__init__.py
deleted file mode 100755
index e6b8d8e..0000000
--- a/tools/copyright_scanner/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-__all__ = ['copyright_scanner']
diff --git a/tools/copyright_scanner/copyright_scanner.py b/tools/copyright_scanner/copyright_scanner.py
deleted file mode 100644
index 7577241..0000000
--- a/tools/copyright_scanner/copyright_scanner.py
+++ /dev/null
@@ -1,400 +0,0 @@
-# Copyright 2014 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 for scanning source files to determine code authorship.
-"""
-
-import itertools
-
-def ForwardSlashesToOsPathSeps(input_api, path):
-  """Converts forward slashes ('/') in the input path to OS-specific
-  path separators. Used when the paths come from outside and are using
-  UNIX path separators. Only works for relative paths!
-  Args:
-    input_api: InputAPI, as in presubmit scripts.
-    path: The path to convert.
-  Returns:
-    Converted path.
-  """
-  return input_api.os_path.join(*path.split('/'))
-
-def FindFiles(input_api, root_dir, start_paths_list, excluded_dirs_list):
-  """Similar to UNIX utility find(1), searches for files in the directories.
-  Automatically leaves out only source code files and excludes third_party
-  directories.
-  Args:
-    input_api: InputAPI, as in presubmit scripts.
-    root_dir: The root directory, to which all other paths are relative.
-    start_paths_list: The list of paths to start search from. Each path can
-      be a file or a directory.
-    excluded_dirs_list: The list of directories to skip.
-  Returns:
-    The list of source code files found, relative to |root_dir|.
-  """
-  excluded_dirs_list = [d for d in excluded_dirs_list if not 'third_party' in d]
-  # Using a common pattern for third-partyies makes the ignore regexp shorter
-  excluded_dirs_list.append('third_party')
-
-  path_join = input_api.os_path.join
-  EXTRA_EXCLUDED_DIRS = [
-    # VCS dirs
-    path_join('.git'),
-    path_join('.svn'),
-    # Build output
-    path_join('out', 'Debug'),
-    path_join('out', 'Release'),
-    # 'Copyright' appears in license agreements
-    path_join('chrome', 'app', 'resources'),
-    # Quickoffice js files from internal src used on buildbots.
-    # crbug.com/350472.
-    path_join('chrome', 'browser', 'resources', 'chromeos', 'quickoffice'),
-    # blink style copy right headers.
-    path_join('content', 'shell', 'renderer', 'test_runner'),
-    # blink style copy right headers.
-    path_join('content', 'shell', 'tools', 'plugin'),
-    # This is tests directory, doesn't exist in the snapshot
-    path_join('content', 'test', 'data'),
-    # This is a tests directory that doesn't exist in the shipped product.
-    path_join('gin', 'test'),
-    # This is a test output directory
-    path_join('data', 'dom_perf'),
-    # This is a tests directory that doesn't exist in the shipped product.
-    path_join('tools', 'perf', 'page_sets'),
-    path_join('tools', 'perf', 'page_sets', 'tough_animation_cases'),
-    # Histogram tools, doesn't exist in the snapshot
-    path_join('tools', 'histograms'),
-    # Swarming tools, doesn't exist in the snapshot
-    path_join('tools', 'swarming_client'),
-    # Don't check downloaded goma client binaries.
-    path_join('build', 'goma', 'client'),
-    # Ignore sysroots.
-    path_join('build', 'linux', 'debian_jessie_arm64-sysroot'),
-    path_join('build', 'linux', 'debian_jessie_arm-sysroot'),
-    path_join('build', 'linux', 'debian_jessie_mips-sysroot'),
-    path_join('build', 'linux', 'debian_jessie_i386-sysroot'),
-    path_join('build', 'linux', 'debian_jessie_amd64-sysroot'),
-    # Data is not part of open source chromium, but are included on some bots.
-    path_join('data'),
-    # This is not part of open source chromium, but are included on some bots.
-    path_join('skia', 'tools', 'clusterfuzz-data'),
-    # Not shipped, only relates to Chrome for Android, but not to WebView
-    path_join('clank'),
-    # Internal-only repository.
-    path_join('remoting', 'android', 'internal'),
-  ]
-  excluded_dirs_list.extend(EXTRA_EXCLUDED_DIRS)
-
-  # Surround the directory names with OS path separators.
-  dirs_blacklist = [path_join('.', d, '')[1:] for d in excluded_dirs_list if d]
-  def IsBlacklistedDir(d):
-    for item in dirs_blacklist:
-      if item in d:
-        return True
-    return False
-
-  files_whitelist_re = input_api.re.compile(
-    r'\.(asm|c(c|pp|xx)?|h(h|pp|xx)?|p(l|m)|xs|sh|php|py(|x)'
-    '|rb|idl|java|el|sc(i|e)|cs|pas|inc|js|pac|html|dtd|xsl|mod|mm?'
-    '|tex|mli?)$')
-  files = []
-
-  base_path_len = len(root_dir)
-  for path in start_paths_list:
-    full_path = path_join(root_dir, path)
-    if input_api.os_path.isfile(full_path):
-      if files_whitelist_re.search(path) and \
-          not IsBlacklistedDir(full_path[base_path_len:]):  # Keep '/' prefix.
-        files.append(path)
-    else:
-      for dirpath, dirnames, filenames in input_api.os_walk(full_path):
-        # Remove excluded subdirs for faster scanning.
-        for item in dirnames[:]:
-          if IsBlacklistedDir(
-              path_join(dirpath, item)[base_path_len + 1:]):
-            dirnames.remove(item)
-        for filename in filenames:
-          filepath = \
-              path_join(dirpath, filename)[base_path_len + 1:]
-          if files_whitelist_re.search(filepath) and \
-              not IsBlacklistedDir(filepath):
-            files.append(filepath)
-  return files
-
-
-class _GeneratedFilesDetector(object):
-  GENERATED_FILE = 'GENERATED FILE'
-  NO_COPYRIGHT = '*No copyright*'
-
-  def __init__(self, input_api):
-    self.python_multiline_string_double_re = \
-      input_api.re.compile(r'"""[^"]*(?:"""|$)', flags=input_api.re.MULTILINE)
-    self.python_multiline_string_single_re = \
-      input_api.re.compile(r"'''[^']*(?:'''|$)", flags=input_api.re.MULTILINE)
-    self.automatically_generated_re = input_api.re.compile(
-      r'(All changes made in this file will be lost'
-      '|DO NOT (EDIT|delete this file)'
-      '|Generated (at|automatically|data)'
-      '|Automatically generated'
-      '|\Wgenerated\s+(?:\w+\s+)*file\W)', flags=input_api.re.IGNORECASE)
-
-  def IsGeneratedFile(self, header):
-    header = header.upper()
-    if '"""' in header:
-      header = self.python_multiline_string_double_re.sub('', header)
-    if "'''" in header:
-      header = self.python_multiline_string_single_re.sub('', header)
-    # First do simple strings lookup to save time.
-    if 'ALL CHANGES MADE IN THIS FILE WILL BE LOST' in header:
-      return True
-    if 'DO NOT EDIT' in header or 'DO NOT DELETE' in header or \
-        'GENERATED' in header:
-      return self.automatically_generated_re.search(header)
-    return False
-
-
-class _CopyrightsScanner(object):
-  @staticmethod
-  def StaticInit(input_api):
-    _CopyrightsScanner._c_comment_re = \
-      input_api.re.compile(r'''"[^"\\]*(?:\\.[^"\\]*)*"''')
-    _CopyrightsScanner._copyright_indicator = \
-      r'(?:copyright|copr\.|\xc2\xa9|\(c\))'
-    _CopyrightsScanner._full_copyright_indicator_re = input_api.re.compile(
-      r'(?:\W|^)' + _CopyrightsScanner._copyright_indicator + \
-      r'(?::\s*|\s+)(\w.*)$', input_api.re.IGNORECASE)
-    _CopyrightsScanner._copyright_disindicator_re = input_api.re.compile(
-      r'\s*\b(?:info(?:rmation)?|notice|and|or)\b', input_api.re.IGNORECASE)
-
-  def __init__(self, input_api):
-    self.max_line_numbers_proximity = 3
-    self.last_a_item_line_number = -200
-    self.last_b_item_line_number = -100
-    self.re = input_api.re
-
-  def _CloseLineNumbers(self, a, b):
-    return 0 <= a - b <= self.max_line_numbers_proximity
-
-  def MatchLine(self, line_number, line):
-    if '"' in line:
-      line = _CopyrightsScanner._c_comment_re.sub('', line)
-    upcase_line = line.upper()
-    # Record '(a)' and '(b)' last occurences in C++ comments.
-    # This is to filter out '(c)' used as a list item inside C++ comments.
-    # E.g. "// blah-blah (a) blah\n// blah-blah (b) and (c) blah"
-    cpp_comment_idx = upcase_line.find('//')
-    if cpp_comment_idx != -1:
-      if upcase_line.find('(A)') > cpp_comment_idx:
-        self.last_a_item_line_number = line_number
-      if upcase_line.find('(B)') > cpp_comment_idx:
-        self.last_b_item_line_number = line_number
-    # Fast bailout, uses the same patterns as _copyright_indicator regexp.
-    if not 'COPYRIGHT' in upcase_line and not 'COPR.' in upcase_line \
-        and not '\xc2\xa9' in upcase_line:
-      c_item_index = upcase_line.find('(C)')
-      if c_item_index == -1:
-        return None
-      if c_item_index > cpp_comment_idx and \
-          self._CloseLineNumbers(line_number,
-                                 self.last_b_item_line_number) and \
-          self._CloseLineNumbers(self.last_b_item_line_number,
-                                 self.last_a_item_line_number):
-        return None
-    copyr = None
-    m = _CopyrightsScanner._full_copyright_indicator_re.search(line)
-    if m and \
-        not _CopyrightsScanner._copyright_disindicator_re.match(m.group(1)):
-      copyr = m.group(0)
-      # Prettify the authorship string.
-      copyr = self.re.sub(r'([,.])?\s*$/', '', copyr)
-      copyr = self.re.sub(
-        _CopyrightsScanner._copyright_indicator, '', copyr, \
-        flags=self.re.IGNORECASE)
-      copyr = self.re.sub(r'^\s+', '', copyr)
-      copyr = self.re.sub(r'\s{2,}', ' ', copyr)
-      copyr = self.re.sub(r'\\@', '@', copyr)
-    return copyr
-
-
-def FindCopyrights(input_api, root_dir, files_to_scan):
-  """Determines code autorship, and finds generated files.
-  Args:
-    input_api: InputAPI, as in presubmit scripts.
-    root_dir: The root directory, to which all other paths are relative.
-    files_to_scan: The list of file names to scan.
-  Returns:
-    The list of copyrights associated with each of the files given.
-    If the certain file is generated, the corresponding list consists a single
-    entry -- 'GENERATED_FILE' string. If the file has no copyright info,
-    the corresponding list contains 'NO_COPYRIGHT' string.
-  """
-  generated_files_detector = _GeneratedFilesDetector(input_api)
-  _CopyrightsScanner.StaticInit(input_api)
-  copyrights = []
-  for file_name in files_to_scan:
-    linenum = 0
-    header = []
-    file_copyrights = []
-    scanner = _CopyrightsScanner(input_api)
-    contents = input_api.ReadFile(
-      input_api.os_path.join(root_dir, file_name), 'r')
-    for l in contents.split('\n'):
-      linenum += 1
-      if linenum <= 25:
-        header.append(l)
-      c = scanner.MatchLine(linenum, l)
-      if c:
-        file_copyrights.append(c)
-    if generated_files_detector.IsGeneratedFile('\n'.join(header)):
-      copyrights.append([_GeneratedFilesDetector.GENERATED_FILE])
-    elif file_copyrights:
-      copyrights.append(file_copyrights)
-    else:
-      copyrights.append([_GeneratedFilesDetector.NO_COPYRIGHT])
-  return copyrights
-
-
-def FindCopyrightViolations(input_api, root_dir, files_to_scan):
-  """Looks for files that are not belong exlusively to the Chromium Authors.
-  Args:
-    input_api: InputAPI, as in presubmit scripts.
-    root_dir: The root directory, to which all other paths are relative.
-    files_to_scan: The list of file names to scan.
-  Returns:
-    The list of file names that contain non-Chromium copyrights.
-  """
-  copyrights = FindCopyrights(input_api, root_dir, files_to_scan)
-  offending_files = []
-  allowed_copyrights_re = input_api.re.compile(
-    r'^(?:20[0-9][0-9](?:-20[0-9][0-9])? The Chromium Authors\. '
-    'All rights reserved.*)$')
-  for f, cs in itertools.izip(files_to_scan, copyrights):
-    if cs[0] == _GeneratedFilesDetector.GENERATED_FILE or \
-       cs[0] == _GeneratedFilesDetector.NO_COPYRIGHT:
-      continue
-    for c in cs:
-      if not allowed_copyrights_re.match(c):
-        offending_files.append(input_api.os_path.normpath(f))
-        break
-  return offending_files
-
-
-def _GetWhitelistFileName(input_api):
-  return input_api.os_path.join(
-    'tools', 'copyright_scanner', 'third_party_files_whitelist.txt')
-
-def _ProcessWhitelistedFilesList(input_api, lines):
-  whitelisted_files = []
-  for line in lines:
-    match = input_api.re.match(r'([^#\s]+)', line)
-    if match:
-      whitelisted_files.append(
-        ForwardSlashesToOsPathSeps(input_api, match.group(1)))
-  return whitelisted_files
-
-
-def LoadWhitelistedFilesList(input_api):
-  """Loads and parses the 3rd party code whitelist file.
-    input_api: InputAPI of presubmit scripts.
-  Returns:
-    The list of files.
-  """
-  full_file_name = input_api.os_path.join(
-    input_api.change.RepositoryRoot(), _GetWhitelistFileName(input_api))
-  file_data = input_api.ReadFile(full_file_name, 'rb')
-  return _ProcessWhitelistedFilesList(input_api, file_data.splitlines())
-
-
-def AnalyzeScanResults(input_api, whitelisted_files, offending_files):
-  """Compares whitelist contents with the results of file scanning.
-    input_api: InputAPI of presubmit scripts.
-    whitelisted_files: Whitelisted files list.
-    offending_files: Files that contain 3rd party code.
-  Returns:
-    A triplet of "unknown", "missing", and "stale" file lists.
-    "Unknown" are files that contain 3rd party code but not whitelisted.
-    "Missing" are files that are whitelisted but doesn't really exist.
-    "Stale" are files that are whitelisted unnecessarily.
-  """
-  unknown = set(offending_files) - set(whitelisted_files)
-  missing = [f for f in whitelisted_files if not input_api.os_path.isfile(
-    input_api.os_path.join(input_api.change.RepositoryRoot(), f))]
-  stale = set(whitelisted_files) - set(offending_files) - set(missing)
-  return (list(unknown), missing, list(stale))
-
-
-def _GetDeletedContents(affected_file):
-  """Returns a list of all deleted lines.
-  AffectedFile class from presubmit_support is lacking this functionality.
-  """
-  deleted_lines = []
-  for line in affected_file.GenerateScmDiff().splitlines():
-    if line.startswith('-') and not line.startswith('--'):
-      deleted_lines.append(line[1:])
-  return deleted_lines
-
-def _DoScanAtPresubmit(input_api, whitelisted_files, files_to_check):
-  # We pass empty 'known third-party' dirs list here. Since this is a patch
-  # for the Chromium's src tree, it must contain properly licensed Chromium
-  # code. Any third-party code must be put into a directory named 'third_party',
-  # and such dirs are automatically excluded by FindFiles.
-  files_to_scan = FindFiles(
-    input_api, input_api.change.RepositoryRoot(), files_to_check, [])
-  offending_files = FindCopyrightViolations(
-    input_api, input_api.change.RepositoryRoot(), files_to_scan)
-  return AnalyzeScanResults(
-    input_api, whitelisted_files, offending_files)
-
-def ScanAtPresubmit(input_api, output_api):
-  """Invoked at change presubmit time. Verifies that updated non third-party
-  code doesn't contain external copyrighted code.
-    input_api: InputAPI of presubmit scripts.
-    output_api: OutputAPI of presubmit scripts.
-  """
-  files_to_check = set([])
-  deleted_files = set([])
-  whitelist_contents_changed = False
-  for f in input_api.AffectedFiles():
-    if f.LocalPath() == _GetWhitelistFileName(input_api):
-      whitelist_contents_changed = True
-      deleted_files |= set(_ProcessWhitelistedFilesList(
-        input_api, _GetDeletedContents(f)))
-      continue
-    if f.Action() != 'D':
-      files_to_check.add(f.LocalPath())
-    else:
-      deleted_files.add(f.LocalPath())
-  whitelisted_files = set(LoadWhitelistedFilesList(input_api))
-  if not whitelist_contents_changed:
-    whitelisted_files &= files_to_check | deleted_files
-  else:
-    # Need to re-check the entire contents of the whitelist file.
-    # Also add files removed from the whitelist. If the file has indeed been
-    # deleted, the scanner will not complain.
-    files_to_check |= whitelisted_files | deleted_files
-
-  (unknown_files, missing_files, stale_files) = _DoScanAtPresubmit(
-    input_api, list(whitelisted_files), list(files_to_check))
-  results = []
-  if unknown_files:
-    results.append(output_api.PresubmitError(
-        'The following files contain a third-party license but are not in ' \
-        'a listed third-party directory and are not whitelisted. You must ' \
-        'add the following files to the whitelist file %s\n' \
-        '(Note that if the code you are adding does not actually contain ' \
-        'any third-party code, it may contain the word "copyright", which ' \
-        'should be masked out, e.g. by writing it as "copy-right"):' \
-        '' % _GetWhitelistFileName(input_api),
-        sorted(unknown_files)))
-  if missing_files:
-    results.append(output_api.PresubmitPromptWarning(
-        'The following files are whitelisted in %s, ' \
-        'but do not exist or not files:' % _GetWhitelistFileName(input_api),
-        sorted(missing_files)))
-  if stale_files:
-    results.append(output_api.PresubmitPromptWarning(
-        'The following files are whitelisted unnecessarily. You must ' \
-        'remove the following files from the whitelist file ' \
-        '%s:' % _GetWhitelistFileName(input_api),
-        sorted(stale_files)))
-  return results
diff --git a/tools/copyright_scanner/copyright_scanner_unittest.py b/tools/copyright_scanner/copyright_scanner_unittest.py
deleted file mode 100755
index 339abde..0000000
--- a/tools/copyright_scanner/copyright_scanner_unittest.py
+++ /dev/null
@@ -1,308 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2014 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.
-
-"""Unit tests for Copyright Scanner utilities."""
-
-import os
-import re
-import sys
-import unittest
-
-test_dir = os.path.dirname(os.path.abspath(__file__))
-sys.path.extend([
-    os.path.normpath(os.path.join(test_dir, '..', '..', 'build')),
-    os.path.join(test_dir),
-])
-
-import find_depot_tools
-from testing_support.super_mox import SuperMoxTestBase
-
-import copyright_scanner
-
-class FindCopyrightsTest(SuperMoxTestBase):
-  def setUp(self):
-    SuperMoxTestBase.setUp(self)
-    self.input_api = self.mox.CreateMockAnything()
-    self.input_api.re = re
-    self.input_api.os_path = os.path
-    self.input_api.os_walk = os.walk
-
-  def ShouldMatchReferenceOutput(self, test_data, expected_output):
-    for data in test_data:
-      self.input_api.ReadFile = lambda _1, _2: data
-      actual_output = copyright_scanner.FindCopyrights(self.input_api, '', [''])
-      self.assertEqual(
-        expected_output,
-        actual_output,
-        'Input """\n%s""", expected output: "%s", actual: "%s"' % \
-            (data, expected_output, actual_output));
-
-  def testCopyrightedFiles(self):
-    test_data = [
-      '// (c) 2014 Google Inc.\n//\n//  (a) One\n//\n//  (b) Two\n//\n',
-      'Copyright 2014 Google Inc.\n',
-      'Copr. 2014 Google Inc.',
-      '\xc2\xa9 2014 Google Inc.',
-      'Copyright 2014    Google  Inc.'
-    ]
-    self.ShouldMatchReferenceOutput(test_data, [['2014 Google Inc.']])
-
-  def testGeneratedFiles(self):
-    test_data = [
-      'ALL CHANGES MADE IN THIS FILE WILL BE LOST\nCopyright 2014 Google\n',
-      'GENERATED FILE. DO NOT EDIT\nCopyright 2014 Google\n',
-      'GENERATED. DO NOT DELETE THIS FILE.\nCopyright 2014 Google\n',
-      'DO NOT EDIT\nCopyright 2014 Google\n',
-      'DO NOT DELETE THIS FILE\nCopyright 2014 Google\n',
-      'All changes made in this file will be lost\nCopyright 2014 Google\n',
-      'Automatically generated file\nCopyright 2014 Google\n',
-      'Synthetically generated dummy file\nCopyright 2014 Google\n',
-      'Generated data (by gnugnu)\nCopyright 2014 Google\n'
-    ]
-    self.ShouldMatchReferenceOutput(test_data, [['GENERATED FILE']])
-
-  def testNonCopyrightedFiles(self):
-    test_data = [
-      'std::cout << "Copyright 2014 Google"\n',
-      '// Several points can be made:\n//\n//  (a) One\n//\n//  (b) Two\n'
-      '//\n//  (c) Three\n//\n',
-      'See \'foo\' for copyright information.\n',
-      'See \'foo\' for the copyright notice.\n',
-      'See \'foo\' for the copyright and other things.\n'
-    ]
-    self.ShouldMatchReferenceOutput(test_data, [['*No copyright*']])
-
-  def testNonGeneratedFiles(self):
-    test_data = [
-      'This file was prohibited from being generated.\n',
-      'Please do not delete our files! They are valuable to us.\n',
-      'Manually generated from dice rolls.\n',
-      '"""This Python script produces generated data\n"""\n',
-      '\'\'\'This Python script produces generated data\n\'\'\'\n'
-    ]
-    self.ShouldMatchReferenceOutput(test_data, [['*No copyright*']])
-
-
-class FindFilesTest(SuperMoxTestBase):
-  def setUp(self):
-    SuperMoxTestBase.setUp(self)
-    self.input_api = self.mox.CreateMockAnything()
-    self.input_api.re = re
-    self.input_api.os_path = os.path
-
-  def testFilesAsStartPaths(self):
-    join = self.input_api.os_path.join
-    self.input_api.os_path.isfile = lambda _: True
-    input_files = [
-      'a',
-      'a.cc',
-      'a.txt',
-      join('foo', 'a'),
-      join('foo', 'a.cc'),
-      join('foo', 'a.txt'),
-      join('third_party', 'a'),
-      join('third_party', 'a.cc'),
-      join('third_party', 'a.txt'),
-      join('foo', 'third_party', 'a'),
-      join('foo', 'third_party', 'a.cc'),
-      join('foo', 'third_party', 'a.txt'),
-    ]
-    root_dir = os.path.sep + 'src'
-    actual = copyright_scanner.FindFiles(
-      self.input_api, root_dir, input_files, [''])
-    self.assertEqual(['a.cc', join('foo', 'a.cc')], actual)
-    actual = copyright_scanner.FindFiles(
-      self.input_api, root_dir, input_files, ['third_party'])
-    self.assertEqual(['a.cc', join('foo', 'a.cc')], actual)
-    actual = copyright_scanner.FindFiles(
-      self.input_api, root_dir, input_files, ['foo'])
-    self.assertEqual(['a.cc'], actual)
-    actual = copyright_scanner.FindFiles(
-      self.input_api, root_dir, input_files, ['foo', 'third_party'])
-    self.assertEqual(['a.cc'], actual)
-    actual = copyright_scanner.FindFiles(
-      self.input_api, root_dir, input_files, [join('foo', 'third_party')])
-    self.assertEqual(['a.cc', join('foo', 'a.cc')], actual)
-
-  def testDirAsStartPath(self):
-    self.input_api.os_path.isfile = lambda _: False
-    join = self.input_api.os_path.join
-    normpath = self.input_api.os_path.normpath
-    root_dir = os.path.sep + 'src'
-    scan_from = '.'
-    base_path = join(root_dir, scan_from)
-
-    def mock_os_walk(path):
-      return lambda _: [(join(base_path, path), [''], ['a', 'a.cc', 'a.txt'])]
-
-    self.input_api.os_walk = mock_os_walk('')
-    actual = map(normpath, copyright_scanner.FindFiles(
-      self.input_api, root_dir, [scan_from], ['']))
-    self.assertEqual(['a.cc'], actual)
-
-    self.input_api.os_walk = mock_os_walk('third_party')
-    actual = map(normpath, copyright_scanner.FindFiles(
-      self.input_api, root_dir, [scan_from], ['']))
-    self.assertEqual([], actual)
-
-    self.input_api.os_walk = mock_os_walk('foo')
-    actual = map(normpath, copyright_scanner.FindFiles(
-      self.input_api, root_dir, [scan_from], ['']))
-    self.assertEqual([join('foo', 'a.cc')], actual)
-
-    self.input_api.os_walk = mock_os_walk('foo')
-    actual = map(normpath, copyright_scanner.FindFiles(
-      self.input_api, root_dir, [scan_from], ['foo']))
-    self.assertEqual([], actual)
-
-    self.input_api.os_walk = mock_os_walk(join('foo', 'bar'))
-    actual = map(normpath, copyright_scanner.FindFiles(
-      self.input_api, root_dir, [scan_from], ['foo']))
-    self.assertEqual([], actual)
-
-    self.input_api.os_walk = mock_os_walk(join('foo', 'third_party'))
-    actual = map(normpath, copyright_scanner.FindFiles(
-      self.input_api, root_dir, [scan_from], ['']))
-    self.assertEqual([], actual)
-
-    self.input_api.os_walk = mock_os_walk(join('foo', 'third_party'))
-    actual = map(normpath, copyright_scanner.FindFiles(
-      self.input_api, root_dir, [scan_from], [join('foo', 'third_party')]))
-    self.assertEqual([], actual)
-
-
-class AnalyzeScanResultsTest(SuperMoxTestBase):
-  def setUp(self):
-    SuperMoxTestBase.setUp(self)
-    self.input_api = self.mox.CreateMockAnything()
-    self.input_api.os_path = os.path
-    self.input_api.change = self.mox.CreateMockAnything()
-    self.input_api.change.RepositoryRoot = lambda: ''
-
-  def testAnalyzeScanResults(self):
-    # Tests whitelisted vs. current files state logic.
-    #
-    # Whitelisted - in whitelist, and contains 3rd party code => OK
-    # Missing - in whitelist, but doesn't exist
-    # Stale - in whitelist, but is clean
-    # Unknown - not in whitelist, but contains 3rd party code
-    self.input_api.os_path.isfile = lambda x: x != 'Missing'
-    self.assertEqual(
-      (['Unknown'], ['Missing'], ['Stale']),
-      copyright_scanner.AnalyzeScanResults(self.input_api, \
-          ['Whitelisted', 'Missing', 'Stale'], ['Whitelisted', 'Unknown']))
-
-
-class ScanAtPresubmitTest(SuperMoxTestBase):
-  def setUp(self):
-    SuperMoxTestBase.setUp(self)
-    self.input_api = self.mox.CreateMockAnything()
-    self.input_api.re = re
-    self.input_api.os_path = os.path
-    self.output_api = self.mox.CreateMockAnything()
-  def tearDown(self):
-    self.mox.UnsetStubs()
-    SuperMoxTestBase.tearDown(self)
-
-  class AffectedFileMock(object):
-    def __init__(self, local_path, action):
-      self._local_path = local_path
-      self._action = action
-    def LocalPath(self):
-      return self._local_path
-    def Action(self):
-      return self._action
-
-  def CreateAffectedFilesFunc(self, paths_and_actions):
-    result = []
-    for i in range(0, len(paths_and_actions), 2):
-      result.append(ScanAtPresubmitTest.AffectedFileMock(
-        paths_and_actions[i], paths_and_actions[i + 1]))
-    return lambda: result
-
-  def CreateDoScanAtPresubmitFunc(self):
-    self._whitelisted_files = None
-    self._files_to_check = None
-    def ScanAtPresubmitStub(_, whitelisted, to_check):
-      self._whitelisted_files = whitelisted
-      self._files_to_check = to_check
-      return ([], [], [])
-    return ScanAtPresubmitStub
-
-  def GetWhitelistedFiles(self):
-    return sorted(self._whitelisted_files)
-
-  def GetFilesToCheck(self):
-    return sorted(self._files_to_check)
-
-  def testWhitelistedUntouched(self):
-    # When a change doesn't touch the whitelist file, any updated files
-    # (except deleted) must be checked. The whitelist used for analysis
-    # must be trimmed to the changed files subset.
-    #
-    # A_NW.cc - added, not whitelisted => check
-    # A_W.cc - added, whitelisted => check, remain on the trimmed whitelist
-    # D_NW.cc - deleted, not whitelisted => ignore
-    # D_W.cc - deleted and whitelisted => remain on w/l
-    # M_NW.cc - modified, not whitelisted => check
-    # M_W.cc - modified and whitelisted => check, remain on w/l
-    # NM_W.cc - not modified, whitelisted => trim from w/l
-    # W - the whitelist file
-
-    self.input_api.AffectedFiles = self.CreateAffectedFilesFunc(
-      ['A_NW.cc', 'A', 'A_W.cc', 'A', 'D_NW.cc', 'D', 'D_W.cc', 'D',
-       'M_NW.cc', 'M', 'M_W.cc', 'M'])
-    self.mox.StubOutWithMock(copyright_scanner, '_GetWhitelistFileName')
-    copyright_scanner._GetWhitelistFileName = lambda _: 'W'
-    self.mox.StubOutWithMock(copyright_scanner, 'LoadWhitelistedFilesList')
-    copyright_scanner.LoadWhitelistedFilesList = \
-        lambda _: ['A_W.cc', 'D_W.cc', 'M_W.cc', 'NM_W.cc']
-    self.mox.StubOutWithMock(copyright_scanner, '_DoScanAtPresubmit')
-    copyright_scanner._DoScanAtPresubmit = self.CreateDoScanAtPresubmitFunc()
-    self.mox.ReplayAll()
-    copyright_scanner.ScanAtPresubmit(self.input_api, self.output_api)
-    self.assertEqual(
-      ['A_W.cc', 'D_W.cc', 'M_W.cc'], self.GetWhitelistedFiles())
-    self.assertEqual(
-      ['A_NW.cc', 'A_W.cc', 'M_NW.cc', 'M_W.cc'], self.GetFilesToCheck())
-
-  def testWhitelistTouched(self):
-    # When the whitelist file is touched by the change, all the files listed in
-    # it, including deleted entries, must be re-checked. All modified files
-    # (including the deleted ones) must be checked as well. The current contents
-    # of the whitelist are used for analysis.
-    # Whitelist addition or deletion are not considered.
-    #
-    # All the files from names testWhitelistedUntouched are re-used, but now
-    # action for all of them is 'check' (except for the w/l file itself).
-    # A_DW.cc - added, deleted from w/l => check
-    # D_DW.cc - deleted from repo and w/l => check
-    # M_DW.cc - modified, deleted from w/l => check
-    self.input_api.AffectedFiles = self.CreateAffectedFilesFunc(
-      ['A_DW.cc', 'A', 'A_NW.cc', 'A', 'A_W.cc', 'A',
-       'D_DW.cc', 'D', 'D_NW.cc', 'D', 'D_W.cc', 'D',
-       'M_DW.cc', 'M', 'M_NW.cc', 'M', 'M_W.cc', 'M', 'W', 'M'])
-    self.mox.StubOutWithMock(copyright_scanner, '_GetWhitelistFileName')
-    copyright_scanner._GetWhitelistFileName = lambda _: 'W'
-    self.mox.StubOutWithMock(copyright_scanner, '_GetDeletedContents')
-    def GetDeletedContentsStub(affected_file):
-      self.assertEqual('W', affected_file.LocalPath())
-      return ['A_DW.cc', 'D_DW.cc', 'M_DW.cc']
-    copyright_scanner._GetDeletedContents = GetDeletedContentsStub
-    self.mox.StubOutWithMock(copyright_scanner, 'LoadWhitelistedFilesList')
-    copyright_scanner.LoadWhitelistedFilesList = \
-        lambda _: ['A_W.cc', 'D_W.cc', 'M_W.cc', 'NM_W.cc']
-    self.mox.StubOutWithMock(copyright_scanner, '_DoScanAtPresubmit')
-    copyright_scanner._DoScanAtPresubmit = self.CreateDoScanAtPresubmitFunc()
-    self.mox.ReplayAll()
-    copyright_scanner.ScanAtPresubmit(self.input_api, self.output_api)
-    self.assertEqual(
-      ['A_W.cc', 'D_W.cc', 'M_W.cc', 'NM_W.cc'], self.GetWhitelistedFiles())
-    self.assertEqual(
-      ['A_DW.cc', 'A_NW.cc', 'A_W.cc', 'D_DW.cc', 'D_NW.cc', 'D_W.cc',
-       'M_DW.cc', 'M_NW.cc', 'M_W.cc', 'NM_W.cc' ], self.GetFilesToCheck())
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/tools/copyright_scanner/third_party_files_whitelist.txt b/tools/copyright_scanner/third_party_files_whitelist.txt
deleted file mode 100644
index 25fe15af..0000000
--- a/tools/copyright_scanner/third_party_files_whitelist.txt
+++ /dev/null
@@ -1,252 +0,0 @@
-# Copyright (c) 2012 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 records third-party licensing information for the purposes of the
-# Android WebView build. See webview_licenses.py for details.
-#
-# New third-party code should be added under a directory named 'third_party',
-# so additions to this file should be rare. See
-# http://www.chromium.org/developers/adding-3rd-party-libraries.
-#
-# Please always use forward slashes '/' as path separators, even if you are
-# on Windows.
-
-# Copyright IBM; MIT license. This third-party code is taken from ICU, the
-# license for which we already pick up from third_party/icu/.
-base/i18n/icu_string_conversions.cc
-# Contains '(c)' in comments
-base/logging.h
-# Copyright Ron Rivest, public domain.
-base/md5.cc
-# Copyright Apple Inc; BSD license. Moved from third_party/WebKit/.
-cc/input/scroll_elasticity_helper.h
-# Copyright Netscape Communications Corporation; MPL, GPL v2 or LGPL v2
-# license. Not used on Android.
-chrome/browser/importer/firefox_profile_lock.cc
-# Copyright Netscape Communications Corporation; MPL, GPL v2 or LGPL v2
-# license. Not used on Android.
-chrome/browser/importer/firefox_profile_lock.h
-# Copyright Netscape Communications Corporation; MPL, GPL v2 or LGPL v2
-# license. Not used on Android.
-chrome/browser/importer/firefox_profile_lock_posix.cc
-# Copyright Netscape Communications Corporation; MPL, GPL v2 or LGPL v2
-# license. Not used on Android.
-chrome/browser/importer/firefox_profile_lock_win.cc
-# String 'copyright' used in code.
-chrome/common/importer/firefox_importer_utils.cc
-# Copyright Netscape Communications Corporation; MPL, GPL v2 or LGPL v2
-# license. Not used on Android.
-chrome/utility/importer/nss_decryptor.cc
-# Copyright Netscape Communications Corporation; MPL, GPL v2 or LGPL v2
-# license. Not used on Android.
-chrome/utility/importer/nss_decryptor_mac.h
-# Copyright Netscape Communications Corporation; MPL, GPL v2 or LGPL v2
-# license. Not used on Android.
-chrome/utility/importer/nss_decryptor_system_nss.cc
-# Copyright Netscape Communications Corporation; MPL, GPL v2 or LGPL v2
-# license. Not used on Android.
-chrome/utility/importer/nss_decryptor_win.h
-# Copyright Google Inc; BSD license. Test code only.
-chrome/tools/test/generate_mime_tests.pl
-# String 'copyright' used in the text presented to the user as part of
-# Google Chrome terms of service.
-components/resources/terms/chromeos/terms_en.html
-components/resources/terms/terms_am.html
-components/resources/terms/terms_ca.html
-components/resources/terms/terms_cs.html
-components/resources/terms/terms_da.html
-components/resources/terms/terms_de.html
-components/resources/terms/terms_en-GB.html
-components/resources/terms/terms_en.html
-components/resources/terms/terms_es-419.html
-components/resources/terms/terms_es.html
-components/resources/terms/terms_et.html
-components/resources/terms/terms_fi.html
-components/resources/terms/terms_fil.html
-components/resources/terms/terms_fr.html
-components/resources/terms/terms_he.html
-components/resources/terms/terms_hr.html
-components/resources/terms/terms_hu.html
-components/resources/terms/terms_id.html
-components/resources/terms/terms_it.html
-components/resources/terms/terms_ja.html
-components/resources/terms/terms_kn.html
-components/resources/terms/terms_ko.html
-components/resources/terms/terms_lt.html
-components/resources/terms/terms_lv.html
-components/resources/terms/terms_ml.html
-components/resources/terms/terms_nb.html
-components/resources/terms/terms_nl.html
-components/resources/terms/terms_pl.html
-components/resources/terms/terms_pt-BR.html
-components/resources/terms/terms_pt-PT.html
-components/resources/terms/terms_ro.html
-components/resources/terms/terms_sk.html
-components/resources/terms/terms_sl.html
-components/resources/terms/terms_sr.html
-components/resources/terms/terms_sv.html
-components/resources/terms/terms_sw.html
-components/resources/terms/terms_ta.html
-components/resources/terms/terms_te.html
-components/resources/terms/terms_th.html
-components/resources/terms/terms_tr.html
-components/resources/terms/terms_vi.html
-# Copyright Apple Inc, Nokia Corporation and Torch Mobile Inc; BSD license.
-# Contains code moved from third_party/WebKit/.
-content/browser/frame_host/navigation_controller_impl.cc
-# Copyright Apple, Inc, Google Inc; BSD license. Not used on Android.
-# Moved from third_party/WebKit/.
-content/browser/renderer_host/input/web_input_event_builders_mac.mm
-# Copyright Apple Inc and Torch Mobile Inc; BSD license. Moved from
-# third_party/WebKit/.
-content/renderer/history_controller.h
-# Copyright Apple Inc, Nokia Corporation and Torch Mobile Inc; BSD license.
-# Moved from third_party/WebKit/.
-content/renderer/history_controller.cc
-# Copyright Apple Inc and Torch Mobile Inc; BSD license. Moved from
-# third_party/WebKit/.
-content/renderer/history_entry.h
-# Copyright Apple Inc, Nokia Corporation and Torch Mobile Inc; BSD license.
-# Moved from third_party/WebKit/.
-content/renderer/history_entry.cc
-# Copyright Google Inc, no license. Not used on Android.
-google_update/google_update_idl.idl
-# Copyright WebM Project authors; BSD license. Copied and modified from
-# third_party/libvpx. Not used on Android.
-media/filters/vp8_bool_decoder.h
-media/filters/vp8_bool_decoder.cc
-# Native client not used in Android. Contains the word "Copyright"
-native_client_sdk/doc_generated/rest-devsite-examples.html
-# String '(c)' used in certificates organization names
-net/cert/x509_certificate_known_roots_win.h
-net/quic/core/crypto/common_cert_set_2a.inc
-net/quic/core/crypto/common_cert_set_2b.inc
-net/quic/core/crypto/common_cert_set_3a.inc
-net/quic/core/crypto/common_cert_set_3b.inc
-# String '(c)' used in certificates organization names
-net/test/test_certificate_data.h
-# Copyright The Chromium Authors and Netscape Communications Corporation; BSD
-# and (MPL, GPL v2 or LGPL v2) licenses. This third-party code is taken from
-# Mozilla, the license for which we already pick up from third_party/npapi/.
-net/cookies/cookie_monster.cc
-# Copyright The Chromium Authors and Netscape Communications Corporation; BSD
-# and (MPL, GPL v2 or LGPL v2) licenses. This third-party code is taken from
-# Mozilla, the license for which we already pick up from third_party/npapi/.
-net/cookies/canonical_cookie.cc
-# Copyright The Chromium Authors and Netscape Communications Corporation; BSD
-# and (MPL, GPL v2 or LGPL v2) licenses. This third-party code is taken from
-# Mozilla, the license for which we already pick up from third_party/npapi/.
-net/cookies/parsed_cookie.cc
-# Copyright The Chromium Authors and Google Inc; BSD and (MPL, GPL v2 or LGPL
-# v2) licenses. This third-party code is taken from Mozilla, the license for
-# which we already pick up from third_party/npapi/.
-net/base/registry_controlled_domains/registry_controlled_domain.cc
-# Copyright The Chromium Authors and Google Inc; BSD and (MPL, GPL v2 or LGPL
-# v2) licenses. This third-party code is taken from Mozilla, the license for
-# which we already pick up from third_party/npapi/.
-net/base/registry_controlled_domains/registry_controlled_domain.h
-# Copyright The Chromium Authors and IBM Corporation; BSD and (MPL, GPL v2 or
-# LGPL v2) licenses. This third-party code is taken from Mozilla, the license
-# for which we already pick up from third_party/npapi/.
-net/http/des.cc
-# Copyright The Chromium Authors and IBM Corporation; BSD and (MPL, GPL v2 or
-# LGPL v2) licenses. This third-party code is taken from Mozilla, the license
-# for which we already pick up from third_party/npapi/.
-net/http/http_auth_handler_ntlm_portable.cc
-# Copyright The Chromium Authors and Netscape Communications; BSD and (MPL, GPL
-# v2 or LGPL v2) licenses. This third-party code is taken from Mozilla, the
-# license for which we already pick up from third_party/npapi/.
-net/http/http_chunked_decoder.cc
-# Copyright The Chromium Authors and Netscape Communications; BSD and (MPL, GPL
-# v2 or LGPL v2) licenses. This third-party code is taken from Mozilla, the
-# license for which we already pick up from third_party/npapi/.
-net/http/http_chunked_decoder.h
-# Copyright IBM Corporation; MPL, GPL v2 or LGPL v2 license. This third-party
-# code is taken from Mozilla, the license for which we already pick up from
-# third_party/npapi/.
-net/http/md4.cc
-# Copyright IBM Corporation; MPL, GPL v2 or LGPL v2 license. This third-party
-# code is taken from Mozilla, the license for which we already pick up from
-# third_party/npapi/.
-net/http/md4.h
-# Netscape Communications Corporation; MPL, GPL v2 or LGPL v2 license. This
-# third-party code is taken from Mozilla, the license for which we already pick
-# up from third_party/npapi/.
-net/proxy/proxy_resolver_script.h
-# Contains the word 'Copyright' in comments
-ppapi/generators/idl_c_proto.py
-ppapi/generators/idl_outfile.py
-# Copyright (c) 2007-2009 The Khronos Group Inc.  Not used on Android
-ppapi/lib/gl/include/EGL/egl.h
-ppapi/lib/gl/include/EGL/eglext.h
-ppapi/lib/gl/include/EGL/eglplatform.h
-ppapi/lib/gl/include/KHR/khrplatform.h
-# Copyright The Android Open Source Project; ASL v2 license.
-skia/config/SkUserConfig.h
-# Generates copyright headers for Chromium.
-tools/boilerplate.py
-# Contains test strings that look like copyrights.
-tools/copyright_scanner/copyright_scanner_unittest.py
-# Contains word 'copyright' in comments.
-tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py
-# This third-party code is taken from Mozilla, but is copyright Google and has
-# been re-licensed under the Chromium license.
-tools/imagediff/image_diff_png.cc
-# Copyright Ero Carrera; BSD license. Tool only.
-tools/symsrc/pefile.py
-# Copyright The Chromium Authors, Sun Microsystems Inc, the V8 project authors;
-# BSD license. Tool only.
-tools/traceline/traceline/assembler.h
-# Copyright Google Inc; BSD license. Tool only.
-tools/traceline/traceline/sidestep/mini_disassembler.cc
-# Copyright Marijn Haverbeke. MIT license. Tool only, not used on Android.
-tools/win/sizeviewer/clike.js
-# Copyright Marijn Haverbeke. MIT license. Tool only, not used on Android.
-tools/win/sizeviewer/codemirror.js
-# Copyright The Chromium Authors, Apple Inc; BSD license. Not used on Android.
-ui/base/clipboard/clipboard_util_win.cc
-# Copyright The Chromium Authors, Apple Inc and Graham Dennis; BSD license. Not
-# used on Android.
-ui/base/cocoa/tool_tip_base_view.mm
-# Copyright The Chromium Authors, Apple Inc; BSD license. Not used on Android.
-ui/base/dragdrop/os_exchange_data_provider_win.cc
-# Copyright Apple Inc; BSD license. Moved from third_party/WebKit/.
-ui/events/blink/input_scroll_elasticity_controller.cc
-ui/events/blink/input_scroll_elasticity_controller.h
-# Copyright The Chromium Authors, Michael Emmel, Google Inc; BSD license. This
-# third-party code is taken from WebKit, the license for which we already pick
-# up from webkit/.
-ui/events/keycodes/keyboard_codes_posix.h
-# String 'copyright' used in code.
-ui/file_manager/file_manager/foreground/js/main_scripts.js
-# String 'copyright' used in code.
-ui/file_manager/gallery/js/gallery_scripts.js
-# String 'copyright' used in code.
-ui/file_manager/video_player/js/video_player_scripts.js
-# This third-party code is taken from Mozilla, but is copyright Google and has
-# been re-licensed under the Chromium license.
-ui/gfx/codec/jpeg_codec.cc
-# This third-party code is taken from Mozilla, but is copyright Google and has
-# been re-licensed under the Chromium license.
-ui/gfx/codec/png_codec.cc
-# Copyright The Chromium Authors and Apple Inc; BSD license. This third-party
-# code is taken from WebKit, the license for which we already pick up from
-# webkit/.
-content/browser/appcache/appcache_manifest_parser.cc
-# Copyright The Chromium Authors and Apple Inc; BSD license. This third-party
-# code is taken from WebKit, the license for which we already pick up from
-# webkit/.
-content/browser/appcache/appcache_manifest_parser.h
-# String 'copyright' used in code.
-ui/webui/resources/js/cr/ui/array_data_model.js
-# Bundles of existing code.
-chrome/browser/resources/md_downloads/vulcanized.html
-chrome/browser/resources/md_history/app.vulcanized.html
-chrome/browser/resources/md_history/lazy_load.vulcanized.html
-# Generated config files, which are checked in outside of the third-party
-# library they configure. Copyright The open-vcdiff Authors; Apache2 license.
-sdch/ios/config.h
-sdch/linux/config.h
-sdch/mac/config.h
-sdch/win/config.h
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index b48fa8ea..756d74f 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -91,7 +91,7 @@
       'Linux ChromiumOS Builder': 'chromeos_with_codecs_release_bot',
       'Linux ChromiumOS Builder (dbg)': 'chromeos_with_codecs_debug_bot',
       'Linux ChromiumOS Full': 'chromeos_with_codecs_release_bot',
-      'Linux ChromiumOS Ozone Builder': 'chromeos_with_codecs_ozone_release_bot',
+      'Linux ChromiumOS Ozone Builder': 'chromeos_with_codecs_release_bot',
     },
 
     'chromium.fyi': {
@@ -205,10 +205,10 @@
       'Linux remote_run Tester': 'release_bot',
       'Mac deterministic': 'release_bot_mac_strip',
       'Mac deterministic (dbg)': 'debug_bot',
-      'Mojo ChromiumOS': 'chromeos_with_codecs_ozone_release_trybot',
+      'Mojo ChromiumOS': 'chromeos_with_codecs_release_trybot',
       'Mojo Linux': 'release_trybot',
       'Mojo Windows': 'release_bot_x86_minimal_symbols',
-      'Ozone Linux': 'release_bot_ozone_linux',
+      'Ozone Linux': 'ozone_linux_release_bot',
       'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64',
       'Site Isolation Linux': 'release_trybot',
       'Site Isolation Win': 'release_trybot_x86',
@@ -259,7 +259,7 @@
       'GPU Win x64 Builder': 'gpu_tests_deqp_gles_release_trybot',
       'GPU Win x64 Builder (dbg)': 'gpu_tests_deqp_gles_debug_trybot',
       'Linux ChromiumOS Builder': 'gpu_fyi_tests_chromeos_release_trybot',
-      'Linux ChromiumOS Ozone Builder': 'gpu_fyi_tests_chromeos_ozone_release_trybot',
+      'Linux ChromiumOS Ozone Builder': 'gpu_fyi_tests_chromeos_release_trybot',
       'Linux GPU TSAN Release': 'gpu_fyi_tests_release_trybot_tsan',
       'Mac GPU ASAN Release': 'gpu_fyi_tests_release_trybot_asan',
     },
@@ -539,7 +539,7 @@
       'linux_chromium_chromeos_compile_rel_ng': 'chromeos_with_codecs_release_trybot',
       'linux_chromium_chromeos_dbg_ng': 'chromeos_with_codecs_debug_trybot',
       'linux_chromium_chromeos_msan_rel_ng': 'chromeos_msan_release_bot',
-      'linux_chromium_chromeos_ozone_rel_ng': 'chromeos_with_codecs_ozone_release_trybot',
+      'linux_chromium_chromeos_ozone_rel_ng': 'chromeos_with_codecs_release_trybot',
       'linux_chromium_chromeos_rel_ng': 'chromeos_with_codecs_release_trybot',
       'linux_chromium_clobber_deterministic': 'release_trybot',
       'linux_chromium_clobber_rel_ng': 'release_trybot',
@@ -947,7 +947,7 @@
     ],
 
     'asan_lsan_chromeos_release_trybot': [
-      'asan', 'lsan', 'chromeos', 'x11_cros', 'release_trybot',
+      'asan', 'lsan', 'chromeos', 'release_trybot',
     ],
 
     'asan_lsan_edge_debug_bot': [
@@ -1015,35 +1015,27 @@
     ],
 
     'chromeos_asan_lsan_edge_fuzzer_v8_heap_release_bot': [
-      'chromeos', 'x11_cros', 'asan', 'lsan', 'edge', 'fuzzer', 'v8_heap', 'release_bot',
+      'chromeos', 'asan', 'lsan', 'edge', 'fuzzer', 'v8_heap', 'release_bot',
     ],
 
     'chromeos_msan_release_bot': [
-      'chromeos', 'x11_cros', 'msan', 'release_bot',
+      'chromeos', 'msan', 'release_bot',
     ],
 
     'chromeos_with_codecs_debug_bot': [
-      'chromeos_with_codecs', 'x11_cros', 'debug_bot',
+      'chromeos_with_codecs', 'debug_bot',
     ],
 
     'chromeos_with_codecs_debug_trybot': [
-      'chromeos_with_codecs', 'x11_cros', 'debug_trybot',
-    ],
-
-    'chromeos_with_codecs_ozone_release_bot': [
-      'chromeos_with_codecs', 'ozone', 'release_bot',
-    ],
-
-    'chromeos_with_codecs_ozone_release_trybot': [
-      'chromeos_with_codecs', 'ozone', 'release_trybot',
+      'chromeos_with_codecs', 'debug_trybot',
     ],
 
     'chromeos_with_codecs_release_bot': [
-      'chromeos_with_codecs', 'x11_cros', 'release_bot',
+      'chromeos_with_codecs', 'release_bot',
     ],
 
     'chromeos_with_codecs_release_trybot': [
-      'chromeos_with_codecs', 'x11_cros', 'release_trybot',
+      'chromeos_with_codecs', 'release_trybot',
     ],
 
     'clang_debug_trybot_x86': [
@@ -1170,7 +1162,7 @@
     ],
 
     'codesearch_gen_chromium_chromiumos_bot': [
-      'goma', 'clang', 'shared', 'debug', 'minimal_symbols', 'x64', 'chromeos', 'ozone',
+      'goma', 'clang', 'shared', 'debug', 'minimal_symbols', 'x64', 'chromeos',
     ],
 
     'codesearch_gen_chromium_linux_bot': [
@@ -1234,12 +1226,8 @@
       'debug_trybot', 'x86',
     ],
 
-    'gpu_fyi_tests_chromeos_ozone_release_trybot': [
-      'gpu_fyi_tests', 'release_trybot', 'ozone', 'ozone_linux', 'system_gbm_libdrm',
-    ],
-
     'gpu_fyi_tests_chromeos_release_trybot': [
-      'gpu_fyi_tests', 'release_trybot', 'chromeos', 'x11_cros',
+      'gpu_fyi_tests', 'release_trybot', 'chromeos', 'system_gbm_libdrm',
     ],
 
     'gpu_fyi_tests_debug_trybot': [
@@ -1368,7 +1356,7 @@
     ],
 
     'official_goma_chromeos': [
-      'official', 'goma', 'chromeos', 'x11_cros',
+      'official', 'goma', 'chromeos',
     ],
 
     'official_goma_thin_lto_use_lld': [
@@ -1403,16 +1391,12 @@
       'official_optimize', 'chrome_pgo_phase_2', 'x86',
     ],
 
-    'release_bot_ozone_linux': [
-      'release_bot', 'ozone', 'ozone_linux',
-    ],
-
-    'release_bot_fuchsia': [
-      'release_bot', 'fuchsia',
+    'ozone_linux_release_bot': [
+      'ozone_linux', 'release_bot',
     ],
 
     'ozone_linux_release_trybot': [
-      'release_trybot', 'ozone', 'ozone_linux',
+      'ozone_linux', 'release_trybot',
     ],
 
     'release_afl_asan': [
@@ -1435,6 +1419,10 @@
       'release_bot', 'chrome_with_codecs',
     ],
 
+    'release_bot_fuchsia': [
+      'release_bot', 'fuchsia',
+    ],
+
     'release_bot_mac_new_sdk': [
       'release_bot', 'mac_new_sdk',
     ],
@@ -1851,11 +1839,6 @@
       'gn_args': 'symbol_level=0',
     },
 
-    'x11_cros': {
-      # When use_ozone=false then use_x11=true.
-      'gn_args': 'use_ozone=false',
-    },
-
     'official': {
       'mixins': ['official_optimize'],
       'gn_args': 'is_chrome_branded=true',
@@ -1869,16 +1852,12 @@
       'gn_args': 'optimize_for_fuzzing=true',
     },
 
-    'ozone': {
-      'gn_args': 'use_ozone=true',
-    },
-
     'ozone_linux': {
       'gn_args': ('ozone_auto_platforms=false ozone_platform_wayland=true '
                   'ozone_platform="x11" '
                   'ozone_platform_x11=true ozone_platform_gbm=true '
                   'enable_package_mash_services=true use_ash=false '
-                  'use_xkbcommon=true'),
+                  'use_xkbcommon=true use_ozone=true'),
     },
 
     'fuchsia': {
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index bde0ced..389d9cc 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -40732,6 +40732,9 @@
 </histogram>
 
 <histogram name="Net.Socket.IdleSocketReuseTime" units="seconds">
+  <obsolete>
+    Deprecated as of 7/2017.
+  </obsolete>
   <owner>mmenke@chromium.org</owner>
   <summary>
     Seconds a socket was idle before it was reused. Emitted upon reuse. Does not
@@ -50201,8 +50204,7 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Network"
-    units="KB">
+<histogram name="PageLoad.Bytes.AdFrames.Aggregate.Network" units="KB">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The size (in KB) of the resources loaded for all of the ad frames on the
@@ -50216,9 +50218,7 @@
   </summary>
 </histogram>
 
-<histogram
-    name="PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.PercentNetwork"
-    units="%">
+<histogram name="PageLoad.Bytes.AdFrames.Aggregate.PercentNetwork" units="%">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The percentage of bytes loaded for all ad frames that were loaded over the
@@ -50232,8 +50232,7 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Total"
-    units="KB">
+<histogram name="PageLoad.Bytes.AdFrames.Aggregate.Total" units="KB">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The size (in KB) of the resources loaded for all of the ad frames on the
@@ -50247,8 +50246,7 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Network"
-    units="KB">
+<histogram name="PageLoad.Bytes.AdFrames.PerFrame.Network" units="KB">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The size (in KB) of the resources loaded for an ad frame from the network.
@@ -50261,9 +50259,7 @@
   </summary>
 </histogram>
 
-<histogram
-    name="PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.PercentNetwork"
-    units="%">
+<histogram name="PageLoad.Bytes.AdFrames.PerFrame.PercentNetwork" units="%">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The percentage of bytes loaded for a single ad frame that were loaded over
@@ -50277,8 +50273,7 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Total"
-    units="KB">
+<histogram name="PageLoad.Bytes.AdFrames.PerFrame.Total" units="KB">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The size (in KB) of the resources loaded for an ad frame.
@@ -50291,7 +50286,7 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.Google.Bytes.FullPage.Network" units="KB">
+<histogram name="PageLoad.Bytes.FullPage.Network" units="KB">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The size (in KB) of all of the page's resources that loaded over the
@@ -50303,8 +50298,7 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.Google.Bytes.FullPage.Network.PercentAds"
-    units="%">
+<histogram name="PageLoad.Bytes.FullPage.Network.PercentAds" units="%">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The percentage of bytes loaded for the page (from the network) that came
@@ -50318,7 +50312,7 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.Google.Bytes.FullPage.Total" units="KB">
+<histogram name="PageLoad.Bytes.FullPage.Total" units="KB">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The size (in KB) of all of the page's resources.
@@ -50329,8 +50323,7 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.Google.Bytes.FullPage.Total.PercentAds"
-    units="%">
+<histogram name="PageLoad.Bytes.FullPage.Total.PercentAds" units="%">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The percentage of bytes loaded for the page that came from resource loads in
@@ -50344,8 +50337,7 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.Google.Bytes.NonAdFrames.Aggregate.Total"
-    units="KB">
+<histogram name="PageLoad.Bytes.NonAdFrames.Aggregate.Total" units="KB">
   <owner>jkarlin@chromium.org</owner>
   <summary>
     The size (in KB) of all of the page's resources except for those loaded in
@@ -50359,18 +50351,51 @@
   </summary>
 </histogram>
 
-<histogram
-    name="PageLoad.Clients.Ads.Google.FrameCounts.AnyParentFrame.AdFrames"
-    units="Ad frames">
+<histogram name="PageLoad.Clients.Ads.All.Navigations.AdFrameRenavigatedToAd"
+    enum="DidNavigateToAd">
   <owner>jkarlin@chromium.org</owner>
   <summary>
-    The number of frames on the page identified as Google Ad Frames that have
-    loaded more than 0 bytes of content.
+    When a frame that is (or previously was) an ad frame renavigates, record
+    whether it renavigated to an ad frame or a non-ad frame.
 
-    For pages with zero ad frames, the other PageLoad.Clients.Ads metrics are
-    not recorded unless otherwise specified.
+    An ad frame consists of the identified ad frame and all of its children. Its
+    children (which may also be ads) are not counted when they renavigate.
 
-    Child frames of an ad frame are not included in the count.
+    This metric is recorded as the event happens. Note that this is unlike most
+    other Clients.Ads metrics, which are recorded when the page load is
+    complete.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.Ads.All.Navigations.NonAdFrameRenavigatedToAd"
+    enum="DidNavigateToAd">
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    When a frame that has never been part of an ad frame renavigates, record
+    whether it renavigated to an ad frame or a non-ad frame.
+
+    This metric is recorded as the event happens. Note that this is unlike most
+    other Clients.Ads metrics, which are recorded when the page load is
+    complete.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Clients.Ads.All.ParentExistsForSubFrame"
+    enum="ParentFrameKnown">
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    Records whether or not a parent frame is found for a subframe that finishes
+    navigating.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Clients.Ads.All.ResourceTypeWhenNoFrameFound"
+    enum="ContentResourceType2">
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    Records the content::ResourceType when a resource finishes loading but the
+    ads metrics aren't aware of a committed frame for the resource.
   </summary>
 </histogram>
 
@@ -50424,6 +50449,10 @@
 <histogram
     name="PageLoad.Clients.Ads.Google.Navigations.AdFrameRenavigatedToAd"
     enum="DidNavigateToAd">
+  <obsolete>
+    Deprecated In July 2017. Use
+    PageLoad.Clients.Ads.All.Navigations.AdFrameRenavigatedToAd instead.
+  </obsolete>
   <owner>jkarlin@chromium.org</owner>
   <summary>
     When a frame that is (or previously was) an ad frame renavigates, record
@@ -50441,6 +50470,10 @@
 <histogram
     name="PageLoad.Clients.Ads.Google.Navigations.NonAdFrameRenavigatedToAd"
     enum="DidNavigateToAd">
+  <obsolete>
+    Deprecated In July 2017. Use
+    PageLoad.Clients.Ads.All.Navigations.NonAdFrameRenavigatedToAd instead.
+  </obsolete>
   <owner>jkarlin@chromium.org</owner>
   <summary>
     When a frame that has never been part of an ad frame renavigates, record
@@ -50454,6 +50487,10 @@
 
 <histogram name="PageLoad.Clients.Ads.Google.ParentExistsForSubFrame"
     enum="ParentFrameKnown">
+  <obsolete>
+    Deprecated In July 2017. Use
+    PageLoad.Clients.Ads.All.ParentExistsForSubFrame instead.
+  </obsolete>
   <owner>jkarlin@chromium.org</owner>
   <summary>
     Records whether or not a parent frame is found for a subframe that finishes
@@ -50463,6 +50500,10 @@
 
 <histogram name="PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound"
     enum="ContentResourceType2">
+  <obsolete>
+    Deprecated In July 2017. Use
+    PageLoad.Clients.Ads.All.ResourceTypeWhenNoFrameFound instead.
+  </obsolete>
   <owner>jkarlin@chromium.org</owner>
   <summary>
     Records the content::ResourceType when a resource finishes loading but the
@@ -51159,6 +51200,20 @@
   </summary>
 </histogram>
 
+<histogram name="PageLoad.FrameCounts.AnyParentFrame.AdFrames"
+    units="Ad frames">
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    The number of frames on the page that have loaded more than 0 bytes of
+    content.
+
+    For pages with zero ad frames, the other PageLoad.Clients.Ads metrics are
+    not recorded unless otherwise specified.
+
+    Child frames of an ad frame are not included in the count.
+  </summary>
+</histogram>
+
 <histogram name="PageLoad.InputTiming.NavigationToFirstNonScroll.AfterPaint"
     units="ms">
   <owner>tdresser@chromium.org</owner>
@@ -88712,6 +88767,25 @@
   <affected-histogram name="MobileStartup.IntentToCreationTime"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="AdsPageLoadMetrics" separator="." ordering="prefix">
+  <suffix name="Clients.Ads.Google" label="Includes only Google ads."/>
+  <suffix name="Clients.Ads.SubresourceFilter"
+      label="Includes only ads discovered by the SubResourceFilter."/>
+  <suffix name="Clients.Ads.All" label="Includes all discovered ads."/>
+  <affected-histogram name="PageLoad.Bytes.AdFrames.Aggregate.Network"/>
+  <affected-histogram name="PageLoad.Bytes.AdFrames.Aggregate.PercentNetwork"/>
+  <affected-histogram name="PageLoad.Bytes.AdFrames.Aggregate.Total"/>
+  <affected-histogram name="PageLoad.Bytes.AdFrames.PerFrame.Network"/>
+  <affected-histogram name="PageLoad.Bytes.AdFrames.PerFrame.PercentNetwork"/>
+  <affected-histogram name="PageLoad.Bytes.AdFrames.PerFrame.Total"/>
+  <affected-histogram name="PageLoad.Bytes.FullPage.Network"/>
+  <affected-histogram name="PageLoad.Bytes.FullPage.Network.PercentAds"/>
+  <affected-histogram name="PageLoad.Bytes.FullPage.Total"/>
+  <affected-histogram name="PageLoad.Bytes.FullPage.Total.PercentAds"/>
+  <affected-histogram name="PageLoad.Bytes.NonAdFrames.Aggregate.Total"/>
+  <affected-histogram name="PageLoad.FrameCounts.AnyParentFrame.AdFrames"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="AffiliationDummyData" separator=".">
   <suffix name="OnStartup"
       label="with the dummy data being requested shortly after start-up"/>
diff --git a/tools/perf/page_sets/update_webrtc_cases b/tools/perf/page_sets/update_webrtc_cases
index 03a8218..01f55fe5 100755
--- a/tools/perf/page_sets/update_webrtc_cases
+++ b/tools/perf/page_sets/update_webrtc_cases
@@ -24,6 +24,7 @@
             'src/multiple-peerconnections',
             'src/pause-play',
         ],
+        'revision': 'cbb12a3994692c63c9d885c95db0f67c5e3e3465',
     },
     'samples': {
         'dirs': [
@@ -35,11 +36,13 @@
         'files': [
             'src/js/common.js',
         ],
+        'revision': '6f9a14c10ee9b990d56c309d86d4b9129a4aa626',
     },
     'adapter': {
         'files': [
             'release/adapter.js',
         ],
+        'revision': '5b7ce4bdce79b9cb754fe27b097106e9491e0354',
     },
 }
 
@@ -132,13 +135,18 @@
     os.makedirs(args.destination)
 
   with TemporaryDirectory() as temp_dir:
-    for repo_name, test_dirs in TEST_PAGES_LOCATION_BY_REPO.items():
+    for repo_name, repo_info in TEST_PAGES_LOCATION_BY_REPO.items():
       p = subprocess.Popen(['git', 'clone', WEBRTC_GITHUB_URL + repo_name],
                            cwd=temp_dir)
       p.wait()
 
-      for test_dir in test_dirs.get('dirs', []):
-        test_dir = os.path.join(temp_dir, repo_name, test_dir)
+      repo_dir = os.path.join(temp_dir, repo_name)
+      p = subprocess.Popen(['git', 'checkout', repo_info.get('revision')],
+                           cwd=repo_dir)
+      p.wait()
+
+      for test_dir in repo_info.get('dirs', []):
+        test_dir = os.path.join(repo_dir, test_dir)
         test_name = os.path.basename(test_dir)
 
         CopyJSFile(os.path.join(test_dir, 'js', 'main.js'),
@@ -146,7 +154,7 @@
         CopyHTMLFile(test_name, os.path.join(test_dir, 'index.html'),
                      os.path.join(args.destination, test_name + '.html'))
 
-      for test_file in test_dirs.get('files', []):
+      for test_file in repo_info.get('files', []):
         file_name = os.path.basename(test_file)
         CopyJSFile(os.path.join(temp_dir, repo_name, test_file),
                    os.path.join(args.destination, file_name), False)
diff --git a/tools/tests/OWNERS b/tools/tests/OWNERS
index 68295e64..704ad91 100644
--- a/tools/tests/OWNERS
+++ b/tools/tests/OWNERS
@@ -1 +1,3 @@
-per-file licenses_test.py=file://tools/copyright_scanner/OWNERS
+per-file licenses_test.py=phajdan.jr@chromium.org
+per-file licenses_test.py=sgurun@chromium.org
+per-file licenses_test.py=torne@chromium.org
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index d2cba5c..df55761 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -62,6 +62,7 @@
     "//cc",
     "//cc/surfaces",
     "//components/viz/common",
+    "//components/viz/host",
     "//components/viz/service",
     "//skia",
     "//ui/base",
diff --git a/ui/android/DEPS b/ui/android/DEPS
index 7f7f43f..410819d26 100644
--- a/ui/android/DEPS
+++ b/ui/android/DEPS
@@ -8,6 +8,7 @@
   "+cc/test/test_task_graph_runner.h",
   "+cc/trees/layer_tree_host.h",
   "+components/viz/common",
+  "+components/viz/host",
   "+components/viz/service/frame_sinks",
   "+jni",
   "+skia/ext",
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc
index 95b4fb5..0bf08b5 100644
--- a/ui/android/delegated_frame_host_android.cc
+++ b/ui/android/delegated_frame_host_android.cc
@@ -13,6 +13,7 @@
 #include "cc/output/copy_output_result.h"
 #include "cc/surfaces/surface.h"
 #include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager.h"
 #include "ui/android/view_android.h"
 #include "ui/android/window_android_compositor.h"
@@ -51,11 +52,13 @@
 
 DelegatedFrameHostAndroid::DelegatedFrameHostAndroid(
     ui::ViewAndroid* view,
+    viz::HostFrameSinkManager* host_frame_sink_manager,
     viz::FrameSinkManager* frame_sink_manager,
     Client* client,
     const viz::FrameSinkId& frame_sink_id)
     : frame_sink_id_(frame_sink_id),
       view_(view),
+      host_frame_sink_manager_(host_frame_sink_manager),
       frame_sink_manager_(frame_sink_manager),
       client_(client),
       begin_frame_source_(this) {
@@ -199,9 +202,9 @@
   constexpr bool handles_frame_sink_id_invalidation = false;
   constexpr bool needs_sync_points = true;
   support_.reset();
-  support_ = viz::CompositorFrameSinkSupport::Create(
-      this, frame_sink_manager_, frame_sink_id_, is_root,
-      handles_frame_sink_id_invalidation, needs_sync_points);
+  support_ = host_frame_sink_manager_->CreateCompositorFrameSinkSupport(
+      this, frame_sink_id_, is_root, handles_frame_sink_id_invalidation,
+      needs_sync_points);
 }
 
 viz::SurfaceId DelegatedFrameHostAndroid::SurfaceId() const {
diff --git a/ui/android/delegated_frame_host_android.h b/ui/android/delegated_frame_host_android.h
index 25fbcdc..56656fc 100644
--- a/ui/android/delegated_frame_host_android.h
+++ b/ui/android/delegated_frame_host_android.h
@@ -17,12 +17,16 @@
 namespace cc {
 
 class CompositorFrame;
-class FrameSinkManager;
 class SurfaceLayer;
 enum class SurfaceDrawStatus;
 
 }  // namespace cc
 
+namespace viz {
+class FrameSinkManager;
+class HostFrameSinkManager;
+}  // namespace viz
+
 namespace ui {
 class ViewAndroid;
 class WindowAndroidCompositor;
@@ -40,6 +44,7 @@
   };
 
   DelegatedFrameHostAndroid(ViewAndroid* view,
+                            viz::HostFrameSinkManager* host_frame_sink_manager,
                             viz::FrameSinkManager* frame_sink_manager,
                             Client* client,
                             const viz::FrameSinkId& frame_sink_id);
@@ -91,6 +96,7 @@
 
   ViewAndroid* view_;
 
+  viz::HostFrameSinkManager* const host_frame_sink_manager_;
   viz::FrameSinkManager* const frame_sink_manager_;
   WindowAndroidCompositor* registered_parent_compositor_ = nullptr;
   Client* client_;
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 4f937e6d..2d22535 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -143,6 +143,7 @@
     "//components/discardable_memory/client",
     "//components/discardable_memory/public/interfaces",
     "//components/viz/client",
+    "//components/viz/host",
     "//components/viz/service",
     "//gpu/ipc/client",
     "//mojo/public/cpp/system",
diff --git a/ui/aura/DEPS b/ui/aura/DEPS
index 865926c..cad39bb 100644
--- a/ui/aura/DEPS
+++ b/ui/aura/DEPS
@@ -3,6 +3,7 @@
   "+cc/output",
   "+cc/surfaces",
   "+components/viz/common",
+  "+components/viz/host",
   "+mojo/common",
   "+mojo/public/cpp/bindings",
   "+net/base/filename_util.h",
diff --git a/ui/aura/local/layer_tree_frame_sink_local.cc b/ui/aura/local/layer_tree_frame_sink_local.cc
index a9adb3d..0a2a064e 100644
--- a/ui/aura/local/layer_tree_frame_sink_local.cc
+++ b/ui/aura/local/layer_tree_frame_sink_local.cc
@@ -5,6 +5,7 @@
 #include "ui/aura/local/layer_tree_frame_sink_local.h"
 
 #include "cc/output/layer_tree_frame_sink_client.h"
+#include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/env.h"
@@ -17,10 +18,10 @@
 
 LayerTreeFrameSinkLocal::LayerTreeFrameSinkLocal(
     const viz::FrameSinkId& frame_sink_id,
-    viz::FrameSinkManager* frame_sink_manager)
+    viz::HostFrameSinkManager* host_frame_sink_manager)
     : cc::LayerTreeFrameSink(nullptr, nullptr, nullptr, nullptr),
       frame_sink_id_(frame_sink_id),
-      frame_sink_manager_(frame_sink_manager) {}
+      host_frame_sink_manager_(host_frame_sink_manager) {}
 
 LayerTreeFrameSinkLocal::~LayerTreeFrameSinkLocal() {}
 
@@ -31,8 +32,8 @@
   DCHECK(!thread_checker_);
   thread_checker_ = base::MakeUnique<base::ThreadChecker>();
 
-  support_ = viz::CompositorFrameSinkSupport::Create(
-      this, frame_sink_manager_, frame_sink_id_, false /* is_root */,
+  support_ = host_frame_sink_manager_->CreateCompositorFrameSinkSupport(
+      this, frame_sink_id_, false /* is_root */,
       true /* handles_frame_sink_id_invalidation */,
       true /* needs_sync_points */);
   begin_frame_source_ = base::MakeUnique<cc::ExternalBeginFrameSource>(this);
diff --git a/ui/aura/local/layer_tree_frame_sink_local.h b/ui/aura/local/layer_tree_frame_sink_local.h
index 7a37fbe..c7b22d2c 100644
--- a/ui/aura/local/layer_tree_frame_sink_local.h
+++ b/ui/aura/local/layer_tree_frame_sink_local.h
@@ -16,8 +16,8 @@
 #include "ui/base/property_data.h"
 
 namespace viz {
-class FrameSinkManager;
 class CompositorFrameSinkSupport;
+class HostFrameSinkManager;
 }
 
 namespace aura {
@@ -31,7 +31,7 @@
                                 public cc::ExternalBeginFrameSourceClient {
  public:
   LayerTreeFrameSinkLocal(const viz::FrameSinkId& frame_sink_id,
-                          viz::FrameSinkManager* frame_sink_manager);
+                          viz::HostFrameSinkManager* host_frame_sink_manager);
   ~LayerTreeFrameSinkLocal() override;
 
   using SurfaceChangedCallback =
@@ -59,7 +59,7 @@
 
  private:
   const viz::FrameSinkId frame_sink_id_;
-  viz::FrameSinkManager* const frame_sink_manager_;
+  viz::HostFrameSinkManager* const host_frame_sink_manager_;
   std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
   gfx::Size surface_size_;
   float device_scale_factor_ = 0;
diff --git a/ui/aura/local/window_port_local.cc b/ui/aura/local/window_port_local.cc
index aeb7ebf..9c8e70a 100644
--- a/ui/aura/local/window_port_local.cc
+++ b/ui/aura/local/window_port_local.cc
@@ -103,7 +103,7 @@
       aura::Env::GetInstance()->context_factory_private();
   frame_sink_id_ = context_factory_private->AllocateFrameSinkId();
   auto frame_sink = base::MakeUnique<LayerTreeFrameSinkLocal>(
-      frame_sink_id_, context_factory_private->GetFrameSinkManager());
+      frame_sink_id_, context_factory_private->GetHostFrameSinkManager());
   frame_sink->SetSurfaceChangedCallback(base::Bind(
       &WindowPortLocal::OnSurfaceChanged, weak_factory_.GetWeakPtr()));
   if (window_->GetRootWindow())
diff --git a/ui/compositor/test/context_factories_for_test.cc b/ui/compositor/test/context_factories_for_test.cc
index 75d15bd9..2ef06c0c 100644
--- a/ui/compositor/test/context_factories_for_test.cc
+++ b/ui/compositor/test/context_factories_for_test.cc
@@ -6,9 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/sys_info.h"
-#include "base/threading/sequenced_task_runner_handle.h"
 #include "components/viz/host/host_frame_sink_manager.h"
-#include "components/viz/service/frame_sinks/frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_switches.h"
@@ -24,21 +22,9 @@
 
 // Connect HostFrameSinkManager to FrameSinkManagerImpl.
 void ConnectFrameSinkManager() {
-  // Interfaces and requests to bind to each of the interfaces.
-  cc::mojom::FrameSinkManagerClientPtr host_mojo;
-  cc::mojom::FrameSinkManagerPtr manager_mojo;
-  cc::mojom::FrameSinkManagerClientRequest host_mojo_request =
-      mojo::MakeRequest(&host_mojo);
-  cc::mojom::FrameSinkManagerRequest manager_mojo_request =
-      mojo::MakeRequest(&manager_mojo);
-
-  // Make the Mojo connections on both ends.
-  g_frame_sink_manager_impl->BindAndSetClient(
-      std::move(manager_mojo_request), base::SequencedTaskRunnerHandle::Get(),
-      std::move(host_mojo));
-  g_host_frame_sink_manager->BindAndSetManager(
-      std::move(host_mojo_request), base::SequencedTaskRunnerHandle::Get(),
-      std::move(manager_mojo));
+  // Directly connect without using Mojo.
+  g_frame_sink_manager_impl->SetLocalClient(g_host_frame_sink_manager);
+  g_host_frame_sink_manager->SetLocalManager(g_frame_sink_manager_impl);
 }
 
 }  // namespace
diff --git a/ui/compositor/test/fake_context_factory.h b/ui/compositor/test/fake_context_factory.h
index 5761aa2..a69a1fc 100644
--- a/ui/compositor/test/fake_context_factory.h
+++ b/ui/compositor/test/fake_context_factory.h
@@ -40,6 +40,11 @@
   void AddObserver(ui::ContextFactoryObserver* observer) override {}
   void RemoveObserver(ui::ContextFactoryObserver* observer) override {}
 
+ protected:
+  const cc::RendererSettings& renderer_settings() const {
+    return renderer_settings_;
+  }
+
  private:
   cc::FakeLayerTreeFrameSink* frame_sink_ = nullptr;
   cc::TestTaskGraphRunner task_graph_runner_;
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index b34ef4f..b36a7ac 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -253,9 +253,10 @@
 
   auto* display = per_compositor_data_[compositor.get()]->display.get();
   auto layer_tree_frame_sink = base::MakeUnique<viz::DirectLayerTreeFrameSink>(
-      compositor->frame_sink_id(), GetFrameSinkManager(), display,
-      context_provider, shared_worker_context_provider_,
-      &gpu_memory_buffer_manager_, &shared_bitmap_manager_);
+      compositor->frame_sink_id(), GetHostFrameSinkManager(),
+      GetFrameSinkManager(), display, context_provider,
+      shared_worker_context_provider_, &gpu_memory_buffer_manager_,
+      &shared_bitmap_manager_);
   compositor->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink));
 
   data->display->Resize(compositor->size());