diff --git a/DEPS b/DEPS
index 4b5df87..6114fd8 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': 'd952a9929b2dc826955249c755b6fed5627491c2',
+  'skia_revision': '4e3e9f858cf111d08be08a7274028d8a6e6a8b5d',
   # 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': '75b2794f5035b8164d29a552680b3cd129a9ebd6',
+  'v8_revision': 'a46abc28ce45b6bdebbe3277b7c7a42616d07811',
   # 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.
@@ -196,7 +196,7 @@
     Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
 
   'src/third_party/webgl/src':
-    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '73fd432435e8a8563f2117737c7639331761bddd',
+    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '40d75ac0e565191d93ff3c4e8fd19f8b2df7f617',
 
   'src/third_party/webdriver/pylib':
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 749d7244..8fe2e7c 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -270,7 +270,7 @@
 void AwContentBrowserClient::AppendExtraCommandLineSwitches(
     base::CommandLine* command_line,
     int child_process_id) {
-  if (command_line->HasSwitch(switches::kWebViewSandboxedRenderer)) {
+  if (!command_line->HasSwitch(switches::kSingleProcess)) {
     // The only kind of a child process WebView can have is renderer.
     DCHECK_EQ(switches::kRendererProcess,
               command_line->GetSwitchValueASCII(switches::kProcessType));
diff --git a/android_webview/browser/surfaces_instance.cc b/android_webview/browser/surfaces_instance.cc
index 109321f7..c09e9a6 100644
--- a/android_webview/browser/surfaces_instance.cc
+++ b/android_webview/browser/surfaces_instance.cc
@@ -121,7 +121,7 @@
   cc::SharedQuadState* quad_state =
       render_pass->CreateAndAppendSharedQuadState();
   quad_state->quad_to_target_transform = transform;
-  quad_state->quad_layer_bounds = frame_size;
+  quad_state->quad_layer_rect = gfx::Rect(frame_size);
   quad_state->visible_quad_layer_rect = gfx::Rect(frame_size);
   quad_state->clip_rect = clip;
   quad_state->is_clipped = true;
@@ -129,8 +129,8 @@
 
   cc::SurfaceDrawQuad* surface_quad =
       render_pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
-  surface_quad->SetNew(quad_state, gfx::Rect(quad_state->quad_layer_bounds),
-                       gfx::Rect(quad_state->quad_layer_bounds), child_id,
+  surface_quad->SetNew(quad_state, gfx::Rect(quad_state->quad_layer_rect),
+                       gfx::Rect(quad_state->quad_layer_rect), child_id,
                        cc::SurfaceDrawQuadType::PRIMARY, nullptr);
 
   cc::CompositorFrame frame;
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index 2b263812..79dd6e0f 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -15,45 +15,57 @@
   ]
 }
 
-android_apk("android_webview_apk") {
-  deps = [
-    ":android_webview_apk_assets",
-    ":android_webview_apk_resources",
-    "//android_webview:android_webview_java",
-    "//android_webview:locale_pak_assets",
-    "//base:base_java",
-    "//base:base_java_test_support",
-    "//components/policy/android:policy_java_test_support",
-    "//content/public/android:content_java",
-    "//ui/android:ui_java",
-  ]
+# TODO(ctzsm): Remove template after WebViewInstrumentation is validated. (crbug/701938)
+template("webview_instrumentation_apk_tmpl") {
+  android_apk(target_name) {
+    forward_variables_from(invoker, "*")
 
+    deps = [
+      ":android_webview_apk_assets",
+      ":android_webview_apk_resources",
+      "//android_webview:android_webview_java",
+      "//android_webview:locale_pak_assets",
+      "//base:base_java",
+      "//base:base_java_test_support",
+      "//components/policy/android:policy_java_test_support",
+      "//content/public/android:content_java",
+      "//ui/android:ui_java",
+    ]
+
+    android_manifest = "shell/AndroidManifest.xml"
+    java_files = [
+      "shell/src/org/chromium/android_webview/shell/AwShellActivity.java",
+      "shell/src/org/chromium/android_webview/shell/AwShellApplication.java",
+      "shell/src/org/chromium/android_webview/shell/AwShellResourceProvider.java",
+      "shell/src/org/chromium/android_webview/shell/AwShellSwitches.java",
+      "shell/src/org/chromium/android_webview/shell/DrawGL.java",
+      "shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java",
+      "shell/src/org/chromium/android_webview/test/AwTestContainerView.java",
+      "shell/src/org/chromium/android_webview/test/AwTestRunnerActivity.java",
+      "shell/src/org/chromium/android_webview/test/NullContentsClient.java",
+      "shell/src/org/chromium/android_webview/test/SecondBrowserProcess.java",
+      "shell/src/org/chromium/android_webview/test/TestContentProvider.java",
+    ]
+    shared_libraries = [
+      ":libdrawgl",
+      ":libstandalonelibwebviewchromium",
+    ]
+
+    native_lib_version_rule = "//build/util:chrome_version_json"
+    _native_lib_file =
+        rebase_path("$root_gen_dir/CHROME_VERSION.json", root_build_dir)
+    native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)"
+
+    enable_multidex = true
+  }
+}
+
+webview_instrumentation_apk_tmpl("webview_instrumentation_apk") {
+  apk_name = "WebViewInstrumentation"
+}
+
+webview_instrumentation_apk_tmpl("android_webview_apk") {
   apk_name = "AndroidWebView"
-  android_manifest = "shell/AndroidManifest.xml"
-  java_files = [
-    "shell/src/org/chromium/android_webview/shell/AwShellActivity.java",
-    "shell/src/org/chromium/android_webview/shell/AwShellApplication.java",
-    "shell/src/org/chromium/android_webview/shell/AwShellResourceProvider.java",
-    "shell/src/org/chromium/android_webview/shell/AwShellSwitches.java",
-    "shell/src/org/chromium/android_webview/shell/DrawGL.java",
-    "shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java",
-    "shell/src/org/chromium/android_webview/test/AwTestContainerView.java",
-    "shell/src/org/chromium/android_webview/test/AwTestRunnerActivity.java",
-    "shell/src/org/chromium/android_webview/test/NullContentsClient.java",
-    "shell/src/org/chromium/android_webview/test/SecondBrowserProcess.java",
-    "shell/src/org/chromium/android_webview/test/TestContentProvider.java",
-  ]
-  shared_libraries = [
-    ":libdrawgl",
-    ":libstandalonelibwebviewchromium",
-  ]
-
-  native_lib_version_rule = "//build/util:chrome_version_json"
-  _native_lib_file =
-      rebase_path("$root_gen_dir/CHROME_VERSION.json", root_build_dir)
-  native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)"
-
-  enable_multidex = true
 }
 
 android_resources("android_webview_apk_resources") {
@@ -98,130 +110,143 @@
   configs += [ "//build/config/android:hide_all_but_jni" ]
 }
 
-instrumentation_test_apk("android_webview_test_apk") {
+# TODO(ctzsm): Remove it after WebViewInstrumentationTest is validated. (crbug/701938)
+template("webview_instrumentation_test_tmpl") {
+  instrumentation_test_apk(target_name) {
+    forward_variables_from(invoker, "*")
+
+    android_manifest = "../javatests/AndroidManifest.xml"
+    deps = [
+      "//android_webview:android_webview_crash_services_java",
+      "//android_webview:android_webview_java",
+      "//android_webview:android_webview_platform_services_java",
+      "//base:base_java",
+      "//base:base_java_test_support",
+      "//components/minidump_uploader:minidump_uploader_java",
+      "//components/minidump_uploader:minidump_uploader_javatests",
+      "//components/policy/android:policy_java",
+      "//components/policy/android:policy_java_test_support",
+      "//components/safe_browsing_db/android:safe_browsing_java",
+      "//components/web_contents_delegate_android:web_contents_delegate_android_java",
+      "//content/public/android:content_java",
+      "//content/public/test/android:content_java_test_support",
+      "//device/geolocation:geolocation_java",
+      "//device/geolocation:geolocation_java_test_support",
+      "//net/android:net_java",
+      "//net/android:net_java_test_support",
+      "//third_party/android_support_test_runner:runner_java",
+      "//ui/android:ui_java",
+    ]
+    java_files = [
+      "../javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java",
+      "../javatests/src/org/chromium/android_webview/test/ArchiveTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsAnchorViewTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientAutoLoginTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientCallbackHelperTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientFaviconTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientGetDefaultVideoPosterTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientGetVideoLoadingProgressViewTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientOnFormResubmissionTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientOnUnhandledKeyEventTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsClientVisitedHistoryTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsLifecycleNotifierTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsStaticsTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwContentsTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwDebugTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwFormDatabaseTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwImeTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwPermissionManagerTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwQuotaManagerBridgeTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwScrollOffsetManagerTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwSecondBrowserProcessTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwServiceWorkerClientTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwSettingsTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwStrictModeTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwTestBase.java",
+      "../javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java",
+      "../javatests/src/org/chromium/android_webview/test/AwZoomTest.java",
+      "../javatests/src/org/chromium/android_webview/test/CleanupReferenceTest.java",
+      "../javatests/src/org/chromium/android_webview/test/ClearHistoryTest.java",
+      "../javatests/src/org/chromium/android_webview/test/ClientAddMessageToConsoleTest.java",
+      "../javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java",
+      "../javatests/src/org/chromium/android_webview/test/ClientOnPageStartedTest.java",
+      "../javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java",
+      "../javatests/src/org/chromium/android_webview/test/ClientOnReceivedErrorTest.java",
+      "../javatests/src/org/chromium/android_webview/test/ClientOnReceivedHttpErrorTest.java",
+      "../javatests/src/org/chromium/android_webview/test/ConsoleMessagesForBlockedLoadsTest.java",
+      "../javatests/src/org/chromium/android_webview/test/ContentViewMiscTest.java",
+      "../javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java",
+      "../javatests/src/org/chromium/android_webview/test/CookieManagerTest.java",
+      "../javatests/src/org/chromium/android_webview/test/DisableHardwareAccelerationForTest.java",
+      "../javatests/src/org/chromium/android_webview/test/FullScreenVideoTestAwContentsClient.java",
+      "../javatests/src/org/chromium/android_webview/test/GeolocationTest.java",
+      "../javatests/src/org/chromium/android_webview/test/GetTitleTest.java",
+      "../javatests/src/org/chromium/android_webview/test/HttpAuthDatabaseTest.java",
+      "../javatests/src/org/chromium/android_webview/test/HttpCacheTest.java",
+      "../javatests/src/org/chromium/android_webview/test/KeySystemTest.java",
+      "../javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java",
+      "../javatests/src/org/chromium/android_webview/test/LoadUrlTest.java",
+      "../javatests/src/org/chromium/android_webview/test/MediaAccessPermissionRequestTest.java",
+      "../javatests/src/org/chromium/android_webview/test/NavigationHistoryTest.java",
+      "../javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java",
+      "../javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java",
+      "../javatests/src/org/chromium/android_webview/test/PopupWindowTest.java",
+      "../javatests/src/org/chromium/android_webview/test/PostMessageTest.java",
+      "../javatests/src/org/chromium/android_webview/test/RenderProcessGoneHelper.java",
+      "../javatests/src/org/chromium/android_webview/test/SaveRestoreStateTest.java",
+      "../javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java",
+      "../javatests/src/org/chromium/android_webview/test/StandaloneAwQuotaManagerBridgeTest.java",
+      "../javatests/src/org/chromium/android_webview/test/TestAwContents.java",
+      "../javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java",
+      "../javatests/src/org/chromium/android_webview/test/TestAwServiceWorkerClient.java",
+      "../javatests/src/org/chromium/android_webview/test/UserAgentTest.java",
+      "../javatests/src/org/chromium/android_webview/test/VisualStateTest.java",
+      "../javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java",
+      "../javatests/src/org/chromium/android_webview/test/WebViewAsynchronousFindApisTest.java",
+      "../javatests/src/org/chromium/android_webview/test/WebViewFindApisTestBase.java",
+      "../javatests/src/org/chromium/android_webview/test/WebViewModalDialogOverrideTest.java",
+      "../javatests/src/org/chromium/android_webview/test/crash/CrashReceiverServiceTest.java",
+      "../javatests/src/org/chromium/android_webview/test/crash/MinidumpUploaderTest.java",
+      "../javatests/src/org/chromium/android_webview/test/crash/VisualStateCallbackTest.java",
+      "../javatests/src/org/chromium/android_webview/test/util/AwQuotaManagerBridgeTestUtil.java",
+      "../javatests/src/org/chromium/android_webview/test/util/AwTestTouchUtils.java",
+      "../javatests/src/org/chromium/android_webview/test/util/CommonResources.java",
+      "../javatests/src/org/chromium/android_webview/test/util/CookieUtils.java",
+      "../javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java",
+      "../javatests/src/org/chromium/android_webview/test/util/ImagePageGenerator.java",
+      "../javatests/src/org/chromium/android_webview/test/util/JSUtils.java",
+      "../javatests/src/org/chromium/android_webview/test/util/JavascriptEventObserver.java",
+      "../javatests/src/org/chromium/android_webview/test/util/VideoSurfaceViewUtils.java",
+      "../javatests/src/org/chromium/android_webview/test/util/VideoTestUtil.java",
+      "../javatests/src/org/chromium/android_webview/test/util/VideoTestWebServer.java",
+    ]
+    data = [
+      "data/",
+    ]
+    additional_apks = [ "//net/android:net_test_support_apk" ]
+  }
+}
+
+webview_instrumentation_test_tmpl("webview_instrumentation_test_apk") {
+  apk_name = "WebViewInstrumentationTest"
+  apk_under_test = ":webview_instrumentation_apk"
+}
+
+webview_instrumentation_test_tmpl("android_webview_test_apk") {
   apk_name = "AndroidWebViewTest"
   apk_under_test = ":android_webview_apk"
-  android_manifest = "../javatests/AndroidManifest.xml"
-  deps = [
-    "//android_webview:android_webview_crash_services_java",
-    "//android_webview:android_webview_java",
-    "//android_webview:android_webview_platform_services_java",
-    "//base:base_java",
-    "//base:base_java_test_support",
-    "//components/minidump_uploader:minidump_uploader_java",
-    "//components/minidump_uploader:minidump_uploader_javatests",
-    "//components/policy/android:policy_java",
-    "//components/policy/android:policy_java_test_support",
-    "//components/safe_browsing_db/android:safe_browsing_java",
-    "//components/web_contents_delegate_android:web_contents_delegate_android_java",
-    "//content/public/android:content_java",
-    "//content/public/test/android:content_java_test_support",
-    "//device/geolocation:geolocation_java",
-    "//device/geolocation:geolocation_java_test_support",
-    "//net/android:net_java",
-    "//net/android:net_java_test_support",
-    "//third_party/android_support_test_runner:runner_java",
-    "//ui/android:ui_java",
-  ]
-  java_files = [
-    "../javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java",
-    "../javatests/src/org/chromium/android_webview/test/ArchiveTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsAnchorViewTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientAutoLoginTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientCallbackHelperTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientFaviconTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientGetDefaultVideoPosterTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientGetVideoLoadingProgressViewTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientOnFormResubmissionTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientOnScaleChangedTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientOnUnhandledKeyEventTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsClientVisitedHistoryTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsLifecycleNotifierTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsStaticsTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwContentsTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwDebugTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwFormDatabaseTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwImeTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwPermissionManagerTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwQuotaManagerBridgeTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwScrollOffsetManagerTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwSecondBrowserProcessTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwServiceWorkerClientTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwSettingsTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwStrictModeTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwTestBase.java",
-    "../javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java",
-    "../javatests/src/org/chromium/android_webview/test/AwZoomTest.java",
-    "../javatests/src/org/chromium/android_webview/test/CleanupReferenceTest.java",
-    "../javatests/src/org/chromium/android_webview/test/ClearHistoryTest.java",
-    "../javatests/src/org/chromium/android_webview/test/ClientAddMessageToConsoleTest.java",
-    "../javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java",
-    "../javatests/src/org/chromium/android_webview/test/ClientOnPageStartedTest.java",
-    "../javatests/src/org/chromium/android_webview/test/ClientOnReceivedError2Test.java",
-    "../javatests/src/org/chromium/android_webview/test/ClientOnReceivedErrorTest.java",
-    "../javatests/src/org/chromium/android_webview/test/ClientOnReceivedHttpErrorTest.java",
-    "../javatests/src/org/chromium/android_webview/test/ConsoleMessagesForBlockedLoadsTest.java",
-    "../javatests/src/org/chromium/android_webview/test/ContentViewMiscTest.java",
-    "../javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java",
-    "../javatests/src/org/chromium/android_webview/test/CookieManagerTest.java",
-    "../javatests/src/org/chromium/android_webview/test/DisableHardwareAccelerationForTest.java",
-    "../javatests/src/org/chromium/android_webview/test/FullScreenVideoTestAwContentsClient.java",
-    "../javatests/src/org/chromium/android_webview/test/GeolocationTest.java",
-    "../javatests/src/org/chromium/android_webview/test/GetTitleTest.java",
-    "../javatests/src/org/chromium/android_webview/test/HttpAuthDatabaseTest.java",
-    "../javatests/src/org/chromium/android_webview/test/HttpCacheTest.java",
-    "../javatests/src/org/chromium/android_webview/test/KeySystemTest.java",
-    "../javatests/src/org/chromium/android_webview/test/LoadDataWithBaseUrlTest.java",
-    "../javatests/src/org/chromium/android_webview/test/LoadUrlTest.java",
-    "../javatests/src/org/chromium/android_webview/test/MediaAccessPermissionRequestTest.java",
-    "../javatests/src/org/chromium/android_webview/test/NavigationHistoryTest.java",
-    "../javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java",
-    "../javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java",
-    "../javatests/src/org/chromium/android_webview/test/PopupWindowTest.java",
-    "../javatests/src/org/chromium/android_webview/test/PostMessageTest.java",
-    "../javatests/src/org/chromium/android_webview/test/RenderProcessGoneHelper.java",
-    "../javatests/src/org/chromium/android_webview/test/SaveRestoreStateTest.java",
-    "../javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java",
-    "../javatests/src/org/chromium/android_webview/test/StandaloneAwQuotaManagerBridgeTest.java",
-    "../javatests/src/org/chromium/android_webview/test/TestAwContents.java",
-    "../javatests/src/org/chromium/android_webview/test/TestAwContentsClient.java",
-    "../javatests/src/org/chromium/android_webview/test/TestAwServiceWorkerClient.java",
-    "../javatests/src/org/chromium/android_webview/test/UserAgentTest.java",
-    "../javatests/src/org/chromium/android_webview/test/VisualStateTest.java",
-    "../javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java",
-    "../javatests/src/org/chromium/android_webview/test/WebViewAsynchronousFindApisTest.java",
-    "../javatests/src/org/chromium/android_webview/test/WebViewFindApisTestBase.java",
-    "../javatests/src/org/chromium/android_webview/test/WebViewModalDialogOverrideTest.java",
-    "../javatests/src/org/chromium/android_webview/test/crash/CrashReceiverServiceTest.java",
-    "../javatests/src/org/chromium/android_webview/test/crash/MinidumpUploaderTest.java",
-    "../javatests/src/org/chromium/android_webview/test/crash/VisualStateCallbackTest.java",
-    "../javatests/src/org/chromium/android_webview/test/util/AwQuotaManagerBridgeTestUtil.java",
-    "../javatests/src/org/chromium/android_webview/test/util/AwTestTouchUtils.java",
-    "../javatests/src/org/chromium/android_webview/test/util/CommonResources.java",
-    "../javatests/src/org/chromium/android_webview/test/util/CookieUtils.java",
-    "../javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java",
-    "../javatests/src/org/chromium/android_webview/test/util/ImagePageGenerator.java",
-    "../javatests/src/org/chromium/android_webview/test/util/JSUtils.java",
-    "../javatests/src/org/chromium/android_webview/test/util/JavascriptEventObserver.java",
-    "../javatests/src/org/chromium/android_webview/test/util/VideoSurfaceViewUtils.java",
-    "../javatests/src/org/chromium/android_webview/test/util/VideoTestUtil.java",
-    "../javatests/src/org/chromium/android_webview/test/util/VideoTestWebServer.java",
-  ]
-  data = [
-    "data/",
-  ]
-  additional_apks = [ "//net/android:net_test_support_apk" ]
 }
 
 test("android_webview_unittests") {
diff --git a/ash/laser/laser_pointer_view.cc b/ash/laser/laser_pointer_view.cc
index 5f5b757a..882fbe85 100644
--- a/ash/laser/laser_pointer_view.cc
+++ b/ash/laser/laser_pointer_view.cc
@@ -721,7 +721,7 @@
 
   cc::SharedQuadState* quad_state =
       render_pass->CreateAndAppendSharedQuadState();
-  quad_state->quad_layer_bounds = quad_rect.size();
+  quad_state->quad_layer_rect = quad_rect;
   quad_state->visible_quad_layer_rect = quad_rect;
   quad_state->opacity = 1.0f;
 
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc
index 9c0ecc4..15f2cc03c 100644
--- a/ash/wallpaper/wallpaper_controller.cc
+++ b/ash/wallpaper/wallpaper_controller.cc
@@ -168,20 +168,6 @@
   InstallDesktopControllerForAllWindows();
 }
 
-bool WallpaperController::MoveToLockedContainer() {
-  if (locked_)
-    return false;
-  locked_ = true;
-  return ReparentWallpaper(GetWallpaperContainerId(true));
-}
-
-bool WallpaperController::MoveToUnlockedContainer() {
-  if (!locked_)
-    return false;
-  locked_ = false;
-  return ReparentWallpaper(GetWallpaperContainerId(false));
-}
-
 void WallpaperController::OnDisplayConfigurationChanged() {
   gfx::Size max_display_size = GetMaxDisplaySizeInNative();
   if (current_max_display_size_ != max_display_size) {
@@ -215,6 +201,11 @@
 void WallpaperController::OnSessionStateChanged(
     session_manager::SessionState state) {
   CalculateWallpaperColors();
+
+  if (state == session_manager::SessionState::ACTIVE)
+    MoveToUnlockedContainer();
+  else
+    MoveToLockedContainer();
 }
 
 // static
@@ -401,4 +392,20 @@
          !image.isNull();
 }
 
+bool WallpaperController::MoveToLockedContainer() {
+  if (locked_)
+    return false;
+
+  locked_ = true;
+  return ReparentWallpaper(GetWallpaperContainerId(true));
+}
+
+bool WallpaperController::MoveToUnlockedContainer() {
+  if (!locked_)
+    return false;
+
+  locked_ = false;
+  return ReparentWallpaper(GetWallpaperContainerId(false));
+}
+
 }  // namespace ash
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h
index 345f469..e72991f2 100644
--- a/ash/wallpaper/wallpaper_controller.h
+++ b/ash/wallpaper/wallpaper_controller.h
@@ -12,7 +12,6 @@
 #include "ash/session/session_observer.h"
 #include "ash/shell_observer.h"
 #include "ash/wm_display_observer.h"
-#include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
 #include "base/timer/timer.h"
@@ -36,7 +35,13 @@
 
 class WallpaperControllerObserver;
 
-// Controls the desktop background wallpaper.
+// Controls the desktop background wallpaper:
+//   - Sets a wallpaper image and layout;
+//   - Handles display change (add/remove display, configuration change etc);
+//   - Calculates prominent color for shelf;
+//   - Move wallpaper to locked container(s) when session state is not ACTIVE to
+//     hide the user desktop and move it to unlocked container when session
+//     state is ACTIVE;
 class ASH_EXPORT WallpaperController
     : public NON_EXPORTED_BASE(mojom::WallpaperController),
       public WmDisplayObserver,
@@ -83,14 +88,6 @@
   // crashes. An example test is SystemGestureEventFilterTest.ThreeFingerSwipe.
   void CreateEmptyWallpaper();
 
-  // Move all wallpaper widgets to the locked container.
-  // Returns true if the wallpaper moved.
-  bool MoveToLockedContainer();
-
-  // Move all wallpaper widgets to unlocked container.
-  // Returns true if the wallpaper moved.
-  bool MoveToUnlockedContainer();
-
   // WmDisplayObserver:
   void OnDisplayConfigurationChanged() override;
 
@@ -132,6 +129,9 @@
   void OnColorCalculationComplete() override;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest, BasicReparenting);
+  FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest,
+                           WallpaperMovementDuringUnlock);
   friend class WallpaperControllerTest;
 
   // Creates a WallpaperWidgetController for |root_window|.
@@ -165,6 +165,14 @@
   // system state (e.g. wallpaper image, SessionState, etc.).
   bool ShouldCalculateColors() const;
 
+  // Move all wallpaper widgets to the locked container.
+  // Returns true if the wallpaper moved.
+  bool MoveToLockedContainer();
+
+  // Move all wallpaper widgets to unlocked container.
+  // Returns true if the wallpaper moved.
+  bool MoveToUnlockedContainer();
+
   bool locked_;
 
   WallpaperMode wallpaper_mode_;
diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc
index d381d87..3c5198a 100644
--- a/base/metrics/persistent_memory_allocator.cc
+++ b/base/metrics/persistent_memory_allocator.cc
@@ -1063,4 +1063,110 @@
 }
 #endif  // !defined(OS_NACL)
 
+//----- DelayedPersistentAllocation --------------------------------------------
+
+// Forwarding constructors.
+DelayedPersistentAllocation::DelayedPersistentAllocation(
+    PersistentMemoryAllocator* allocator,
+    subtle::Atomic32* ref,
+    uint32_t type,
+    size_t size,
+    bool make_iterable)
+    : DelayedPersistentAllocation(
+          allocator,
+          reinterpret_cast<std::atomic<Reference>*>(ref),
+          type,
+          size,
+          0,
+          make_iterable) {}
+
+DelayedPersistentAllocation::DelayedPersistentAllocation(
+    PersistentMemoryAllocator* allocator,
+    subtle::Atomic32* ref,
+    uint32_t type,
+    size_t size,
+    size_t offset,
+    bool make_iterable)
+    : DelayedPersistentAllocation(
+          allocator,
+          reinterpret_cast<std::atomic<Reference>*>(ref),
+          type,
+          size,
+          offset,
+          make_iterable) {}
+
+DelayedPersistentAllocation::DelayedPersistentAllocation(
+    PersistentMemoryAllocator* allocator,
+    std::atomic<Reference>* ref,
+    uint32_t type,
+    size_t size,
+    bool make_iterable)
+    : DelayedPersistentAllocation(allocator,
+                                  ref,
+                                  type,
+                                  size,
+                                  0,
+                                  make_iterable) {}
+
+// Real constructor.
+DelayedPersistentAllocation::DelayedPersistentAllocation(
+    PersistentMemoryAllocator* allocator,
+    std::atomic<Reference>* ref,
+    uint32_t type,
+    size_t size,
+    size_t offset,
+    bool make_iterable)
+    : allocator_(allocator),
+      type_(type),
+      size_(size),
+      offset_(offset),
+      make_iterable_(make_iterable),
+      reference_(ref) {
+  DCHECK(allocator_);
+  DCHECK_NE(0U, type_);
+  DCHECK_LT(0U, size_);
+  DCHECK(reference_);
+}
+
+DelayedPersistentAllocation::~DelayedPersistentAllocation() {}
+
+void* DelayedPersistentAllocation::Get() const {
+  // Relaxed operations are acceptable here because it's not protecting the
+  // contents of the allocation in any way.
+  Reference ref = reference_->load(std::memory_order_relaxed);
+  if (!ref) {
+    ref = allocator_->Allocate(size_, type_);
+    if (!ref)
+      return nullptr;
+
+    // Store the new reference in its proper location using compare-and-swap.
+    // Use a "strong" exchange to ensure no false-negatives since the operation
+    // cannot be retried.
+    Reference existing = 0;  // Must be mutable; receives actual value.
+    if (reference_->compare_exchange_strong(existing, ref,
+                                            std::memory_order_relaxed,
+                                            std::memory_order_relaxed)) {
+      if (make_iterable_)
+        allocator_->MakeIterable(ref);
+    } else {
+      // Failure indicates that something else has raced ahead, performed the
+      // allocation, and stored its reference. Purge the allocation that was
+      // just done and use the other one instead.
+      DCHECK_EQ(type_, allocator_->GetType(existing));
+      DCHECK_LE(size_, allocator_->GetAllocSize(existing));
+      allocator_->ChangeType(ref, 0, type_, /*clear=*/false);
+      ref = existing;
+    }
+  }
+
+  char* mem = allocator_->GetAsArray<char>(ref, type_, size_);
+  if (!mem) {
+    // This should never happen but be tolerant if it does as corruption from
+    // the outside is something to guard against.
+    NOTREACHED();
+    return nullptr;
+  }
+  return mem + offset_;
+}
+
 }  // namespace base
diff --git a/base/metrics/persistent_memory_allocator.h b/base/metrics/persistent_memory_allocator.h
index 94a7744b..b931b2f 100644
--- a/base/metrics/persistent_memory_allocator.h
+++ b/base/metrics/persistent_memory_allocator.h
@@ -767,6 +767,102 @@
 };
 #endif  // !defined(OS_NACL)
 
+// An allocation that is defined but not executed until required at a later
+// time. This allows for potential users of an allocation to be decoupled
+// from the logic that defines it. In addition, there can be multiple users
+// of the same allocation or any region thereof that are guaranteed to always
+// use the same space. It's okay to copy/move these objects.
+//
+// This is a top-level class instead of an inner class of the PMA so that it
+// can be forward-declared in other header files without the need to include
+// the full contents of this file.
+class BASE_EXPORT DelayedPersistentAllocation {
+ public:
+  using Reference = PersistentMemoryAllocator::Reference;
+
+  // Creates a delayed allocation using the specified |allocator|. When
+  // needed, the memory will be allocated using the specified |type| and
+  // |size|. If |offset| is given, the returned pointer will be at that
+  // offset into the segment; this allows combining allocations into a
+  // single persistent segment to reduce overhead and means an "all or
+  // nothing" request. Note that |size| is always the total memory size
+  // and |offset| is just indicating the start of a block within it.  If
+  // |make_iterable| was true, the allocation will made iterable when it
+  // is created; already existing allocations are not changed.
+  //
+  // Once allocated, a reference to the segment will be stored at |ref|.
+  // This shared location must be initialized to zero (0); it is checked
+  // with every Get() request to see if the allocation has already been
+  // done.
+  //
+  // For convenience, methods taking both Atomic32 and std::atomic<Reference>
+  // are defined.
+  DelayedPersistentAllocation(PersistentMemoryAllocator* allocator,
+                              subtle::Atomic32* ref,
+                              uint32_t type,
+                              size_t size,
+                              bool make_iterable);
+  DelayedPersistentAllocation(PersistentMemoryAllocator* allocator,
+                              subtle::Atomic32* ref,
+                              uint32_t type,
+                              size_t size,
+                              size_t offset,
+                              bool make_iterable);
+  DelayedPersistentAllocation(PersistentMemoryAllocator* allocator,
+                              std::atomic<Reference>* ref,
+                              uint32_t type,
+                              size_t size,
+                              bool make_iterable);
+  DelayedPersistentAllocation(PersistentMemoryAllocator* allocator,
+                              std::atomic<Reference>* ref,
+                              uint32_t type,
+                              size_t size,
+                              size_t offset,
+                              bool make_iterable);
+  ~DelayedPersistentAllocation();
+
+  // Gets a pointer to the defined allocation. This will realize the request
+  // and update the reference provided during construction. The memory will
+  // be zeroed the first time it is returned, after that it is shared with
+  // all other Get() requests and so shows any changes made to it elsewhere.
+  //
+  // If the allocation fails for any reason, null will be returned. This works
+  // even on "const" objects because the allocation is already defined, just
+  // delayed.
+  void* Get() const;
+
+  // Gets the internal reference value. If this returns a non-zero value then
+  // a subsequent call to Get() will do nothing but convert that reference into
+  // a memory location -- useful for accessing an existing allocation without
+  // creating one unnecessarily.
+  Reference reference() const {
+    return reference_->load(std::memory_order_relaxed);
+  }
+
+ private:
+  // The underlying object that does the actual allocation of memory. Its
+  // lifetime must exceed that of all DelayedPersistentAllocation objects
+  // that use it.
+  PersistentMemoryAllocator* const allocator_;
+
+  // The desired type and size of the allocated segment plus the offset
+  // within it for the defined request.
+  const uint32_t type_;
+  const size_t size_;
+  const size_t offset_;
+
+  // Flag indicating if allocation should be made iterable when done.
+  const bool make_iterable_;
+
+  // The location at which a reference to the allocated segment is to be
+  // stored once the allocation is complete. If multiple delayed allocations
+  // share the same pointer then an allocation on one will amount to an
+  // allocation for all.
+  volatile std::atomic<Reference>* const reference_;
+
+  // No DISALLOW_COPY_AND_ASSIGN as it's okay to copy/move these objects.
+};
+
 }  // namespace base
 
 #endif  // BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_
diff --git a/base/metrics/persistent_memory_allocator_unittest.cc b/base/metrics/persistent_memory_allocator_unittest.cc
index c3027ec..f67da0c 100644
--- a/base/metrics/persistent_memory_allocator_unittest.cc
+++ b/base/metrics/persistent_memory_allocator_unittest.cc
@@ -472,6 +472,47 @@
 #endif
 }
 
+TEST_F(PersistentMemoryAllocatorTest, DelayedAllocationTest) {
+  std::atomic<Reference> ref1, ref2;
+  ref1.store(0, std::memory_order_relaxed);
+  ref2.store(0, std::memory_order_relaxed);
+  DelayedPersistentAllocation da1(allocator_.get(), &ref1, 1001, 100, true);
+  DelayedPersistentAllocation da2a(allocator_.get(), &ref2, 2002, 200, 0, true);
+  DelayedPersistentAllocation da2b(allocator_.get(), &ref2, 2002, 200, 5, true);
+
+  // Nothing should yet have been allocated.
+  uint32_t type;
+  PersistentMemoryAllocator::Iterator iter(allocator_.get());
+  EXPECT_EQ(0U, iter.GetNext(&type));
+
+  // Do first delayed allocation and check that a new persistent object exists.
+  EXPECT_EQ(0U, da1.reference());
+  void* mem1 = da1.Get();
+  ASSERT_TRUE(mem1);
+  EXPECT_NE(0U, da1.reference());
+  EXPECT_EQ(allocator_->GetAsReference(mem1, 1001),
+            ref1.load(std::memory_order_relaxed));
+  EXPECT_NE(0U, iter.GetNext(&type));
+  EXPECT_EQ(1001U, type);
+  EXPECT_EQ(0U, iter.GetNext(&type));
+
+  // Do second delayed allocation and check.
+  void* mem2a = da2a.Get();
+  ASSERT_TRUE(mem2a);
+  EXPECT_EQ(allocator_->GetAsReference(mem2a, 2002),
+            ref2.load(std::memory_order_relaxed));
+  EXPECT_NE(0U, iter.GetNext(&type));
+  EXPECT_EQ(2002U, type);
+  EXPECT_EQ(0U, iter.GetNext(&type));
+
+  // Third allocation should just return offset into second allocation.
+  void* mem2b = da2b.Get();
+  ASSERT_TRUE(mem2b);
+  EXPECT_EQ(0U, iter.GetNext(&type));
+  EXPECT_EQ(reinterpret_cast<uintptr_t>(mem2a) + 5,
+            reinterpret_cast<uintptr_t>(mem2b));
+}
+
 // This test doesn't verify anything other than it doesn't crash. Its goal
 // is to find coding errors that aren't otherwise tested for, much like a
 // "fuzzer" would.
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py
index a1b0504b..776cded 100755
--- a/build/android/gradle/generate_gradle.py
+++ b/build/android/gradle/generate_gradle.py
@@ -44,8 +44,8 @@
     # because it has resources as deps of android_apk() rather than using an
     #  android_library() intermediate target.
     # '//android_webview:system_webview_apk',
-    '//android_webview/test:android_webview_apk',
-    '//android_webview/test:android_webview_test_apk',
+    '//android_webview/test:webview_instrumentation_apk',
+    '//android_webview/test:webview_instrumentation_test_apk',
     '//base:base_junit_tests',
     '//chrome/android:chrome_junit_tests',
     '//chrome/android:chrome_public_apk',
diff --git a/cc/ipc/cc_param_traits_macros.h b/cc/ipc/cc_param_traits_macros.h
index 39a4ecf..24fd9e22 100644
--- a/cc/ipc/cc_param_traits_macros.h
+++ b/cc/ipc/cc_param_traits_macros.h
@@ -126,7 +126,7 @@
 
 IPC_STRUCT_TRAITS_BEGIN(cc::SharedQuadState)
   IPC_STRUCT_TRAITS_MEMBER(quad_to_target_transform)
-  IPC_STRUCT_TRAITS_MEMBER(quad_layer_bounds)
+  IPC_STRUCT_TRAITS_MEMBER(quad_layer_rect)
   IPC_STRUCT_TRAITS_MEMBER(visible_quad_layer_rect)
   IPC_STRUCT_TRAITS_MEMBER(clip_rect)
   IPC_STRUCT_TRAITS_MEMBER(is_clipped)
diff --git a/cc/ipc/cc_param_traits_unittest.cc b/cc/ipc/cc_param_traits_unittest.cc
index edd451d..da75f2f1 100644
--- a/cc/ipc/cc_param_traits_unittest.cc
+++ b/cc/ipc/cc_param_traits_unittest.cc
@@ -81,7 +81,7 @@
 
   void Compare(const SharedQuadState* a, const SharedQuadState* b) {
     EXPECT_EQ(a->quad_to_target_transform, b->quad_to_target_transform);
-    EXPECT_EQ(a->quad_layer_bounds, b->quad_layer_bounds);
+    EXPECT_EQ(a->quad_layer_rect, b->quad_layer_rect);
     EXPECT_EQ(a->visible_quad_layer_rect, b->visible_quad_layer_rect);
     EXPECT_EQ(a->clip_rect, b->clip_rect);
     EXPECT_EQ(a->is_clipped, b->is_clipped);
@@ -315,7 +315,7 @@
                   arbitrary_bool1);
 
   SharedQuadState* shared_state1_in = pass_in->CreateAndAppendSharedQuadState();
-  shared_state1_in->SetAll(arbitrary_matrix1, arbitrary_size1, arbitrary_rect1,
+  shared_state1_in->SetAll(arbitrary_matrix1, arbitrary_rect1, arbitrary_rect1,
                            arbitrary_rect2, arbitrary_bool1, arbitrary_float1,
                            arbitrary_blend_mode1, arbitrary_context_id1);
 
@@ -338,7 +338,7 @@
                                       debugborder_in->shared_quad_state);
 
   SharedQuadState* shared_state2_in = pass_in->CreateAndAppendSharedQuadState();
-  shared_state2_in->SetAll(arbitrary_matrix2, arbitrary_size2, arbitrary_rect2,
+  shared_state2_in->SetAll(arbitrary_matrix2, arbitrary_rect2, arbitrary_rect2,
                            arbitrary_rect3, arbitrary_bool1, arbitrary_float2,
                            arbitrary_blend_mode2, arbitrary_context_id2);
   SharedQuadState* shared_state2_cmp =
@@ -357,7 +357,7 @@
       renderpass_in->render_pass_id);
 
   SharedQuadState* shared_state3_in = pass_in->CreateAndAppendSharedQuadState();
-  shared_state3_in->SetAll(arbitrary_matrix1, arbitrary_size3, arbitrary_rect3,
+  shared_state3_in->SetAll(arbitrary_matrix1, arbitrary_rect3, arbitrary_rect3,
                            arbitrary_rect1, arbitrary_bool1, arbitrary_float3,
                            arbitrary_blend_mode3, arbitrary_context_id3);
   SharedQuadState* shared_state3_cmp =
@@ -505,7 +505,7 @@
 
   // The first SharedQuadState is used.
   SharedQuadState* shared_state1_in = pass_in->CreateAndAppendSharedQuadState();
-  shared_state1_in->SetAll(gfx::Transform(), gfx::Size(1, 1), gfx::Rect(),
+  shared_state1_in->SetAll(gfx::Transform(), gfx::Rect(1, 1), gfx::Rect(),
                            gfx::Rect(), false, 1.f, SkBlendMode::kSrcOver, 0);
 
   SolidColorDrawQuad* quad1 =
@@ -515,16 +515,16 @@
 
   // The second and third SharedQuadStates are not used.
   SharedQuadState* shared_state2_in = pass_in->CreateAndAppendSharedQuadState();
-  shared_state2_in->SetAll(gfx::Transform(), gfx::Size(2, 2), gfx::Rect(),
+  shared_state2_in->SetAll(gfx::Transform(), gfx::Rect(2, 2), gfx::Rect(),
                            gfx::Rect(), false, 1.f, SkBlendMode::kSrcOver, 0);
 
   SharedQuadState* shared_state3_in = pass_in->CreateAndAppendSharedQuadState();
-  shared_state3_in->SetAll(gfx::Transform(), gfx::Size(3, 3), gfx::Rect(),
+  shared_state3_in->SetAll(gfx::Transform(), gfx::Rect(3, 3), gfx::Rect(),
                            gfx::Rect(), false, 1.f, SkBlendMode::kSrcOver, 0);
 
   // The fourth SharedQuadState is used.
   SharedQuadState* shared_state4_in = pass_in->CreateAndAppendSharedQuadState();
-  shared_state4_in->SetAll(gfx::Transform(), gfx::Size(4, 4), gfx::Rect(),
+  shared_state4_in->SetAll(gfx::Transform(), gfx::Rect(4, 4), gfx::Rect(),
                            gfx::Rect(), false, 1.f, SkBlendMode::kSrcOver, 0);
 
   SolidColorDrawQuad* quad2 =
@@ -534,7 +534,7 @@
 
   // The fifth is not used again.
   SharedQuadState* shared_state5_in = pass_in->CreateAndAppendSharedQuadState();
-  shared_state5_in->SetAll(gfx::Transform(), gfx::Size(5, 5), gfx::Rect(),
+  shared_state5_in->SetAll(gfx::Transform(), gfx::Rect(5, 5), gfx::Rect(),
                            gfx::Rect(), false, 1.f, SkBlendMode::kSrcOver, 0);
 
   // 5 SharedQuadStates go in.
@@ -559,12 +559,12 @@
   ASSERT_EQ(2u, pass_out->shared_quad_state_list.size());
   ASSERT_EQ(2u, pass_out->quad_list.size());
 
-  EXPECT_EQ(gfx::Size(1, 1).ToString(),
+  EXPECT_EQ(gfx::Rect(1, 1).ToString(),
             pass_out->shared_quad_state_list.ElementAt(0)
-                ->quad_layer_bounds.ToString());
-  EXPECT_EQ(gfx::Size(4, 4).ToString(),
+                ->quad_layer_rect.ToString());
+  EXPECT_EQ(gfx::Rect(4, 4).ToString(),
             pass_out->shared_quad_state_list.ElementAt(1)
-                ->quad_layer_bounds.ToString());
+                ->quad_layer_rect.ToString());
 }
 
 TEST_F(CCParamTraitsTest, Resources) {
diff --git a/cc/ipc/cc_serialization_perftest.cc b/cc/ipc/cc_serialization_perftest.cc
index ee90e503..85a03a0 100644
--- a/cc/ipc/cc_serialization_perftest.cc
+++ b/cc/ipc/cc_serialization_perftest.cc
@@ -309,7 +309,7 @@
     for (uint32_t i = 0; i < 10; ++i) {
       SharedQuadState* shared_state1_in =
           pass_in->CreateAndAppendSharedQuadState();
-      shared_state1_in->SetAll(arbitrary_matrix1, arbitrary_size1,
+      shared_state1_in->SetAll(arbitrary_matrix1, arbitrary_rect1,
                                arbitrary_rect1, arbitrary_rect2,
                                arbitrary_bool1, arbitrary_float1,
                                arbitrary_blend_mode1, arbitrary_context_id1);
@@ -355,7 +355,7 @@
     for (uint32_t i = 0; i < 10; ++i) {
       SharedQuadState* shared_state2_in =
           pass_in->CreateAndAppendSharedQuadState();
-      shared_state2_in->SetAll(arbitrary_matrix2, arbitrary_size2,
+      shared_state2_in->SetAll(arbitrary_matrix2, arbitrary_rect2,
                                arbitrary_rect2, arbitrary_rect3,
                                arbitrary_bool1, arbitrary_float2,
                                arbitrary_blend_mode2, arbitrary_context_id2);
@@ -374,7 +374,7 @@
     for (uint32_t i = 0; i < 5; ++i) {
       SharedQuadState* shared_state3_in =
           pass_in->CreateAndAppendSharedQuadState();
-      shared_state3_in->SetAll(arbitrary_matrix1, arbitrary_size3,
+      shared_state3_in->SetAll(arbitrary_matrix1, arbitrary_rect3,
                                arbitrary_rect3, arbitrary_rect1,
                                arbitrary_bool1, arbitrary_float3,
                                arbitrary_blend_mode3, arbitrary_context_id3);
diff --git a/cc/ipc/shared_quad_state.mojom b/cc/ipc/shared_quad_state.mojom
index d819acb..cb1fdc0 100644
--- a/cc/ipc/shared_quad_state.mojom
+++ b/cc/ipc/shared_quad_state.mojom
@@ -11,8 +11,8 @@
   // gfx.mojom.Transforms quad rects into the target content space.
   gfx.mojom.Transform quad_to_target_transform;
 
-  // The size of the quads' originating layer in the space of the quad rects.
-  gfx.mojom.Size quad_layer_bounds;
+  // The rect of the quads' originating layer in the space of the quad rects.
+  gfx.mojom.Rect quad_layer_rect;
 
   // The size of the visible area in the quads' originating layer, in the space
   // of the quad rects.
diff --git a/cc/ipc/shared_quad_state_struct_traits.h b/cc/ipc/shared_quad_state_struct_traits.h
index 8b62a34..5b6dd287 100644
--- a/cc/ipc/shared_quad_state_struct_traits.h
+++ b/cc/ipc/shared_quad_state_struct_traits.h
@@ -25,8 +25,8 @@
     return input.sqs->quad_to_target_transform;
   }
 
-  static const gfx::Size& quad_layer_bounds(const OptSharedQuadState& input) {
-    return input.sqs->quad_layer_bounds;
+  static const gfx::Rect& quad_layer_rect(const OptSharedQuadState& input) {
+    return input.sqs->quad_layer_rect;
   }
 
   static const gfx::Rect& visible_quad_layer_rect(
@@ -62,8 +62,8 @@
     return sqs.quad_to_target_transform;
   }
 
-  static const gfx::Size& quad_layer_bounds(const cc::SharedQuadState& sqs) {
-    return sqs.quad_layer_bounds;
+  static const gfx::Rect& quad_layer_rect(const cc::SharedQuadState& sqs) {
+    return sqs.quad_layer_rect;
   }
 
   static const gfx::Rect& visible_quad_layer_rect(
@@ -92,7 +92,7 @@
   static bool Read(cc::mojom::SharedQuadStateDataView data,
                    cc::SharedQuadState* out) {
     if (!data.ReadQuadToTargetTransform(&out->quad_to_target_transform) ||
-        !data.ReadQuadLayerBounds(&out->quad_layer_bounds) ||
+        !data.ReadQuadLayerRect(&out->quad_layer_rect) ||
         !data.ReadVisibleQuadLayerRect(&out->visible_quad_layer_rect) ||
         !data.ReadClipRect(&out->clip_rect)) {
       return false;
diff --git a/cc/ipc/struct_traits_unittest.cc b/cc/ipc/struct_traits_unittest.cc
index f27c9c7e..46aa122 100644
--- a/cc/ipc/struct_traits_unittest.cc
+++ b/cc/ipc/struct_traits_unittest.cc
@@ -229,7 +229,7 @@
   const gfx::Transform sqs_quad_to_target_transform(
       1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f, 14.f,
       15.f, 16.f);
-  const gfx::Size sqs_layer_bounds(1234, 5678);
+  const gfx::Rect sqs_layer_rect(1234, 5678);
   const gfx::Rect sqs_visible_layer_rect(12, 34, 56, 78);
   const gfx::Rect sqs_clip_rect(123, 456, 789, 101112);
   const bool sqs_is_clipped = true;
@@ -237,7 +237,7 @@
   const SkBlendMode sqs_blend_mode = SkBlendMode::kSrcOver;
   const int sqs_sorting_context_id = 1337;
   SharedQuadState* sqs = render_pass->CreateAndAppendSharedQuadState();
-  sqs->SetAll(sqs_quad_to_target_transform, sqs_layer_bounds,
+  sqs->SetAll(sqs_quad_to_target_transform, sqs_layer_rect,
               sqs_visible_layer_rect, sqs_clip_rect, sqs_is_clipped,
               sqs_opacity, sqs_blend_mode, sqs_sorting_context_id);
 
@@ -315,7 +315,7 @@
   const SharedQuadState* out_sqs =
       out_render_pass->shared_quad_state_list.ElementAt(0);
   EXPECT_EQ(sqs_quad_to_target_transform, out_sqs->quad_to_target_transform);
-  EXPECT_EQ(sqs_layer_bounds, out_sqs->quad_layer_bounds);
+  EXPECT_EQ(sqs_layer_rect, out_sqs->quad_layer_rect);
   EXPECT_EQ(sqs_visible_layer_rect, out_sqs->visible_quad_layer_rect);
   EXPECT_EQ(sqs_clip_rect, out_sqs->clip_rect);
   EXPECT_EQ(sqs_is_clipped, out_sqs->is_clipped);
@@ -844,14 +844,14 @@
   shared_state_1->SetAll(
       gfx::Transform(16.1f, 15.3f, 14.3f, 13.7f, 12.2f, 11.4f, 10.4f, 9.8f,
                      8.1f, 7.3f, 6.3f, 5.7f, 4.8f, 3.4f, 2.4f, 1.2f),
-      gfx::Size(1, 2), gfx::Rect(1337, 5679, 9101112, 131415),
+      gfx::Rect(1, 2), gfx::Rect(1337, 5679, 9101112, 131415),
       gfx::Rect(1357, 2468, 121314, 1337), true, 2, SkBlendMode::kSrcOver, 1);
 
   SharedQuadState* shared_state_2 = input->CreateAndAppendSharedQuadState();
   shared_state_2->SetAll(
       gfx::Transform(1.1f, 2.3f, 3.3f, 4.7f, 5.2f, 6.4f, 7.4f, 8.8f, 9.1f,
                      10.3f, 11.3f, 12.7f, 13.8f, 14.4f, 15.4f, 16.2f),
-      gfx::Size(1337, 1234), gfx::Rect(1234, 5678, 9101112, 13141516),
+      gfx::Rect(1337, 1234), gfx::Rect(1234, 5678, 9101112, 13141516),
       gfx::Rect(1357, 2468, 121314, 1337), true, 2, SkBlendMode::kSrcOver, 1);
 
   // This quad uses the first shared quad state. The next two quads use the
@@ -896,7 +896,7 @@
   SharedQuadState* out_sqs1 = output->shared_quad_state_list.ElementAt(0);
   EXPECT_EQ(shared_state_1->quad_to_target_transform,
             out_sqs1->quad_to_target_transform);
-  EXPECT_EQ(shared_state_1->quad_layer_bounds, out_sqs1->quad_layer_bounds);
+  EXPECT_EQ(shared_state_1->quad_layer_rect, out_sqs1->quad_layer_rect);
   EXPECT_EQ(shared_state_1->visible_quad_layer_rect,
             out_sqs1->visible_quad_layer_rect);
   EXPECT_EQ(shared_state_1->clip_rect, out_sqs1->clip_rect);
@@ -908,7 +908,7 @@
   SharedQuadState* out_sqs2 = output->shared_quad_state_list.ElementAt(1);
   EXPECT_EQ(shared_state_2->quad_to_target_transform,
             out_sqs2->quad_to_target_transform);
-  EXPECT_EQ(shared_state_2->quad_layer_bounds, out_sqs2->quad_layer_bounds);
+  EXPECT_EQ(shared_state_2->quad_layer_rect, out_sqs2->quad_layer_rect);
   EXPECT_EQ(shared_state_2->visible_quad_layer_rect,
             out_sqs2->visible_quad_layer_rect);
   EXPECT_EQ(shared_state_2->clip_rect, out_sqs2->clip_rect);
@@ -1064,7 +1064,7 @@
   const gfx::Transform quad_to_target_transform(1.f, 2.f, 3.f, 4.f, 5.f, 6.f,
                                                 7.f, 8.f, 9.f, 10.f, 11.f, 12.f,
                                                 13.f, 14.f, 15.f, 16.f);
-  const gfx::Size layer_bounds(1234, 5678);
+  const gfx::Rect layer_rect(1234, 5678);
   const gfx::Rect visible_layer_rect(12, 34, 56, 78);
   const gfx::Rect clip_rect(123, 456, 789, 101112);
   const bool is_clipped = true;
@@ -1072,14 +1072,14 @@
   const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
   const int sorting_context_id = 1337;
   SharedQuadState input_sqs;
-  input_sqs.SetAll(quad_to_target_transform, layer_bounds, visible_layer_rect,
+  input_sqs.SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
                    clip_rect, is_clipped, opacity, blend_mode,
                    sorting_context_id);
   mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
   SharedQuadState output_sqs;
   proxy->EchoSharedQuadState(input_sqs, &output_sqs);
   EXPECT_EQ(quad_to_target_transform, output_sqs.quad_to_target_transform);
-  EXPECT_EQ(layer_bounds, output_sqs.quad_layer_bounds);
+  EXPECT_EQ(layer_rect, output_sqs.quad_layer_rect);
   EXPECT_EQ(visible_layer_rect, output_sqs.visible_quad_layer_rect);
   EXPECT_EQ(clip_rect, output_sqs.clip_rect);
   EXPECT_EQ(is_clipped, output_sqs.is_clipped);
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 4e2b151..ea79a82e 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -147,7 +147,7 @@
 }
 
 void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const {
-  state->SetAll(draw_properties_.target_space_transform, bounds(),
+  state->SetAll(draw_properties_.target_space_transform, gfx::Rect(bounds()),
                 draw_properties_.visible_layer_rect, draw_properties_.clip_rect,
                 draw_properties_.is_clipped, draw_properties_.opacity,
                 SkBlendMode::kSrcOver, GetSortingContextId());
@@ -167,10 +167,10 @@
       visible_layer_rect(), layer_to_content_scale_x, layer_to_content_scale_y);
   scaled_visible_layer_rect.Intersect(gfx::Rect(scaled_bounds));
 
-  state->SetAll(scaled_draw_transform, scaled_bounds, scaled_visible_layer_rect,
-                draw_properties().clip_rect, draw_properties().is_clipped,
-                draw_properties().opacity, SkBlendMode::kSrcOver,
-                GetSortingContextId());
+  state->SetAll(scaled_draw_transform, gfx::Rect(scaled_bounds),
+                scaled_visible_layer_rect, draw_properties().clip_rect,
+                draw_properties().is_clipped, draw_properties().opacity,
+                SkBlendMode::kSrcOver, GetSortingContextId());
 }
 
 bool LayerImpl::WillDraw(DrawMode draw_mode,
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index a85580b..f385bddd 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -215,8 +215,9 @@
 
   if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
     AppendDebugBorderQuad(
-        render_pass, shared_quad_state->quad_layer_bounds, shared_quad_state,
-        append_quads_data, DebugColors::DirectPictureBorderColor(),
+        render_pass, shared_quad_state->quad_layer_rect.size(),
+        shared_quad_state, append_quads_data,
+        DebugColors::DirectPictureBorderColor(),
         DebugColors::DirectPictureBorderWidth(device_scale_factor));
 
     gfx::Rect geometry_rect = shared_quad_state->visible_quad_layer_rect;
@@ -250,7 +251,7 @@
     return;
   }
 
-  AppendDebugBorderQuad(render_pass, shared_quad_state->quad_layer_bounds,
+  AppendDebugBorderQuad(render_pass, shared_quad_state->quad_layer_rect.size(),
                         shared_quad_state, append_quads_data);
 
   if (ShowDebugBorders(DebugBorderType::LAYER)) {
@@ -365,7 +366,8 @@
           float alpha =
               (SkColorGetA(draw_info.solid_color()) * (1.0f / 255.0f)) *
               shared_quad_state->opacity;
-          if (alpha >= std::numeric_limits<float>::epsilon()) {
+          if (mask_type_ == Layer::LayerMaskType::MULTI_TEXTURE_MASK ||
+              alpha >= std::numeric_limits<float>::epsilon()) {
             SolidColorDrawQuad* quad =
                 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
             quad->SetNew(shared_quad_state, geometry_rect,
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 45458f7..94edce6 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -3570,9 +3570,9 @@
                 ->quad_to_target_transform.ToString());
   // The content_bounds should be scaled by the
   // MaximumTilingContentsScale on the layer.
-  EXPECT_EQ(gfx::Size(2500u, 5000u).ToString(),
-            render_pass->shared_quad_state_list.front()
-                ->quad_layer_bounds.ToString());
+  EXPECT_EQ(
+      gfx::Rect(2500u, 5000u).ToString(),
+      render_pass->shared_quad_state_list.front()->quad_layer_rect.ToString());
   // The visible_layer_rect should be scaled by the
   // MaximumTilingContentsScale on the layer.
   EXPECT_EQ(gfx::Rect(0u, 0u, 2500u, 5000u).ToString(),
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index a03fb00..fc05a4e 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -385,7 +385,7 @@
   SharedQuadState* shared_quad_state =
       render_pass->CreateAndAppendSharedQuadState();
   shared_quad_state->SetAll(
-      draw_transform(), content_rect().size(), content_rect(),
+      draw_transform(), content_rect(), content_rect(),
       draw_properties_.clip_rect, draw_properties_.is_clipped,
       draw_properties_.draw_opacity, BlendMode(), sorting_context_id);
 
@@ -461,18 +461,18 @@
   shared_quad_state->quad_to_target_transform.matrix().preScale(
       mask_quad_to_surface_contents_scale.x(),
       mask_quad_to_surface_contents_scale.y(), 1.f);
-  shared_quad_state->quad_layer_bounds =
-      gfx::ScaleToCeiledSize(shared_quad_state->quad_layer_bounds,
-                             1.f / mask_quad_to_surface_contents_scale.x(),
-                             1.f / mask_quad_to_surface_contents_scale.y());
+  shared_quad_state->quad_layer_rect =
+      gfx::ScaleToEnclosingRect(shared_quad_state->quad_layer_rect,
+                                1.f / mask_quad_to_surface_contents_scale.x(),
+                                1.f / mask_quad_to_surface_contents_scale.y());
   shared_quad_state->visible_quad_layer_rect =
-      gfx::ScaleToEnclosedRect(shared_quad_state->visible_quad_layer_rect,
-                               mask_quad_to_surface_contents_scale.x(),
-                               mask_quad_to_surface_contents_scale.y());
-  gfx::Rect content_rect_in_coverage_space = gfx::ScaleToEnclosedRect(
+      gfx::ScaleToEnclosingRect(shared_quad_state->visible_quad_layer_rect,
+                                mask_quad_to_surface_contents_scale.x(),
+                                mask_quad_to_surface_contents_scale.y());
+  gfx::Rect content_rect_in_coverage_space = gfx::ScaleToEnclosingRect(
       content_rect(), 1.f / mask_quad_to_surface_contents_scale.x(),
       1.f / mask_quad_to_surface_contents_scale.y());
-  gfx::Rect visible_layer_rect_in_coverage_space = gfx::ScaleToEnclosedRect(
+  gfx::Rect visible_layer_rect_in_coverage_space = gfx::ScaleToEnclosingRect(
       visible_layer_rect, 1.f / mask_quad_to_surface_contents_scale.x(),
       1.f / mask_quad_to_surface_contents_scale.y());
 
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index 26ecdde4..b2d98eea2 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -169,9 +169,10 @@
 
   SharedQuadState* shared_quad_state =
       render_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(transform, rotated_size, visible_layer_rect(),
-                            clip_rect(), is_clipped(), draw_opacity(),
-                            SkBlendMode::kSrcOver, GetSortingContextId());
+  shared_quad_state->SetAll(transform, gfx::Rect(rotated_size),
+                            visible_layer_rect(), clip_rect(), is_clipped(),
+                            draw_opacity(), SkBlendMode::kSrcOver,
+                            GetSortingContextId());
 
   AppendDebugBorderQuad(
       render_pass, rotated_size, shared_quad_state, append_quads_data);
diff --git a/cc/output/ca_layer_overlay.cc b/cc/output/ca_layer_overlay.cc
index 1acd952..972c8c40 100644
--- a/cc/output/ca_layer_overlay.cc
+++ b/cc/output/ca_layer_overlay.cc
@@ -74,34 +74,23 @@
   }
 }
 
-static const FilterOperations* FiltersForPass(
-    int render_pass_id,
-    const RenderPassFilterList& filter_list) {
-  auto it = std::lower_bound(
-      filter_list.begin(), filter_list.end(),
-      std::pair<int, FilterOperations*>(render_pass_id, nullptr));
-  if (it != filter_list.end() && it->first == render_pass_id)
-    return it->second;
-  return nullptr;
-}
-
 CALayerResult FromRenderPassQuad(
     ResourceProvider* resource_provider,
     const RenderPassDrawQuad* quad,
-    const RenderPassFilterList& render_pass_filters,
-    const RenderPassFilterList& render_pass_background_filters,
+    const base::flat_map<int, FilterOperations*>& render_pass_filters,
+    const base::flat_map<int, FilterOperations*>&
+        render_pass_background_filters,
     CALayerOverlay* ca_layer_overlay) {
-  if (FiltersForPass(quad->render_pass_id, render_pass_background_filters)) {
+  if (render_pass_background_filters.count(quad->render_pass_id)) {
     return CA_LAYER_FAILED_RENDER_PASS_BACKGROUND_FILTERS;
   }
 
   if (quad->shared_quad_state->sorting_context_id != 0)
     return CA_LAYER_FAILED_RENDER_PASS_SORTING_CONTEXT_ID;
 
-  const FilterOperations* filters =
-      FiltersForPass(quad->render_pass_id, render_pass_filters);
-  if (filters) {
-    for (const FilterOperation& operation : filters->operations()) {
+  auto it = render_pass_filters.find(quad->render_pass_id);
+  if (it != render_pass_filters.end()) {
+    for (const FilterOperation& operation : it->second->operations()) {
       bool success = FilterOperationSupported(operation);
       if (!success)
         return CA_LAYER_FAILED_RENDER_PASS_FILTER_OPERATION;
@@ -188,8 +177,9 @@
       ResourceProvider* resource_provider,
       const gfx::RectF& display_rect,
       const DrawQuad* quad,
-      const RenderPassFilterList& render_pass_filters,
-      const RenderPassFilterList& render_pass_background_filters,
+      const base::flat_map<int, FilterOperations*>& render_pass_filters,
+      const base::flat_map<int, FilterOperations*>&
+          render_pass_background_filters,
       CALayerOverlay* ca_layer_overlay,
       bool* skip,
       bool* render_pass_draw_quad) {
@@ -286,8 +276,9 @@
     ResourceProvider* resource_provider,
     const gfx::RectF& display_rect,
     const QuadList& quad_list,
-    const RenderPassFilterList& render_pass_filters,
-    const RenderPassFilterList& render_pass_background_filters,
+    const base::flat_map<int, FilterOperations*>& render_pass_filters,
+    const base::flat_map<int, FilterOperations*>&
+        render_pass_background_filters,
     CALayerOverlayList* ca_layer_overlays) {
   CALayerResult result = CA_LAYER_SUCCESS;
   ca_layer_overlays->reserve(quad_list.size());
diff --git a/cc/output/ca_layer_overlay.h b/cc/output/ca_layer_overlay.h
index 513ba667..da003f9 100644
--- a/cc/output/ca_layer_overlay.h
+++ b/cc/output/ca_layer_overlay.h
@@ -5,6 +5,7 @@
 #ifndef CC_OUTPUT_CA_LAYER_OVERLAY_H_
 #define CC_OUTPUT_CA_LAYER_OVERLAY_H_
 
+#include "base/containers/flat_map.h"
 #include "base/memory/ref_counted.h"
 #include "cc/quads/render_pass.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -76,8 +77,9 @@
     ResourceProvider* resource_provider,
     const gfx::RectF& display_rect,
     const QuadList& quad_list,
-    const RenderPassFilterList& render_pass_filters,
-    const RenderPassFilterList& render_pass_background_filters,
+    const base::flat_map<int, FilterOperations*>& render_pass_filters,
+    const base::flat_map<int, FilterOperations*>&
+        render_pass_background_filters,
     CALayerOverlayList* ca_layer_overlays);
 
 }  // namespace cc
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc
index 523f3c6..8d565a0 100644
--- a/cc/output/direct_renderer.cc
+++ b/cc/output/direct_renderer.cc
@@ -288,14 +288,9 @@
 
   for (const auto& pass : *render_passes_in_draw_order) {
     if (!pass->filters.IsEmpty())
-      render_pass_filters_.push_back(std::make_pair(pass->id, &pass->filters));
-    if (!pass->background_filters.IsEmpty()) {
-      render_pass_background_filters_.push_back(
-          std::make_pair(pass->id, &pass->background_filters));
-    }
-    std::sort(render_pass_filters_.begin(), render_pass_filters_.end());
-    std::sort(render_pass_background_filters_.begin(),
-              render_pass_background_filters_.end());
+      render_pass_filters_[pass->id] = &pass->filters;
+    if (!pass->background_filters.IsEmpty())
+      render_pass_background_filters_[pass->id] = &pass->background_filters;
   }
 
   // Draw all non-root render passes except for the root render pass.
@@ -456,24 +451,14 @@
 
 const FilterOperations* DirectRenderer::FiltersForPass(
     int render_pass_id) const {
-  auto it = std::lower_bound(
-      render_pass_filters_.begin(), render_pass_filters_.end(),
-      std::pair<int, FilterOperations*>(render_pass_id, nullptr));
-  if (it != render_pass_filters_.end() && it->first == render_pass_id)
-    return it->second;
-  return nullptr;
+  auto it = render_pass_filters_.find(render_pass_id);
+  return it == render_pass_filters_.end() ? nullptr : it->second;
 }
 
 const FilterOperations* DirectRenderer::BackgroundFiltersForPass(
     int render_pass_id) const {
-  auto it = std::lower_bound(
-      render_pass_background_filters_.begin(),
-      render_pass_background_filters_.end(),
-      std::pair<int, FilterOperations*>(render_pass_id, nullptr));
-  if (it != render_pass_background_filters_.end() &&
-      it->first == render_pass_id)
-    return it->second;
-  return nullptr;
+  auto it = render_pass_background_filters_.find(render_pass_id);
+  return it == render_pass_background_filters_.end() ? nullptr : it->second;
 }
 
 void DirectRenderer::FlushPolygons(
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h
index 96e66133..c3496a4 100644
--- a/cc/output/direct_renderer.h
+++ b/cc/output/direct_renderer.h
@@ -199,11 +199,15 @@
   // DirectComposition layers needed to be used.
   int frames_since_using_dc_layers_ = 0;
 
+  // A map from RenderPass id to the texture used to draw the RenderPass from.
   base::flat_map<int, std::unique_ptr<ScopedResource>> render_pass_textures_;
+  // A map from RenderPass id to the single quad present in and replacing the
+  // RenderPass.
   base::flat_map<int, TileDrawQuad> render_pass_bypass_quads_;
 
-  RenderPassFilterList render_pass_filters_;
-  RenderPassFilterList render_pass_background_filters_;
+  // A map from RenderPass id to the filters used when drawing the RenderPass.
+  base::flat_map<int, FilterOperations*> render_pass_filters_;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters_;
 
   bool visible_ = false;
   bool disable_color_checks_for_testing_ = false;
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index a7fe452..fab5742 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -1000,7 +1000,7 @@
       quad->rect != pass->output_rect)
     return nullptr;
   // The quad is expected to be the entire layer so that AA edges are correct.
-  if (gfx::Rect(quad->shared_quad_state->quad_layer_bounds) != quad->rect)
+  if (quad->shared_quad_state->quad_layer_rect != quad->rect)
     return nullptr;
   if (quad->material != DrawQuad::TILED_CONTENT)
     return nullptr;
@@ -1102,8 +1102,11 @@
                            static_cast<float>(dst_rect.width()),
                            static_cast<float>(dst_rect.height()));
   gfx::Transform quad_rect_matrix;
+  gfx::Rect quad_layer_rect(quad->shared_quad_state->quad_layer_rect);
+  if (params->filters)
+    quad_layer_rect = params->filters->MapRect(quad_layer_rect, local_matrix);
   QuadRectTransform(&quad_rect_matrix, params->quad_to_target_transform,
-                    params->dst_rect);
+                    gfx::RectF(quad_layer_rect));
   params->contents_device_transform =
       params->window_matrix * params->projection_matrix * quad_rect_matrix;
   params->contents_device_transform.FlattenTo2d();
@@ -1112,10 +1115,10 @@
   if (!params->contents_device_transform.IsInvertible())
     return false;
 
+  // TODO(sunxd): unify the anti-aliasing logic of RPDQ and TileDrawQuad.
   params->surface_quad = SharedGeometryQuad();
-
   gfx::QuadF device_layer_quad;
-  if (settings_->allow_antialiasing) {
+  if (settings_->allow_antialiasing && quad->IsEdge()) {
     bool clipped = false;
     device_layer_quad = MathUtil::MapQuad(params->contents_device_transform,
                                           params->surface_quad, &clipped);
@@ -1481,10 +1484,10 @@
     return true;
 
   return std::abs(clip_region->p3().y() -
-                  quad->shared_quad_state->quad_layer_bounds.height()) <
+                  quad->shared_quad_state->quad_layer_rect.height()) <
              kAntiAliasingEpsilon &&
          std::abs(clip_region->p4().y() -
-                  quad->shared_quad_state->quad_layer_bounds.height()) <
+                  quad->shared_quad_state->quad_layer_rect.height()) <
              kAntiAliasingEpsilon;
 }
 
@@ -1505,10 +1508,10 @@
     return true;
 
   return std::abs(clip_region->p2().x() -
-                  quad->shared_quad_state->quad_layer_bounds.width()) <
+                  quad->shared_quad_state->quad_layer_rect.width()) <
              kAntiAliasingEpsilon &&
          std::abs(clip_region->p3().x() -
-                  quad->shared_quad_state->quad_layer_bounds.width()) <
+                  quad->shared_quad_state->quad_layer_rect.width()) <
              kAntiAliasingEpsilon;
 }
 }  // anonymous namespace
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 144b574..1637718 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -1977,7 +1977,7 @@
   TextureDrawQuad* overlay_quad =
       root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
   SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), viewport_size,
+  shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
                        gfx::Rect(viewport_size), gfx::Rect(viewport_size),
                        false, 1, SkBlendMode::kSrcOver, 0);
   overlay_quad->SetNew(shared_state, gfx::Rect(viewport_size),
@@ -2173,7 +2173,7 @@
       gfx::RectF tex_coord_rect(0, 0, 1, 1);
       SharedQuadState* shared_state =
           root_pass->CreateAndAppendSharedQuadState();
-      shared_state->SetAll(gfx::Transform(), rect.size(), rect, rect, false, 1,
+      shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, 1,
                            SkBlendMode::kSrcOver, 0);
       YUVVideoDrawQuad* quad =
           root_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
diff --git a/cc/output/overlay_processor.cc b/cc/output/overlay_processor.cc
index c07eecf..73e0a59a 100644
--- a/cc/output/overlay_processor.cc
+++ b/cc/output/overlay_processor.cc
@@ -62,8 +62,9 @@
 bool OverlayProcessor::ProcessForCALayers(
     ResourceProvider* resource_provider,
     RenderPass* render_pass,
-    const RenderPassFilterList& render_pass_filters,
-    const RenderPassFilterList& render_pass_background_filters,
+    const base::flat_map<int, FilterOperations*>& render_pass_filters,
+    const base::flat_map<int, FilterOperations*>&
+        render_pass_background_filters,
     OverlayCandidateList* overlay_candidates,
     CALayerOverlayList* ca_layer_overlays,
     gfx::Rect* damage_rect) {
@@ -90,8 +91,9 @@
 bool OverlayProcessor::ProcessForDCLayers(
     ResourceProvider* resource_provider,
     RenderPass* render_pass,
-    const RenderPassFilterList& render_pass_filters,
-    const RenderPassFilterList& render_pass_background_filters,
+    const base::flat_map<int, FilterOperations*>& render_pass_filters,
+    const base::flat_map<int, FilterOperations*>&
+        render_pass_background_filters,
     OverlayCandidateList* overlay_candidates,
     DCLayerOverlayList* dc_layer_overlays,
     gfx::Rect* damage_rect) {
@@ -111,8 +113,9 @@
 void OverlayProcessor::ProcessForOverlays(
     ResourceProvider* resource_provider,
     RenderPass* render_pass,
-    const RenderPassFilterList& render_pass_filters,
-    const RenderPassFilterList& render_pass_background_filters,
+    const base::flat_map<int, FilterOperations*>& render_pass_filters,
+    const base::flat_map<int, FilterOperations*>&
+        render_pass_background_filters,
     OverlayCandidateList* candidates,
     CALayerOverlayList* ca_layer_overlays,
     DCLayerOverlayList* dc_layer_overlays,
diff --git a/cc/output/overlay_processor.h b/cc/output/overlay_processor.h
index a00574e..31e1ef5 100644
--- a/cc/output/overlay_processor.h
+++ b/cc/output/overlay_processor.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "cc/cc_export.h"
 #include "cc/output/ca_layer_overlay.h"
@@ -46,8 +47,9 @@
   void ProcessForOverlays(
       ResourceProvider* resource_provider,
       RenderPass* root_render_pass,
-      const RenderPassFilterList& render_pass_filters,
-      const RenderPassFilterList& render_pass_background_filters,
+      const base::flat_map<int, FilterOperations*>& render_pass_filters,
+      const base::flat_map<int, FilterOperations*>&
+          render_pass_background_filters,
       OverlayCandidateList* overlay_candidates,
       CALayerOverlayList* ca_layer_overlays,
       DCLayerOverlayList* dc_layer_overlays,
@@ -64,16 +66,18 @@
   bool ProcessForCALayers(
       ResourceProvider* resource_provider,
       RenderPass* render_pass,
-      const RenderPassFilterList& render_pass_filters,
-      const RenderPassFilterList& render_pass_background_filters,
+      const base::flat_map<int, FilterOperations*>& render_pass_filters,
+      const base::flat_map<int, FilterOperations*>&
+          render_pass_background_filters,
       OverlayCandidateList* overlay_candidates,
       CALayerOverlayList* ca_layer_overlays,
       gfx::Rect* damage_rect);
   bool ProcessForDCLayers(
       ResourceProvider* resource_provider,
       RenderPass* render_pass,
-      const RenderPassFilterList& render_pass_filters,
-      const RenderPassFilterList& render_pass_background_filters,
+      const base::flat_map<int, FilterOperations*>& render_pass_filters,
+      const base::flat_map<int, FilterOperations*>&
+          render_pass_background_filters,
       OverlayCandidateList* overlay_candidates,
       DCLayerOverlayList* dc_layer_overlays,
       gfx::Rect* damage_rect);
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index ee804f3..70d81f6 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/containers/flat_map.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "cc/base/filter_operation.h"
@@ -417,8 +418,8 @@
          exp_iter != expected->quad_list.cend();
          ++exp_iter, ++act_iter) {
       EXPECT_EQ(exp_iter->rect.ToString(), act_iter->rect.ToString());
-      EXPECT_EQ(exp_iter->shared_quad_state->quad_layer_bounds.ToString(),
-                act_iter->shared_quad_state->quad_layer_bounds.ToString());
+      EXPECT_EQ(exp_iter->shared_quad_state->quad_layer_rect.ToString(),
+                act_iter->shared_quad_state->quad_layer_rect.ToString());
     }
   }
 }
@@ -502,8 +503,8 @@
 
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -528,8 +529,8 @@
 
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -551,8 +552,8 @@
 
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -578,8 +579,8 @@
 
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -601,8 +602,8 @@
 
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -631,8 +632,8 @@
 
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -661,8 +662,8 @@
 
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -709,8 +710,8 @@
 
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -750,8 +751,8 @@
   output_surface_plane.overlay_handled = true;
   candidate_list.push_back(output_surface_plane);
 
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -773,8 +774,8 @@
   RenderPass::CopyAll(pass_list, &original_pass_list);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass_list.back().get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -802,8 +803,8 @@
   RenderPass::CopyAll(pass_list, &original_pass_list);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass_list.back().get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -828,8 +829,8 @@
 
   // Check for potential candidates.
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -847,8 +848,8 @@
   quad->opaque_rect = gfx::Rect(0, 0, 0, 0);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -865,8 +866,8 @@
   quad->background_color = SK_ColorBLACK;
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -882,8 +883,8 @@
   pass->shared_quad_state_list.back()->blend_mode = SkBlendMode::kScreen;
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -899,8 +900,8 @@
   pass->shared_quad_state_list.back()->opacity = 0.5f;
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -917,8 +918,8 @@
       ->quad_to_target_transform.RotateAboutXAxis(45.f);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -935,8 +936,8 @@
   pass->shared_quad_state_list.back()->clip_rect = kOverlayClipRect;
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -954,8 +955,8 @@
   pass->shared_quad_state_list.back()->quad_to_target_transform.Scale(2.0f,
                                                                       -1.0f);
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -976,8 +977,8 @@
                                                                       2.0f);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -996,8 +997,8 @@
   pass->shared_quad_state_list.back()->quad_to_target_transform.Scale(2.0f,
                                                                       1.0f);
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1015,8 +1016,8 @@
       ->quad_to_target_transform.RotateAboutZAxis(90.f);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1034,8 +1035,8 @@
       ->quad_to_target_transform.RotateAboutZAxis(90.f);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1054,8 +1055,8 @@
       ->quad_to_target_transform.RotateAboutZAxis(180.f);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1074,8 +1075,8 @@
       ->quad_to_target_transform.RotateAboutZAxis(270.f);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1098,8 +1099,8 @@
                         kOverlayBottomRightRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1122,8 +1123,8 @@
                         kOverlayBottomRightRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1144,8 +1145,8 @@
                         kOverlayBottomRightRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1165,8 +1166,8 @@
                         kOverlayBottomRightRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1184,8 +1185,8 @@
                         kOverlayBottomRightRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1200,8 +1201,8 @@
                                      pass.get(), kSwapTransform);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1216,8 +1217,8 @@
                                      pass.get(), kXMirrorTransform);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1232,8 +1233,8 @@
                                      pass.get(), kBothMirrorTransform);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1248,8 +1249,8 @@
                                      pass.get(), kNormalTransform);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1264,8 +1265,8 @@
                                      pass.get(), kYMirrorTransform);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1285,8 +1286,8 @@
                         kOverlayBottomRightRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1308,8 +1309,8 @@
                              pass->shared_quad_state_list.back(), pass.get());
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1330,8 +1331,8 @@
   damage_rect_ = kOverlayRect;
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1356,8 +1357,8 @@
                                pass->shared_quad_state_list.back(), pass.get());
 
     OverlayCandidateList candidate_list;
-    RenderPassFilterList render_pass_filters;
-    RenderPassFilterList render_pass_background_filters;
+    base::flat_map<int, FilterOperations*> render_pass_filters;
+    base::flat_map<int, FilterOperations*> render_pass_background_filters;
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), pass.get(), render_pass_filters,
         render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1386,8 +1387,8 @@
     damage_rect_ = overlay_rects[i];
 
     OverlayCandidateList candidate_list;
-    RenderPassFilterList render_pass_filters;
-    RenderPassFilterList render_pass_background_filters;
+    base::flat_map<int, FilterOperations*> render_pass_filters;
+    base::flat_map<int, FilterOperations*> render_pass_background_filters;
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), pass.get(), render_pass_filters,
         render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1410,8 +1411,8 @@
     damage_rect_ = kOverlayRect;
 
     OverlayCandidateList candidate_list;
-    RenderPassFilterList render_pass_filters;
-    RenderPassFilterList render_pass_background_filters;
+    base::flat_map<int, FilterOperations*> render_pass_filters;
+    base::flat_map<int, FilterOperations*> render_pass_background_filters;
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), pass.get(), render_pass_filters,
         render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1438,8 +1439,8 @@
     damage_rect_ = kOverlayBottomRightRect;
 
     OverlayCandidateList candidate_list;
-    RenderPassFilterList render_pass_filters;
-    RenderPassFilterList render_pass_background_filters;
+    base::flat_map<int, FilterOperations*> render_pass_filters;
+    base::flat_map<int, FilterOperations*> render_pass_background_filters;
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), pass.get(), render_pass_filters,
         render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1457,8 +1458,8 @@
                      kOverlayTopLeftRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1473,8 +1474,8 @@
                         kOverlayRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1503,8 +1504,8 @@
                      SK_ColorBLACK);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1524,8 +1525,8 @@
                         kOverlayRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1548,8 +1549,8 @@
                         kOverlayRect);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1578,8 +1579,8 @@
                      gfx::Rect(0, 0, 10, 10), SK_ColorWHITE);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1609,8 +1610,8 @@
                      gfx::Rect(0, 0, 255, 255), SK_ColorWHITE);
 
   OverlayCandidateList candidate_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &candidate_list, nullptr, nullptr,
@@ -1643,8 +1644,8 @@
   gfx::Rect damage_rect;
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr,
@@ -1666,8 +1667,8 @@
   gfx::Rect damage_rect;
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr,
@@ -1692,8 +1693,8 @@
   gfx::Rect damage_rect;
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr,
@@ -1715,8 +1716,8 @@
   gfx::Rect damage_rect;
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr,
@@ -1740,8 +1741,8 @@
   gfx::Rect damage_rect;
   CALayerOverlayList ca_layer_list;
   OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
       render_pass_background_filters, &overlay_list, &ca_layer_list, nullptr,
@@ -1766,8 +1767,8 @@
   gfx::Rect damage_rect;
   DCLayerOverlayList dc_layer_list;
   OverlayCandidateList overlay_list;
-  RenderPassFilterList render_pass_filters;
-  RenderPassFilterList render_pass_background_filters;
+  base::flat_map<int, FilterOperations*> render_pass_filters;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters;
   damage_rect_ = gfx::Rect(1, 1, 10, 10);
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), pass.get(), render_pass_filters,
@@ -1796,8 +1797,8 @@
     gfx::Rect damage_rect;
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
-    RenderPassFilterList render_pass_filters;
-    RenderPassFilterList render_pass_background_filters;
+    base::flat_map<int, FilterOperations*> render_pass_filters;
+    base::flat_map<int, FilterOperations*> render_pass_background_filters;
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), pass.get(), render_pass_filters,
@@ -1823,8 +1824,8 @@
     gfx::Rect damage_rect;
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
-    RenderPassFilterList render_pass_filters;
-    RenderPassFilterList render_pass_background_filters;
+    base::flat_map<int, FilterOperations*> render_pass_filters;
+    base::flat_map<int, FilterOperations*> render_pass_background_filters;
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), pass.get(), render_pass_filters,
@@ -1851,8 +1852,8 @@
     gfx::Rect damage_rect;
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
-    RenderPassFilterList render_pass_filters;
-    RenderPassFilterList render_pass_background_filters;
+    base::flat_map<int, FilterOperations*> render_pass_filters;
+    base::flat_map<int, FilterOperations*> render_pass_background_filters;
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), pass.get(), render_pass_filters,
@@ -1897,8 +1898,8 @@
 
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
-    RenderPassFilterList render_pass_filters;
-    RenderPassFilterList render_pass_background_filters;
+    base::flat_map<int, FilterOperations*> render_pass_filters;
+    base::flat_map<int, FilterOperations*> render_pass_background_filters;
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), pass.get(), render_pass_filters,
@@ -1932,8 +1933,8 @@
 
     DCLayerOverlayList dc_layer_list;
     OverlayCandidateList overlay_list;
-    RenderPassFilterList render_pass_filters;
-    RenderPassFilterList render_pass_background_filters;
+    base::flat_map<int, FilterOperations*> render_pass_filters;
+    base::flat_map<int, FilterOperations*> render_pass_background_filters;
     damage_rect_ = gfx::Rect(1, 1, 10, 10);
     overlay_processor_->ProcessForOverlays(
         resource_provider_.get(), pass.get(), render_pass_filters,
@@ -2492,8 +2493,8 @@
   int render_pass_id_;
   FilterOperations filters_;
   FilterOperations background_filters_;
-  RenderPassFilterList render_pass_filters_;
-  RenderPassFilterList render_pass_background_filters_;
+  base::flat_map<int, FilterOperations*> render_pass_filters_;
+  base::flat_map<int, FilterOperations*> render_pass_background_filters_;
   CALayerOverlayList ca_layer_list_;
   OverlayCandidateList overlay_list_;
 };
@@ -2519,7 +2520,7 @@
   filters_.Append(FilterOperation::CreateBlurFilter(0.9f));
   filters_.Append(FilterOperation::CreateDropShadowFilter(gfx::Point(10, 20),
                                                           1.0f, SK_ColorGREEN));
-  render_pass_filters_.push_back(std::make_pair(render_pass_id_, &filters_));
+  render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
                 gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF());
@@ -2530,7 +2531,7 @@
 
 TEST_F(CALayerOverlayRPDQTest, RenderPassDrawQuadOpacityFilterScale) {
   filters_.Append(FilterOperation::CreateOpacityFilter(0.8f));
-  render_pass_filters_.push_back(std::make_pair(render_pass_id_, &filters_));
+  render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
                 gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF());
@@ -2540,7 +2541,7 @@
 
 TEST_F(CALayerOverlayRPDQTest, RenderPassDrawQuadBlurFilterScale) {
   filters_.Append(FilterOperation::CreateBlurFilter(0.8f));
-  render_pass_filters_.push_back(std::make_pair(render_pass_id_, &filters_));
+  render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
                 gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF());
@@ -2551,7 +2552,7 @@
 TEST_F(CALayerOverlayRPDQTest, RenderPassDrawQuadDropShadowFilterScale) {
   filters_.Append(FilterOperation::CreateDropShadowFilter(gfx::Point(10, 20),
                                                           1.0f, SK_ColorGREEN));
-  render_pass_filters_.push_back(std::make_pair(render_pass_id_, &filters_));
+  render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
                 gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF());
@@ -2561,8 +2562,7 @@
 
 TEST_F(CALayerOverlayRPDQTest, RenderPassDrawQuadBackgroundFilter) {
   background_filters_.Append(FilterOperation::CreateGrayscaleFilter(0.1f));
-  render_pass_background_filters_.push_back(
-      std::make_pair(render_pass_id_, &background_filters_));
+  render_pass_background_filters_[render_pass_id_] = &background_filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
                 gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF());
@@ -2580,7 +2580,7 @@
 
 TEST_F(CALayerOverlayRPDQTest, RenderPassDrawQuadUnsupportedFilter) {
   filters_.Append(FilterOperation::CreateZoomFilter(0.9f, 1));
-  render_pass_filters_.push_back(std::make_pair(render_pass_id_, &filters_));
+  render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
                 gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF());
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
index 7a9851e..ce4c650 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -62,7 +62,7 @@
     gfx::Transform quad_to_target_transform,
     const gfx::Rect& rect,
     RenderPass* render_pass) {
-  const gfx::Size layer_bounds = rect.size();
+  const gfx::Rect layer_rect = rect;
   const gfx::Rect visible_layer_rect = rect;
   const gfx::Rect clip_rect = rect;
   const bool is_clipped = false;
@@ -70,9 +70,9 @@
   const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
   int sorting_context_id = 0;
   SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(quad_to_target_transform, layer_bounds,
-                       visible_layer_rect, clip_rect, is_clipped, opacity,
-                       blend_mode, sorting_context_id);
+  shared_state->SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
+                       clip_rect, is_clipped, opacity, blend_mode,
+                       sorting_context_id);
   return shared_state;
 }
 
@@ -81,16 +81,16 @@
     const gfx::Rect& rect,
     const gfx::Rect& clip_rect,
     RenderPass* render_pass) {
-  const gfx::Size layer_bounds = rect.size();
+  const gfx::Rect layer_rect = rect;
   const gfx::Rect visible_layer_rect = clip_rect;
   const bool is_clipped = true;
   const float opacity = 1.0f;
   const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
   int sorting_context_id = 0;
   SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(quad_to_target_transform, layer_bounds,
-                       visible_layer_rect, clip_rect, is_clipped, opacity,
-                       blend_mode, sorting_context_id);
+  shared_state->SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
+                       clip_rect, is_clipped, opacity, blend_mode,
+                       sorting_context_id);
   return shared_state;
 }
 
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc
index 15da1b6..b6867fe7 100644
--- a/cc/output/software_renderer_unittest.cc
+++ b/cc/output/software_renderer_unittest.cc
@@ -104,7 +104,7 @@
                            gfx::Transform());
   SharedQuadState* shared_quad_state =
       root_render_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(gfx::Transform(), outer_size, outer_rect,
+  shared_quad_state->SetAll(gfx::Transform(), outer_rect, outer_rect,
                             outer_rect, false, 1.0, SkBlendMode::kSrcOver, 0);
   SolidColorDrawQuad* inner_quad =
       root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -170,7 +170,7 @@
                            gfx::Transform());
   SharedQuadState* shared_quad_state =
       root_render_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(gfx::Transform(), outer_size, outer_rect,
+  shared_quad_state->SetAll(gfx::Transform(), outer_rect, outer_rect,
                             outer_rect, false, 1.0, SkBlendMode::kSrcOver, 0);
   TileDrawQuad* inner_quad =
       root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
@@ -230,7 +230,7 @@
                            gfx::Transform());
   SharedQuadState* shared_quad_state =
       root_render_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(gfx::Transform(), tile_size, tile_rect, tile_rect,
+  shared_quad_state->SetAll(gfx::Transform(), tile_rect, tile_rect, tile_rect,
                             false, 1.0, SkBlendMode::kSrcOver, 0);
   TileDrawQuad* quad =
       root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
diff --git a/cc/quads/draw_quad.h b/cc/quads/draw_quad.h
index 5e46ea4..1b5775c2 100644
--- a/cc/quads/draw_quad.h
+++ b/cc/quads/draw_quad.h
@@ -95,13 +95,13 @@
   // Is the right edge of this tile aligned with the originating layer's
   // right edge?
   bool IsRightEdge() const {
-    return rect.right() == shared_quad_state->quad_layer_bounds.width();
+    return rect.right() == shared_quad_state->quad_layer_rect.right();
   }
 
   // Is the bottom edge of this tile aligned with the originating layer's
   // bottom edge?
   bool IsBottomEdge() const {
-    return rect.bottom() == shared_quad_state->quad_layer_bounds.height();
+    return rect.bottom() == shared_quad_state->quad_layer_rect.bottom();
   }
 
   // Is any edge of this tile aligned with the originating layer's
diff --git a/cc/quads/draw_quad_perftest.cc b/cc/quads/draw_quad_perftest.cc
index 5d6c4c2..669da21 100644
--- a/cc/quads/draw_quad_perftest.cc
+++ b/cc/quads/draw_quad_perftest.cc
@@ -22,7 +22,7 @@
 
 SharedQuadState* CreateSharedQuadState(RenderPass* render_pass) {
   gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0);
-  gfx::Size content_bounds(26, 28);
+  gfx::Rect content_rect(26, 28);
   gfx::Rect visible_layer_rect(10, 12, 14, 16);
   gfx::Rect clip_rect(19, 21, 23, 25);
   bool is_clipped = false;
@@ -31,7 +31,7 @@
   SkBlendMode blend_mode = SkBlendMode::kSrcOver;
 
   SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState();
-  state->SetAll(quad_transform, content_bounds, visible_layer_rect, clip_rect,
+  state->SetAll(quad_transform, content_rect, visible_layer_rect, clip_rect,
                 is_clipped, opacity, blend_mode, sorting_context_id);
   return state;
 }
diff --git a/cc/quads/draw_quad_unittest.cc b/cc/quads/draw_quad_unittest.cc
index fce24b15..7f559054 100644
--- a/cc/quads/draw_quad_unittest.cc
+++ b/cc/quads/draw_quad_unittest.cc
@@ -36,7 +36,7 @@
 
 TEST(DrawQuadTest, CopySharedQuadState) {
   gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0);
-  gfx::Size layer_bounds(26, 28);
+  gfx::Rect layer_rect(26, 28);
   gfx::Rect visible_layer_rect(10, 12, 14, 16);
   gfx::Rect clip_rect(19, 21, 23, 25);
   bool is_clipped = true;
@@ -45,7 +45,7 @@
   int sorting_context_id = 65536;
 
   std::unique_ptr<SharedQuadState> state(new SharedQuadState);
-  state->SetAll(quad_transform, layer_bounds, visible_layer_rect, clip_rect,
+  state->SetAll(quad_transform, layer_rect, visible_layer_rect, clip_rect,
                 is_clipped, opacity, blend_mode, sorting_context_id);
 
   std::unique_ptr<SharedQuadState> copy(new SharedQuadState(*state));
@@ -59,7 +59,7 @@
 
 SharedQuadState* CreateSharedQuadState(RenderPass* render_pass) {
   gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0);
-  gfx::Size layer_bounds(26, 28);
+  gfx::Rect layer_rect(26, 28);
   gfx::Rect visible_layer_rect(10, 12, 14, 16);
   gfx::Rect clip_rect(19, 21, 23, 25);
   bool is_clipped = false;
@@ -68,7 +68,7 @@
   SkBlendMode blend_mode = SkBlendMode::kSrcOver;
 
   SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState();
-  state->SetAll(quad_transform, layer_bounds, visible_layer_rect, clip_rect,
+  state->SetAll(quad_transform, layer_rect, visible_layer_rect, clip_rect,
                 is_clipped, opacity, blend_mode, sorting_context_id);
   return state;
 }
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index fbb43237..54f67f27 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -153,10 +153,6 @@
 
 using RenderPassList = std::vector<std::unique_ptr<RenderPass>>;
 
-// List of pairs of render pass id and filter, sorted by render pass id so that
-// it can be searched using std::lower_bound.
-using RenderPassFilterList = std::vector<std::pair<int, FilterOperations*>>;
-
 }  // namespace cc
 
 #endif  // CC_QUADS_RENDER_PASS_H_
diff --git a/cc/quads/render_pass_unittest.cc b/cc/quads/render_pass_unittest.cc
index 9fced65..485bf71 100644
--- a/cc/quads/render_pass_unittest.cc
+++ b/cc/quads/render_pass_unittest.cc
@@ -61,8 +61,8 @@
          exp_iter != expected->quad_list.cend();
          ++exp_iter, ++act_iter) {
       EXPECT_EQ(exp_iter->rect.ToString(), act_iter->rect.ToString());
-      EXPECT_EQ(exp_iter->shared_quad_state->quad_layer_bounds.ToString(),
-                act_iter->shared_quad_state->quad_layer_bounds.ToString());
+      EXPECT_EQ(exp_iter->shared_quad_state->quad_layer_rect.ToString(),
+                act_iter->shared_quad_state->quad_layer_rect.ToString());
     }
   }
 }
@@ -87,7 +87,7 @@
 
   // Stick a quad in the pass, this should not get copied.
   SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), gfx::Size(), gfx::Rect(), gfx::Rect(),
+  shared_state->SetAll(gfx::Transform(), gfx::Rect(), gfx::Rect(), gfx::Rect(),
                        false, 1, SkBlendMode::kSrcOver, 0);
 
   SolidColorDrawQuad* color_quad =
@@ -135,7 +135,7 @@
 
   // Two quads using one shared state.
   SharedQuadState* shared_state1 = pass->CreateAndAppendSharedQuadState();
-  shared_state1->SetAll(gfx::Transform(), gfx::Size(1, 1), gfx::Rect(),
+  shared_state1->SetAll(gfx::Transform(), gfx::Rect(0, 0, 1, 1), gfx::Rect(),
                         gfx::Rect(), false, 1, SkBlendMode::kSrcOver, 0);
 
   SolidColorDrawQuad* color_quad1 =
@@ -152,7 +152,7 @@
 
   // And two quads using another shared state.
   SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
-  shared_state2->SetAll(gfx::Transform(), gfx::Size(2, 2), gfx::Rect(),
+  shared_state2->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
                         gfx::Rect(), false, 1, SkBlendMode::kSrcOver, 0);
 
   SolidColorDrawQuad* color_quad3 =
@@ -188,8 +188,9 @@
 
   SharedQuadState* contrib_shared_state =
       contrib->CreateAndAppendSharedQuadState();
-  contrib_shared_state->SetAll(gfx::Transform(), gfx::Size(2, 2), gfx::Rect(),
-                               gfx::Rect(), false, 1, SkBlendMode::kSrcOver, 0);
+  contrib_shared_state->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2),
+                               gfx::Rect(), gfx::Rect(), false, 1,
+                               SkBlendMode::kSrcOver, 0);
 
   SolidColorDrawQuad* contrib_quad =
       contrib->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -235,7 +236,7 @@
 
   // A shared state with a quad.
   SharedQuadState* shared_state1 = pass->CreateAndAppendSharedQuadState();
-  shared_state1->SetAll(gfx::Transform(), gfx::Size(1, 1), gfx::Rect(),
+  shared_state1->SetAll(gfx::Transform(), gfx::Rect(0, 0, 1, 1), gfx::Rect(),
                         gfx::Rect(), false, 1, SkBlendMode::kSrcOver, 0);
 
   SolidColorDrawQuad* color_quad1 =
@@ -246,17 +247,17 @@
 
   // A shared state with no quads, they were culled.
   SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
-  shared_state2->SetAll(gfx::Transform(), gfx::Size(2, 2), gfx::Rect(),
+  shared_state2->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
                         gfx::Rect(), false, 1, SkBlendMode::kSrcOver, 0);
 
   // A second shared state with no quads.
   SharedQuadState* shared_state3 = pass->CreateAndAppendSharedQuadState();
-  shared_state3->SetAll(gfx::Transform(), gfx::Size(2, 2), gfx::Rect(),
+  shared_state3->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
                         gfx::Rect(), false, 1, SkBlendMode::kSrcOver, 0);
 
   // A last shared state with a quad again.
   SharedQuadState* shared_state4 = pass->CreateAndAppendSharedQuadState();
-  shared_state4->SetAll(gfx::Transform(), gfx::Size(2, 2), gfx::Rect(),
+  shared_state4->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
                         gfx::Rect(), false, 1, SkBlendMode::kSrcOver, 0);
 
   SolidColorDrawQuad* color_quad2 =
diff --git a/cc/quads/shared_quad_state.cc b/cc/quads/shared_quad_state.cc
index de2d75e7..bc6e15e9 100644
--- a/cc/quads/shared_quad_state.cc
+++ b/cc/quads/shared_quad_state.cc
@@ -28,7 +28,7 @@
 }
 
 void SharedQuadState::SetAll(const gfx::Transform& quad_to_target_transform,
-                             const gfx::Size& quad_layer_bounds,
+                             const gfx::Rect& quad_layer_rect,
                              const gfx::Rect& visible_quad_layer_rect,
                              const gfx::Rect& clip_rect,
                              bool is_clipped,
@@ -36,7 +36,7 @@
                              SkBlendMode blend_mode,
                              int sorting_context_id) {
   this->quad_to_target_transform = quad_to_target_transform;
-  this->quad_layer_bounds = quad_layer_bounds;
+  this->quad_layer_rect = quad_layer_rect;
   this->visible_quad_layer_rect = visible_quad_layer_rect;
   this->clip_rect = clip_rect;
   this->is_clipped = is_clipped;
@@ -47,7 +47,7 @@
 
 void SharedQuadState::AsValueInto(base::trace_event::TracedValue* value) const {
   MathUtil::AddToTracedValue("transform", quad_to_target_transform, value);
-  MathUtil::AddToTracedValue("layer_content_bounds", quad_layer_bounds, value);
+  MathUtil::AddToTracedValue("layer_content_rect", quad_layer_rect, value);
   MathUtil::AddToTracedValue("layer_visible_content_rect",
                              visible_quad_layer_rect, value);
 
diff --git a/cc/quads/shared_quad_state.h b/cc/quads/shared_quad_state.h
index f3758fb..c496b7b3 100644
--- a/cc/quads/shared_quad_state.h
+++ b/cc/quads/shared_quad_state.h
@@ -32,7 +32,7 @@
   ~SharedQuadState();
 
   void SetAll(const gfx::Transform& quad_to_target_transform,
-              const gfx::Size& layer_bounds,
+              const gfx::Rect& layer_rect,
               const gfx::Rect& visible_layer_rect,
               const gfx::Rect& clip_rect,
               bool is_clipped,
@@ -43,8 +43,8 @@
 
   // Transforms quad rects into the target content space.
   gfx::Transform quad_to_target_transform;
-  // The size of the quads' originating layer in the space of the quad rects.
-  gfx::Size quad_layer_bounds;
+  // The rect of the quads' originating layer in the space of the quad rects.
+  gfx::Rect quad_layer_rect;
   // The size of the visible area in the quads' originating layer, in the space
   // of the quad rects.
   gfx::Rect visible_quad_layer_rect;
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index 898328c4..935b9f7 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -361,7 +361,7 @@
 
   SharedQuadState* shared_quad_state =
       color_conversion_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->quad_layer_bounds = output_rect.size();
+  shared_quad_state->quad_layer_rect = output_rect;
   shared_quad_state->visible_quad_layer_rect = output_rect;
   shared_quad_state->opacity = 1.f;
 
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc
index 04cca79..008b668 100644
--- a/cc/surfaces/surface_aggregator_unittest.cc
+++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -1042,7 +1042,7 @@
                                     RenderPass* pass,
                                     const SkBlendMode blend_mode) {
   const gfx::Transform layer_to_target_transform;
-  const gfx::Size layer_bounds(size);
+  const gfx::Rect layer_rect(size);
   const gfx::Rect visible_layer_rect(size);
   const gfx::Rect clip_rect(size);
 
@@ -1051,7 +1051,7 @@
 
   bool force_anti_aliasing_off = false;
   SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
-  sqs->SetAll(layer_to_target_transform, layer_bounds, visible_layer_rect,
+  sqs->SetAll(layer_to_target_transform, layer_rect, visible_layer_rect,
               clip_rect, is_clipped, opacity, blend_mode, 0);
 
   SolidColorDrawQuad* color_quad =
diff --git a/cc/surfaces/surfaces_pixeltest.cc b/cc/surfaces/surfaces_pixeltest.cc
index 0b81474c..8ba7439 100644
--- a/cc/surfaces/surfaces_pixeltest.cc
+++ b/cc/surfaces/surfaces_pixeltest.cc
@@ -51,14 +51,14 @@
     RenderPass* render_pass,
     const gfx::Transform& transform,
     const gfx::Size& size) {
-  const gfx::Size layer_bounds = size;
+  const gfx::Rect layer_rect = gfx::Rect(size);
   const gfx::Rect visible_layer_rect = gfx::Rect(size);
   const gfx::Rect clip_rect = gfx::Rect(size);
   bool is_clipped = false;
   float opacity = 1.f;
   const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
   SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(transform, layer_bounds, visible_layer_rect, clip_rect,
+  shared_state->SetAll(transform, layer_rect, visible_layer_rect, clip_rect,
                        is_clipped, opacity, blend_mode, 0);
   return shared_state;
 }
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc
index f550fcb4..05f329d 100644
--- a/cc/test/render_pass_test_utils.cc
+++ b/cc/test/render_pass_test_utils.cc
@@ -39,7 +39,7 @@
                             const gfx::Rect& rect,
                             SkColor color) {
   SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect.size(), rect, rect, false, 1,
+  shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, 1,
                        SkBlendMode::kSrcOver, 0);
   SolidColorDrawQuad* quad =
       pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -51,7 +51,7 @@
                                    const gfx::Rect& rect,
                                    SkColor color) {
   SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect.size(), rect, rect, true, 1,
+  shared_state->SetAll(gfx::Transform(), rect, rect, rect, true, 1,
                        SkBlendMode::kSrcOver, 0);
   SolidColorDrawQuad* quad =
       pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -64,7 +64,7 @@
                                        SkColor color,
                                        const gfx::Transform& transform) {
   SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(transform, rect.size(), rect, rect, false, 1,
+  shared_state->SetAll(transform, rect, rect, rect, false, 1,
                        SkBlendMode::kSrcOver, 0);
   SolidColorDrawQuad* quad =
       pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -75,8 +75,8 @@
 void AddRenderPassQuad(RenderPass* to_pass, RenderPass* contributing_pass) {
   gfx::Rect output_rect = contributing_pass->output_rect;
   SharedQuadState* shared_state = to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), output_rect.size(), output_rect,
-                       output_rect, false, 1, SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), output_rect, output_rect, output_rect,
+                       false, 1, SkBlendMode::kSrcOver, 0);
   RenderPassDrawQuad* quad =
       to_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
   quad->SetNew(shared_state, output_rect, output_rect, contributing_pass->id, 0,
@@ -91,14 +91,8 @@
                        SkBlendMode blend_mode) {
   gfx::Rect output_rect = contributing_pass->output_rect;
   SharedQuadState* shared_state = to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(transform,
-                       output_rect.size(),
-                       output_rect,
-                       output_rect,
-                       false,
-                       1,
-                       blend_mode,
-                       0);
+  shared_state->SetAll(transform, output_rect, output_rect, output_rect, false,
+                       1, blend_mode, 0);
   RenderPassDrawQuad* quad =
       to_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
   gfx::Size arbitrary_nonzero_size(1, 1);
@@ -167,7 +161,7 @@
   resource_provider->AllocateForTesting(resource8);
 
   SharedQuadState* shared_state = to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect.size(), rect, rect, false, 1,
+  shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, 1,
                        SkBlendMode::kSrcOver, 0);
 
   DebugBorderDrawQuad* debug_border_quad =
@@ -226,7 +220,7 @@
       gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), false, false);
 
   SharedQuadState* shared_state2 = to_pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), rect.size(), rect, rect, false, 1,
+  shared_state->SetAll(gfx::Transform(), rect, rect, rect, false, 1,
                        SkBlendMode::kSrcOver, 0);
 
   TileDrawQuad* tile_quad = to_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
diff --git a/cc/test/surface_aggregator_test_helpers.cc b/cc/test/surface_aggregator_test_helpers.cc
index cb015bc..145e292 100644
--- a/cc/test/surface_aggregator_test_helpers.cc
+++ b/cc/test/surface_aggregator_test_helpers.cc
@@ -35,7 +35,7 @@
   SkBlendMode blend_mode = SkBlendMode::kSrcOver;
 
   SharedQuadState* shared_quad_state = pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(layer_to_target_transform, layer_bounds,
+  shared_quad_state->SetAll(layer_to_target_transform, gfx::Rect(layer_bounds),
                             visible_layer_rect, clip_rect, is_clipped, opacity,
                             blend_mode, 0);
 
@@ -60,8 +60,8 @@
 void AddRenderPassQuad(RenderPass* pass, int render_pass_id) {
   gfx::Rect output_rect = gfx::Rect(0, 0, 5, 5);
   SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->SetAll(gfx::Transform(), output_rect.size(), output_rect,
-                       output_rect, false, 1, SkBlendMode::kSrcOver, 0);
+  shared_state->SetAll(gfx::Transform(), output_rect, output_rect, output_rect,
+                       false, 1, SkBlendMode::kSrcOver, 0);
   RenderPassDrawQuad* quad =
       pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
   quad->SetNew(shared_state, output_rect, output_rect, render_pass_id, 0,
diff --git a/cc/test/surface_hittest_test_helpers.cc b/cc/test/surface_hittest_test_helpers.cc
index 654d6b21..ac18aee 100644
--- a/cc/test/surface_hittest_test_helpers.cc
+++ b/cc/test/surface_hittest_test_helpers.cc
@@ -17,8 +17,8 @@
                            const gfx::Transform& transform,
                            const gfx::Rect& root_rect) {
   SharedQuadState* child_shared_state = pass->CreateAndAppendSharedQuadState();
-  child_shared_state->SetAll(transform, root_rect.size(), root_rect, root_rect,
-                             false, 1.0f, SkBlendMode::kSrcOver, 0);
+  child_shared_state->SetAll(transform, root_rect, root_rect, root_rect, false,
+                             1.0f, SkBlendMode::kSrcOver, 0);
 }
 
 void CreateSolidColorDrawQuad(RenderPass* pass,
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index bb4190b..6965594 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -755,7 +755,7 @@
   int sorting_context_id = 0;
   SharedQuadState* shared_quad_state =
       target_render_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(gfx::Transform(), root_target_rect.size(),
+  shared_quad_state->SetAll(gfx::Transform(), root_target_rect,
                             root_target_rect, root_target_rect, false, opacity,
                             SkBlendMode::kSrcOver, sorting_context_id);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelDefinitions.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelDefinitions.java
index c7842aa..8e66a2e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelDefinitions.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelDefinitions.java
@@ -33,13 +33,17 @@
     static final String CHANNEL_GROUP_ID_GENERAL = "general";
     /**
      * Version number identifying the current set of channels. This must be incremented whenever
-     * any channels are added or removed from the set of channels created in
-     * {@link ChannelsInitializer#initializeStartupChannels()}.
+     * the set of channels returned by {@link #getStartupChannelIds()} or
+     * {@link #getLegacyChannelIds()} changes.
      */
     static final int CHANNELS_VERSION = 0;
 
-    // To define a new channel, add the channel ID to this StringDef and add a new entry to
-    // PredefinedChannels.MAP below with the appropriate channel parameters.
+    /**
+     * To define a new channel, add the channel ID to this StringDef and add a new entry to
+     * PredefinedChannels.MAP below with the appropriate channel parameters.
+     * To remove an existing channel, remove the ID from this StringDef, remove its entry from
+     * Predefined Channels.MAP, and add the ID to the LEGACY_CHANNELS_ID array below.
+     */
     @StringDef({CHANNEL_ID_BROWSER, CHANNEL_ID_DOWNLOADS, CHANNEL_ID_INCOGNITO, CHANNEL_ID_MEDIA,
             CHANNEL_ID_SITES})
     @Retention(RetentionPolicy.SOURCE)
@@ -55,6 +59,7 @@
         /**
          * The set of predefined channels to be initialized on startup. CHANNELS_VERSION must be
          * incremented every time an entry is modified, removed or added to this map.
+         * If an entry is removed from here then it must be added to the LEGACY_CHANNEL_IDs array.
          */
         static final Map<String, Channel> MAP;
         static {
@@ -83,6 +88,13 @@
         }
     }
 
+    /**
+     * When channels become deprecated they should be removed from PredefinedChannels and their ids
+     * added to this array so they can be deleted on upgrade.
+     * We also want to keep track of old channel ids so they aren't accidentally reused.
+     */
+    private static final String[] LEGACY_CHANNEL_IDS = {};
+
     // Map defined in static inner class so it's only initialized lazily.
     private static class PredefinedChannelGroups {
         static final Map<String, ChannelGroup> MAP;
@@ -95,11 +107,22 @@
         }
     }
 
+    /**
+     * @return A set of channel ids of channels that should be initialized on startup.
+     */
     Set<String> getStartupChannelIds() {
         // CHANNELS_VERSION must be incremented if the set of channels returned here changes.
         return PredefinedChannels.MAP.keySet();
     }
 
+    /**
+     * @return An array of old ChannelIds that may have been returned by
+     * {@link #getStartupChannelIds} in the past, but are no longer in use.
+     */
+    public String[] getLegacyChannelIds() {
+        return LEGACY_CHANNEL_IDS;
+    }
+
     ChannelGroup getChannelGroupFromId(Channel channel) {
         return PredefinedChannelGroups.MAP.get(channel.mGroupId);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelsInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelsInitializer.java
index 526295fd..299189c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelsInitializer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelsInitializer.java
@@ -28,8 +28,12 @@
         }
     }
 
-    void deleteAllChannels() {
-        for (String channelId : mNotificationManager.getNotificationChannelIds()) {
+    /**
+     * Cleans up any old channels that are no longer required from previous versions of the app.
+     * It's safe to call this multiple times since deleting an already-deleted channel is a no-op.
+     */
+    void deleteLegacyChannels() {
+        for (String channelId : mChannelDefinitions.getLegacyChannelIds()) {
             mNotificationManager.deleteNotificationChannel(channelId);
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelsUpdater.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelsUpdater.java
index 19c16eb..8a7a1a95 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelsUpdater.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/ChannelsUpdater.java
@@ -59,8 +59,7 @@
     public void updateChannels() {
         if (!mIsAtLeastO) return;
         assert mChannelsInitializer != null;
-        // TODO(crbug.com/710843) Iterate through existing channels instead of deleting them all.
-        mChannelsInitializer.deleteAllChannels();
+        mChannelsInitializer.deleteLegacyChannels();
         mChannelsInitializer.initializeStartupChannels();
         storeChannelVersionInPrefs();
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
index fe352e8..2544485 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
@@ -25,6 +25,8 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
 import org.chromium.chrome.browser.util.MathUtils;
+import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
+import org.chromium.chrome.browser.widget.bottomsheet.EmptyBottomSheetObserver;
 import org.chromium.ui.UiUtils;
 
 /**
@@ -154,7 +156,6 @@
      * @param hasFocus Whether the URL field has gained focus.
      */
     public void finishUrlFocusChange(boolean hasFocus) {
-        final WindowDelegate windowDelegate = getWindowDelegate();
         if (!hasFocus) {
             // Remove the selection from the url text.  The ending selection position
             // will determine the scroll position when the url field is restored.  If
@@ -184,32 +185,15 @@
             }, KEYBOARD_HIDE_DELAY_MS);
             // Convert the keyboard back to resize mode (delay the change for an arbitrary amount
             // of time in hopes the keyboard will be completely hidden before making this change).
-            if (mKeyboardResizeModeTask == null
-                    && windowDelegate.getWindowSoftInputMode()
-                            != WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
-                mKeyboardResizeModeTask = new Runnable() {
-                    @Override
-                    public void run() {
-                        windowDelegate.setWindowSoftInputMode(
-                                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
-                        mKeyboardResizeModeTask = null;
-                    }
-                };
-                postDelayed(mKeyboardResizeModeTask, KEYBOARD_MODE_CHANGE_DELAY_MS);
+            // If Chrome Home is enabled, it will handle its own mode changes.
+            if (mBottomSheet == null) {
+                setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE, true);
             }
             mUrlActionsContainer.setVisibility(GONE);
         } else {
-            if (mKeyboardResizeModeTask != null) {
-                removeCallbacks(mKeyboardResizeModeTask);
-                mKeyboardResizeModeTask = null;
-            }
-            // TODO(mdjones): SOFT_INPUT_ADJUST_NOTHING breaks omnibox suggestions but fixes a
-            // content jumping bug in Chrome Home. See https://crbug.com/706918
-            int softInputMode = mBottomSheet != null
-                    ? WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
-                    : WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
-            if (windowDelegate.getWindowSoftInputMode() != softInputMode) {
-                windowDelegate.setWindowSoftInputMode(softInputMode);
+            // If Chrome Home is enabled, it will handle its own mode changes.
+            if (mBottomSheet == null) {
+                setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN, false);
             }
             UiUtils.showKeyboard(mUrlBar);
             // As the position of the navigation icon has changed, ensure the suggestions are
@@ -316,4 +300,54 @@
         super.setLayoutDirection(layoutDirection);
         updateIncognitoBadgePadding();
     }
+
+    /**
+     * @param softInputMode The software input resize mode.
+     * @param delay Delay the change in input mode.
+     */
+    private void setSoftInputMode(final int softInputMode, boolean delay) {
+        final WindowDelegate delegate = getWindowDelegate();
+
+        if (mKeyboardResizeModeTask != null) {
+            removeCallbacks(mKeyboardResizeModeTask);
+            mKeyboardResizeModeTask = null;
+        }
+
+        if (delegate == null || delegate.getWindowSoftInputMode() == softInputMode) return;
+
+        if (delay) {
+            mKeyboardResizeModeTask = new Runnable() {
+                @Override
+                public void run() {
+                    delegate.setWindowSoftInputMode(softInputMode);
+                    mKeyboardResizeModeTask = null;
+                }
+            };
+            postDelayed(mKeyboardResizeModeTask, KEYBOARD_MODE_CHANGE_DELAY_MS);
+        } else {
+            delegate.setWindowSoftInputMode(softInputMode);
+        }
+    }
+
+    @Override
+    public void setBottomSheet(BottomSheet sheet) {
+        super.setBottomSheet(sheet);
+
+        sheet.addObserver(new EmptyBottomSheetObserver() {
+            @Override
+            public void onSheetStateChanged(int state) {
+                switch (state) {
+                    case BottomSheet.SHEET_STATE_FULL:
+                        setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN, false);
+                        break;
+                    case BottomSheet.SHEET_STATE_PEEK:
+                        setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE, true);
+                        break;
+                    default:
+                        setSoftInputMode(
+                                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING, false);
+                }
+            }
+        });
+    }
 }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index b46689f..a24e67e 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1664,6 +1664,7 @@
   "junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerServiceLifecycleTest.java",
   "junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerNotificationTest.java",
   "junit/src/org/chromium/chrome/browser/metrics/VariationsSessionTest.java",
+  "junit/src/org/chromium/chrome/browser/notifications/ChannelDefinitionsTest.java",
   "junit/src/org/chromium/chrome/browser/notifications/ChannelsInitializerTest.java",
   "junit/src/org/chromium/chrome/browser/notifications/ChannelsUpdaterTest.java",
   "junit/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeUnitTest.java",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelDefinitionsTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelDefinitionsTest.java
new file mode 100644
index 0000000..26e4098
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelDefinitionsTest.java
@@ -0,0 +1,27 @@
+// 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.notifications;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.everyItem;
+import static org.hamcrest.Matchers.isIn;
+import static org.hamcrest.Matchers.not;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+/**
+ * Java unit tests for ChannelDefinitions.
+ */
+@RunWith(BlockJUnit4ClassRunner.class)
+public class ChannelDefinitionsTest {
+    @Test
+    public void testNoOverlapBetweenStartupAndLegacyChannelIds() throws Exception {
+        ChannelDefinitions channelDefinitions = new ChannelDefinitions();
+        assertThat(channelDefinitions.getStartupChannelIds(),
+                everyItem(not(isIn(channelDefinitions.getLegacyChannelIds()))));
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelsInitializerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelsInitializerTest.java
index 5e61cd6..af09641 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelsInitializerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelsInitializerTest.java
@@ -5,7 +5,10 @@
 package org.chromium.chrome.browser.notifications;
 
 import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertThat;
 
 import android.app.NotificationManager;
@@ -33,6 +36,21 @@
     }
 
     @Test
+    public void testDeleteLegacyChannels_noopOnCurrentDefinitions() throws Exception {
+        assertThat(mMockNotificationManager.getNotificationChannelIds(), is(empty()));
+
+        mChannelsInitializer.deleteLegacyChannels();
+        assertThat(mMockNotificationManager.getNotificationChannelIds(), is(empty()));
+
+        mChannelsInitializer.initializeStartupChannels();
+        assertThat(mMockNotificationManager.getNotificationChannelIds(), is(not(empty())));
+
+        int nChannels = mMockNotificationManager.getNotificationChannelIds().size();
+        mChannelsInitializer.deleteLegacyChannels();
+        assertThat(mMockNotificationManager.getNotificationChannelIds(), hasSize(nChannels));
+    }
+
+    @Test
     public void testInitializeStartupChannels() throws Exception {
         mChannelsInitializer.initializeStartupChannels();
         assertThat(mMockNotificationManager.getNotificationChannelIds(),
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelsUpdaterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelsUpdaterTest.java
index 7e725b9e..03f85d0 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelsUpdaterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/notifications/ChannelsUpdaterTest.java
@@ -92,10 +92,17 @@
         assertThat(mMockSharedPreferences.getInt(ChannelsUpdater.CHANNELS_VERSION_KEY, -1), is(21));
     }
 
-    // Suppressed in order to construct the old channels with invalid parameters.
+    // Warnings suppressed in order to construct the legacy channels with invalid channel ids.
     @SuppressWarnings("WrongConstant")
     @Test
     public void testUpdateChannels_deletesLegacyChannelsAndCreatesExpectedOnes() throws Exception {
+        // Fake some legacy channels (since we don't have any yet).
+        ChannelDefinitions channelDefinitions = new ChannelDefinitions() {
+            @Override
+            public String[] getLegacyChannelIds() {
+                return new String[] {"OldChannel", "AnotherOldChannel"};
+            }
+        };
         mMockNotificationManager.createNotificationChannel(new ChannelDefinitions.Channel(
                 "OldChannel", 8292304, NotificationManager.IMPORTANCE_HIGH,
                 ChannelDefinitions.CHANNEL_GROUP_ID_GENERAL));
@@ -105,8 +112,8 @@
         assertThat(mMockNotificationManager.getNotificationChannelIds(),
                 containsInAnyOrder("OldChannel", "AnotherOldChannel"));
 
-        ChannelsUpdater updater = new ChannelsUpdater(
-                true /* isAtLeastO */, mMockSharedPreferences, mChannelsInitializer, 12);
+        ChannelsUpdater updater = new ChannelsUpdater(true /* isAtLeastO */, mMockSharedPreferences,
+                new ChannelsInitializer(mMockNotificationManager, channelDefinitions), 12);
         updater.updateChannels();
 
         assertThat(mMockNotificationManager.getNotificationChannelIds(),
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.h b/chrome/browser/autofill/android/personal_data_manager_android.h
index 801e8b6c..996bf75 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.h
+++ b/chrome/browser/autofill/android/personal_data_manager_android.h
@@ -11,7 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
-#include "components/payments/core/address_normalizer.h"
+#include "components/payments/core/address_normalizer_impl.h"
 
 namespace autofill {
 
@@ -360,7 +360,7 @@
   PersonalDataManager* personal_data_manager_;
 
   // The address validator used to normalize addresses.
-  payments::AddressNormalizer address_normalizer_;
+  payments::AddressNormalizerImpl address_normalizer_;
 
   DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerAndroid);
 };
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index e67e5992a..42a3399 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include "ash/shell.h"
-#include "ash/wallpaper/wallpaper_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_state_aura.h"
 #include "ash/wm/window_util.h"
@@ -510,9 +509,6 @@
     authenticator_->SetConsumer(NULL);
   ClearErrors();
 
-  VLOG(1) << "Moving wallpaper to unlocked container";
-  ash::Shell::Get()->wallpaper_controller()->MoveToUnlockedContainer();
-
   screen_locker_ = NULL;
   bool state = false;
   VLOG(1) << "Emitting SCREEN_LOCK_STATE_CHANGED with state=" << state;
@@ -544,9 +540,6 @@
           << delta.InSecondsF() << " second(s)";
   UMA_HISTOGRAM_TIMES("ScreenLocker.ScreenLockTime", delta);
 
-  VLOG(1) << "Moving wallpaper to locked container";
-  ash::Shell::Get()->wallpaper_controller()->MoveToLockedContainer();
-
   bool state = true;
   VLOG(1) << "Emitting SCREEN_LOCK_STATE_CHANGED with state=" << state;
   content::NotificationService::current()->Notify(
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
index 4c494a9..f2ed9636 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "ash/shell.h"
-#include "ash/wallpaper/wallpaper_controller.h"
 #include "base/memory/ptr_util.h"
 #include "base/rand_util.h"
 #include "base/values.h"
@@ -363,9 +362,6 @@
       ->NotifySupervisedUserCreationStarted();
   manager_signin_in_progress_ = false;
   DCHECK(controller_.get());
-  // For manager user, move wallpaper to locked container so that windows
-  // created during the user image picker step are below it.
-  ash::Shell::Get()->wallpaper_controller()->MoveToLockedContainer();
 
   controller_->SetManagerProfile(manager_profile);
   if (view_)
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
index c4fa3aa..6db2b1af 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
@@ -11,7 +11,6 @@
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/system/tray/system_tray.h"
-#include "ash/wallpaper/wallpaper_controller.h"
 #include "ash/wallpaper/wallpaper_delegate.h"
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -537,14 +536,7 @@
 }
 
 void LoginDisplayHostImpl::Finalize() {
-  DVLOG(1) << "Session starting";
-  // When adding another user into the session, we defer the wallpaper's
-  // animation in order to prevent the flashing of the previous user's windows.
-  // See crbug.com/541864.
-  if (ash::ShellPort::HasInstance() &&
-      finalize_animation_type_ != ANIMATION_ADD_USER) {
-    ash::Shell::Get()->wallpaper_controller()->MoveToUnlockedContainer();
-  }
+  DVLOG(1) << "Finalizing LoginDisplayHost. User session starting";
 
   switch (finalize_animation_type_) {
     case ANIMATION_NONE:
@@ -566,6 +558,7 @@
       // animation (which is done by UserSwitchAnimatorChromeOS) is finished.
       // This is to guarantee OnUserSwitchAnimationFinished() is called before
       // LoginDisplayHost deletes itself.
+      // See crbug.com/541864.
       break;
     default:
       break;
@@ -655,8 +648,6 @@
         ash::Shell::GetPrimaryRootWindow(),
         ash::kShellWindowId_LockScreenContainersContainer);
     lock_container->layer()->SetOpacity(1.0);
-
-    ash::Shell::Get()->wallpaper_controller()->MoveToLockedContainer();
   } else {
     NOTIMPLEMENTED();
   }
@@ -911,13 +902,6 @@
                       content::NotificationService::AllSources());
   } else if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED &&
              user_manager::UserManager::Get()->IsCurrentUserNew()) {
-    if (!ash_util::IsRunningInMash()) {
-      // For new user, move wallpaper to lock container so that windows created
-      // during the user image picker step are below it.
-      ash::Shell::Get()->wallpaper_controller()->MoveToLockedContainer();
-    } else {
-      NOTIMPLEMENTED();
-    }
     registrar_.Remove(this,
                       chrome::NOTIFICATION_LOGIN_USER_CHANGED,
                       content::NotificationService::AllSources());
@@ -1042,17 +1026,9 @@
   if (post_quit_task)
     base::MessageLoop::current()->QuitWhenIdle();
 
-  if (!completion_callback_.is_null())
+  if (!completion_callback_.is_null()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                   completion_callback_);
-
-  if (ash::Shell::HasInstance() &&
-      finalize_animation_type_ == ANIMATION_ADD_USER) {
-    if (!ash_util::IsRunningInMash()) {
-      ash::Shell::Get()->wallpaper_controller()->MoveToUnlockedContainer();
-    } else {
-      NOTIMPLEMENTED();
-    }
   }
 }
 
diff --git a/chrome/browser/chromeos/login/ui/login_feedback.cc b/chrome/browser/chromeos/login/ui/login_feedback.cc
index bd60b41..6b216df 100644
--- a/chrome/browser/chromeos/login/ui/login_feedback.cc
+++ b/chrome/browser/chromeos/login/ui/login_feedback.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h"
@@ -17,6 +18,7 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/browser_resources.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
@@ -60,6 +62,8 @@
   explicit FeedbackExtensionLoader(Profile* profile);
   ~FeedbackExtensionLoader() override;
 
+  void Initialize();
+
   void AddOnReadyCallback(const base::Closure& on_ready_callback);
   void RunOnReadyCallbacks();
 
@@ -83,8 +87,10 @@
 // static
 void FeedbackExtensionLoader::Load(Profile* profile,
                                    const base::Closure& on_ready_callback) {
-  if (instance == nullptr)
+  if (instance == nullptr) {
     instance = new FeedbackExtensionLoader(profile);
+    instance->Initialize();
+  }
 
   DCHECK_EQ(instance->profile_, profile);
   DCHECK(!on_ready_callback.is_null());
@@ -92,18 +98,7 @@
 }
 
 FeedbackExtensionLoader::FeedbackExtensionLoader(Profile* profile)
-    : profile_(profile) {
-  extensions::ComponentLoader* component_loader = GetComponentLoader(profile_);
-  DCHECK(!component_loader->Exists(extension_misc::kFeedbackExtensionId))
-      << "Feedback extension should not be loaded in signin profile by default";
-  component_loader->Add(IDR_FEEDBACK_MANIFEST,
-                        base::FilePath(FILE_PATH_LITERAL("feedback")));
-
-  extensions::ProcessManager* pm = GetProcessManager(profile_);
-  pm->AddObserver(this);
-  DCHECK(
-      !pm->GetBackgroundHostForExtension(extension_misc::kFeedbackExtensionId));
-}
+    : profile_(profile) {}
 
 FeedbackExtensionLoader::~FeedbackExtensionLoader() {
   DCHECK_EQ(instance, this);
@@ -113,6 +108,25 @@
   GetComponentLoader(profile_)->Remove(extension_misc::kFeedbackExtensionId);
 }
 
+void FeedbackExtensionLoader::Initialize() {
+  extensions::ProcessManager* pm = GetProcessManager(profile_);
+  pm->AddObserver(this);
+  extensions::ExtensionHost* const host =
+      pm->GetBackgroundHostForExtension(extension_misc::kFeedbackExtensionId);
+  if (host) {
+    OnBackgroundHostCreated(host);
+    if (!host->host_contents()->IsLoading())
+      DocumentOnLoadCompletedInMainFrame();
+    return;
+  }
+
+  extensions::ComponentLoader* component_loader = GetComponentLoader(profile_);
+  if (!component_loader->Exists(extension_misc::kFeedbackExtensionId)) {
+    component_loader->Add(IDR_FEEDBACK_MANIFEST,
+                          base::FilePath(FILE_PATH_LITERAL("feedback")));
+  }
+}
+
 void FeedbackExtensionLoader::AddOnReadyCallback(
     const base::Closure& on_ready_callback) {
   on_ready_callbacks_.push_back(on_ready_callback);
@@ -241,6 +255,12 @@
   api->RequestFeedbackForFlow(
       description_, "Login", GURL(),
       extensions::api::feedback_private::FeedbackFlow::FEEDBACK_FLOW_LOGIN);
+
+  // Make sure there is a feedback app window opened.
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE,
+      base::Bind(&LoginFeedback::EnsureFeedbackUI, weak_factory_.GetWeakPtr()),
+      base::TimeDelta::FromSeconds(1));
 }
 
 void LoginFeedback::OnFeedbackFinished() {
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
index 7ee83e0..8f3fc4cc 100644
--- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
+++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
@@ -122,7 +122,7 @@
 }
 
 void WebrtcAudioPrivateFunction::InitDeviceIDSalt() {
-  device_id_salt_ = GetProfile()->GetResourceContext()->GetMediaDeviceIDSalt();
+  device_id_salt_ = GetProfile()->GetMediaDeviceIDSalt();
 }
 
 std::string WebrtcAudioPrivateFunction::device_id_salt() const {
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
index 53fa13be..4bd6a7bc 100644
--- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
+++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
@@ -155,7 +155,7 @@
         media::AudioDeviceDescription::IsDefaultDevice(it->unique_id)
             ? media::AudioDeviceDescription::kDefaultDeviceId
             : content::GetHMACForMediaDeviceID(
-                  profile()->GetResourceContext()->GetMediaDeviceIDSalt(),
+                  profile()->GetMediaDeviceIDSalt(),
                   url::Origin(source_url_.GetOrigin()), it->unique_id);
 
     EXPECT_EQ(expected_id, sink_id);
@@ -189,8 +189,7 @@
     VLOG(2) << "Trying to find associated sink for device " << raw_device_id;
     GURL origin(GURL("http://www.google.com/").GetOrigin());
     std::string source_id_in_origin = content::GetHMACForMediaDeviceID(
-        profile()->GetResourceContext()->GetMediaDeviceIDSalt(),
-        url::Origin(origin), raw_device_id);
+        profile()->GetMediaDeviceIDSalt(), url::Origin(origin), raw_device_id);
 
     base::ListValue parameters;
     parameters.AppendString(origin.spec());
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
index 2b55079b..55c77226 100644
--- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -351,7 +351,8 @@
     const content::GlobalRequestID& request_id,
     ResourceType resource_type,
     bool was_cached,
-    bool used_data_reduction_proxy,
+    std::unique_ptr<data_reduction_proxy::DataReductionProxyData>
+        data_reduction_proxy_data,
     int net_error,
     int64_t total_received_bytes,
     int64_t raw_body_bytes,
@@ -380,9 +381,10 @@
       page_load_metrics::MetricsWebContentsObserver::FromWebContents(
           web_contents);
   if (metrics_observer) {
-    metrics_observer->OnRequestComplete(
-        request_id, resource_type, was_cached, used_data_reduction_proxy,
-        raw_body_bytes, original_content_length, request_creation_time);
+    metrics_observer->OnRequestComplete(request_id, resource_type, was_cached,
+                                        std::move(data_reduction_proxy_data),
+                                        raw_body_bytes, original_content_length,
+                                        request_creation_time);
   }
 }
 
@@ -823,9 +825,12 @@
 
   data_reduction_proxy::DataReductionProxyData* data =
       data_reduction_proxy::DataReductionProxyData::GetData(*url_request);
-  bool used_data_reduction_proxy = data && data->used_data_reduction_proxy();
+  std::unique_ptr<data_reduction_proxy::DataReductionProxyData>
+      data_reduction_proxy_data;
+  if (data)
+    data_reduction_proxy_data = data->DeepCopy();
   int64_t original_content_length =
-      used_data_reduction_proxy
+      data && data->used_data_reduction_proxy()
           ? data_reduction_proxy::util::CalculateEffectiveOCL(*url_request)
           : url_request->GetRawBodyBytes();
 
@@ -834,8 +839,9 @@
       base::BindOnce(&NotifyUIThreadOfRequestComplete,
                      info->GetWebContentsGetterForRequest(), url_request->url(),
                      info->GetGlobalRequestID(), info->GetResourceType(),
-                     url_request->was_cached(), used_data_reduction_proxy,
-                     net_error, url_request->GetTotalReceivedBytes(),
+                     url_request->was_cached(),
+                     base::Passed(&data_reduction_proxy_data), net_error,
+                     url_request->GetTotalReceivedBytes(),
                      url_request->GetRawBodyBytes(), original_content_length,
                      url_request->creation_time(),
                      base::TimeTicks::Now() - url_request->creation_time()));
diff --git a/chrome/browser/media/media_device_id_salt.cc b/chrome/browser/media/media_device_id_salt.cc
index f8fcfcf..a8702e2 100644
--- a/chrome/browser/media/media_device_id_salt.cc
+++ b/chrome/browser/media/media_device_id_salt.cc
@@ -8,8 +8,8 @@
 #include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/resource_context.h"
 
 using content::BrowserThread;
 
@@ -19,18 +19,13 @@
   media_device_id_salt_.Init(prefs::kMediaDeviceIdSalt, pref_service);
   if (media_device_id_salt_.GetValue().empty()) {
     media_device_id_salt_.SetValue(
-        content::ResourceContext::CreateRandomMediaDeviceIDSalt());
+        content::BrowserContext::CreateRandomMediaDeviceIDSalt());
   }
 }
 
 MediaDeviceIDSalt::~MediaDeviceIDSalt() {
 }
 
-void MediaDeviceIDSalt::ShutdownOnUIThread() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  media_device_id_salt_.Destroy();
-}
-
 std::string MediaDeviceIDSalt::GetSalt() const {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return media_device_id_salt_.GetValue();
@@ -44,5 +39,5 @@
 void MediaDeviceIDSalt::Reset(PrefService* pref_service) {
   pref_service->SetString(
       prefs::kMediaDeviceIdSalt,
-      content::ResourceContext::CreateRandomMediaDeviceIDSalt());
+      content::BrowserContext::CreateRandomMediaDeviceIDSalt());
 }
diff --git a/chrome/browser/media/media_device_id_salt.h b/chrome/browser/media/media_device_id_salt.h
index 8db2731..698f398 100644
--- a/chrome/browser/media/media_device_id_salt.h
+++ b/chrome/browser/media/media_device_id_salt.h
@@ -23,7 +23,6 @@
 class MediaDeviceIDSalt : public base::RefCountedThreadSafe<MediaDeviceIDSalt> {
  public:
   explicit MediaDeviceIDSalt(PrefService* pref_service);
-  void ShutdownOnUIThread();
 
   std::string GetSalt() const;
 
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 a589846..3e41fa8 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -256,7 +256,8 @@
     const content::GlobalRequestID& request_id,
     content::ResourceType resource_type,
     bool was_cached,
-    bool used_data_reduction_proxy,
+    std::unique_ptr<data_reduction_proxy::DataReductionProxyData>
+        data_reduction_proxy_data,
     int64_t raw_body_bytes,
     int64_t original_content_length,
     base::TimeTicks creation_time) {
@@ -264,8 +265,8 @@
       GetTrackerOrNullForRequest(request_id, resource_type, creation_time);
   if (tracker) {
     ExtraRequestInfo extra_request_info(
-        was_cached, raw_body_bytes, used_data_reduction_proxy,
-        was_cached ? 0 : original_content_length);
+        was_cached, raw_body_bytes, was_cached ? 0 : original_content_length,
+        std::move(data_reduction_proxy_data));
     tracker->OnLoadedResource(extra_request_info);
   }
 }
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
index f9e9587..3096854 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -13,6 +13,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
 #include "chrome/common/page_load_metrics/page_load_timing.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -76,13 +77,15 @@
 
   // A resource request completed on the IO thread. This method is invoked on
   // the UI thread.
-  void OnRequestComplete(const content::GlobalRequestID& request_id,
-                         content::ResourceType resource_type,
-                         bool was_cached,
-                         bool used_data_reduction_proxy,
-                         int64_t raw_body_bytes,
-                         int64_t original_content_length,
-                         base::TimeTicks creation_time);
+  void OnRequestComplete(
+      const content::GlobalRequestID& request_id,
+      content::ResourceType resource_type,
+      bool was_cached,
+      std::unique_ptr<data_reduction_proxy::DataReductionProxyData>
+          data_reduction_proxy_data,
+      int64_t raw_body_bytes,
+      int64_t original_content_length,
+      base::TimeTicks creation_time);
 
   // Invoked on navigations where a navigation delay was added by the
   // DelayNavigationThrottle. This is a temporary method that will be removed
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
index ac8a004..db9a01ca 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
@@ -418,12 +418,12 @@
   page_load_metrics::ExtraRequestInfo resources[] = {
       // Cached request.
       {true /*was_cached*/, 1024 * 20 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       0 /* original_network_content_length */},
+       0 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
       // Uncached non-proxied request.
       {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       1024 * 40 /* original_network_content_length */},
+       1024 * 40 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
   };
 
   int64_t network_bytes = 0;
@@ -504,12 +504,12 @@
   page_load_metrics::ExtraRequestInfo resources[] = {
       // Cached request.
       {true /*was_cached*/, 1024 * 20 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       0 /* original_network_content_length */},
+       0 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
       // Uncached non-proxied request.
       {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       1024 * 40 /* original_network_content_length */},
+       1024 * 40 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
   };
 
   int64_t network_bytes = 0;
@@ -584,17 +584,17 @@
   page_load_metrics::ExtraRequestInfo resources[] = {
       // Cached request.
       {true /*was_cached*/, 1024 * 20 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       0 /* original_network_content_length */},
+       0 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
       // Uncached non-proxied request.
       {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       1024 * 40 /* original_network_content_length */},
+       1024 * 40 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
   };
 
   int64_t network_bytes = 0;
   int64_t cache_bytes = 0;
-  for (auto request : resources) {
+  for (const auto& request : resources) {
     SimulateLoadedResource(request);
     if (!request.was_cached) {
       network_bytes += request.raw_body_bytes;
diff --git a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc
index 4dafee81..c9e3c305 100644
--- a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc
@@ -174,7 +174,7 @@
   // notification, so we send a pingback with data collected up to this point.
   if (info.did_commit) {
     RecordPageSizeUMA();
-    SendPingback(timing, info);
+    SendPingback(timing, info, true /* app_background_occurred */);
   }
   return STOP_OBSERVING;
 }
@@ -183,7 +183,7 @@
     const page_load_metrics::PageLoadTiming& timing,
     const page_load_metrics::PageLoadExtraInfo& info) {
   RecordPageSizeUMA();
-  SendPingback(timing, info);
+  SendPingback(timing, info, false /* app_background_occurred */);
 }
 
 void DataReductionProxyMetricsObserver::RecordPageSizeUMA() const {
@@ -271,7 +271,8 @@
 
 void DataReductionProxyMetricsObserver::SendPingback(
     const page_load_metrics::PageLoadTiming& timing,
-    const page_load_metrics::PageLoadExtraInfo& info) {
+    const page_load_metrics::PageLoadExtraInfo& info,
+    bool app_background_occurred) {
   // TODO(ryansturm): Move to OnFirstBackgroundEvent to handle some fast
   // shutdown cases. crbug.com/618072
   if (!browser_context_ || !data_)
@@ -325,7 +326,7 @@
       first_image_paint, first_contentful_paint,
       experimental_first_meaningful_paint,
       parse_blocked_on_script_load_duration, parse_stop, network_bytes_,
-      original_network_bytes_);
+      original_network_bytes_, app_background_occurred);
   GetPingbackClient()->SendPingback(*data_, data_reduction_proxy_timing);
 }
 
@@ -419,13 +420,20 @@
 
 void DataReductionProxyMetricsObserver::OnLoadedResource(
     const page_load_metrics::ExtraRequestInfo& extra_request_info) {
+  if (extra_request_info.data_reduction_proxy_data &&
+      extra_request_info.data_reduction_proxy_data->lofi_received()) {
+    data_->set_lofi_received(true);
+  }
   if (extra_request_info.was_cached)
     return;
   original_network_bytes_ += extra_request_info.original_network_content_length;
   network_bytes_ += extra_request_info.raw_body_bytes;
   num_network_resources_++;
-  if (!extra_request_info.data_reduction_proxy_used)
+  if (!extra_request_info.data_reduction_proxy_data ||
+      !extra_request_info.data_reduction_proxy_data
+           ->used_data_reduction_proxy()) {
     return;
+  }
   num_data_reduction_proxy_resources_++;
   network_bytes_proxied_ += extra_request_info.raw_body_bytes;
 }
diff --git a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.h b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.h
index 19b92c1..7e58d4c 100644
--- a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.h
@@ -110,7 +110,8 @@
  private:
   // Sends the page load information to the pingback client.
   void SendPingback(const page_load_metrics::PageLoadTiming& timing,
-                    const page_load_metrics::PageLoadExtraInfo& info);
+                    const page_load_metrics::PageLoadExtraInfo& info,
+                    bool app_background_occurred);
 
   // Records UMA of page size when the observer is about to be deleted.
   void RecordPageSizeUMA() const;
diff --git a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_unittest.cc
index a0fe3c6..fbaeae30 100644
--- a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_unittest.cc
@@ -62,12 +62,17 @@
     timing_.reset(
         new data_reduction_proxy::DataReductionProxyPageLoadTiming(timing));
     send_pingback_called_ = true;
+    data_ = data.DeepCopy();
   }
 
   data_reduction_proxy::DataReductionProxyPageLoadTiming* timing() const {
     return timing_.get();
   }
 
+  const data_reduction_proxy::DataReductionProxyData& data() const {
+    return *data_;
+  }
+
   bool send_pingback_called() const { return send_pingback_called_; }
 
   void Reset() {
@@ -78,6 +83,7 @@
  private:
   std::unique_ptr<data_reduction_proxy::DataReductionProxyPageLoadTiming>
       timing_;
+  std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data_;
   bool send_pingback_called_;
 
   DISALLOW_COPY_AND_ASSIGN(TestPingbackClient);
@@ -195,6 +201,11 @@
                        pingback_client_->timing()->first_image_paint);
   }
 
+  void ValidateLoFiInPingback(bool lofi_expected) {
+    EXPECT_TRUE(pingback_client_->send_pingback_called());
+    EXPECT_EQ(lofi_expected, pingback_client_->data().lofi_received());
+  }
+
   void ValidateHistograms() {
     ValidateHistogramsForSuffix(
         internal::kHistogramDOMContentLoadedEventFiredSuffix,
@@ -397,6 +408,25 @@
   timing_.document_timing.load_event_start = base::nullopt;
   RunTestAndNavigateToUntrackedUrl(true, false);
   ValidateTimes();
+  ValidateLoFiInPingback(false);
+
+  ResetTest();
+
+  std::unique_ptr<DataReductionProxyData> data =
+      base::MakeUnique<DataReductionProxyData>();
+  data->set_used_data_reduction_proxy(true);
+  data->set_lofi_received(true);
+
+  // Verify LoFi is tracked when a LoFi response is received.
+  page_load_metrics::ExtraRequestInfo resource = {
+      true /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
+      0 /* original_network_content_length */, std::move(data)};
+
+  RunTest(true, false);
+  SimulateLoadedResource(resource);
+  NavigateToUntrackedUrl();
+  ValidateTimes();
+  ValidateLoFiInPingback(true);
 
   ResetTest();
   // Verify that when data reduction proxy was not used, SendPingback is not
@@ -418,24 +448,26 @@
 
   RunTest(true, false);
 
+  std::unique_ptr<DataReductionProxyData> data =
+      base::MakeUnique<DataReductionProxyData>();
+  data->set_used_data_reduction_proxy(true);
+
   // Prepare 4 resources of varying size and configurations.
   page_load_metrics::ExtraRequestInfo resources[] = {
       // Cached request.
       {true /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       0 /* original_network_content_length */},
+       0 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
       // Uncached non-proxied request.
       {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       1024 * 40 /* original_network_content_length */},
+       1024 * 40 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
       // Uncached proxied request with .1 compression ratio.
       {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-       true /* data_reduction_proxy_used*/,
-       1024 * 40 * 10 /* original_network_content_length */},
+       1024 * 40 * 10 /* original_network_content_length */, data->DeepCopy()},
       // Uncached proxied request with .5 compression ratio.
       {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-       true /* data_reduction_proxy_used*/,
-       1024 * 40 * 5 /* original_network_content_length */},
+       1024 * 40 * 5 /* original_network_content_length */, std::move(data)},
   };
 
   int network_resources = 0;
@@ -443,14 +475,15 @@
   int64_t network_bytes = 0;
   int64_t drp_bytes = 0;
   int64_t ocl_bytes = 0;
-  for (auto request : resources) {
+  for (const auto& request : resources) {
     SimulateLoadedResource(request);
     if (!request.was_cached) {
       network_bytes += request.raw_body_bytes;
       ocl_bytes += request.original_network_content_length;
       ++network_resources;
     }
-    if (request.data_reduction_proxy_used) {
+    if (request.data_reduction_proxy_data &&
+        request.data_reduction_proxy_data->used_data_reduction_proxy()) {
       drp_bytes += request.raw_body_bytes;
       ++drp_resources;
     }
@@ -467,24 +500,26 @@
 
   RunTest(true, false);
 
+  std::unique_ptr<DataReductionProxyData> data =
+      base::MakeUnique<DataReductionProxyData>();
+  data->set_used_data_reduction_proxy(true);
+
   // Prepare 4 resources of varying size and configurations.
   page_load_metrics::ExtraRequestInfo resources[] = {
       // Cached request.
       {true /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       0 /* original_network_content_length */},
+       0 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
       // Uncached non-proxied request.
       {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-       false /* data_reduction_proxy_used*/,
-       1024 * 40 /* original_network_content_length */},
+       1024 * 40 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */},
       // Uncached proxied request with .1 compression ratio.
       {false /*was_cached*/, 1024 * 40 * 10 /* raw_body_bytes */,
-       true /* data_reduction_proxy_used*/,
-       1024 * 40 /* original_network_content_length */},
+       1024 * 40 /* original_network_content_length */, data->DeepCopy()},
       // Uncached proxied request with .5 compression ratio.
       {false /*was_cached*/, 1024 * 40 * 5 /* raw_body_bytes */,
-       true /* data_reduction_proxy_used*/,
-       1024 * 40 /* original_network_content_length */},
+       1024 * 40 /* original_network_content_length */, std::move(data)},
   };
 
   int network_resources = 0;
@@ -492,14 +527,15 @@
   int64_t network_bytes = 0;
   int64_t drp_bytes = 0;
   int64_t ocl_bytes = 0;
-  for (auto request : resources) {
+  for (const auto& request : resources) {
     SimulateLoadedResource(request);
     if (!request.was_cached) {
       network_bytes += request.raw_body_bytes;
       ocl_bytes += request.original_network_content_length;
       ++network_resources;
     }
-    if (request.data_reduction_proxy_used) {
+    if (request.data_reduction_proxy_data &&
+        request.data_reduction_proxy_data->used_data_reduction_proxy()) {
       drp_bytes += request.raw_body_bytes;
       ++drp_resources;
     }
diff --git a/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer_unittest.cc
index 50eb3f8..c64186d 100644
--- a/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/media_page_load_metrics_observer_unittest.cc
@@ -57,23 +57,23 @@
     page_load_metrics::ExtraRequestInfo resources[] = {
         // Cached request.
         {true /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-         false /* data_reduction_proxy_used*/,
-         0 /* original_network_content_length */},
+         0 /* original_network_content_length */,
+         nullptr /* data_reduction_proxy_data */},
         // Uncached non-proxied request.
         {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-         false /* data_reduction_proxy_used*/,
-         1024 * 40 /* original_network_content_length */},
+         1024 * 40 /* original_network_content_length */,
+         nullptr /* data_reduction_proxy_data */},
         // Uncached proxied request with .1 compression ratio.
         {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-         false /* data_reduction_proxy_used*/,
-         1024 * 40 /* original_network_content_length */},
+         1024 * 40 /* original_network_content_length */,
+         nullptr /* data_reduction_proxy_data */},
         // Uncached proxied request with .5 compression ratio.
         {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-         false /* data_reduction_proxy_used*/,
-         1024 * 40 /* original_network_content_length */},
+         1024 * 40 /* original_network_content_length */,
+         nullptr /* data_reduction_proxy_data */},
     };
 
-    for (auto request : resources) {
+    for (const auto& request : resources) {
       SimulateLoadedResource(request);
       if (!request.was_cached) {
         network_bytes_ += request.raw_body_bytes;
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc
index 72e61bb..17313de 100644
--- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc
+++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/page_load_metrics/page_load_metrics_embedder_interface.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
 #include "chrome/common/page_load_metrics/page_load_metrics_messages.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -150,10 +151,14 @@
 
 void PageLoadMetricsObserverTestHarness::SimulateLoadedResource(
     const ExtraRequestInfo& info) {
-  observer_->OnRequestComplete(
-      content::GlobalRequestID(), content::RESOURCE_TYPE_SCRIPT,
-      info.was_cached, info.data_reduction_proxy_used, info.raw_body_bytes,
-      info.original_network_content_length, base::TimeTicks::Now());
+  observer_->OnRequestComplete(content::GlobalRequestID(),
+                               content::RESOURCE_TYPE_SCRIPT, info.was_cached,
+                               info.data_reduction_proxy_data
+                                   ? info.data_reduction_proxy_data->DeepCopy()
+                                   : nullptr,
+                               info.raw_body_bytes,
+                               info.original_network_content_length,
+                               base::TimeTicks::Now());
 }
 
 void PageLoadMetricsObserverTestHarness::SimulateInputEvent(
diff --git a/chrome/browser/page_load_metrics/observers/subresource_filter_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/subresource_filter_metrics_observer_unittest.cc
index 7e28223..3d222d7 100644
--- a/chrome/browser/page_load_metrics/observers/subresource_filter_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/subresource_filter_metrics_observer_unittest.cc
@@ -155,8 +155,8 @@
 
   SimulateLoadedResource({false /* was_cached */,
                           1024 * 40 /* raw_body_bytes */,
-                          false /* data_reduction_proxy_used */,
-                          0 /* original_network_content_length */});
+                          0 /* original_network_content_length */,
+                          nullptr /* data_reduction_proxy_data */});
 
   page_load_metrics::PageLoadTiming timing;
   timing.navigation_start = base::Time::FromDoubleT(1);
@@ -167,12 +167,12 @@
 
   SimulateLoadedResource({false /* was_cached */,
                           1024 * 20 /* raw_body_bytes */,
-                          false /* data_reduction_proxy_used */,
-                          0 /* original_network_content_length */});
+                          0 /* original_network_content_length */,
+                          nullptr /* data_reduction_proxy_data */});
 
   SimulateLoadedResource({true /* was_cached */, 1024 * 10 /* raw_body_bytes */,
-                          false /* data_reduction_proxy_used */,
-                          0 /* original_network_content_length */});
+                          0 /* original_network_content_length */,
+                          nullptr /* data_reduction_proxy_data */});
 
   histogram_tester().ExpectTotalCount(
       internal::kHistogramSubresourceFilterCount, 1);
@@ -250,8 +250,8 @@
 
   SimulateLoadedResource({false /* was_cached */,
                           1024 * 40 /* raw_body_bytes */,
-                          false /* data_reduction_proxy_used */,
-                          0 /* original_network_content_length */});
+                          0 /* original_network_content_length */,
+                          nullptr /* data_reduction_proxy_data */});
 
   page_load_metrics::PageLoadTiming timing;
   timing.navigation_start = base::Time::FromDoubleT(1);
@@ -262,12 +262,12 @@
 
   SimulateLoadedResource({false /* was_cached */,
                           1024 * 20 /* raw_body_bytes */,
-                          false /* data_reduction_proxy_used */,
-                          0 /* original_network_content_length */});
+                          0 /* original_network_content_length */,
+                          nullptr /* data_reduction_proxy_data */});
 
   SimulateLoadedResource({true /* was_cached */, 1024 * 10 /* raw_body_bytes */,
-                          false /* data_reduction_proxy_used */,
-                          0 /* original_network_content_length */});
+                          0 /* original_network_content_length */,
+                          nullptr /* data_reduction_proxy_data */});
 
   histogram_tester().ExpectTotalCount(
       internal::kHistogramSubresourceFilterCount, 1);
diff --git a/chrome/browser/page_load_metrics/observers/tab_restore_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/tab_restore_page_load_metrics_observer_unittest.cc
index 6b0963e..4c5569c6 100644
--- a/chrome/browser/page_load_metrics/observers/tab_restore_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/tab_restore_page_load_metrics_observer_unittest.cc
@@ -72,23 +72,23 @@
     page_load_metrics::ExtraRequestInfo resources[] = {
         // Cached request.
         {true /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-         false /* data_reduction_proxy_used*/,
-         0 /* original_network_content_length */},
+         0 /* original_network_content_length */,
+         nullptr /* data_reduction_proxy_data */},
         // Uncached non-proxied request.
         {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-         false /* data_reduction_proxy_used*/,
-         1024 * 40 /* original_network_content_length */},
+         1024 * 40 /* original_network_content_length */,
+         nullptr /* data_reduction_proxy_data */},
         // Uncached proxied request with .1 compression ratio.
         {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-         false /* data_reduction_proxy_used*/,
-         1024 * 40 /* original_network_content_length */},
+         1024 * 40 /* original_network_content_length */,
+         nullptr /* data_reduction_proxy_data */},
         // Uncached proxied request with .5 compression ratio.
         {false /*was_cached*/, 1024 * 40 /* raw_body_bytes */,
-         false /* data_reduction_proxy_used*/,
-         1024 * 40 /* original_network_content_length */},
+         1024 * 40 /* original_network_content_length */,
+         nullptr /* data_reduction_proxy_data */},
     };
 
-    for (auto request : resources) {
+    for (const auto& request : resources) {
       SimulateLoadedResource(request);
       if (!request.was_cached) {
         network_bytes_ += request.raw_body_bytes;
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/page_load_metrics_observer.cc
index f3fa5d03b..e3f395a 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
 
+#include <utility>
+
 namespace page_load_metrics {
 
 PageLoadExtraInfo::PageLoadExtraInfo(
@@ -54,16 +56,16 @@
       page_load_metrics::PageLoadMetadata());
 }
 
-ExtraRequestInfo::ExtraRequestInfo(bool was_cached,
-                                   int64_t raw_body_bytes,
-                                   bool data_reduction_proxy_used,
-                                   int64_t original_network_content_length)
+ExtraRequestInfo::ExtraRequestInfo(
+    bool was_cached,
+    int64_t raw_body_bytes,
+    int64_t original_network_content_length,
+    std::unique_ptr<data_reduction_proxy::DataReductionProxyData>
+        data_reduction_proxy_data)
     : was_cached(was_cached),
       raw_body_bytes(raw_body_bytes),
-      data_reduction_proxy_used(data_reduction_proxy_used),
-      original_network_content_length(original_network_content_length) {}
-
-ExtraRequestInfo::ExtraRequestInfo(const ExtraRequestInfo& other) = default;
+      original_network_content_length(original_network_content_length),
+      data_reduction_proxy_data(std::move(data_reduction_proxy_data)) {}
 
 ExtraRequestInfo::~ExtraRequestInfo() {}
 
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
index 11a9889..5c5b29fb 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -5,11 +5,13 @@
 #ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_METRICS_OBSERVER_H_
 #define CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_METRICS_OBSERVER_H_
 
+#include <memory>
 #include <string>
 
 #include "base/macros.h"
 #include "base/optional.h"
 #include "chrome/common/page_load_metrics/page_load_timing.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
@@ -199,10 +201,9 @@
 struct ExtraRequestInfo {
   ExtraRequestInfo(bool was_cached,
                    int64_t raw_body_bytes,
-                   bool data_reduction_proxy_used,
-                   int64_t original_network_content_length);
-
-  ExtraRequestInfo(const ExtraRequestInfo& other);
+                   int64_t original_network_content_length,
+                   std::unique_ptr<data_reduction_proxy::DataReductionProxyData>
+                       data_reduction_proxy_data);
 
   ~ExtraRequestInfo();
 
@@ -212,12 +213,13 @@
   // The number of body (not header) prefilter bytes.
   const int64_t raw_body_bytes;
 
-  // Whether this request used Data Reduction Proxy.
-  const bool data_reduction_proxy_used;
-
   // The number of body (not header) bytes that the data reduction proxy saw
   // before it compressed the requests.
   const int64_t original_network_content_length;
+
+  // Data related to data saver.
+  const std::unique_ptr<data_reduction_proxy::DataReductionProxyData>
+      data_reduction_proxy_data;
 };
 
 // Interface for PageLoadMetrics observers. All instances of this class are
diff --git a/chrome/browser/payments/chrome_payment_request_delegate.cc b/chrome/browser/payments/chrome_payment_request_delegate.cc
index 44126e7..9fc817a5 100644
--- a/chrome/browser/payments/chrome_payment_request_delegate.cc
+++ b/chrome/browser/payments/chrome_payment_request_delegate.cc
@@ -20,7 +20,11 @@
 
 ChromePaymentRequestDelegate::ChromePaymentRequestDelegate(
     content::WebContents* web_contents)
-    : dialog_(nullptr), web_contents_(web_contents) {}
+    : dialog_(nullptr),
+      web_contents_(web_contents),
+      address_normalizer_(GetAddressInputSource(), GetAddressInputStorage()) {}
+
+ChromePaymentRequestDelegate::~ChromePaymentRequestDelegate() {}
 
 void ChromePaymentRequestDelegate::ShowDialog(PaymentRequest* request) {
   DCHECK_EQ(nullptr, dialog_);
@@ -71,7 +75,7 @@
   dialog_->ShowCvcUnmaskPrompt(credit_card, result_delegate, web_contents_);
 }
 
-std::unique_ptr<const ::i18n::addressinput::Source>
+std::unique_ptr<::i18n::addressinput::Source>
 ChromePaymentRequestDelegate::GetAddressInputSource() {
   return base::WrapUnique(new autofill::ChromeMetadataSource(
       I18N_ADDRESS_VALIDATION_DATA_URL,
@@ -82,4 +86,8 @@
   return autofill::ValidationRulesStorageFactory::CreateStorage();
 }
 
+AddressNormalizer* ChromePaymentRequestDelegate::GetAddressNormalizer() {
+  return &address_normalizer_;
+}
+
 }  // namespace payments
diff --git a/chrome/browser/payments/chrome_payment_request_delegate.h b/chrome/browser/payments/chrome_payment_request_delegate.h
index 69a9a2b..3e18a277 100644
--- a/chrome/browser/payments/chrome_payment_request_delegate.h
+++ b/chrome/browser/payments/chrome_payment_request_delegate.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "components/payments/core/address_normalizer_impl.h"
 #include "components/payments/core/payment_request_delegate.h"
 
 namespace content {
@@ -22,7 +23,7 @@
 class ChromePaymentRequestDelegate : public PaymentRequestDelegate {
  public:
   explicit ChromePaymentRequestDelegate(content::WebContents* web_contents);
-  ~ChromePaymentRequestDelegate() override {}
+  ~ChromePaymentRequestDelegate() override;
 
   // PaymentRequestDelegate:
   void ShowDialog(PaymentRequest* request) override;
@@ -37,10 +38,11 @@
       const autofill::CreditCard& credit_card,
       base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>
           result_delegate) override;
-  std::unique_ptr<const ::i18n::addressinput::Source> GetAddressInputSource()
+  std::unique_ptr<::i18n::addressinput::Source> GetAddressInputSource()
       override;
   std::unique_ptr<::i18n::addressinput::Storage> GetAddressInputStorage()
       override;
+  AddressNormalizer* GetAddressNormalizer() override;
 
  protected:
   // Reference to the dialog so that we can satisfy calls to CloseDialog(). This
@@ -52,6 +54,9 @@
   // Not owned but outlives the PaymentRequest object that owns this.
   content::WebContents* web_contents_;
 
+  // The address normalizer to use for the duration of the Payment Request.
+  AddressNormalizerImpl address_normalizer_;
+
   DISALLOW_COPY_AND_ASSIGN(ChromePaymentRequestDelegate);
 };
 
diff --git a/chrome/browser/previews/previews_infobar_delegate.cc b/chrome/browser/previews/previews_infobar_delegate.cc
index 2444cde5..f37679a5 100644
--- a/chrome/browser/previews/previews_infobar_delegate.cc
+++ b/chrome/browser/previews/previews_infobar_delegate.cc
@@ -5,12 +5,15 @@
 #include "chrome/browser/previews/previews_infobar_delegate.h"
 
 #include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
 #include "chrome/browser/android/android_theme_resources.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
 #include "chrome/browser/previews/previews_infobar_tab_helper.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
 #include "components/infobars/core/infobar.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
@@ -147,16 +150,25 @@
   content::WebContents* web_contents =
       InfoBarService::WebContentsFromInfoBar(infobar());
   if (infobar_type_ == LITE_PAGE || infobar_type_ == LOFI) {
+    auto* data_reduction_proxy_settings =
+        DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+            web_contents->GetBrowserContext());
+    data_reduction_proxy_settings->IncrementLoFiUserRequestsForImages();
+    PreviewsInfoBarTabHelper* infobar_tab_helper =
+        PreviewsInfoBarTabHelper::FromWebContents(web_contents);
+    if (infobar_tab_helper &&
+        infobar_tab_helper->committed_data_saver_navigation_id()) {
+      data_reduction_proxy_settings->data_reduction_proxy_service()
+          ->pingback_client()
+          ->AddOptOut(
+              infobar_tab_helper->committed_data_saver_navigation_id().value());
+    }
+
     if (infobar_type_ == LITE_PAGE)
       web_contents->GetController().Reload(
           content::ReloadType::DISABLE_LOFI_MODE, true);
     else if (infobar_type_ == LOFI)
       web_contents->ReloadLoFiImages();
-
-    auto* data_reduction_proxy_settings =
-        DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
-            web_contents->GetBrowserContext());
-    data_reduction_proxy_settings->IncrementLoFiUserRequestsForImages();
   } else if (infobar_type_ == OFFLINE) {
     // Prevent LoFi and lite page modes from showing after reload.
     // TODO(ryansturm): rename DISABLE_LOFI_MODE to DISABLE_PREVIEWS.
diff --git a/chrome/browser/previews/previews_infobar_delegate_unittest.cc b/chrome/browser/previews/previews_infobar_delegate_unittest.cc
index c4fb5754..15fad9d 100644
--- a/chrome/browser/previews/previews_infobar_delegate_unittest.cc
+++ b/chrome/browser/previews/previews_infobar_delegate_unittest.cc
@@ -15,11 +15,16 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/android/android_theme_resources.h"
 #include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/loader/chrome_navigation_data.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
 #include "chrome/browser/previews/previews_infobar_tab_helper.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
@@ -67,6 +72,19 @@
     return last_navigation_reload_type_;
   }
 
+  void DidStartNavigation(
+      content::NavigationHandle* navigation_handle) override {
+    ChromeNavigationData* chrome_navigation_data = new ChromeNavigationData();
+    content::WebContentsTester::For(web_contents())
+        ->SetNavigationData(navigation_handle,
+                            base::WrapUnique(chrome_navigation_data));
+    data_reduction_proxy::DataReductionProxyData* data =
+        new data_reduction_proxy::DataReductionProxyData();
+    chrome_navigation_data->SetDataReductionProxyData(base::WrapUnique(data));
+    data->set_used_data_reduction_proxy(true);
+    data->set_page_id(1u);
+  }
+
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override {
     last_navigation_reload_type_ = navigation_handle->GetReloadType();
@@ -202,6 +220,14 @@
                            1);
   EXPECT_EQ(0, drp_test_context_->pref_service()->GetInteger(
                    data_reduction_proxy::prefs::kLoFiLoadImagesPerSession));
+
+  auto* data_reduction_proxy_settings =
+      DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+          web_contents()->GetBrowserContext());
+
+  EXPECT_EQ(0u, data_reduction_proxy_settings->data_reduction_proxy_service()
+                    ->pingback_client()
+                    ->OptOutsSizeForTesting());
 }
 
 TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestUserDismissal) {
@@ -243,6 +269,8 @@
 TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestClickLinkLoFi) {
   base::HistogramTester tester;
 
+  NavigateAndCommit(GURL(kTestUrl));
+
   ConfirmInfoBarDelegate* infobar = CreateInfoBar(
       PreviewsInfoBarDelegate::LOFI, true /* is_data_saver_user */);
 
@@ -257,6 +285,14 @@
   EXPECT_EQ(1, drp_test_context_->pref_service()->GetInteger(
                    data_reduction_proxy::prefs::kLoFiLoadImagesPerSession));
   EXPECT_TRUE(user_opt_out_.value());
+
+  auto* data_reduction_proxy_settings =
+      DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+          web_contents()->GetBrowserContext());
+
+  EXPECT_EQ(1u, data_reduction_proxy_settings->data_reduction_proxy_service()
+                    ->pingback_client()
+                    ->OptOutsSizeForTesting());
 }
 
 TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestClickLinkLitePage) {
@@ -281,6 +317,14 @@
   EXPECT_EQ(content::ReloadType::DISABLE_LOFI_MODE,
             TestPreviewsWebContentsObserver::FromWebContents(web_contents())
                 ->last_navigation_reload_type());
+
+  auto* data_reduction_proxy_settings =
+      DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+          web_contents()->GetBrowserContext());
+
+  EXPECT_EQ(1u, data_reduction_proxy_settings->data_reduction_proxy_service()
+                    ->pingback_client()
+                    ->OptOutsSizeForTesting());
 }
 
 TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestShownOncePerNavigation) {
@@ -421,4 +465,62 @@
   EXPECT_EQ(content::ReloadType::DISABLE_LOFI_MODE,
             TestPreviewsWebContentsObserver::FromWebContents(web_contents())
                 ->last_navigation_reload_type());
+
+  auto* data_reduction_proxy_settings =
+      DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+          web_contents()->GetBrowserContext());
+
+  EXPECT_EQ(0u, data_reduction_proxy_settings->data_reduction_proxy_service()
+                    ->pingback_client()
+                    ->OptOutsSizeForTesting());
+}
+
+TEST_F(PreviewsInfoBarDelegateUnitTest, PingbackClientClearedTabClosed) {
+  base::HistogramTester tester;
+
+  NavigateAndCommit(GURL(kTestUrl));
+
+  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
+      PreviewsInfoBarDelegate::LITE_PAGE, true /* is_data_saver_user */);
+
+  // Simulate clicking the infobar link.
+  if (infobar->LinkClicked(WindowOpenDisposition::CURRENT_TAB))
+    infobar_service()->infobar_at(0)->RemoveSelf();
+  EXPECT_EQ(0U, infobar_service()->infobar_count());
+
+  tester.ExpectBucketCount(
+      kUMAPreviewsInfoBarActionLitePage,
+      PreviewsInfoBarDelegate::INFOBAR_LOAD_ORIGINAL_CLICKED, 1);
+
+  content::WebContentsTester::For(web_contents())->CommitPendingNavigation();
+
+  EXPECT_EQ(content::ReloadType::DISABLE_LOFI_MODE,
+            TestPreviewsWebContentsObserver::FromWebContents(web_contents())
+                ->last_navigation_reload_type());
+
+  auto* data_reduction_proxy_settings =
+      DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+          web_contents()->GetBrowserContext());
+
+  EXPECT_EQ(1u, data_reduction_proxy_settings->data_reduction_proxy_service()
+                    ->pingback_client()
+                    ->OptOutsSizeForTesting());
+
+  {
+    std::unique_ptr<content::NavigationHandle> navigation_handle(
+        content::NavigationHandle::CreateNavigationHandleForTesting(
+            GURL("url"), main_rfh(), true));
+  }
+
+  SetContents(nullptr);
+
+  EXPECT_EQ(1u, data_reduction_proxy_settings->data_reduction_proxy_service()
+                    ->pingback_client()
+                    ->OptOutsSizeForTesting());
+
+  drp_test_context_->RunUntilIdle();
+
+  EXPECT_EQ(0u, data_reduction_proxy_settings->data_reduction_proxy_service()
+                    ->pingback_client()
+                    ->OptOutsSizeForTesting());
 }
diff --git a/chrome/browser/previews/previews_infobar_tab_helper.cc b/chrome/browser/previews/previews_infobar_tab_helper.cc
index 917d3eb..3083f0c3 100644
--- a/chrome/browser/previews/previews_infobar_tab_helper.cc
+++ b/chrome/browser/previews/previews_infobar_tab_helper.cc
@@ -6,12 +6,15 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "chrome/browser/loader/chrome_navigation_data.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
 #include "chrome/browser/previews/previews_infobar_delegate.h"
 #include "chrome/browser/previews/previews_service.h"
 #include "chrome/browser/previews/previews_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
 #include "components/previews/core/previews_experiments.h"
@@ -49,12 +52,15 @@
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PreviewsInfoBarTabHelper);
 
-PreviewsInfoBarTabHelper::~PreviewsInfoBarTabHelper() {}
+PreviewsInfoBarTabHelper::~PreviewsInfoBarTabHelper() {
+  ClearLastNavigationAsync();
+}
 
 PreviewsInfoBarTabHelper::PreviewsInfoBarTabHelper(
     content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
-      displayed_preview_infobar_(false){
+      browser_context_(web_contents->GetBrowserContext()),
+      displayed_preview_infobar_(false) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 }
 
@@ -65,6 +71,26 @@
       !navigation_handle->HasCommitted() || navigation_handle->IsSameDocument())
     return;
   displayed_preview_infobar_ = false;
+  ClearLastNavigationAsync();
+  committed_data_saver_navigation_id_.reset();
+
+  // As documented in content/public/browser/navigation_handle.h, this
+  // NavigationData is a clone of the NavigationData instance returned from
+  // ResourceDispatcherHostDelegate::GetNavigationData during commit.
+  // Because ChromeResourceDispatcherHostDelegate always returns a
+  // ChromeNavigationData, it is safe to static_cast here.
+  ChromeNavigationData* chrome_navigation_data =
+      static_cast<ChromeNavigationData*>(
+          navigation_handle->GetNavigationData());
+  if (chrome_navigation_data) {
+    data_reduction_proxy::DataReductionProxyData* data =
+        chrome_navigation_data->GetDataReductionProxyData();
+
+    if (data && data->page_id()) {
+      committed_data_saver_navigation_id_ = data_reduction_proxy::NavigationID(
+          data->page_id().value(), data->session_key());
+    }
+  }
 
 #if defined(OS_ANDROID)
   offline_pages::OfflinePageTabHelper* tab_helper =
@@ -83,9 +109,9 @@
         web_contents(), PreviewsInfoBarDelegate::OFFLINE,
         data_reduction_proxy_settings &&
             data_reduction_proxy_settings->IsDataReductionProxyEnabled(),
-        base::Bind(
-            &AddPreviewNavigationCallback, web_contents()->GetBrowserContext(),
-            navigation_handle->GetURL(), previews::PreviewsType::OFFLINE));
+        base::Bind(&AddPreviewNavigationCallback, browser_context_,
+                   navigation_handle->GetURL(),
+                   previews::PreviewsType::OFFLINE));
     // Don't try to show other infobars if this is an offline preview.
     return;
   }
@@ -101,3 +127,17 @@
   }
 }
 
+void PreviewsInfoBarTabHelper::ClearLastNavigationAsync() const {
+  if (!committed_data_saver_navigation_id_)
+    return;
+  auto* data_reduction_proxy_settings =
+      DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+          browser_context_);
+  if (!data_reduction_proxy_settings ||
+      !data_reduction_proxy_settings->data_reduction_proxy_service()) {
+    return;
+  }
+  data_reduction_proxy_settings->data_reduction_proxy_service()
+      ->pingback_client()
+      ->ClearNavigationKeyAsync(committed_data_saver_navigation_id_.value());
+}
diff --git a/chrome/browser/previews/previews_infobar_tab_helper.h b/chrome/browser/previews/previews_infobar_tab_helper.h
index 512726f1..949ac7e 100644
--- a/chrome/browser/previews/previews_infobar_tab_helper.h
+++ b/chrome/browser/previews/previews_infobar_tab_helper.h
@@ -6,6 +6,8 @@
 #define CHROME_BROWSER_PREVIEWS_PREVIEWS_INFOBAR_TAB_HELPER_H_
 
 #include "base/macros.h"
+#include "base/optional.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
@@ -29,19 +31,35 @@
     displayed_preview_infobar_ = displayed;
   }
 
+  // The data saver page identifier of the current page load.
+  const base::Optional<data_reduction_proxy::NavigationID>&
+  committed_data_saver_navigation_id() {
+    return committed_data_saver_navigation_id_;
+  }
+
  private:
   friend class content::WebContentsUserData<PreviewsInfoBarTabHelper>;
   friend class PreviewsInfoBarTabHelperUnitTest;
 
   explicit PreviewsInfoBarTabHelper(content::WebContents* web_contents);
 
+  // Clears the last navigation from this tab in the pingback client.
+  void ClearLastNavigationAsync() const;
+
   // Overridden from content::WebContentsObserver:
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
 
+  // Stored for use in the destructor.
+  content::BrowserContext* browser_context_;
+
   // True if the InfoBar for a preview has been shown for the page.
   bool displayed_preview_infobar_;
 
+  // The data saver page identifier of the current page load.
+  base::Optional<data_reduction_proxy::NavigationID>
+      committed_data_saver_navigation_id_;
+
   DISALLOW_COPY_AND_ASSIGN(PreviewsInfoBarTabHelper);
 };
 
diff --git a/chrome/browser/previews/previews_infobar_tab_helper_unittest.cc b/chrome/browser/previews/previews_infobar_tab_helper_unittest.cc
index 9d2a3a0..5bda74c6 100644
--- a/chrome/browser/previews/previews_infobar_tab_helper_unittest.cc
+++ b/chrome/browser/previews/previews_infobar_tab_helper_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/infobars/infobar_service.h"
@@ -15,6 +16,9 @@
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
 #include "chrome/browser/previews/previews_infobar_tab_helper.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 84c5eb8..d3f0653 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -44,6 +44,7 @@
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
 #include "chrome/browser/download/download_service.h"
 #include "chrome/browser/download/download_service_factory.h"
+#include "chrome/browser/media/media_device_id_salt.h"
 #include "chrome/browser/net/predictor.h"
 #include "chrome/browser/net/proxy_service_factory.h"
 #include "chrome/browser/permissions/permission_manager.h"
@@ -562,6 +563,8 @@
       base::Bind(&ProfileImpl::UpdateIsEphemeralInStorage,
                  base::Unretained(this)));
 
+  media_device_id_salt_ = new MediaDeviceIDSalt(prefs_.get());
+
   // It would be nice to use PathService for fetching this directory, but
   // the cache directory depends on the profile directory, which isn't available
   // to PathService.
@@ -1093,6 +1096,10 @@
       std::make_pair(identity::mojom::kServiceName, identity_service_info));
 }
 
+std::string ProfileImpl::GetMediaDeviceIDSalt() {
+  return media_device_id_salt_->GetSalt();
+}
+
 bool ProfileImpl::IsSameProfile(Profile* profile) {
   if (profile == static_cast<Profile*>(this))
     return true;
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 7956e02..d2cd7334 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -25,6 +25,7 @@
 #include "content/public/browser/host_zoom_map.h"
 #include "extensions/features/features.h"
 
+class MediaDeviceIDSalt;
 class PrefService;
 
 #if defined(OS_CHROMEOS)
@@ -97,6 +98,7 @@
       const base::FilePath& partition_path,
       bool in_memory) override;
   void RegisterInProcessServices(StaticServiceMap* services) override;
+  std::string GetMediaDeviceIDSalt() override;
 
   // Profile implementation:
   scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() override;
@@ -251,6 +253,11 @@
 
   std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
 
+  // TODO(mmenke):  This should be removed from the Profile, and use a
+  // BrowserContextKeyedService instead.
+  // See https://crbug.com/713733
+  scoped_refptr<MediaDeviceIDSalt> media_device_id_salt_;
+
   // STOP!!!! DO NOT ADD ANY MORE ITEMS HERE!!!!
   //
   // Instead, make your Service/Manager/whatever object you're hanging off the
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 7f5eb85..addedb5 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -36,7 +36,6 @@
 #include "chrome/browser/download/download_service.h"
 #include "chrome/browser/download/download_service_factory.h"
 #include "chrome/browser/io_thread.h"
-#include "chrome/browser/media/media_device_id_salt.h"
 #include "chrome/browser/net/chrome_http_user_agent_settings.h"
 #include "chrome/browser/net/chrome_network_delegate.h"
 #include "chrome/browser/net/chrome_url_request_context_getter.h"
@@ -480,9 +479,6 @@
     google_services_user_account_id_.MoveToThread(io_task_runner);
   }
 
-  if (!IsOffTheRecord())
-    media_device_id_salt_ = new MediaDeviceIDSalt(pref_service);
-
   network_prediction_options_.Init(prefs::kNetworkPredictionOptions,
                                    pref_service);
 
@@ -857,11 +853,6 @@
   return host_content_settings_map_.get();
 }
 
-std::string ProfileIOData::GetMediaDeviceIDSalt() const {
-  DCHECK(media_device_id_salt_);
-  return media_device_id_salt_->GetSalt();
-}
-
 bool ProfileIOData::IsOffTheRecord() const {
   return profile_type() == Profile::INCOGNITO_PROFILE
       || profile_type() == Profile::GUEST_PROFILE;
@@ -959,13 +950,6 @@
   return request_context_;
 }
 
-std::string ProfileIOData::ResourceContext::GetMediaDeviceIDSalt() {
-  if (io_data_->HasMediaDeviceIDSalt())
-    return io_data_->GetMediaDeviceIDSalt();
-
-  return content::ResourceContext::GetMediaDeviceIDSalt();
-}
-
 void ProfileIOData::Init(
     content::ProtocolHandlerMap* protocol_handlers,
     content::URLRequestInterceptorScopedVector request_interceptors) const {
@@ -1226,8 +1210,6 @@
   enable_metrics_.Destroy();
   safe_browsing_enabled_.Destroy();
   network_prediction_options_.Destroy();
-  if (media_device_id_salt_.get())
-    media_device_id_salt_->ShutdownOnUIThread();
   if (url_blacklist_manager_)
     url_blacklist_manager_->ShutdownOnUIThread();
   if (ct_policy_manager_)
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h
index ef8fd8d..9f3ea25 100644
--- a/chrome/browser/profiles/profile_io_data.h
+++ b/chrome/browser/profiles/profile_io_data.h
@@ -43,7 +43,6 @@
 class ChromeURLRequestContextGetter;
 class ChromeExpectCTReporter;
 class HostContentSettingsMap;
-class MediaDeviceIDSalt;
 class NetHttpSessionParamsObserver;
 class ProtocolHandlerRegistry;
 
@@ -180,12 +179,6 @@
     return &network_prediction_options_;
   }
 
-  bool HasMediaDeviceIDSalt() const {
-    return media_device_id_salt_.get() != nullptr;
-  }
-
-  std::string GetMediaDeviceIDSalt() const;
-
   DevToolsNetworkControllerHandle* network_controller_handle() const {
     return &network_controller_handle_;
   }
@@ -433,7 +426,6 @@
     // ResourceContext implementation:
     net::HostResolver* GetHostResolver() override;
     net::URLRequestContext* GetRequestContext() override;
-    std::string GetMediaDeviceIDSalt() override;
 
    private:
     friend class ProfileIOData;
@@ -526,8 +518,6 @@
 
   mutable StringPrefMember google_services_user_account_id_;
 
-  mutable scoped_refptr<MediaDeviceIDSalt> media_device_id_salt_;
-
   // Member variables which are pointed to by the various context objects.
   mutable BooleanPrefMember enable_referrers_;
   mutable BooleanPrefMember enable_do_not_track_;
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
index 3ce0930..982a3ea 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -427,10 +427,14 @@
       speak: '$earcon(ALERT_MODAL) $name $nameOrTextContent $state $role'
     },
     cell: {
-      enter: '@cell_summary($tableCellRowIndex, $tableCellColumnIndex) ' +
-          '$node(tableColumnHeader)',
-      speak: '@cell_summary($tableCellRowIndex, $tableCellColumnIndex) ' +
-          '$node(tableColumnHeader) $state'
+      enter: '@cell_summary($if($ariaCellRowIndex, $ariaCellRowIndex, ' +
+      '$tableCellRowIndex), ' +
+      '$if($ariaCellColumnIndex, $ariaCellColumnIndex, ' +
+      '$tableCellColumnIndex)) $node(tableColumnHeader)',
+      speak: '@cell_summary($if($ariaCellRowIndex, $ariaCellRowIndex, ' +
+      '$tableCellRowIndex), ' +
+      '$if($ariaCellColumnIndex, $ariaCellColumnIndex, ' +
+      '$tableCellColumnIndex)) $node(tableColumnHeader) $state'
     },
     checkBox: {
       speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' +
@@ -564,7 +568,9 @@
           '$if($setSize, @describe_index($posInSet, $setSize))',
     },
     table: {
-      enter: '@table_summary($name, $tableRowCount, $tableColumnCount) ' +
+      enter: '@table_summary($name, ' +
+          '$if($ariaRowCount, $ariaRowCount, $tableRowCount), ' +
+          '$if($ariaColumnCount, $ariaColumnCount, $tableColumnCount)) ' +
           '$node(tableHeader)'
     },
     tableHeaderContainer: {
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
index cc59729..15c91f95 100644
--- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
+++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
@@ -117,16 +117,23 @@
             </div>
             <div class="username-column selectable text-elide"
                 id="username">[[item.loginPair.username]]</div>
-            <div class="password-column">
-              <!-- Password type and disabled in order to match mock. -->
-              <input id="password" type="password" disabled
-                  value="[[getEmptyPassword_(item.numCharactersInPassword)]]">
-              </input>
-              <paper-icon-button id="passwordMenu" icon="cr:more-vert"
+            <div class="password-column text-elide">
+              <template is="dom-if" if="[[!item.federationText]]">
+                <!-- Password type and disabled in order to match mock. -->
+                <input id="password" type="password" disabled
+                    value="[[getEmptyPassword_(item.numCharactersInPassword)]]">
+                </input>
+              </template>
+              <template is="dom-if" if="{{item.federationText}}">
+                <span class="selectable text-elide">
+                  {{item.federationText}}
+                </span>
+              </template>
+            </div>
+            <paper-icon-button id="passwordMenu" icon="cr:more-vert"
                   on-tap="onPasswordMenuTap_" title="$i18n{moreActions}"
                   tabindex$="[[tabIndex]]">
-              </paper-icon-button>
-            </div>
+            </paper-icon-button>
           </div>
         </template>
       </iron-list>
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index 7a3ad1a..e0619029 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -106,7 +106,7 @@
     : BaseBlockingPage(
           ui_manager,
           web_contents,
-          unsafe_resources[0].url,
+          main_frame_url,
           unsafe_resources,
           CreateControllerClient(web_contents, unsafe_resources, ui_manager),
           display_options) {
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
index b7b5542..a8c8bff 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -78,6 +78,9 @@
 const char kHTTPSPage[] = "/ssl/google.html";
 const char kMaliciousPage[] = "safe_browsing/malware.html";
 const char kCrossSiteMaliciousPage[] = "safe_browsing/malware2.html";
+const char kPageWithCrossOriginMaliciousIframe[] =
+    "safe_browsing/malware3.html";
+const char kCrossOriginMaliciousIframeHost[] = "malware.test";
 const char kMaliciousIframe[] = "safe_browsing/malware_iframe.html";
 const char kUnrelatedUrl[] = "https://www.google.com";
 
@@ -430,6 +433,27 @@
     return url;
   }
 
+  // Adds a safebrowsing threat results to the fake safebrowsing service, and
+  // navigates to a page with a cross-origin iframe containing the threat site.
+  // Returns the url of the parent page and sets |iframe_url| to the malicious
+  // cross-origin iframe.
+  GURL SetupCrossOriginThreatIframeWarningAndNavigate(GURL* iframe_url) {
+    content::SetupCrossSiteRedirector(embedded_test_server());
+    EXPECT_TRUE(embedded_test_server()->Start());
+    GURL url = embedded_test_server()->GetURL(
+        std::string("/") + kPageWithCrossOriginMaliciousIframe);
+    *iframe_url =
+        embedded_test_server()->GetURL(std::string("/") + kMaliciousIframe);
+    GURL::Replacements replace_host;
+    replace_host.SetHostStr(kCrossOriginMaliciousIframeHost);
+    *iframe_url = iframe_url->ReplaceComponents(replace_host);
+    SetURLThreatType(*iframe_url, testing::get<0>(GetParam()));
+
+    ui_test_utils::NavigateToURL(browser(), url);
+    EXPECT_TRUE(WaitForReady());
+    return url;
+  }
+
   void SendCommand(
       security_interstitials::SecurityInterstitialCommands command) {
     WebContents* contents =
@@ -1295,8 +1319,13 @@
       net::URLRequestMockHTTPJob::GetMockUrl("http://example.test");
   ui_test_utils::NavigateToURL(browser(), start_url);
 
-  // The security indicator should be downgraded while the interstitial shows.
-  SetupThreatIframeWarningAndNavigate();
+  // The security indicator should be downgraded while the interstitial
+  // shows. Load a cross-origin iframe to be sure that the main frame origin
+  // (rather than the subresource origin) is being added and removed from the
+  // whitelist; this is a regression test for https://crbug.com/710955.
+  GURL bad_iframe_url;
+  GURL main_url =
+      SetupCrossOriginThreatIframeWarningAndNavigate(&bad_iframe_url);
   WebContents* error_tab = browser()->tab_strip_model()->GetActiveWebContents();
   ASSERT_TRUE(error_tab);
   ExpectSecurityIndicatorDowngrade(error_tab, 0u);
@@ -1320,6 +1349,13 @@
   ASSERT_TRUE(entry);
   EXPECT_EQ(start_url, entry->GetURL());
   ExpectNoSecurityIndicatorDowngrade(post_tab);
+
+  // Clear the malicious subresource URL, and check that the hostname of the
+  // interstitial is no longer marked as Dangerous.
+  ClearBadURL(bad_iframe_url);
+  ui_test_utils::NavigateToURL(browser(), main_url);
+  ExpectNoSecurityIndicatorDowngrade(
+      browser()->tab_strip_model()->GetActiveWebContents());
 }
 
 // Test that the security indicator is downgraded after clicking through a
diff --git a/chrome/browser/site_per_process_interactive_browsertest.cc b/chrome/browser/site_per_process_interactive_browsertest.cc
index f00961a..d3598fa 100644
--- a/chrome/browser/site_per_process_interactive_browsertest.cc
+++ b/chrome/browser/site_per_process_interactive_browsertest.cc
@@ -327,7 +327,7 @@
   EXPECT_EQ(main_frame, web_contents->GetFocusedFrame());
 }
 
-#if (defined(OS_LINUX) && !defined(USE_OZONE)) || defined(OS_WIN)
+#if (defined(OS_LINUX) && !defined(USE_OZONE))
 // Ensures that renderers know to advance focus to sibling frames and parent
 // frames in the presence of mouse click initiated focus changes.
 // Verifies against regression of https://crbug.com/702330
diff --git a/chrome/browser/ui/views/payments/payment_request_payment_response_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_payment_response_browsertest.cc
index dbd458f..66f7dae 100644
--- a/chrome/browser/ui/views/payments/payment_request_payment_response_browsertest.cc
+++ b/chrome/browser/ui/views/payments/payment_request_payment_response_browsertest.cc
@@ -102,7 +102,7 @@
                       "\"postalCode\": \"48838\"", "\"sortingCode\": \"\"",
                       "\"languageCode\": \"\"", "\"organization\": \"ACME\"",
                       "\"recipient\": \"Jane A. Smith\"",
-                      "\"phone\": \"13105557889\""});
+                      "\"phone\": \"+13105557889\""});
 
   // Test that the shipping option was sent to the merchant.
   ExpectBodyContains({"\"shippingOption\": \"freeShippingOption\""});
diff --git a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
index bcfd5ca1..1d5430f 100644
--- a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
@@ -42,7 +42,7 @@
   void EnableAddressInputOverride() { SetAddressInputOverride(this); }
 
   // TestChromePaymentRequestDelegate::AddressInputProvider.
-  std::unique_ptr<const ::i18n::addressinput::Source> GetAddressInputSource()
+  std::unique_ptr<::i18n::addressinput::Source> GetAddressInputSource()
       override {
     return base::MakeUnique<TestSource>(address_input_override_data_);
   }
diff --git a/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.cc b/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.cc
index e884578..fa148ed 100644
--- a/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.cc
+++ b/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.cc
@@ -45,7 +45,7 @@
   return is_valid_ssl_;
 }
 
-std::unique_ptr<const ::i18n::addressinput::Source>
+std::unique_ptr<::i18n::addressinput::Source>
 TestChromePaymentRequestDelegate::GetAddressInputSource() {
   if (address_input_provider_)
     return address_input_provider_->GetAddressInputSource();
diff --git a/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.h b/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.h
index 7ee6458..2f4fe94 100644
--- a/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.h
+++ b/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.h
@@ -36,7 +36,7 @@
   // This class allows tests to provide their own AddressInput data.
   class AddressInputProvider {
    public:
-    virtual std::unique_ptr<const ::i18n::addressinput::Source>
+    virtual std::unique_ptr<::i18n::addressinput::Source>
     GetAddressInputSource() = 0;
     virtual std::unique_ptr<::i18n::addressinput::Storage>
     GetAddressInputStorage() = 0;
@@ -50,7 +50,7 @@
   void ShowDialog(PaymentRequest* request) override;
   bool IsIncognito() const override;
   bool IsSslCertificateValid() override;
-  std::unique_ptr<const ::i18n::addressinput::Source> GetAddressInputSource()
+  std::unique_ptr<::i18n::addressinput::Source> GetAddressInputSource()
       override;
   std::unique_ptr<::i18n::addressinput::Storage> GetAddressInputStorage()
       override;
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
index 7bfb4be..3dbd4336 100644
--- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
@@ -198,7 +198,7 @@
 }
 
 void EncryptionMigrationScreenHandler::HandleRequestRestart() {
-  chrome::AttemptRestart();
+  DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
 }
 
 void EncryptionMigrationScreenHandler::UpdateUIState(UIState state) {
@@ -313,7 +313,7 @@
       break;
     case cryptohome::DIRCRYPTO_MIGRATION_SUCCESS:
       // Restart immediately after successful migration.
-      chrome::AttemptRestart();
+      DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
       break;
     case cryptohome::DIRCRYPTO_MIGRATION_FAILED:
       UpdateUIState(UIState::MIGRATION_FAILED);
diff --git a/chrome/common/extensions/api/automation.idl b/chrome/common/extensions/api/automation.idl
index 08fc1863..d15cbbb01 100644
--- a/chrome/common/extensions/api/automation.idl
+++ b/chrome/common/extensions/api/automation.idl
@@ -551,25 +551,39 @@
     // Table attributes.
     //
 
-    // The number of rows in this table.
+    // The number of rows in this table as specified in the DOM.
     long? tableRowCount;
 
-    // The number of columns in this table.
+    // The number of rows in this table as specified by the page author.
+    long? ariaRowCount;
+
+    // The number of columns in this table as specified in the DOM.
     long? tableColumnCount;
 
+    // The number of columns in this table as specified by the page author.
+    long? ariaColumnCount;
+
     //
     // Table cell attributes.
     //
 
-    // The zero-based index of the column that this cell is in.
+    // The zero-based index of the column that this cell is in as specified in
+    // the DOM.
     long? tableCellColumnIndex;
 
+    // The ARIA column index as specified by the page author.
+    long? ariaCellColumnIndex;
+
     // The number of columns that this cell spans (default is 1).
     long? tableCellColumnSpan;
 
-    // The zero-based index of the row that this cell is in.
+    // The zero-based index of the row that this cell is in as specified in the
+    // DOM.
     long? tableCellRowIndex;
 
+    // The ARIA row index as specified by the page author.
+    long? ariaCellRowIndex;
+
     // The number of rows that this cell spans (default is 1).
     long? tableCellRowSpan;
 
diff --git a/chrome/renderer/resources/extensions/automation/automation_node.js b/chrome/renderer/resources/extensions/automation/automation_node.js
index 543ed83..c246a11 100644
--- a/chrome/renderer/resources/extensions/automation/automation_node.js
+++ b/chrome/renderer/resources/extensions/automation/automation_node.js
@@ -735,12 +735,16 @@
     'scrollYMin',
     'setSize',
     'tableCellColumnIndex',
+    'ariaCellColumnIndex',
     'tableCellColumnSpan',
     'tableCellRowIndex',
+    'ariaCellRowIndex',
     'tableCellRowSpan',
     'tableColumnCount',
+    'ariaColumnCount',
     'tableColumnIndex',
     'tableRowCount',
+    'ariaRowCount',
     'tableRowIndex',
     'textSelEnd',
     'textSelStart'];
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index a717053a..e67e253 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -73,6 +73,8 @@
 
 _VERSION_SPECIFIC_FILTER = {}
 _VERSION_SPECIFIC_FILTER['HEAD'] = [
+    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1775
+    'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
 ]
 _VERSION_SPECIFIC_FILTER['58'] = [
     # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1673
diff --git a/chrome/test/data/extensions/api_test/automation/sites/attributes.html b/chrome/test/data/extensions/api_test/automation/sites/attributes.html
index cb9713c0..b2ddb3b 100644
--- a/chrome/test/data/extensions/api_test/automation/sites/attributes.html
+++ b/chrome/test/data/extensions/api_test/automation/sites/attributes.html
@@ -53,18 +53,19 @@
   <div id="main" aria-label="main">Content for scrollbar to control</div>
 
   <!-- table and cell attributes -->
-  <table id="table" role="grid">
+  <!-- The first 100 rows and the first 50 columns are missing. -->
+  <table id="table" role="grid" aria-rowcount="103" aria-colcount="53">
     <tr role="row">
-      <td role="cell">Cell spanning one column</td>
-      <td role="cell">Cell spanning one column</td>
-      <td role="cell">Cell spanning one column</td>
+      <td role="cell" aria-rowindex="101" aria-colindex="51">Cell spanning one column</td>
+      <td role="cell" aria-rowindex="101" aria-colindex="52">Cell spanning one column</td>
+      <td role="cell" aria-rowindex="101" aria-colindex="53">Cell spanning one column</td>
     <tr role="row">
-      <td colspan="2" role="cell">Cell spanning two columns</td>
-      <td rowspan="2" role="cell">Cell spanning two rows</td>
+      <td colspan="2" role="cell" aria-rowindex="102" aria-colindex="51">Cell spanning two columns</td>
+      <td rowspan="2" role="cell" aria-rowindex="102" aria-colindex="53">Cell spanning two rows</td>
     </tr>
     <tr role="row">
-      <td role="cell">Cell spanning one column</td>
-      <td role="cell">Cell spanning one column</td>
+      <td role="cell" aria-rowindex="103" aria-colindex="51">Cell spanning one column</td>
+      <td role="cell" aria-rowindex="103" aria-colindex="52">Cell spanning one column</td>
     </tr>
   </table>
 
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/attributes.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/attributes.js
index 75cdaf59..8de91b4 100644
--- a/chrome/test/data/extensions/api_test/automation/tests/tabs/attributes.js
+++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/attributes.js
@@ -20,10 +20,14 @@
                         'minValueForRange',
                         'maxValueForRange' ];
 var TableAttributes = [ 'tableRowCount',
-                        'tableColumnCount' ];
+                        'tableColumnCount',
+                        'ariaRowCount',
+                        'ariaColumnCount' ];
 var TableCellAttributes = [ 'tableCellColumnIndex',
+                            'ariaCellColumnIndex',
                             'tableCellColumnSpan',
                             'tableCellRowIndex',
+                            'ariaCellRowIndex',
                             'tableCellRowSpan' ];
 
 var allTests = [
@@ -170,51 +174,67 @@
   function testTableAttributes() {
     var table = rootNode.find({ role: 'grid' });;
     assertEq(3, table.tableRowCount);
+    assertEq(103, table.ariaRowCount);
     assertEq(3, table.tableColumnCount);
+    assertEq(53, table.ariaColumnCount);
 
     var row1 = table.firstChild;
     var cell1 = row1.firstChild;
     assertEq(0, cell1.tableCellColumnIndex);
+    assertEq(51, cell1.ariaCellColumnIndex);
     assertEq(1, cell1.tableCellColumnSpan);
     assertEq(0, cell1.tableCellRowIndex);
+    assertEq(101, cell1.ariaCellRowIndex);
     assertEq(1, cell1.tableCellRowSpan);
 
     var cell2 = cell1.nextSibling;
     assertEq(1, cell2.tableCellColumnIndex);
+    assertEq(52, cell2.ariaCellColumnIndex);
     assertEq(1, cell2.tableCellColumnSpan);
     assertEq(0, cell2.tableCellRowIndex);
+    assertEq(101, cell2.ariaCellRowIndex);
     assertEq(1, cell2.tableCellRowSpan);
 
     var cell3 = cell2.nextSibling;
     assertEq(2, cell3.tableCellColumnIndex);
+    assertEq(53, cell3.ariaCellColumnIndex);
     assertEq(1, cell3.tableCellColumnSpan);
     assertEq(0, cell3.tableCellRowIndex);
+    assertEq(101, cell3.ariaCellRowIndex);
     assertEq(1, cell3.tableCellRowSpan);
 
     var row2 = row1.nextSibling;
     var cell4 = row2.firstChild;
     assertEq(0, cell4.tableCellColumnIndex);
+    assertEq(51, cell4.ariaCellColumnIndex);
     assertEq(2, cell4.tableCellColumnSpan);
     assertEq(1, cell4.tableCellRowIndex);
+    assertEq(102, cell4.ariaCellRowIndex);
     assertEq(1, cell4.tableCellRowSpan);
 
     var cell5 = cell4.nextSibling;
     assertEq(2, cell5.tableCellColumnIndex);
+    assertEq(53, cell5.ariaCellColumnIndex);
     assertEq(1, cell5.tableCellColumnSpan);
     assertEq(1, cell5.tableCellRowIndex);
+    assertEq(102, cell5.ariaCellRowIndex);
     assertEq(2, cell5.tableCellRowSpan);
 
     var row3 = row2.nextSibling;
     var cell6 = row3.firstChild;
     assertEq(0, cell6.tableCellColumnIndex);
+    assertEq(51, cell6.ariaCellColumnIndex);
     assertEq(1, cell6.tableCellColumnSpan);
     assertEq(2, cell6.tableCellRowIndex);
+    assertEq(103, cell6.ariaCellRowIndex);
     assertEq(1, cell6.tableCellRowSpan);
 
     var cell7 = cell6.nextSibling;
     assertEq(1, cell7.tableCellColumnIndex);
+    assertEq(52, cell7.ariaCellColumnIndex);
     assertEq(1, cell7.tableCellColumnSpan);
     assertEq(2, cell7.tableCellRowIndex);
+    assertEq(103, cell7.ariaCellRowIndex);
     assertEq(1, cell7.tableCellRowSpan);
 
     chrome.test.succeed();
diff --git a/chrome/test/data/safe_browsing/malware3.html b/chrome/test/data/safe_browsing/malware3.html
new file mode 100644
index 0000000..074e753
--- /dev/null
+++ b/chrome/test/data/safe_browsing/malware3.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+<div foo=1>
+<div bar=1>
+<iframe src="/cross-site/malware.test/safe_browsing/malware_iframe.html"></iframe>
+</div>
+</div>
+</body>
+</html>
diff --git a/components/autofill/core/browser/address.cc b/components/autofill/core/browser/address.cc
index 813d615..3a44121 100644
--- a/components/autofill/core/browser/address.cc
+++ b/components/autofill/core/browser/address.cc
@@ -7,11 +7,13 @@
 #include <stddef.h>
 #include <algorithm>
 
+#include "base/i18n/case_conversion.h"
 #include "base/logging.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_profile_comparator.h"
@@ -134,8 +136,8 @@
 
     case ADDRESS_HOME_COUNTRY:
       DCHECK(value.empty() ||
-             (value.length() == 2u && base::IsStringASCII(value)));
-      country_code_ = base::UTF16ToASCII(value);
+             data_util::IsValidCountryCode(base::i18n::ToUpper(value)));
+      country_code_ = base::ToUpperASCII(base::UTF16ToASCII(value));
       break;
 
     case ADDRESS_HOME_ZIP:
@@ -173,7 +175,7 @@
                       const base::string16& value,
                       const std::string& app_locale) {
   if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
-    if (!value.empty() && (value.size() != 2u || !base::IsStringASCII(value))) {
+    if (!data_util::IsValidCountryCode(base::i18n::ToUpper(value))) {
       country_code_ = std::string();
       return false;
     }
diff --git a/components/autofill/core/browser/autofill_data_util.cc b/components/autofill/core/browser/autofill_data_util.cc
index 974ab70..80b15d2f 100644
--- a/components/autofill/core/browser/autofill_data_util.cc
+++ b/components/autofill/core/browser/autofill_data_util.cc
@@ -15,6 +15,7 @@
 #include "components/grit/components_scaled_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "third_party/icu/source/common/unicode/uscript.h"
+#include "third_party/re2/src/re2/re2.h"
 
 namespace autofill {
 namespace data_util {
@@ -423,5 +424,16 @@
   return kGenericPaymentRequestData.card_type;
 }
 
+bool IsValidCountryCode(const std::string& country_code) {
+  if (country_code.size() != 2)
+    return false;
+
+  return re2::RE2::FullMatch(country_code, "^[A-Z]{2}$");
+}
+
+bool IsValidCountryCode(const base::string16& country_code) {
+  return IsValidCountryCode(base::UTF16ToUTF8(country_code));
+}
+
 }  // namespace data_util
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_data_util.h b/components/autofill/core/browser/autofill_data_util.h
index c95e87fc..b71585e 100644
--- a/components/autofill/core/browser/autofill_data_util.h
+++ b/components/autofill/core/browser/autofill_data_util.h
@@ -57,6 +57,10 @@
 // API basic card payment spec |type|.
 const char* GetCardTypeForBasicCardPaymentType(const std::string& type);
 
+// Returns whether the specified |country_code| is a valid country code.
+bool IsValidCountryCode(const std::string& country_code);
+bool IsValidCountryCode(const base::string16& country_code);
+
 }  // namespace data_util
 }  // namespace autofill
 
diff --git a/components/autofill/core/browser/autofill_data_util_unittest.cc b/components/autofill/core/browser/autofill_data_util_unittest.cc
index 9aadd58b..1a66f8e 100644
--- a/components/autofill/core/browser/autofill_data_util_unittest.cc
+++ b/components/autofill/core/browser/autofill_data_util_unittest.cc
@@ -198,5 +198,46 @@
       ProfileMatchesFullName(base::UTF8ToUTF16("Kirby Puckett"), profile));
 }
 
+struct ValidCountryCodeTestCase {
+  std::string country_code;
+  bool expected_result;
+};
+
+class ValidCountryCodeTest
+    : public testing::TestWithParam<ValidCountryCodeTestCase> {};
+
+TEST_P(ValidCountryCodeTest, ValidCountryCode) {
+  auto test_case = GetParam();
+  EXPECT_EQ(test_case.expected_result,
+            IsValidCountryCode(test_case.country_code));
+}
+
+INSTANTIATE_TEST_CASE_P(
+    AutofillDataUtil,
+    ValidCountryCodeTest,
+    testing::Values(
+        // Valid country codes.
+        ValidCountryCodeTestCase{"US", true},
+        ValidCountryCodeTestCase{"CA", true},
+        ValidCountryCodeTestCase{"CN", true},
+
+        // Country names should not be considered valid.
+        ValidCountryCodeTestCase{"United States", false},
+        ValidCountryCodeTestCase{"Canada", false},
+        ValidCountryCodeTestCase{"China", false},
+
+        // Codes with numbers should not be considered valid.
+        ValidCountryCodeTestCase{"C2", false},
+
+        // Three letters abbreviations should not be considered valid.
+        ValidCountryCodeTestCase{"USA", false},
+        ValidCountryCodeTestCase{"CAN", false},
+        ValidCountryCodeTestCase{"CHN", false},
+
+        // Lowercase is invalid.
+        ValidCountryCodeTestCase{"us", false},
+        ValidCountryCodeTestCase{"Ca", false},
+        ValidCountryCodeTestCase{"cN", false}));
+
 }  // namespace data_util
 }  // namespace autofill
diff --git a/components/chrome_cleaner/public/constants/constants.h b/components/chrome_cleaner/public/constants/constants.h
index 551238d52..d31232a 100644
--- a/components/chrome_cleaner/public/constants/constants.h
+++ b/components/chrome_cleaner/public/constants/constants.h
@@ -110,6 +110,10 @@
   // user (UI handled by Chrome) and logs will only be uploaded if the user
   // opted into Extended Safe Browsing Reporting v2.
   kCleanup = 2,
+  // The cleaner will run in post-reboot validation mode. No UI will be shown
+  // to the user and logs will only be uploaded if the user opted into Extended
+  // Safe Browsing Reporting v2.
+  kPostRebootValidation = 3,
 };
 
 }  // namespace chrome_cleaner
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
index c14d723f..0a54c86 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
@@ -120,7 +120,7 @@
 
   // Examines |response_headers| to determine if an authentication failure
   // occurred on a Data Reduction Proxy. Returns true if authentication failure
-  // occured, and the session key specified in |request_headers| matches the
+  // occurred, and the session key specified in |request_headers| matches the
   // current session in use by the client. If an authentication failure is
   // detected,  it fetches a new config.
   bool ShouldRetryDueToAuthFailure(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.cc
index 612a3f02..425d1be 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.cc
@@ -14,6 +14,8 @@
 DataReductionProxyData::DataReductionProxyData()
     : used_data_reduction_proxy_(false),
       lofi_requested_(false),
+      lite_page_received_(false),
+      lofi_received_(false),
       effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {}
 
 DataReductionProxyData::~DataReductionProxyData() {}
@@ -23,6 +25,8 @@
   std::unique_ptr<DataReductionProxyData> copy(new DataReductionProxyData());
   copy->used_data_reduction_proxy_ = used_data_reduction_proxy_;
   copy->lofi_requested_ = lofi_requested_;
+  copy->lite_page_received_ = lite_page_received_;
+  copy->lofi_received_ = lofi_received_;
   copy->session_key_ = session_key_;
   copy->request_url_ = request_url_;
   copy->effective_connection_type_ = effective_connection_type_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
index fd8f4f5..1f12d47 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_DATA_H_
 #define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_DATA_H_
 
+#include <stdint.h>
+
 #include <memory>
 #include <string>
 
@@ -41,14 +43,24 @@
     lofi_requested_ = lofi_requested;
   }
 
-  // The session key used for this request.
+  // Whether a lite page response was seen for the request or navigation.
+  bool lite_page_received() const { return lite_page_received_; }
+  void set_lite_page_received(bool lite_page_received) {
+    lite_page_received_ = lite_page_received;
+  }
+
+  // Whether a lite page response was seen for the request or navigation.
+  bool lofi_received() const { return lofi_received_; }
+  void set_lofi_received(bool lofi_received) { lofi_received_ = lofi_received; }
+
+  // The session key used for this request. Only set for main frame requests.
   std::string session_key() const { return session_key_; }
   void set_session_key(const std::string& session_key) {
     session_key_ = session_key;
   }
 
   // The URL the frame is navigating to. This may change during the navigation
-  // when encountering a server redirect.
+  // when encountering a server redirect. Only set for main frame requests.
   GURL request_url() const { return request_url_; }
   void set_request_url(const GURL& request_url) { request_url_ = request_url; }
 
@@ -64,7 +76,7 @@
 
   // An identifier that is guaranteed to be unique to each page load during a
   // data saver session. Only present on main frame requests.
-  base::Optional<uint64_t> page_id() const { return page_id_; }
+  const base::Optional<uint64_t>& page_id() const { return page_id_; }
   void set_page_id(uint64_t page_id) { page_id_ = page_id; }
 
   // Removes |this| from |request|.
@@ -92,6 +104,12 @@
   // slow.
   bool lofi_requested_;
 
+  // Whether a lite page response was seen for the request or navigation.
+  bool lite_page_received_;
+
+  // Whether a lite page response was seen for the request or navigation.
+  bool lofi_received_;
+
   // The session key used for this request or navigation.
   std::string session_key_;
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
index 5ee76c7..a7deafb 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
@@ -7,6 +7,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <string>
 
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
@@ -44,21 +45,36 @@
   data->set_lofi_requested(false);
   EXPECT_FALSE(data->lofi_requested());
 
+  EXPECT_FALSE(data->lite_page_received());
+  data->set_lite_page_received(true);
+  EXPECT_TRUE(data->lite_page_received());
+  data->set_lite_page_received(false);
+  EXPECT_FALSE(data->lite_page_received());
+
+  EXPECT_FALSE(data->lofi_received());
+  data->set_lofi_received(true);
+  EXPECT_TRUE(data->lofi_received());
+  data->set_lofi_received(false);
+  EXPECT_FALSE(data->lofi_received());
+
   EXPECT_EQ(std::string(), data->session_key());
-  EXPECT_EQ(GURL(std::string()), data->request_url());
   std::string session_key = "test-key";
   data->set_session_key(session_key);
   EXPECT_EQ(session_key, data->session_key());
+
+  EXPECT_EQ(GURL(std::string()), data->request_url());
   GURL test_url("test-url");
   data->set_request_url(test_url);
   EXPECT_EQ(test_url, data->request_url());
+
   EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
             data->effective_connection_type());
   data->set_effective_connection_type(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
   EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE,
             data->effective_connection_type());
-  uint64_t page_id = 1;
+
   EXPECT_FALSE(data->page_id());
+  uint64_t page_id = 1;
   data->set_page_id(page_id);
   EXPECT_EQ(page_id, data->page_id().value());
 }
@@ -84,7 +100,7 @@
 TEST_F(DataReductionProxyDataTest, DeepCopy) {
   const struct {
     bool data_reduction_used;
-    bool lofi_on;
+    bool lofi_test_value;
   } tests[] = {
       {
           false, true,
@@ -105,13 +121,17 @@
     static const GURL kTestURL("test-url");
     std::unique_ptr<DataReductionProxyData> data(new DataReductionProxyData());
     data->set_used_data_reduction_proxy(tests[i].data_reduction_used);
-    data->set_lofi_requested(tests[i].lofi_on);
+    data->set_lofi_requested(tests[i].lofi_test_value);
+    data->set_lite_page_received(tests[i].lofi_test_value);
+    data->set_lofi_received(tests[i].lofi_test_value);
     data->set_session_key(kSessionKey);
     data->set_request_url(kTestURL);
     data->set_effective_connection_type(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
     data->set_page_id(2u);
     std::unique_ptr<DataReductionProxyData> copy = data->DeepCopy();
-    EXPECT_EQ(tests[i].lofi_on, copy->lofi_requested());
+    EXPECT_EQ(tests[i].lofi_test_value, copy->lofi_requested());
+    EXPECT_EQ(tests[i].lofi_test_value, copy->lite_page_received());
+    EXPECT_EQ(tests[i].lofi_test_value, copy->lofi_received());
     EXPECT_EQ(tests[i].data_reduction_used, copy->used_data_reduction_proxy());
     EXPECT_EQ(kSessionKey, copy->session_key());
     EXPECT_EQ(kTestURL, copy->request_url());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
index 3e79f4a6..6752c41 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -297,14 +297,17 @@
   data = DataReductionProxyData::GetDataAndCreateIfNecessary(request);
   if (data) {
     data->set_used_data_reduction_proxy(true);
-    data->set_session_key(
-        data_reduction_proxy_request_options_->GetSecureSession());
-    data->set_request_url(request->url());
-    if ((request->load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) &&
-        request->context()->network_quality_estimator()) {
-      data->set_effective_connection_type(request->context()
-                                              ->network_quality_estimator()
-                                              ->GetEffectiveConnectionType());
+    // Only set GURL, NQE and session key string for main frame requests since
+    // they are not needed for sub-resources.
+    if (request->load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) {
+      data->set_session_key(
+          data_reduction_proxy_request_options_->GetSecureSession());
+      data->set_request_url(request->url());
+      if (request->context()->network_quality_estimator()) {
+        data->set_effective_connection_type(request->context()
+                                                ->network_quality_estimator()
+                                                ->GetEffectiveConnectionType());
+      }
     }
   }
 
@@ -414,6 +417,25 @@
   RecordContentLength(*request, request_type, original_content_length);
 }
 
+void DataReductionProxyNetworkDelegate::OnHeadersReceivedInternal(
+    net::URLRequest* request,
+    const net::CompletionCallback& callback,
+    const net::HttpResponseHeaders* original_response_headers,
+    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
+  if (!original_response_headers)
+    return;
+  if (IsEmptyImagePreview(*original_response_headers)) {
+    DataReductionProxyData* data =
+        DataReductionProxyData::GetDataAndCreateIfNecessary(request);
+    data->set_lofi_received(true);
+  } else if (IsLitePagePreview(*original_response_headers)) {
+    DataReductionProxyData* data =
+        DataReductionProxyData::GetDataAndCreateIfNecessary(request);
+    data->set_lite_page_received(true);
+  }
+}
+
 void DataReductionProxyNetworkDelegate::CalculateAndRecordDataUsage(
     const net::URLRequest& request,
     DataReductionProxyRequestType request_type) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
index f32107b..600445d 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
@@ -115,6 +115,15 @@
   void OnCompletedInternal(net::URLRequest* request,
                            bool started) override;
 
+  // Checks if a LoFi or Lite Pages response was received and sets the state on
+  // DataReductionProxyData for |request|.
+  void OnHeadersReceivedInternal(
+      net::URLRequest* request,
+      const net::CompletionCallback& callback,
+      const net::HttpResponseHeaders* original_response_headers,
+      scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) override;
+
   // Calculates actual data usage that went over the network at the HTTP layer
   // (e.g. not including network layer overhead) and estimates original data
   // usage for |request|.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
index 8609191..8f277a9 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -996,8 +996,8 @@
                                 : net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
                 data->effective_connection_type());
       EXPECT_TRUE(data->used_data_reduction_proxy());
-      EXPECT_EQ(GURL(kTestURL), data->request_url());
-      EXPECT_EQ("fake-session", data->session_key());
+      EXPECT_EQ(test.main_frame ? GURL(kTestURL) : GURL(), data->request_url());
+      EXPECT_EQ(test.main_frame ? "fake-session" : "", data->session_key());
       EXPECT_EQ(test.lofi_on, data->lofi_requested());
     }
   }
@@ -1317,8 +1317,10 @@
       response_headers += "Chrome-Proxy-Content-Transform: empty-image\r\n";
 
     response_headers += "\r\n";
-    FetchURLRequest(GURL(kTestURL), nullptr, response_headers, 140, 0);
-
+    auto request =
+        FetchURLRequest(GURL(kTestURL), nullptr, response_headers, 140, 0);
+    EXPECT_EQ(tests[i].lofi_response,
+              DataReductionProxyData::GetData(*request)->lofi_received());
     VerifyDidNotifyLoFiResponse(tests[i].lofi_response);
   }
 }
@@ -1346,7 +1348,9 @@
       "x-original-content-length: 200\r\n";
 
   response_headers += "\r\n";
-  FetchURLRequest(GURL(kTestURL), nullptr, response_headers, 140, 0);
+  auto request =
+      FetchURLRequest(GURL(kTestURL), nullptr, response_headers, 140, 0);
+  EXPECT_TRUE(DataReductionProxyData::GetData(*request)->lite_page_received());
 
   histogram_tester.ExpectBucketCount(kLoFiTransformationTypeHistogram,
                                      LITE_PAGE, 1);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.cc
index 76f0ddd..4d21e66 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.cc
@@ -6,9 +6,11 @@
 
 #include <stdint.h>
 
+#include "base/bind_helpers.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "base/rand_util.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h"
@@ -36,7 +38,8 @@
 // timing and data reduction proxy state.
 void AddDataToPageloadMetrics(const DataReductionProxyData& request_data,
                               const DataReductionProxyPageLoadTiming& timing,
-                              PageloadMetrics* request) {
+                              PageloadMetrics* request,
+                              bool opted_out) {
   request->set_session_key(request_data.session_key());
   // For the timing events, any of them could be zero. Fill the message as a
   // best effort.
@@ -96,6 +99,28 @@
   if (request_data.page_id()) {
     request->set_page_id(request_data.page_id().value());
   }
+
+  bool was_preview_shown = false;
+  if (request_data.lofi_received()) {
+    request->set_previews_type(PageloadMetrics_PreviewsType_LOFI);
+    was_preview_shown = true;
+  } else if (request_data.lite_page_received()) {
+    request->set_previews_type(PageloadMetrics_PreviewsType_LITE_PAGE);
+    was_preview_shown = true;
+  } else {
+    request->set_previews_type(PageloadMetrics_PreviewsType_NONE);
+  }
+
+  if (!was_preview_shown || timing.app_background_occurred) {
+    request->set_previews_opt_out(PageloadMetrics_PreviewsOptOut_UNKNOWN);
+    return;
+  }
+
+  if (opted_out) {
+    request->set_previews_opt_out(PageloadMetrics_PreviewsOptOut_OPT_OUT);
+    return;
+  }
+  request->set_previews_opt_out(PageloadMetrics_PreviewsOptOut_NON_OPT_OUT);
 }
 
 // Adds |current_time| as the metrics sent time to |request_data|, and returns
@@ -119,6 +144,7 @@
       pingback_reporting_fraction_(0.0) {}
 
 DataReductionProxyPingbackClient::~DataReductionProxyPingbackClient() {
+  DCHECK(opt_outs_.empty());
   DCHECK(thread_checker_.CalledOnValidThread());
 }
 
@@ -141,8 +167,18 @@
   UMA_HISTOGRAM_BOOLEAN(kHistogramAttempted, send_pingback);
   if (!send_pingback)
     return;
+
+  bool opted_out = false;
+  if (request_data.page_id()) {
+    auto opt_out = opt_outs_.find(NavigationID(request_data.page_id().value(),
+                                               request_data.session_key()));
+    opted_out = opt_out != opt_outs_.end();
+    if (opted_out)
+      opt_outs_.erase(opt_out);
+  }
+
   PageloadMetrics* pageload_metrics = metrics_request_.add_pageloads();
-  AddDataToPageloadMetrics(request_data, timing, pageload_metrics);
+  AddDataToPageloadMetrics(request_data, timing, pageload_metrics, opted_out);
   if (current_fetcher_.get())
     return;
   DCHECK_EQ(1, metrics_request_.pageloads_size());
@@ -191,4 +227,26 @@
   pingback_reporting_fraction_ = pingback_reporting_fraction;
 }
 
+void DataReductionProxyPingbackClient::AddOptOut(
+    const NavigationID& navigation_id) {
+  opt_outs_.emplace(navigation_id);
+}
+
+void DataReductionProxyPingbackClient::ClearNavigationKeySync(
+    const NavigationID& navigation_id) {
+  opt_outs_.erase(navigation_id);
+}
+
+void DataReductionProxyPingbackClient::ClearNavigationKeyAsync(
+    const NavigationID& navigation_id) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::Bind(&DataReductionProxyPingbackClient::ClearNavigationKeySync,
+                 base::Unretained(this), navigation_id));
+}
+
+size_t DataReductionProxyPingbackClient::OptOutsSizeForTesting() const {
+  return opt_outs_.size();
+}
+
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h
index a91a44c..1f437b6 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h
@@ -5,8 +5,12 @@
 #ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_PINGBACK_CLIENT_H_
 #define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_PINGBACK_CLIENT_H_
 
+#include <stdint.h>
+
 #include <memory>
+#include <set>
 #include <string>
+#include <utility>
 
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
@@ -27,6 +31,8 @@
 class DataReductionProxyData;
 struct DataReductionProxyPageLoadTiming;
 
+using NavigationID = std::pair<uint64_t, std::string>;
+
 // Manages pingbacks about page load timing information to the data saver proxy
 // server. This class is not thread safe.
 class DataReductionProxyPingbackClient : public net::URLFetcherDelegate {
@@ -46,6 +52,17 @@
   // call to SendPingback.
   void SetPingbackReportingFraction(float pingback_reporting_fraction);
 
+  // Adds an opt out for |tab_identifier_key| for a data saver |page_id|. An opt
+  // out occurs when users dismiss the preview in favor of the full page.
+  void AddOptOut(const NavigationID& navigation_id);
+
+  // Removes any stored data associated with |tab_identifier_key| in a task that
+  // runs later.
+  void ClearNavigationKeyAsync(const NavigationID& navigation_id);
+
+  // The total number of pending loads being tracked due to opt outs.
+  size_t OptOutsSizeForTesting() const;
+
  protected:
   // Generates a float in the range [0, 1). Virtualized in testing.
   virtual float GenerateRandomFloat() const;
@@ -66,6 +83,9 @@
   // reset to an empty RecordPageloadMetricsRequest.
   void CreateFetcherForDataAndStart();
 
+  // Removes any stored data associated with |tab_identifier_key|.
+  void ClearNavigationKeySync(const NavigationID& navigation_id);
+
   net::URLRequestContextGetter* url_request_context_;
 
   // The URL for the data saver proxy's ping back service.
@@ -80,6 +100,9 @@
   // The probability of sending a pingback to the server.
   float pingback_reporting_fraction_;
 
+  // The map of tab identifier keys to page IDs.
+  std::set<NavigationID> opt_outs_;
+
   base::ThreadChecker thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(DataReductionProxyPingbackClient);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client_unittest.cc
index de728bf..65c03f3 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <stdint.h>
 
+#include <list>
 #include <memory>
 #include <string>
 
@@ -13,6 +14,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/optional.h"
+#include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
 #include "base/time/time.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
@@ -41,7 +43,6 @@
 static const char kFakeURL[] = "http://www.google.com/";
 static const int64_t kBytes = 10000;
 static const int64_t kBytesOriginal = 1000000;
-static const uint64_t kPageId = 1;
 
 }  // namespace
 
@@ -87,25 +88,7 @@
 
 class DataReductionProxyPingbackClientTest : public testing::Test {
  public:
-  DataReductionProxyPingbackClientTest()
-      : timing_(
-            base::Time::FromJsTime(1500) /* navigation_start */,
-            base::Optional<base::TimeDelta>(
-                base::TimeDelta::FromMilliseconds(1600)) /* response_start */,
-            base::Optional<base::TimeDelta>(
-                base::TimeDelta::FromMilliseconds(1700)) /* load_event_start */,
-            base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
-                1800)) /* first_image_paint */,
-            base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
-                1900)) /* first_contentful_paint */,
-            base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
-                2000)) /* experimental_first_meaningful_paint */,
-            base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
-                100)) /* parse_blocked_on_script_load_duration */,
-            base::Optional<base::TimeDelta>(
-                base::TimeDelta::FromMilliseconds(2000)) /* parse_stop */,
-            kBytes /* network_bytes */,
-            kBytesOriginal /* original_network_bytes */) {}
+  DataReductionProxyPingbackClientTest() {}
 
   TestDataReductionProxyPingbackClient* pingback_client() const {
     return pingback_client_.get();
@@ -117,32 +100,60 @@
     pingback_client_ = base::WrapUnique<TestDataReductionProxyPingbackClient>(
         new TestDataReductionProxyPingbackClient(
             request_context_getter_.get()));
+    page_id_ = 0u;
   }
 
-  void CreateAndSendPingback() {
+  void CreateAndSendPingback(bool lofi_received,
+                             bool lite_page_received,
+                             bool app_background_occurred) {
+    timing_ = base::MakeUnique<DataReductionProxyPageLoadTiming>(
+        base::Time::FromJsTime(1500) /* navigation_start */,
+        base::Optional<base::TimeDelta>(
+            base::TimeDelta::FromMilliseconds(1600)) /* response_start */,
+        base::Optional<base::TimeDelta>(
+            base::TimeDelta::FromMilliseconds(1700)) /* load_event_start */,
+        base::Optional<base::TimeDelta>(
+            base::TimeDelta::FromMilliseconds(1800)) /* first_image_paint */,
+        base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
+            1900)) /* first_contentful_paint */,
+        base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
+            2000)) /* experimental_first_meaningful_paint */,
+        base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
+            100)) /* parse_blocked_on_script_load_duration */,
+        base::Optional<base::TimeDelta>(
+            base::TimeDelta::FromMilliseconds(2000)) /* parse_stop */,
+        kBytes /* network_bytes */, kBytesOriginal /* original_network_bytes */,
+        app_background_occurred /* app_background_occurred */);
+
     DataReductionProxyData request_data;
     request_data.set_session_key(kSessionKey);
     request_data.set_request_url(GURL(kFakeURL));
     request_data.set_effective_connection_type(
         net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
-    request_data.set_page_id(kPageId);
+    request_data.set_lofi_received(lofi_received);
+    request_data.set_lite_page_received(lite_page_received);
+    request_data.set_page_id(page_id_);
     factory()->set_remove_fetcher_on_delete(true);
-    pingback_client()->SendPingback(request_data, timing_);
+    pingback_client()->SendPingback(request_data, *timing_);
+    page_id_++;
   }
 
   net::TestURLFetcherFactory* factory() { return &factory_; }
 
-  const DataReductionProxyPageLoadTiming& timing() { return timing_; }
+  const DataReductionProxyPageLoadTiming& timing() { return *timing_; }
 
   const base::HistogramTester& histogram_tester() { return histogram_tester_; }
 
+  uint64_t page_id() const { return page_id_; }
+
  private:
   base::MessageLoopForIO message_loop_;
   scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
   std::unique_ptr<TestDataReductionProxyPingbackClient> pingback_client_;
   net::TestURLFetcherFactory factory_;
-  DataReductionProxyPageLoadTiming timing_;
+  std::unique_ptr<DataReductionProxyPageLoadTiming> timing_;
   base::HistogramTester histogram_tester_;
+  uint64_t page_id_;
 };
 
 TEST_F(DataReductionProxyPingbackClientTest, VerifyPingbackContent) {
@@ -152,7 +163,10 @@
   pingback_client()->SetPingbackReportingFraction(1.0f);
   base::Time current_time = base::Time::UnixEpoch();
   pingback_client()->set_current_time(current_time);
-  CreateAndSendPingback();
+  uint64_t data_page_id = page_id();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
   net::TestURLFetcher* test_fetcher = factory()->GetFetcherByID(0);
   EXPECT_EQ(test_fetcher->upload_content_type(), "application/x-protobuf");
@@ -191,7 +205,12 @@
   EXPECT_EQ(kFakeURL, pageload_metrics.first_request_url());
   EXPECT_EQ(kBytes, pageload_metrics.compressed_page_size_bytes());
   EXPECT_EQ(kBytesOriginal, pageload_metrics.original_page_size_bytes());
-  EXPECT_EQ(kPageId, pageload_metrics.page_id());
+  EXPECT_EQ(data_page_id, pageload_metrics.page_id());
+
+  EXPECT_EQ(PageloadMetrics_PreviewsType_NONE,
+            pageload_metrics.previews_type());
+  EXPECT_EQ(PageloadMetrics_PreviewsOptOut_UNKNOWN,
+            pageload_metrics.previews_opt_out());
 
   EXPECT_EQ(
       PageloadMetrics_EffectiveConnectionType_EFFECTIVE_CONNECTION_TYPE_OFFLINE,
@@ -209,13 +228,22 @@
   base::Time current_time = base::Time::UnixEpoch();
   pingback_client()->set_current_time(current_time);
   // First pingback
-  CreateAndSendPingback();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
 
   histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
   // Two more pingbacks batched together.
-  CreateAndSendPingback();
+  std::list<uint64_t> page_ids;
+  page_ids.push_back(page_id());
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 2);
-  CreateAndSendPingback();
+  page_ids.push_back(page_id());
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 3);
 
   // Ignore the first pingback.
@@ -264,7 +292,8 @@
     EXPECT_EQ(kFakeURL, pageload_metrics.first_request_url());
     EXPECT_EQ(kBytes, pageload_metrics.compressed_page_size_bytes());
     EXPECT_EQ(kBytesOriginal, pageload_metrics.original_page_size_bytes());
-    EXPECT_EQ(kPageId, pageload_metrics.page_id());
+    EXPECT_EQ(page_ids.front(), pageload_metrics.page_id());
+    page_ids.pop_front();
     EXPECT_EQ(
         PageloadMetrics_EffectiveConnectionType_EFFECTIVE_CONNECTION_TYPE_OFFLINE,
         pageload_metrics.effective_connection_type());
@@ -280,9 +309,13 @@
   EXPECT_FALSE(factory()->GetFetcherByID(0));
   pingback_client()->OverrideRandom(true, 0.5f);
   pingback_client()->SetPingbackReportingFraction(1.0f);
-  CreateAndSendPingback();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
-  CreateAndSendPingback();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 2);
 
   net::TestURLFetcher* test_fetcher = factory()->GetFetcherByID(0);
@@ -301,7 +334,9 @@
   EXPECT_FALSE(factory()->GetFetcherByID(0));
   pingback_client()->OverrideRandom(true, 0.5f);
   pingback_client()->SetPingbackReportingFraction(0.0f);
-  CreateAndSendPingback();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectUniqueSample(kHistogramAttempted, false, 1);
   histogram_tester().ExpectTotalCount(kHistogramSucceeded, 0);
   EXPECT_FALSE(factory()->GetFetcherByID(0));
@@ -315,7 +350,9 @@
   // pingback is created.
   pingback_client()->SetPingbackReportingFraction(0.5f);
   pingback_client()->OverrideRandom(true, 0.4f);
-  CreateAndSendPingback();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
   net::TestURLFetcher* test_fetcher = factory()->GetFetcherByID(0);
   EXPECT_TRUE(test_fetcher);
@@ -325,7 +362,9 @@
   // Verify that if the random number is greater than the reporting fraction,
   // the pingback is not created.
   pingback_client()->OverrideRandom(true, 0.6f);
-  CreateAndSendPingback();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectBucketCount(kHistogramAttempted, false, 1);
   test_fetcher = factory()->GetFetcherByID(0);
   EXPECT_FALSE(test_fetcher);
@@ -335,7 +374,9 @@
   // and the random number is zero, no pingback is sent.
   pingback_client()->SetPingbackReportingFraction(0.0f);
   pingback_client()->OverrideRandom(true, 0.0f);
-  CreateAndSendPingback();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectBucketCount(kHistogramAttempted, false, 2);
   test_fetcher = factory()->GetFetcherByID(0);
   EXPECT_FALSE(test_fetcher);
@@ -345,7 +386,9 @@
       data_reduction_proxy::switches::kEnableDataReductionProxyForcePingback);
   pingback_client()->SetPingbackReportingFraction(0.0f);
   pingback_client()->OverrideRandom(true, 1.0f);
-  CreateAndSendPingback();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectBucketCount(kHistogramAttempted, true, 2);
   test_fetcher = factory()->GetFetcherByID(0);
   EXPECT_TRUE(test_fetcher);
@@ -358,7 +401,9 @@
   EXPECT_FALSE(factory()->GetFetcherByID(0));
   pingback_client()->OverrideRandom(true, 0.5f);
   pingback_client()->SetPingbackReportingFraction(1.0f);
-  CreateAndSendPingback();
+  CreateAndSendPingback(false /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
   histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
   net::TestURLFetcher* test_fetcher = factory()->GetFetcherByID(0);
   EXPECT_TRUE(test_fetcher);
@@ -369,4 +414,166 @@
   histogram_tester().ExpectUniqueSample(kHistogramSucceeded, false, 1);
 }
 
+TEST_F(DataReductionProxyPingbackClientTest, VerifyLoFiContentNoOptOut) {
+  Init();
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+  pingback_client()->OverrideRandom(true, 0.5f);
+  pingback_client()->SetPingbackReportingFraction(1.0f);
+  base::Time current_time = base::Time::UnixEpoch();
+  pingback_client()->set_current_time(current_time);
+  CreateAndSendPingback(true /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
+  histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
+  net::TestURLFetcher* test_fetcher = factory()->GetFetcherByID(0);
+  EXPECT_EQ(test_fetcher->upload_content_type(), "application/x-protobuf");
+  RecordPageloadMetricsRequest batched_request;
+  batched_request.ParseFromString(test_fetcher->upload_data());
+  EXPECT_EQ(batched_request.pageloads_size(), 1);
+  PageloadMetrics pageload_metrics = batched_request.pageloads(0);
+  EXPECT_EQ(PageloadMetrics_PreviewsType_LOFI,
+            pageload_metrics.previews_type());
+  EXPECT_EQ(PageloadMetrics_PreviewsOptOut_NON_OPT_OUT,
+            pageload_metrics.previews_opt_out());
+
+  test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+}
+
+TEST_F(DataReductionProxyPingbackClientTest, VerifyLoFiContentOptOut) {
+  Init();
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+  pingback_client()->OverrideRandom(true, 0.5f);
+  pingback_client()->SetPingbackReportingFraction(1.0f);
+  base::Time current_time = base::Time::UnixEpoch();
+  pingback_client()->set_current_time(current_time);
+  pingback_client()->AddOptOut(NavigationID(page_id(), kSessionKey));
+  CreateAndSendPingback(true /* lofi_received */,
+                        false /* lite_page_received */,
+                        false /* app_background_occurred */);
+  histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
+  net::TestURLFetcher* test_fetcher = factory()->GetFetcherByID(0);
+  EXPECT_EQ(test_fetcher->upload_content_type(), "application/x-protobuf");
+  RecordPageloadMetricsRequest batched_request;
+  batched_request.ParseFromString(test_fetcher->upload_data());
+  EXPECT_EQ(batched_request.pageloads_size(), 1);
+  PageloadMetrics pageload_metrics = batched_request.pageloads(0);
+  EXPECT_EQ(PageloadMetrics_PreviewsType_LOFI,
+            pageload_metrics.previews_type());
+  EXPECT_EQ(PageloadMetrics_PreviewsOptOut_OPT_OUT,
+            pageload_metrics.previews_opt_out());
+
+  test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+}
+
+TEST_F(DataReductionProxyPingbackClientTest, VerifyLoFiContentBackground) {
+  Init();
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+  pingback_client()->OverrideRandom(true, 0.5f);
+  pingback_client()->SetPingbackReportingFraction(1.0f);
+  base::Time current_time = base::Time::UnixEpoch();
+  pingback_client()->set_current_time(current_time);
+  pingback_client()->AddOptOut(NavigationID(page_id(), kSessionKey));
+  CreateAndSendPingback(true /* lofi_received */,
+                        false /* lite_page_received */,
+                        true /* app_background_occurred */);
+  histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
+  net::TestURLFetcher* test_fetcher = factory()->GetFetcherByID(0);
+  EXPECT_EQ(test_fetcher->upload_content_type(), "application/x-protobuf");
+  RecordPageloadMetricsRequest batched_request;
+  batched_request.ParseFromString(test_fetcher->upload_data());
+  EXPECT_EQ(batched_request.pageloads_size(), 1);
+  PageloadMetrics pageload_metrics = batched_request.pageloads(0);
+  EXPECT_EQ(PageloadMetrics_PreviewsType_LOFI,
+            pageload_metrics.previews_type());
+  EXPECT_EQ(PageloadMetrics_PreviewsOptOut_UNKNOWN,
+            pageload_metrics.previews_opt_out());
+
+  test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+}
+
+TEST_F(DataReductionProxyPingbackClientTest, VerifyLitePageContent) {
+  Init();
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+  pingback_client()->OverrideRandom(true, 0.5f);
+  pingback_client()->SetPingbackReportingFraction(1.0f);
+  base::Time current_time = base::Time::UnixEpoch();
+  pingback_client()->set_current_time(current_time);
+  pingback_client()->AddOptOut(NavigationID(page_id(), kSessionKey));
+  CreateAndSendPingback(false /* lofi_received */,
+                        true /* lite_page_received */,
+                        false /* app_background_occurred */);
+  histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
+  net::TestURLFetcher* test_fetcher = factory()->GetFetcherByID(0);
+  EXPECT_EQ(test_fetcher->upload_content_type(), "application/x-protobuf");
+  RecordPageloadMetricsRequest batched_request;
+  batched_request.ParseFromString(test_fetcher->upload_data());
+  EXPECT_EQ(batched_request.pageloads_size(), 1);
+  PageloadMetrics pageload_metrics = batched_request.pageloads(0);
+  EXPECT_EQ(PageloadMetrics_PreviewsType_LITE_PAGE,
+            pageload_metrics.previews_type());
+  EXPECT_EQ(PageloadMetrics_PreviewsOptOut_OPT_OUT,
+            pageload_metrics.previews_opt_out());
+
+  test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+}
+
+TEST_F(DataReductionProxyPingbackClientTest, VerifyTwoLitePagePingbacks) {
+  Init();
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+  pingback_client()->OverrideRandom(true, 0.5f);
+  pingback_client()->SetPingbackReportingFraction(1.0f);
+  base::Time current_time = base::Time::UnixEpoch();
+  pingback_client()->set_current_time(current_time);
+  pingback_client()->AddOptOut(NavigationID(page_id(), kSessionKey));
+  CreateAndSendPingback(false /* lofi_received */,
+                        true /* lite_page_received */,
+                        false /* app_background_occurred */);
+  pingback_client()->AddOptOut(NavigationID(page_id(), kSessionKey));
+  CreateAndSendPingback(false /* lofi_received */,
+                        true /* lite_page_received */,
+                        false /* app_background_occurred */);
+  histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 2);
+  net::TestURLFetcher* test_fetcher = factory()->GetFetcherByID(0);
+  EXPECT_EQ(test_fetcher->upload_content_type(), "application/x-protobuf");
+  RecordPageloadMetricsRequest batched_request;
+  batched_request.ParseFromString(test_fetcher->upload_data());
+  EXPECT_EQ(batched_request.pageloads_size(), 1);
+  PageloadMetrics pageload_metrics = batched_request.pageloads(0);
+  EXPECT_EQ(PageloadMetrics_PreviewsType_LITE_PAGE,
+            pageload_metrics.previews_type());
+  EXPECT_EQ(PageloadMetrics_PreviewsOptOut_OPT_OUT,
+            pageload_metrics.previews_opt_out());
+  test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
+  test_fetcher = factory()->GetFetcherByID(0);
+  EXPECT_EQ(test_fetcher->upload_content_type(), "application/x-protobuf");
+  batched_request.ParseFromString(test_fetcher->upload_data());
+  EXPECT_EQ(batched_request.pageloads_size(), 1);
+  pageload_metrics = batched_request.pageloads(0);
+  EXPECT_EQ(PageloadMetrics_PreviewsType_LITE_PAGE,
+            pageload_metrics.previews_type());
+  EXPECT_EQ(PageloadMetrics_PreviewsOptOut_OPT_OUT,
+            pageload_metrics.previews_opt_out());
+  test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+}
+
+TEST_F(DataReductionProxyPingbackClientTest, VerifyClearingPendingLoads) {
+  Init();
+  EXPECT_FALSE(factory()->GetFetcherByID(0));
+  pingback_client()->OverrideRandom(true, 0.5f);
+  pingback_client()->SetPingbackReportingFraction(1.0f);
+  base::Time current_time = base::Time::UnixEpoch();
+  pingback_client()->set_current_time(current_time);
+  pingback_client()->AddOptOut(NavigationID(page_id(), kSessionKey));
+  EXPECT_EQ(1u, pingback_client()->OptOutsSizeForTesting());
+  pingback_client()->ClearNavigationKeyAsync(
+      NavigationID(page_id(), kSessionKey));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(0u, pingback_client()->OptOutsSizeForTesting());
+}
+
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.cc
index 22a9b10..13ff57d2 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.cc
@@ -17,7 +17,8 @@
         parse_blocked_on_script_load_duration,
     const base::Optional<base::TimeDelta>& parse_stop,
     int64_t network_bytes,
-    int64_t original_network_bytes)
+    int64_t original_network_bytes,
+    bool app_background_occurred)
     : navigation_start(navigation_start),
       response_start(response_start),
       load_event_start(load_event_start),
@@ -28,7 +29,8 @@
           parse_blocked_on_script_load_duration),
       parse_stop(parse_stop),
       network_bytes(network_bytes),
-      original_network_bytes(original_network_bytes) {}
+      original_network_bytes(original_network_bytes),
+      app_background_occurred(app_background_occurred) {}
 
 DataReductionProxyPageLoadTiming::DataReductionProxyPageLoadTiming(
     const DataReductionProxyPageLoadTiming& other) = default;
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h
index a1224225..84e1357 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h
@@ -26,7 +26,8 @@
           parse_blocked_on_script_load_duration,
       const base::Optional<base::TimeDelta>& parse_stop,
       int64_t network_bytes,
-      int64_t original_network_bytes);
+      int64_t original_network_bytes,
+      bool app_background_occurred);
 
   DataReductionProxyPageLoadTiming(
       const DataReductionProxyPageLoadTiming& other);
@@ -57,6 +58,8 @@
   // The number of bytes that would have been served over the network if the
   // user were not using data reduction proxy, not including headers.
   const int64_t original_network_bytes;
+  // True when android app background occurred during the page load lifetime.
+  const bool app_background_occurred;
 };
 
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/proto/pageload_metrics.proto b/components/data_reduction_proxy/proto/pageload_metrics.proto
index ca26f38..1725604 100644
--- a/components/data_reduction_proxy/proto/pageload_metrics.proto
+++ b/components/data_reduction_proxy/proto/pageload_metrics.proto
@@ -34,6 +34,26 @@
     EFFECTIVE_CONNECTION_TYPE_4G = 5;
   };
 
+  // The various opt out states seen by server previews.
+  enum PreviewsOptOut {
+    // Set for non-previews navigations and app background navigations.
+    UNKNOWN = 0;
+    // Set for previews navigations that clicked "show original".
+    OPT_OUT = 1;
+    // Set for previews navigations that did not click "show original".
+    NON_OPT_OUT = 2;
+  }
+
+  // The various server previews that can be shown.
+  enum PreviewsType {
+    // No server preview was applied.
+    NONE = 0;
+    // Image placeholders were used on the page.
+    LOFI = 1;
+    // The main resource was a lite page.
+    LITE_PAGE = 2;
+  }
+
   // The session key used to load the page.
   optional string session_key = 1;
   // The time at which the first request of the pageload was made, according to
@@ -75,4 +95,10 @@
 
   // The unique identifier for the page load.
   optional uint64 page_id = 16;
+
+  // The opt out state of the page load.
+  optional PreviewsOptOut previews_opt_out = 17;
+
+  // The previews type that was used on the page.
+  optional PreviewsType previews_type = 18;
 }
diff --git a/components/display_compositor/host_shared_bitmap_manager.cc b/components/display_compositor/host_shared_bitmap_manager.cc
index cd914f5..a72ab949 100644
--- a/components/display_compositor/host_shared_bitmap_manager.cc
+++ b/components/display_compositor/host_shared_bitmap_manager.cc
@@ -86,19 +86,6 @@
   this->ChildAllocatedSharedBitmap(size, memory_handle, id);
 }
 
-void HostSharedBitmapManagerClient::AllocateSharedBitmapForChild(
-    base::ProcessHandle process_handle,
-    size_t buffer_size,
-    const cc::SharedBitmapId& id,
-    base::SharedMemoryHandle* shared_memory_handle) {
-  manager_->AllocateSharedBitmapForChild(process_handle, buffer_size, id,
-                                         shared_memory_handle);
-  if (*shared_memory_handle != base::SharedMemory::NULLHandle()) {
-    base::AutoLock lock(lock_);
-    owned_bitmaps_.insert(id);
-  }
-}
-
 void HostSharedBitmapManagerClient::ChildAllocatedSharedBitmap(
     size_t buffer_size,
     const base::SharedMemoryHandle& handle,
@@ -215,35 +202,6 @@
   return true;
 }
 
-void HostSharedBitmapManager::AllocateSharedBitmapForChild(
-    base::ProcessHandle process_handle,
-    size_t buffer_size,
-    const cc::SharedBitmapId& id,
-    base::SharedMemoryHandle* shared_memory_handle) {
-  base::AutoLock lock(lock_);
-  if (handle_map_.find(id) != handle_map_.end()) {
-    *shared_memory_handle = base::SharedMemory::NULLHandle();
-    return;
-  }
-  std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
-  if (!shared_memory->CreateAndMapAnonymous(buffer_size)) {
-    LOG(ERROR) << "Cannot create shared memory buffer";
-    *shared_memory_handle = base::SharedMemory::NULLHandle();
-    return;
-  }
-
-  scoped_refptr<BitmapData> data(new BitmapData(buffer_size));
-  data->memory = std::move(shared_memory);
-
-  handle_map_[id] = data;
-  if (!data->memory->ShareToProcess(process_handle, shared_memory_handle)) {
-    LOG(ERROR) << "Cannot share shared memory buffer";
-    *shared_memory_handle = base::SharedMemory::NULLHandle();
-    return;
-  }
-  data->memory->Close();
-}
-
 void HostSharedBitmapManager::ChildDeletedSharedBitmap(
     const cc::SharedBitmapId& id) {
   base::AutoLock lock(lock_);
diff --git a/components/display_compositor/host_shared_bitmap_manager.h b/components/display_compositor/host_shared_bitmap_manager.h
index 05706c3..e2ebc5f 100644
--- a/components/display_compositor/host_shared_bitmap_manager.h
+++ b/components/display_compositor/host_shared_bitmap_manager.h
@@ -50,11 +50,6 @@
                                const cc::SharedBitmapId& id) override;
   void DidDeleteSharedBitmap(const cc::SharedBitmapId& id) override;
 
-  void AllocateSharedBitmapForChild(
-      base::ProcessHandle process_handle,
-      size_t buffer_size,
-      const cc::SharedBitmapId& id,
-      base::SharedMemoryHandle* shared_memory_handle);
   void ChildAllocatedSharedBitmap(size_t buffer_size,
                                   const base::SharedMemoryHandle& handle,
                                   const cc::SharedBitmapId& id);
@@ -97,11 +92,6 @@
  private:
   friend class HostSharedBitmapManagerClient;
 
-  void AllocateSharedBitmapForChild(
-      base::ProcessHandle process_handle,
-      size_t buffer_size,
-      const cc::SharedBitmapId& id,
-      base::SharedMemoryHandle* shared_memory_handle);
   bool ChildAllocatedSharedBitmap(size_t buffer_size,
                                   const base::SharedMemoryHandle& handle,
                                   const cc::SharedBitmapId& id);
diff --git a/components/display_compositor/host_shared_bitmap_manager_unittest.cc b/components/display_compositor/host_shared_bitmap_manager_unittest.cc
index e3ea524..dd6bbe99 100644
--- a/components/display_compositor/host_shared_bitmap_manager_unittest.cc
+++ b/components/display_compositor/host_shared_bitmap_manager_unittest.cc
@@ -76,31 +76,6 @@
   shared_bitmap.reset();
 }
 
-TEST_F(HostSharedBitmapManagerTest, TestCreateForChild) {
-  gfx::Size bitmap_size(1, 1);
-  size_t size_in_bytes;
-  EXPECT_TRUE(cc::SharedBitmap::SizeInBytes(bitmap_size, &size_in_bytes));
-  cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
-  HostSharedBitmapManagerClient client(manager_.get());
-  base::SharedMemoryHandle handle;
-  client.AllocateSharedBitmapForChild(base::GetCurrentProcessHandle(),
-                                      size_in_bytes, id, &handle);
-
-  EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle));
-  std::unique_ptr<base::SharedMemory> bitmap(
-      new base::SharedMemory(handle, false));
-  EXPECT_TRUE(bitmap->Map(size_in_bytes));
-  memset(bitmap->memory(), 0xff, size_in_bytes);
-
-  std::unique_ptr<cc::SharedBitmap> shared_bitmap;
-  shared_bitmap = manager_->GetSharedBitmapFromId(bitmap_size, id);
-  EXPECT_TRUE(shared_bitmap);
-  EXPECT_TRUE(
-      memcmp(bitmap->memory(), shared_bitmap->pixels(), size_in_bytes) == 0);
-
-  client.DidDeleteSharedBitmap(id);
-}
-
 TEST_F(HostSharedBitmapManagerTest, RemoveProcess) {
   gfx::Size bitmap_size(1, 1);
   size_t size_in_bytes;
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index ab863b1..7b57ba8 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -833,7 +833,7 @@
   gfx::Rect quad_rect = output_rect;
   cc::SharedQuadState* quad_state =
       render_pass->CreateAndAppendSharedQuadState();
-  quad_state->quad_layer_bounds = contents_surface_size;
+  quad_state->quad_layer_rect = gfx::Rect(contents_surface_size);
   quad_state->visible_quad_layer_rect = quad_rect;
   quad_state->opacity = state_.alpha;
 
diff --git a/components/omnibox/browser/base_search_provider.cc b/components/omnibox/browser/base_search_provider.cc
index 8a331e7..51e9d5b 100644
--- a/components/omnibox/browser/base_search_provider.cc
+++ b/components/omnibox/browser/base_search_provider.cc
@@ -23,6 +23,7 @@
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_service.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "url/gurl.h"
@@ -62,9 +63,44 @@
   GURL url(deletion_url);
   DCHECK(url.is_valid());
 
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("omnibox_suggest_deletion", R"(
+        semantics {
+          sender: "Omnibox"
+          description:
+            "When users attempt to delete server-provided personalized search "
+            "or navigation suggestions from the omnibox dropdown, Chrome sends "
+            "a message to the server requesting deletion of the suggestion."
+          trigger:
+            "A user attempt to delete a server-provided omnibox suggestion, "
+            "for which the server provided a custom deletion URL."
+          data:
+            "No user data is explicitly sent with the request, but because the "
+            "requested URL is provided by the server for each specific "
+            "suggestion, it necessarily uniquely identifies the suggestion the "
+            "user is attempting to delete."
+          destination: WEBSITE
+        }
+        policy {
+          cookies_allowed: true
+          cookies_store: "user"
+          setting:
+            "Since this can only be triggered on seeing server-provided "
+            "suggestions in the omnibox dropdown, whether it is enabled is the "
+            "same as whether those suggestions are enabled.\n"
+            "Users can control this feature via the 'Use a prediction service "
+            "to help complete searches and URLs typed in the address bar' "
+            "setting under 'Privacy'. The feature is enabled by default."
+          chrome_policy {
+            SearchSuggestEnabled {
+                policy_options {mode: MANDATORY}
+                SearchSuggestEnabled: false
+            }
+          }
+        })");
   deletion_fetcher_ =
       net::URLFetcher::Create(BaseSearchProvider::kDeletionURLFetcherID, url,
-                              net::URLFetcher::GET, this);
+                              net::URLFetcher::GET, this, traffic_annotation);
   data_use_measurement::DataUseUserData::AttachToFetcher(
       deletion_fetcher_.get(), data_use_measurement::DataUseUserData::OMNIBOX);
   deletion_fetcher_->SetRequestContext(request_context);
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc
index 202de541..98e697c 100644
--- a/components/omnibox/browser/search_provider.cc
+++ b/components/omnibox/browser/search_provider.cc
@@ -41,6 +41,7 @@
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_request_headers.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -902,8 +903,36 @@
 
   LogOmniboxSuggestRequest(REQUEST_SENT);
 
-  std::unique_ptr<net::URLFetcher> fetcher =
-      net::URLFetcher::Create(id, suggest_url, net::URLFetcher::GET, this);
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("omnibox_suggest", R"(
+        semantics {
+          sender: "Omnibox"
+          description:
+            "Chrome can provide search and navigation suggestions from the "
+            "currently-selected search provider in the omnibox dropdown, based "
+            "on user input."
+          trigger: "User typing in the omnibox."
+          data:
+            "The text typed into the address bar. Potentially other metadata, "
+            "such as the current cursor position or URL of the current page."
+          destination: WEBSITE
+        }
+        policy {
+          cookies_allowed: true
+          cookies_store: "user"
+          setting:
+            "Users can control this feature via the 'Use a prediction service "
+            "to help complete searches and URLs typed in the address bar' "
+            "setting under 'Privacy'. The feature is enabled by default."
+          chrome_policy {
+            SearchSuggestEnabled {
+                policy_options {mode: MANDATORY}
+                SearchSuggestEnabled: false
+            }
+          }
+        })");
+  std::unique_ptr<net::URLFetcher> fetcher = net::URLFetcher::Create(
+      id, suggest_url, net::URLFetcher::GET, this, traffic_annotation);
   data_use_measurement::DataUseUserData::AttachToFetcher(
       fetcher.get(), data_use_measurement::DataUseUserData::OMNIBOX);
   fetcher->SetRequestContext(client()->GetRequestContext());
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc
index 8a7dcf7..17569a2 100644
--- a/components/omnibox/browser/zero_suggest_provider.cc
+++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -38,6 +38,7 @@
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_request_headers.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
 #include "url/gurl.h"
@@ -378,9 +379,39 @@
                      weak_ptr_factory_.GetWeakPtr()), false);
     }
   } else {
+    net::NetworkTrafficAnnotationTag traffic_annotation =
+        net::DefineNetworkTrafficAnnotation("omnibox_zerosuggest", R"(
+        semantics {
+          sender: "Omnibox"
+          description:
+            "When the user focuses the omnibox, Chrome can provide search or "
+            "navigation suggestions from the default search provider in the "
+            "omnibox dropdown, based on the current page URL.\n"
+            "This is limited to users whose default search engine is Google, "
+            "as no other search engines currently support this kind of "
+            "suggestion."
+          trigger: "The omnibox receives focus."
+          data: "The URL of the current page."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: true
+          cookies_store: "user"
+          setting:
+            "Users can control this feature via the 'Use a prediction service "
+            "to help complete searches and URLs typed in the address bar' "
+            "settings under 'Privacy'. The feature is enabled by default."
+          chrome_policy {
+            SearchSuggestEnabled {
+                policy_options {mode: MANDATORY}
+                SearchSuggestEnabled: false
+            }
+          }
+        })");
     const int kFetcherID = 1;
-    fetcher_ = net::URLFetcher::Create(kFetcherID, suggest_url,
-                                       net::URLFetcher::GET, this);
+    fetcher_ =
+        net::URLFetcher::Create(kFetcherID, suggest_url, net::URLFetcher::GET,
+                                this, traffic_annotation);
     data_use_measurement::DataUseUserData::AttachToFetcher(
         fetcher_.get(), data_use_measurement::DataUseUserData::OMNIBOX);
     fetcher_->SetRequestContext(client()->GetRequestContext());
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
index aaf180d..236650e3 100644
--- a/components/payments/content/payment_request_state.cc
+++ b/components/payments/content/payment_request_state.cc
@@ -80,8 +80,8 @@
 
   // Once the response is ready, will call back into OnPaymentResponseReady.
   response_helper_ = base::MakeUnique<PaymentResponseHelper>(
-      app_locale_, spec_, selected_instrument_, selected_shipping_profile_,
-      selected_contact_profile_, this);
+      app_locale_, spec_, selected_instrument_, payment_request_delegate_,
+      selected_shipping_profile_, selected_contact_profile_, this);
 }
 
 void PaymentRequestState::AddAutofillPaymentInstrument(
diff --git a/components/payments/content/payment_response_helper.cc b/components/payments/content/payment_response_helper.cc
index 0d1177a..0ce64fa 100644
--- a/components/payments/content/payment_response_helper.cc
+++ b/components/payments/content/payment_response_helper.cc
@@ -6,36 +6,58 @@
 
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/payments/content/payment_request_spec.h"
-#include "third_party/libphonenumber/phonenumber_api.h"
+#include "components/payments/core/payment_request_data_util.h"
+#include "components/payments/core/payment_request_delegate.h"
 
 namespace payments {
 
-namespace {
-
-using ::i18n::phonenumbers::PhoneNumberUtil;
-
-}  // namespace
-
 PaymentResponseHelper::PaymentResponseHelper(
     const std::string& app_locale,
     PaymentRequestSpec* spec,
     PaymentInstrument* selected_instrument,
+    PaymentRequestDelegate* payment_request_delegate,
     autofill::AutofillProfile* selected_shipping_profile,
     autofill::AutofillProfile* selected_contact_profile,
     Delegate* delegate)
     : app_locale_(app_locale),
+      is_waiting_for_shipping_address_normalization_(false),
+      is_waiting_for_instrument_details_(false),
       spec_(spec),
       delegate_(delegate),
       selected_instrument_(selected_instrument),
-      selected_shipping_profile_(selected_shipping_profile),
+      payment_request_delegate_(payment_request_delegate),
       selected_contact_profile_(selected_contact_profile) {
   DCHECK(spec_);
   DCHECK(selected_instrument_);
   DCHECK(delegate_);
 
+  is_waiting_for_instrument_details_ = true;
+
+  // Start to normalize the shipping address, if necessary.
+  if (spec_->request_shipping()) {
+    DCHECK(selected_shipping_profile);
+    DCHECK(spec_->selected_shipping_option());
+
+    is_waiting_for_shipping_address_normalization_ = true;
+
+    // Use the country code from the profile if it is set, otherwise infer it
+    // from the |app_locale_|.
+    std::string country_code = base::UTF16ToUTF8(
+        selected_shipping_profile->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY));
+    if (!autofill::data_util::IsValidCountryCode(country_code)) {
+      country_code =
+          autofill::AutofillCountry::CountryCodeForLocale(app_locale_);
+    }
+
+    payment_request_delegate_->GetAddressNormalizer()
+        ->StartAddressNormalization(*selected_shipping_profile, country_code,
+                                    /*timeout_seconds=*/5, this);
+  }
+
   // Start to get the instrument details. Will call back into
   // OnInstrumentDetailsReady.
   selected_instrument_->InvokePaymentApp(this);
@@ -83,25 +105,52 @@
 void PaymentResponseHelper::OnInstrumentDetailsReady(
     const std::string& method_name,
     const std::string& stringified_details) {
+  method_name_ = method_name;
+  stringified_details_ = stringified_details;
+  is_waiting_for_instrument_details_ = false;
+
+  if (!is_waiting_for_shipping_address_normalization_)
+    GeneratePaymentResponse();
+}
+
+void PaymentResponseHelper::OnAddressNormalized(
+    const autofill::AutofillProfile& normalized_profile) {
+  if (is_waiting_for_shipping_address_normalization_) {
+    shipping_address_ = normalized_profile;
+    is_waiting_for_shipping_address_normalization_ = false;
+
+    if (!is_waiting_for_instrument_details_)
+      GeneratePaymentResponse();
+  }
+}
+
+void PaymentResponseHelper::OnCouldNotNormalize(
+    const autofill::AutofillProfile& profile) {
+  // Since the phone number is formatted in either case, this profile should be
+  // used.
+  OnAddressNormalized(profile);
+}
+
+void PaymentResponseHelper::GeneratePaymentResponse() {
+  DCHECK(!is_waiting_for_instrument_details_);
+  DCHECK(!is_waiting_for_shipping_address_normalization_);
+
   mojom::PaymentResponsePtr payment_response = mojom::PaymentResponse::New();
 
   // Make sure that we return the method name that the merchant specified for
   // this instrument: cards can be either specified through their name (e.g.,
   // "visa") or through basic-card's supportedNetworks.
   payment_response->method_name =
-      spec_->IsMethodSupportedThroughBasicCard(method_name)
+      spec_->IsMethodSupportedThroughBasicCard(method_name_)
           ? kBasicCardMethodName
-          : method_name;
-  payment_response->stringified_details = stringified_details;
+          : method_name_;
+  payment_response->stringified_details = stringified_details_;
 
   // Shipping Address section
   if (spec_->request_shipping()) {
-    DCHECK(selected_shipping_profile_);
     payment_response->shipping_address =
-        GetMojomPaymentAddressFromAutofillProfile(selected_shipping_profile_,
+        GetMojomPaymentAddressFromAutofillProfile(&shipping_address_,
                                                   app_locale_);
-
-    DCHECK(spec_->selected_shipping_option());
     payment_response->shipping_option = spec_->selected_shipping_option()->id;
   }
 
@@ -124,23 +173,15 @@
     // Response, as defined in the Payment Request spec. If it's not possible,
     // send the original. More info at:
     // https://w3c.github.io/browser-payment-api/#paymentrequest-updated-algorithm
-    // TODO(sebsg): Move this code to a reusable location.
     const std::string original_number =
         base::UTF16ToUTF8(selected_contact_profile_->GetInfo(
             autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER),
             app_locale_));
-    i18n::phonenumbers::PhoneNumber parsed_number;
-    PhoneNumberUtil* phone_number_util = PhoneNumberUtil::GetInstance();
-    if (phone_number_util->Parse(original_number, "US", &parsed_number) ==
-        ::i18n::phonenumbers::PhoneNumberUtil::NO_PARSING_ERROR) {
-      std::string formatted_number;
-      phone_number_util->Format(parsed_number,
-                                PhoneNumberUtil::PhoneNumberFormat::E164,
-                                &formatted_number);
-      payment_response->payer_phone = formatted_number;
-    } else {
-      payment_response->payer_phone = original_number;
-    }
+
+    const std::string default_region_code =
+        autofill::AutofillCountry::CountryCodeForLocale(app_locale_);
+    payment_response->payer_phone =
+        data_util::FormatPhoneForResponse(original_number, default_region_code);
   }
 
   delegate_->OnPaymentResponseReady(std::move(payment_response));
diff --git a/components/payments/content/payment_response_helper.h b/components/payments/content/payment_response_helper.h
index 69e0383..fde039d7 100644
--- a/components/payments/content/payment_response_helper.h
+++ b/components/payments/content/payment_response_helper.h
@@ -6,21 +6,21 @@
 #define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_RESPONSE_HELPER_H_
 
 #include "base/macros.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/payments/core/address_normalizer.h"
 #include "components/payments/core/payment_instrument.h"
 #include "components/payments/mojom/payment_request.mojom.h"
 
-namespace autofill {
-class AutofillProfile;
-}  // namespace autofill
-
 namespace payments {
 
+class PaymentRequestDelegate;
 class PaymentRequestSpec;
 
 // TODO(sebsg): Asynchronously normalize the billing and shipping addresses
 // before adding them to the PaymentResponse.
 // A helper class to facilitate the creation of the PaymentResponse.
-class PaymentResponseHelper : public PaymentInstrument::Delegate {
+class PaymentResponseHelper : public PaymentInstrument::Delegate,
+                              AddressNormalizer::Delegate {
  public:
   class Delegate {
    public:
@@ -34,6 +34,7 @@
   PaymentResponseHelper(const std::string& app_locale,
                         PaymentRequestSpec* spec,
                         PaymentInstrument* selected_instrument,
+                        PaymentRequestDelegate* payment_request_delegate,
                         autofill::AutofillProfile* selected_shipping_profile,
                         autofill::AutofillProfile* selected_contact_profile,
                         Delegate* delegate);
@@ -51,18 +52,34 @@
       const std::string& stringified_details) override;
   void OnInstrumentDetailsError() override {}
 
+  // AddressNormalizer::Delegate
+  void OnAddressNormalized(
+      const autofill::AutofillProfile& normalized_profile) override;
+  void OnCouldNotNormalize(const autofill::AutofillProfile& profile) override;
+
  private:
+  // Generates the Payment Response and sends it to the delegate.
+  void GeneratePaymentResponse();
+
   const std::string& app_locale_;
+  bool is_waiting_for_shipping_address_normalization_;
+  bool is_waiting_for_instrument_details_;
 
   // Not owned, cannot be null.
   PaymentRequestSpec* spec_;
   Delegate* delegate_;
   PaymentInstrument* selected_instrument_;
+  PaymentRequestDelegate* payment_request_delegate_;
 
   // Not owned, can be null (dependent on the spec).
-  autofill::AutofillProfile* selected_shipping_profile_;
   autofill::AutofillProfile* selected_contact_profile_;
 
+  autofill::AutofillProfile shipping_address_;
+
+  // Instrument Details.
+  std::string method_name_;
+  std::string stringified_details_;
+
   DISALLOW_COPY_AND_ASSIGN(PaymentResponseHelper);
 };
 
diff --git a/components/payments/content/payment_response_helper_unittest.cc b/components/payments/content/payment_response_helper_unittest.cc
index ed9757c5..a79d8d1 100644
--- a/components/payments/content/payment_response_helper_unittest.cc
+++ b/components/payments/content/payment_response_helper_unittest.cc
@@ -16,6 +16,7 @@
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/payments/content/payment_request_spec.h"
+#include "components/payments/core/address_normalizer.h"
 #include "components/payments/core/autofill_payment_instrument.h"
 #include "components/payments/core/payment_request_delegate.h"
 #include "components/payments/mojom/payment_request.mojom.h"
@@ -23,6 +24,28 @@
 
 namespace payments {
 
+class FakeAddressNormalizer : public AddressNormalizer {
+ public:
+  FakeAddressNormalizer() {}
+
+  void LoadRulesForRegion(const std::string& region_code) override {}
+
+  bool AreRulesLoadedForRegion(const std::string& region_code) override {
+    return true;
+  }
+
+  void StartAddressNormalization(
+      const autofill::AutofillProfile& profile,
+      const std::string& region_code,
+      int timeout_seconds,
+      AddressNormalizer::Delegate* requester) override {
+    requester->OnAddressNormalized(profile);
+  }
+
+  void OnAddressValidationRulesLoaded(const std::string& region_code,
+                                      bool success) override {}
+};
+
 class FakePaymentRequestDelegate : public PaymentRequestDelegate {
  public:
   FakePaymentRequestDelegate(
@@ -58,7 +81,7 @@
                                                 base::ASCIIToUTF16("123"));
   }
 
-  std::unique_ptr<const ::i18n::addressinput::Source> GetAddressInputSource()
+  std::unique_ptr<::i18n::addressinput::Source> GetAddressInputSource()
       override {
     return nullptr;
   }
@@ -68,10 +91,15 @@
     return nullptr;
   }
 
+  AddressNormalizer* GetAddressNormalizer() override {
+    return &address_normalizer_;
+  }
+
  private:
   autofill::PersonalDataManager* personal_data_manager_;
   std::string locale_;
   const GURL last_committed_url_;
+  FakeAddressNormalizer address_normalizer_;
   DISALLOW_COPY_AND_ASSIGN(FakePaymentRequestDelegate);
 };
 
@@ -140,6 +168,9 @@
   const mojom::PaymentResponsePtr& response() { return payment_response_; }
   autofill::AutofillProfile* test_address() { return &address_; }
   PaymentInstrument* test_instrument() { return autofill_instrument_.get(); }
+  PaymentRequestDelegate* test_payment_request_delegate() {
+    return &payment_request_delegate_;
+  }
 
  private:
   std::unique_ptr<PaymentRequestSpec> spec_;
@@ -162,7 +193,8 @@
   // "visa" is specified directly in the supportedMethods so it is returned
   // as the method name.
   PaymentResponseHelper helper("en-US", spec(), test_instrument(),
-                               test_address(), test_address(), this);
+                               test_payment_request_delegate(), test_address(),
+                               test_address(), this);
   EXPECT_EQ("visa", response()->method_name);
   EXPECT_EQ(
       "{\"billingAddress\":"
@@ -198,7 +230,8 @@
   // TODO(mathp): Currently synchronous, when async will need a RunLoop.
   // "basic-card" is specified so it is returned as the method name.
   PaymentResponseHelper helper("en-US", spec(), test_instrument(),
-                               test_address(), test_address(), this);
+                               test_payment_request_delegate(), test_address(),
+                               test_address(), this);
   EXPECT_EQ("basic-card", response()->method_name);
   EXPECT_EQ(
       "{\"billingAddress\":"
@@ -235,7 +268,8 @@
                                     GetMethodDataForVisa());
 
   PaymentResponseHelper helper("en-US", spec(), test_instrument(),
-                               test_address(), test_address(), this);
+                               test_payment_request_delegate(), test_address(),
+                               test_address(), this);
 
   // Check that all the expected values were set.
   EXPECT_EQ("US", response()->shipping_address->country);
@@ -263,7 +297,8 @@
   RecreateSpecWithOptions(std::move(options));
 
   PaymentResponseHelper helper("en-US", spec(), test_instrument(),
-                               test_address(), test_address(), this);
+                               test_payment_request_delegate(), test_address(),
+                               test_address(), this);
 
   // Check that all the expected values were set.
   EXPECT_EQ("John H. Doe", response()->payer_name.value());
@@ -280,7 +315,8 @@
   RecreateSpecWithOptions(std::move(options));
 
   PaymentResponseHelper helper("en-US", spec(), test_instrument(),
-                               test_address(), test_address(), this);
+                               test_payment_request_delegate(), test_address(),
+                               test_address(), this);
 
   // Check that the name was set, but not the other values.
   EXPECT_EQ("John H. Doe", response()->payer_name.value());
@@ -300,7 +336,8 @@
   RecreateSpecWithOptions(std::move(options));
 
   PaymentResponseHelper helper("en-US", spec(), test_instrument(),
-                               test_address(), test_address(), this);
+                               test_payment_request_delegate(), test_address(),
+                               test_address(), this);
 
   // Check that the phone was formatted.
   EXPECT_EQ("+15151231234", response()->payer_phone.value());
diff --git a/components/payments/core/BUILD.gn b/components/payments/core/BUILD.gn
index 0a8ca3b..0bb0482 100644
--- a/components/payments/core/BUILD.gn
+++ b/components/payments/core/BUILD.gn
@@ -4,8 +4,9 @@
 
 static_library("core") {
   sources = [
-    "address_normalizer.cc",
     "address_normalizer.h",
+    "address_normalizer_impl.cc",
+    "address_normalizer_impl.h",
     "autofill_payment_instrument.cc",
     "autofill_payment_instrument.h",
     "basic_card_response.cc",
@@ -49,7 +50,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
-    "address_normalizer_unittest.cc",
+    "address_normalizer_impl_unittest.cc",
     "autofill_payment_instrument_unittest.cc",
     "basic_card_response_unittest.cc",
     "currency_formatter_unittest.cc",
diff --git a/components/payments/core/address_normalizer.h b/components/payments/core/address_normalizer.h
index f3d2a24..c46371cf 100644
--- a/components/payments/core/address_normalizer.h
+++ b/components/payments/core/address_normalizer.h
@@ -5,25 +5,14 @@
 #ifndef COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_H_
 #define COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_H_
 
-#include <map>
-#include <memory>
 #include <string>
-#include <vector>
 
-#include "base/macros.h"
 #include "third_party/libaddressinput/chromium/chrome_address_validator.h"
 
 namespace autofill {
 class AutofillProfile;
 }
 
-namespace i18n {
-namespace libadderssinput {
-class Source;
-class Storage;
-}
-}
-
 namespace payments {
 
 // A class used to normalize addresses.
@@ -49,16 +38,12 @@
     virtual ~Request() {}
   };
 
-  AddressNormalizer(std::unique_ptr<::i18n::addressinput::Source> source,
-                    std::unique_ptr<::i18n::addressinput::Storage> storage);
-  ~AddressNormalizer() override;
-
   // Start loading the validation rules for the specified |region_code|.
-  virtual void LoadRulesForRegion(const std::string& region_code);
+  virtual void LoadRulesForRegion(const std::string& region_code) = 0;
 
   // Returns whether the rules for the specified |region_code| have finished
   // loading.
-  bool AreRulesLoadedForRegion(const std::string& region_code);
+  virtual bool AreRulesLoadedForRegion(const std::string& region_code) = 0;
 
   // Starts the normalization of the |profile| based on the |region_code|. The
   // normalized profile will be returned to the |requester| possibly
@@ -68,25 +53,11 @@
   // happen synchronously, or not at all if the rules are not already loaded.
   // Will start loading the rules for the |region_code| if they had not started
   // loading.
-  void StartAddressNormalization(const autofill::AutofillProfile& profile,
-                                 const std::string& region_code,
-                                 int timeout_seconds,
-                                 Delegate* requester);
-
- private:
-  // Called when the validation rules for the |region_code| have finished
-  // loading. Implementation of the LoadRulesListener interface.
-  void OnAddressValidationRulesLoaded(const std::string& region_code,
-                                      bool success) override;
-
-  // Map associating a region code to pending normalizations.
-  std::map<std::string, std::vector<std::unique_ptr<Request>>>
-      pending_normalization_;
-
-  // The address validator used to normalize addresses.
-  autofill::AddressValidator address_validator_;
-
-  DISALLOW_COPY_AND_ASSIGN(AddressNormalizer);
+  virtual void StartAddressNormalization(
+      const autofill::AutofillProfile& profile,
+      const std::string& region_code,
+      int timeout_seconds,
+      Delegate* requester) = 0;
 };
 
 }  // namespace payments
diff --git a/components/payments/core/address_normalizer.cc b/components/payments/core/address_normalizer_impl.cc
similarity index 92%
rename from components/payments/core/address_normalizer.cc
rename to components/payments/core/address_normalizer_impl.cc
index d432ff11..12961bd 100644
--- a/components/payments/core/address_normalizer.cc
+++ b/components/payments/core/address_normalizer_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/payments/core/address_normalizer.h"
+#include "components/payments/core/address_normalizer_impl.h"
 
 #include <stddef.h>
 #include <utility>
@@ -123,22 +123,22 @@
 
 }  // namespace
 
-AddressNormalizer::AddressNormalizer(std::unique_ptr<Source> source,
-                                     std::unique_ptr<Storage> storage)
+AddressNormalizerImpl::AddressNormalizerImpl(std::unique_ptr<Source> source,
+                                             std::unique_ptr<Storage> storage)
     : address_validator_(std::move(source), std::move(storage), this) {}
 
-AddressNormalizer::~AddressNormalizer() {}
+AddressNormalizerImpl::~AddressNormalizerImpl() {}
 
-void AddressNormalizer::LoadRulesForRegion(const std::string& region_code) {
+void AddressNormalizerImpl::LoadRulesForRegion(const std::string& region_code) {
   address_validator_.LoadRules(region_code);
 }
 
-bool AddressNormalizer::AreRulesLoadedForRegion(
+bool AddressNormalizerImpl::AreRulesLoadedForRegion(
     const std::string& region_code) {
   return address_validator_.AreRulesLoadedForRegion(region_code);
 }
 
-void AddressNormalizer::StartAddressNormalization(
+void AddressNormalizerImpl::StartAddressNormalization(
     const AutofillProfile& profile,
     const std::string& region_code,
     int timeout_seconds,
@@ -173,7 +173,7 @@
   }
 }
 
-void AddressNormalizer::OnAddressValidationRulesLoaded(
+void AddressNormalizerImpl::OnAddressValidationRulesLoaded(
     const std::string& region_code,
     bool success) {
   // Check if an address normalization is pending.
diff --git a/components/payments/core/address_normalizer_impl.h b/components/payments/core/address_normalizer_impl.h
new file mode 100644
index 0000000..1444e8a
--- /dev/null
+++ b/components/payments/core/address_normalizer_impl.h
@@ -0,0 +1,62 @@
+// 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_PAYMENTS_CORE_ADDRESS_NORMALIZER_IMPL_H_
+#define COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_IMPL_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "components/payments/core/address_normalizer.h"
+
+namespace autofill {
+class AutofillProfile;
+}
+
+namespace i18n {
+namespace addressinput {
+class Source;
+class Storage;
+}
+}
+
+namespace payments {
+
+// A class used to normalize addresses.
+class AddressNormalizerImpl : public AddressNormalizer {
+ public:
+  AddressNormalizerImpl(std::unique_ptr<::i18n::addressinput::Source> source,
+                        std::unique_ptr<::i18n::addressinput::Storage> storage);
+  ~AddressNormalizerImpl() override;
+
+  // AddressNormalizer implementation.
+  void LoadRulesForRegion(const std::string& region_code) override;
+  bool AreRulesLoadedForRegion(const std::string& region_code) override;
+  void StartAddressNormalization(const autofill::AutofillProfile& profile,
+                                 const std::string& region_code,
+                                 int timeout_seconds,
+                                 Delegate* requester) override;
+
+ private:
+  // Called when the validation rules for the |region_code| have finished
+  // loading. Implementation of the LoadRulesListener interface.
+  void OnAddressValidationRulesLoaded(const std::string& region_code,
+                                      bool success) override;
+
+  // Map associating a region code to pending normalizations.
+  std::map<std::string, std::vector<std::unique_ptr<Request>>>
+      pending_normalization_;
+
+  // The address validator used to normalize addresses.
+  autofill::AddressValidator address_validator_;
+
+  DISALLOW_COPY_AND_ASSIGN(AddressNormalizerImpl);
+};
+
+}  // namespace payments
+
+#endif  // COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_IMPL_H_
diff --git a/components/payments/core/address_normalizer_unittest.cc b/components/payments/core/address_normalizer_impl_unittest.cc
similarity index 95%
rename from components/payments/core/address_normalizer_unittest.cc
rename to components/payments/core/address_normalizer_impl_unittest.cc
index da9760b3..495dd040 100644
--- a/components/payments/core/address_normalizer_unittest.cc
+++ b/components/payments/core/address_normalizer_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/payments/core/address_normalizer.h"
+#include "components/payments/core/address_normalizer_impl.h"
 
 #include <utility>
 
@@ -79,13 +79,13 @@
   DISALLOW_COPY_AND_ASSIGN(ChromiumTestdataSource);
 };
 
-// A test subclass of the AddressNormalizer. Used to simulate rules not being
-// loaded.
-class TestAddressNormalizer : public AddressNormalizer {
+// A test subclass of the AddressNormalizerImpl. Used to simulate rules not
+// being loaded.
+class TestAddressNormalizer : public AddressNormalizerImpl {
  public:
   TestAddressNormalizer(std::unique_ptr<::i18n::addressinput::Source> source,
                         std::unique_ptr<::i18n::addressinput::Storage> storage)
-      : AddressNormalizer(std::move(source), std::move(storage)),
+      : AddressNormalizerImpl(std::move(source), std::move(storage)),
         should_load_rules_(true) {}
 
   ~TestAddressNormalizer() override {}
@@ -96,7 +96,7 @@
 
   void LoadRulesForRegion(const std::string& region_code) override {
     if (should_load_rules_) {
-      AddressNormalizer::LoadRulesForRegion(region_code);
+      AddressNormalizerImpl::LoadRulesForRegion(region_code);
     }
   }
 
diff --git a/components/payments/core/payment_request_delegate.h b/components/payments/core/payment_request_delegate.h
index 8ebc229..1ab4989 100644
--- a/components/payments/core/payment_request_delegate.h
+++ b/components/payments/core/payment_request_delegate.h
@@ -29,6 +29,7 @@
 
 namespace payments {
 
+class AddressNormalizer;
 class PaymentRequest;
 
 class PaymentRequestDelegate {
@@ -69,10 +70,14 @@
           result_delegate) = 0;
 
   // Returns the source and storage for country/region data loads.
-  virtual std::unique_ptr<const ::i18n::addressinput::Source>
+  virtual std::unique_ptr<::i18n::addressinput::Source>
   GetAddressInputSource() = 0;
   virtual std::unique_ptr<::i18n::addressinput::Storage>
   GetAddressInputStorage() = 0;
+
+  // Returns a pointer to the address normalizer to use for the duration of this
+  // Payment Request.
+  virtual AddressNormalizer* GetAddressNormalizer() = 0;
 };
 
 }  // namespace payments
diff --git a/components/policy/core/common/preg_parser.cc b/components/policy/core/common/preg_parser.cc
index 6e53ceba..4d188946 100644
--- a/components/policy/core/common/preg_parser.cc
+++ b/components/policy/core/common/preg_parser.cc
@@ -292,8 +292,8 @@
   return res;
 }
 
-POLICY_EXPORT bool ReadDataInternal(const uint8_t* data,
-                                    size_t data_size,
+POLICY_EXPORT bool ReadDataInternal(const uint8_t* preg_data,
+                                    size_t preg_data_size,
                                     const base::string16& root,
                                     RegistryDict* dict,
                                     PolicyLoadStatus* status,
@@ -302,16 +302,16 @@
   DCHECK(root.empty() || root.back() != kRegistryPathSeparator[0]);
 
   // Check data size.
-  if (data_size > kMaxPRegFileSize) {
-    LOG(ERROR) << "PReg " << debug_name << " too large: " << data_size;
+  if (preg_data_size > kMaxPRegFileSize) {
+    LOG(ERROR) << "PReg " << debug_name << " too large: " << preg_data_size;
     *status = POLICY_LOAD_STATUS_TOO_BIG;
     return false;
   }
 
   // Check the header.
   const int kHeaderSize = arraysize(kPRegFileHeader);
-  if (!data || data_size < kHeaderSize ||
-      memcmp(kPRegFileHeader, data, kHeaderSize) != 0) {
+  if (!preg_data || preg_data_size < kHeaderSize ||
+      memcmp(kPRegFileHeader, preg_data, kHeaderSize) != 0) {
     LOG(ERROR) << "Bad PReg " << debug_name;
     *status = POLICY_LOAD_STATUS_PARSE_ERROR;
     return false;
@@ -320,8 +320,8 @@
   // Parse data, which is expected to be UCS-2 and little-endian. The latter I
   // couldn't find documentation on, but the example I saw were all
   // little-endian. It'd be interesting to check on big-endian hardware.
-  const uint8_t* cursor = data + kHeaderSize;
-  const uint8_t* end = data + data_size;
+  const uint8_t* cursor = preg_data + kHeaderSize;
+  const uint8_t* end = preg_data + preg_data_size;
   while (true) {
     if (cursor == end)
       return true;
@@ -376,7 +376,7 @@
   }
 
   LOG(ERROR) << "Error parsing PReg " << debug_name << " at offset "
-             << (reinterpret_cast<const uint8_t*>(cursor - 1) - data);
+             << (reinterpret_cast<const uint8_t*>(cursor - 1) - preg_data);
   *status = POLICY_LOAD_STATUS_PARSE_ERROR;
   return false;
 }
diff --git a/components/policy/core/common/preg_parser.h b/components/policy/core/common/preg_parser.h
index be24e1e..bf0367ba8 100644
--- a/components/policy/core/common/preg_parser.h
+++ b/components/policy/core/common/preg_parser.h
@@ -39,13 +39,13 @@
                             RegistryDict* dict,
                             PolicyLoadStatusSample* status_sample);
 
-// Similar to ReadFile, but reads from |data| of length |data_size| instead of
-// a file, and writes status to the enum PolicyLoadStatus, which does not record
-// UMA stats, unlike |PolicyLoadStatusSample|. |debug_name| is printed out along
-// with error messages. Used internally and for testing only. All other callers
-// should use ReadFile instead.
-POLICY_EXPORT bool ReadDataInternal(const uint8_t* data,
-                                    size_t data_size,
+// Similar to ReadFile, but reads from |preg_data| of length |preg_data_size|
+// instead of a file, and writes status to the enum PolicyLoadStatus, which does
+// not record UMA stats, unlike |PolicyLoadStatusSample|. |debug_name| is
+// printed out along with error messages. Used internally and for testing only.
+// All other callers should use ReadFile instead.
+POLICY_EXPORT bool ReadDataInternal(const uint8_t* preg_data,
+                                    size_t preg_data_size,
                                     const base::string16& root,
                                     RegistryDict* dict,
                                     PolicyLoadStatus* status,
diff --git a/components/subresource_filter/OWNERS b/components/subresource_filter/OWNERS
index c21f3df..2fadb14a 100644
--- a/components/subresource_filter/OWNERS
+++ b/components/subresource_filter/OWNERS
@@ -1,4 +1,5 @@
 battre@chromium.org
+csharrison@chromium.org
 engedy@chromium.org
 melandory@chromium.org
 pkalinnikov@chromium.org
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 1b2a0b9..da2de209 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -725,8 +725,6 @@
     "gpu/gpu_main_thread_factory.h",
     "gpu/gpu_process_host.cc",
     "gpu/gpu_process_host.h",
-    "gpu/gpu_process_host_ui_shim.cc",
-    "gpu/gpu_process_host_ui_shim.h",
     "gpu/shader_cache_factory.cc",
     "gpu/shader_cache_factory.h",
     "histogram_controller.cc",
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index 6e4d970..a1685ae 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -661,9 +661,10 @@
   if (!browserAccessibility_->IsTableLikeRole())
     return nil;
   int count = -1;
-  if (!browserAccessibility_->GetIntAttribute(
-      ui::AX_ATTR_ARIA_COL_COUNT, &count))
+  if (!browserAccessibility_->GetIntAttribute(ui::AX_ATTR_ARIA_COLUMN_COUNT,
+                                              &count)) {
     return nil;
+  }
   return [NSNumber numberWithInt:count];
 }
 
@@ -672,8 +673,9 @@
     return nil;
   int index = -1;
   if (!browserAccessibility_->GetIntAttribute(
-      ui::AX_ATTR_ARIA_COL_INDEX, &index))
+          ui::AX_ATTR_ARIA_CELL_COLUMN_INDEX, &index)) {
     return nil;
+  }
   return [NSNumber numberWithInt:index];
 }
 
@@ -702,9 +704,10 @@
   if (!browserAccessibility_->IsTableLikeRole())
     return nil;
   int count = -1;
-  if (!browserAccessibility_->GetIntAttribute(
-      ui::AX_ATTR_ARIA_ROW_COUNT, &count))
+  if (!browserAccessibility_->GetIntAttribute(ui::AX_ATTR_ARIA_ROW_COUNT,
+                                              &count)) {
     return nil;
+  }
   return [NSNumber numberWithInt:count];
 }
 
@@ -712,9 +715,10 @@
   if (!browserAccessibility_->IsCellOrTableHeaderRole())
     return nil;
   int index = -1;
-  if (!browserAccessibility_->GetIntAttribute(
-      ui::AX_ATTR_ARIA_ROW_INDEX, &index))
+  if (!browserAccessibility_->GetIntAttribute(ui::AX_ATTR_ARIA_CELL_ROW_INDEX,
+                                              &index)) {
     return nil;
+  }
   return [NSNumber numberWithInt:index];
 }
 
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc
index ae80379..162f1917 100644
--- a/content/browser/accessibility/browser_accessibility_win.cc
+++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -3818,15 +3818,15 @@
 
   // Expose aria-colcount and aria-rowcount in a table, grid or treegrid.
   if (IsTableLikeRole()) {
-    IntAttributeToIA2(ui::AX_ATTR_ARIA_COL_COUNT, "colcount");
+    IntAttributeToIA2(ui::AX_ATTR_ARIA_COLUMN_COUNT, "colcount");
     IntAttributeToIA2(ui::AX_ATTR_ARIA_ROW_COUNT, "rowcount");
   }
 
   // Expose aria-colindex and aria-rowindex in a cell or row.
   if (IsCellOrTableHeaderRole() || GetRole() == ui::AX_ROLE_ROW) {
     if (GetRole() != ui::AX_ROLE_ROW)
-      IntAttributeToIA2(ui::AX_ATTR_ARIA_COL_INDEX, "colindex");
-    IntAttributeToIA2(ui::AX_ATTR_ARIA_ROW_INDEX, "rowindex");
+      IntAttributeToIA2(ui::AX_ATTR_ARIA_CELL_COLUMN_INDEX, "colindex");
+    IntAttributeToIA2(ui::AX_ATTR_ARIA_CELL_ROW_INDEX, "rowindex");
   }
 
   // Expose row or column header sort direction.
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index b7a99d5..c5410b5 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -12,9 +12,11 @@
 #include <utility>
 #include <vector>
 
+#include "base/base64.h"
 #include "base/command_line.h"
 #include "base/guid.h"
 #include "base/lazy_instance.h"
+#include "base/logging.h"
 #include "base/macros.h"
 #include "base/rand_util.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -505,6 +507,9 @@
                            : nullptr;
 }
 
+BrowserContext::BrowserContext()
+    : media_device_id_salt_(CreateRandomMediaDeviceIDSalt()) {}
+
 BrowserContext::~BrowserContext() {
   CHECK(GetUserData(kMojoWasInitialized))
       << "Attempting to destroy a BrowserContext that never called "
@@ -524,4 +529,16 @@
     RemoveUserData(kStoragePartitionMapKeyName);
 }
 
+std::string BrowserContext::GetMediaDeviceIDSalt() {
+  return media_device_id_salt_;
+}
+
+// static
+std::string BrowserContext::CreateRandomMediaDeviceIDSalt() {
+  std::string salt;
+  base::Base64Encode(base::RandBytesAsString(16), &salt);
+  DCHECK(!salt.empty());
+  return salt;
+}
+
 }  // namespace content
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 5021cd5..c9828a5 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -61,7 +61,6 @@
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/gpu/gpu_process_host_ui_shim.h"
 #include "content/browser/gpu/shader_cache_factory.h"
 #include "content/browser/histogram_synchronizer.h"
 #include "content/browser/leveldb_wrapper_impl.h"
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index b730c3c..88f071a 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -80,7 +80,6 @@
 #include "content/public/browser/permission_type.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/resource_context.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/stream_handle.h"
 #include "content/public/common/bindings_policy.h"
@@ -2550,7 +2549,6 @@
         base::Bind(&MediaDevicesDispatcherHost::Create, GetProcess()->GetID(),
                    GetRoutingID(), GetProcess()
                                        ->GetBrowserContext()
-                                       ->GetResourceContext()
                                        ->GetMediaDeviceIDSalt(),
                    base::Unretained(media_stream_manager)),
         BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 7749da46..57ae36c0 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -29,10 +29,10 @@
 #include "components/tracing/common/tracing_switches.h"
 #include "content/browser/browser_child_process_host_impl.h"
 #include "content/browser/browser_main_loop.h"
+#include "content/browser/field_trial_recorder.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_main_thread_factory.h"
-#include "content/browser/gpu/gpu_process_host_ui_shim.h"
 #include "content/browser/gpu/shader_cache_factory.h"
 #include "content/browser/service_manager/service_manager_context.h"
 #include "content/common/child_process_host_impl.h"
@@ -71,6 +71,8 @@
 
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
+#include "content/public/browser/android/java_interfaces.h"
+#include "media/mojo/interfaces/android_overlay.mojom.h"
 #endif
 
 #if defined(OS_WIN)
@@ -194,6 +196,7 @@
 }
 
 #if defined(USE_OZONE)
+// The ozone platform use this callback to send IPC messages to the gpu process.
 void SendGpuProcessMessage(base::WeakPtr<GpuProcessHost> host,
                            IPC::Message* message) {
   if (host)
@@ -201,8 +204,27 @@
   else
     delete message;
 }
+
+void RouteMessageToOzoneOnUI(const IPC::Message& message) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  ui::OzonePlatform::GetInstance()
+      ->GetGpuPlatformSupportHost()
+      ->OnMessageReceived(message);
+}
+
 #endif  // defined(USE_OZONE)
 
+void OnGpuProcessHostDestroyedOnUI(int host_id, const std::string& message) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  GpuDataManagerImpl::GetInstance()->AddLogMessage(
+      logging::LOG_ERROR, "GpuProcessHostUIShim", message);
+#if defined(USE_OZONE)
+  ui::OzonePlatform::GetInstance()
+      ->GetGpuPlatformSupportHost()
+      ->OnChannelDestroyed(host_id);
+#endif
+}
+
 // NOTE: changes to this class need to be reviewed by the security team.
 class GpuSandboxedProcessLauncherDelegate
     : public SandboxedProcessLauncherDelegate {
@@ -306,12 +328,33 @@
 #endif  // OS_WIN
 };
 
+#if defined(OS_ANDROID)
+template <typename Interface>
+void BindJavaInterface(mojo::InterfaceRequest<Interface> request) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  content::GetGlobalJavaInterfaces()->GetInterface(std::move(request));
+}
+#endif  // defined(OS_ANDROID)
+
 }  // anonymous namespace
 
 class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter {
  public:
   ConnectionFilterImpl() {
-    GpuProcessHostUIShim::RegisterUIThreadMojoInterfaces(&registry_);
+    auto task_runner = BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
+    registry_.AddInterface(base::Bind(&FieldTrialRecorder::Create),
+                           task_runner);
+    registry_.AddInterface(
+        base::Bind(
+            &memory_instrumentation::CoordinatorImpl::BindCoordinatorRequest,
+            base::Unretained(
+                memory_instrumentation::CoordinatorImpl::GetInstance())),
+        task_runner);
+#if defined(OS_ANDROID)
+    registry_.AddInterface(
+        base::Bind(&BindJavaInterface<media::mojom::AndroidOverlayProvider>),
+        task_runner);
+#endif
   }
 
  private:
@@ -466,15 +509,6 @@
 
   g_gpu_process_hosts[kind] = this;
 
-  // Post a task to create the corresponding GpuProcessHostUIShim. The
-  // GpuProcessHostUIShim will be destroyed when the GpuProcessHost is
-  // destroyed, which happens when the corresponding GPU process terminates or
-  // fails to launch. On browser exit, the shim can be leaked.
-  BrowserThread::PostTask(
-      BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(base::IgnoreResult(&GpuProcessHostUIShim::Create), host_id));
-
   process_.reset(new BrowserChildProcessHostImpl(
       PROCESS_TYPE_GPU, this, mojom::kGpuServiceName));
 }
@@ -562,11 +596,9 @@
   if (block_offscreen_contexts)
     BlockLiveOffscreenContexts();
 
-  BrowserThread::PostTask(BrowserThread::UI,
-                          FROM_HERE,
-                          base::Bind(&GpuProcessHostUIShim::Destroy,
-                                     host_id_,
-                                     message));
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&OnGpuProcessHostDestroyedOnUI, host_id_, message));
 }
 
 bool GpuProcessHost::Init() {
@@ -619,20 +651,14 @@
   ui::OzonePlatform::GetInstance()
       ->GetGpuPlatformSupportHost()
       ->OnGpuProcessLaunched(
-          host_id_, base::ThreadTaskRunnerHandle::Get(),
+          host_id_, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
+          base::ThreadTaskRunnerHandle::Get(),
           base::Bind(&SendGpuProcessMessage, weak_ptr_factory_.GetWeakPtr()));
 #endif
 
   return true;
 }
 
-void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) {
-  BrowserThread::PostTask(
-      BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&RouteToGpuProcessHostUIShimTask, host_id_, message));
-}
-
 bool GpuProcessHost::Send(IPC::Message* msg) {
   DCHECK(CalledOnValidThread());
   if (process_->GetHost()->IsChannelOpening()) {
@@ -652,7 +678,10 @@
 
 bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
   DCHECK(CalledOnValidThread());
-  RouteOnUIThread(message);
+#if defined(USE_OZONE)
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::Bind(&RouteMessageToOzoneOnUI, message));
+#endif
   return true;
 }
 
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 7b25454..bd98b70 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -173,9 +173,6 @@
 
   bool Init();
 
-  // Post an IPC message to the UI shim's message handler on the UI thread.
-  void RouteOnUIThread(const IPC::Message& message);
-
   // BrowserChildProcessHostDelegate implementation.
   bool OnMessageReceived(const IPC::Message& message) override;
   void OnChannelConnected(int32_t peer_pid) override;
diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc
deleted file mode 100644
index e4fd842..0000000
--- a/content/browser/gpu/gpu_process_host_ui_shim.cc
+++ /dev/null
@@ -1,143 +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.
-
-#include "content/browser/gpu/gpu_process_host_ui_shim.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/id_map.h"
-#include "base/lazy_instance.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/browser/compositor/gpu_process_transport_factory.h"
-#include "content/browser/field_trial_recorder.h"
-#include "content/browser/gpu/compositor_util.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/render_widget_helper.h"
-#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/public/browser/browser_thread.h"
-#include "gpu/ipc/common/memory_stats.h"
-#include "services/resource_coordinator/memory/coordinator/coordinator_impl.h"
-#include "ui/gfx/swap_result.h"
-
-#if defined(OS_ANDROID)
-#include "content/public/browser/android/java_interfaces.h"
-#include "media/mojo/interfaces/android_overlay.mojom.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#endif
-
-#if defined(USE_OZONE)
-#include "ui/ozone/public/gpu_platform_support_host.h"
-#include "ui/ozone/public/ozone_platform.h"
-#endif
-
-namespace content {
-
-namespace {
-
-base::LazyInstance<IDMap<GpuProcessHostUIShim*>>::Leaky g_hosts_by_id =
-    LAZY_INSTANCE_INITIALIZER;
-
-#if defined(OS_ANDROID)
-template <typename Interface>
-void BindJavaInterface(mojo::InterfaceRequest<Interface> request) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  content::GetGlobalJavaInterfaces()->GetInterface(std::move(request));
-}
-#endif
-
-}  // namespace
-
-void RouteToGpuProcessHostUIShimTask(int host_id, const IPC::Message& msg) {
-  GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(host_id);
-  if (ui_shim)
-    ui_shim->OnMessageReceived(msg);
-}
-
-GpuProcessHostUIShim::GpuProcessHostUIShim(int host_id)
-    : host_id_(host_id) {
-  g_hosts_by_id.Pointer()->AddWithID(this, host_id_);
-#if defined(USE_OZONE)
-  ui::OzonePlatform::GetInstance()
-      ->GetGpuPlatformSupportHost()
-      ->OnChannelEstablished();
-#endif
-}
-
-// static
-GpuProcessHostUIShim* GpuProcessHostUIShim::Create(int host_id) {
-  DCHECK(!FromID(host_id));
-  return new GpuProcessHostUIShim(host_id);
-}
-
-// static
-void GpuProcessHostUIShim::Destroy(int host_id, const std::string& message) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  GpuDataManagerImpl::GetInstance()->AddLogMessage(
-      logging::LOG_ERROR, "GpuProcessHostUIShim",
-      message);
-
-#if defined(USE_OZONE)
-  ui::OzonePlatform::GetInstance()
-      ->GetGpuPlatformSupportHost()
-      ->OnChannelDestroyed(host_id);
-#endif
-
-  delete FromID(host_id);
-}
-
-// static
-GpuProcessHostUIShim* GpuProcessHostUIShim::FromID(int host_id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  return g_hosts_by_id.Pointer()->Lookup(host_id);
-}
-
-void GpuProcessHostUIShim::OnMessageReceived(const IPC::Message& message) {
-  DCHECK(CalledOnValidThread());
-
-#if defined(USE_OZONE)
-  if (ui::OzonePlatform::GetInstance()
-          ->GetGpuPlatformSupportHost()
-          ->OnMessageReceived(message))
-    return;
-#endif
-
-  if (message.routing_id() == MSG_ROUTING_CONTROL) {
-    NOTREACHED() << "Invalid message with type = " << message.type();
-  }
-}
-
-GpuProcessHostUIShim::~GpuProcessHostUIShim() {
-  DCHECK(CalledOnValidThread());
-  g_hosts_by_id.Pointer()->Remove(host_id_);
-}
-
-// static
-void GpuProcessHostUIShim::RegisterUIThreadMojoInterfaces(
-    service_manager::BinderRegistry* registry) {
-  auto task_runner = BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
-
-  registry->AddInterface(base::Bind(&FieldTrialRecorder::Create), task_runner);
-  registry->AddInterface(
-      base::Bind(
-          &memory_instrumentation::CoordinatorImpl::BindCoordinatorRequest,
-          base::Unretained(
-              memory_instrumentation::CoordinatorImpl::GetInstance())),
-      task_runner);
-#if defined(OS_ANDROID)
-  registry->AddInterface(
-      base::Bind(&BindJavaInterface<media::mojom::AndroidOverlayProvider>),
-      task_runner);
-#endif
-}
-
-}  // namespace content
diff --git a/content/browser/gpu/gpu_process_host_ui_shim.h b/content/browser/gpu/gpu_process_host_ui_shim.h
deleted file mode 100644
index b7f19fb2..0000000
--- a/content/browser/gpu/gpu_process_host_ui_shim.h
+++ /dev/null
@@ -1,73 +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.
-
-#ifndef CONTENT_BROWSER_GPU_GPU_PROCESS_HOST_UI_SHIM_H_
-#define CONTENT_BROWSER_GPU_GPU_PROCESS_HOST_UI_SHIM_H_
-
-// This class lives on the UI thread and supports classes like the
-// BackingStoreProxy, which must live on the UI thread. The IO thread
-// portion of this class, the GpuProcessHost, is responsible for
-// shuttling messages between the browser and GPU processes.
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
-#include "build/build_config.h"
-#include "content/common/content_export.h"
-#include "gpu/config/gpu_info.h"
-#include "gpu/ipc/common/memory_stats.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-#include "ipc/message_router.h"
-
-namespace IPC {
-class Message;
-}
-
-namespace service_manager {
-class BinderRegistry;
-}
-
-namespace content {
-void RouteToGpuProcessHostUIShimTask(int host_id, const IPC::Message& msg);
-
-class GpuProcessHostUIShim : public base::NonThreadSafe {
- public:
-  // Create a GpuProcessHostUIShim with the given ID.  The object can be found
-  // using FromID with the same id.
-  static GpuProcessHostUIShim* Create(int host_id);
-
-  // Destroy the GpuProcessHostUIShim with the given host ID. This can only
-  // be called on the UI thread. Only the GpuProcessHost should destroy the
-  // UI shim.
-  static void Destroy(int host_id, const std::string& message);
-
-  CONTENT_EXPORT static GpuProcessHostUIShim* FromID(int host_id);
-
-  // The GpuProcessHost causes this to be called on the UI thread to
-  // dispatch the incoming messages from the GPU process, which are
-  // actually received on the IO thread.
-  void OnMessageReceived(const IPC::Message& message);
-
-  // Register Mojo interfaces that must be bound on the UI thread.
-  static void RegisterUIThreadMojoInterfaces(
-      service_manager::BinderRegistry* registry);
-
- private:
-  explicit GpuProcessHostUIShim(int host_id);
-  ~GpuProcessHostUIShim();
-
-  // The serial number of the GpuProcessHost / GpuProcessHostUIShim pair.
-  int host_id_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_GPU_GPU_PROCESS_HOST_UI_SHIM_H_
diff --git a/content/browser/media/media_browsertest.cc b/content/browser/media/media_browsertest.cc
index 0e6650b..8997c57 100644
--- a/content/browser/media/media_browsertest.cc
+++ b/content/browser/media/media_browsertest.cc
@@ -17,6 +17,7 @@
 #include "media/base/test_data_util.h"
 #include "media/media_features.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/url_util.h"
 
 namespace content {
 
@@ -70,6 +71,14 @@
   return base::UTF16ToASCII(result);
 }
 
+std::string MediaBrowserTest::EncodeErrorMessage(
+    const std::string& original_message) {
+  url::RawCanonOutputT<char> buffer;
+  url::EncodeURIComponent(original_message.data(), original_message.size(),
+                          &buffer);
+  return std::string(buffer.data(), buffer.length());
+}
+
 void MediaBrowserTest::AddTitlesToAwait(content::TitleWatcher* title_watcher) {
   title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kEnded));
   title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kError));
@@ -102,6 +111,17 @@
     RunMediaTestPage("player.html", query_params, kEnded, http);
   }
 
+  void RunErrorMessageTest(const std::string& tag,
+                           const std::string& media_file,
+                           const std::string& expected_error_substring,
+                           bool http) {
+    base::StringPairs query_params;
+    query_params.push_back(std::make_pair(tag, media_file));
+    query_params.push_back(std::make_pair(
+        "error_substr", EncodeErrorMessage(expected_error_substring)));
+    RunMediaTestPage("player.html", query_params, kErrorEvent, http);
+  }
+
   void RunVideoSizeTest(const char* media_file, int width, int height) {
     std::string expected;
     expected += base::IntToString(width);
@@ -259,6 +279,23 @@
   PlayVideo("tulip2.webm", GetParam());
 }
 
+IN_PROC_BROWSER_TEST_P(MediaTest, VideoErrorMissingResource) {
+  RunErrorMessageTest("video", "nonexistent_file.webm",
+                      "MEDIA_ELEMENT_ERROR: Format error", GetParam());
+}
+
+IN_PROC_BROWSER_TEST_P(MediaTest, VideoErrorEmptySrcAttribute) {
+  RunErrorMessageTest("video", "", "MEDIA_ELEMENT_ERROR: Empty src attribute",
+                      GetParam());
+}
+
+IN_PROC_BROWSER_TEST_P(MediaTest, VideoErrorNoSupportedStreams) {
+  RunErrorMessageTest(
+      "video", "no_streams.webm",
+      "DEMUXER_ERROR_NO_SUPPORTED_STREAMS: FFmpegDemuxer: no supported streams",
+      GetParam());
+}
+
 // Covers tear-down when navigating away as opposed to browser exiting.
 IN_PROC_BROWSER_TEST_F(MediaTest, Navigate) {
   PlayVideo("bear.webm", false);
diff --git a/content/browser/media/media_browsertest.h b/content/browser/media/media_browsertest.h
index 238b667..c2f7047 100644
--- a/content/browser/media/media_browsertest.h
+++ b/content/browser/media/media_browsertest.h
@@ -39,6 +39,11 @@
   // titles. Returns the matching title.
   std::string RunTest(const GURL& gurl, const std::string& expected_title);
 
+  // Encodes |original_message| to be used in a URI query parameter suitable for
+  // decoding and usage with DecodeURIComponent in test pages that verify error
+  // message contents.
+  std::string EncodeErrorMessage(const std::string& original_message);
+
   // Adds titles that RunTest() should wait for.
   virtual void AddTitlesToAwait(content::TitleWatcher* title_watcher);
 };
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
index 1c94874..9f31b8a 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -16,10 +16,10 @@
 #include "content/browser/renderer_host/media/media_stream_manager.h"
 #include "content/browser/renderer_host/media/video_capture_manager.h"
 #include "content/common/media/media_devices.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/media_device_id.h"
 #include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/resource_context.h"
 #include "content/public/common/media_stream_request.h"
 #include "media/base/video_facing.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
@@ -114,7 +114,7 @@
     : render_process_id_(render_process_id),
       render_frame_id_(render_frame_id),
       device_id_salt_(device_id_salt),
-      group_id_salt_(ResourceContext::CreateRandomMediaDeviceIDSalt()),
+      group_id_salt_(BrowserContext::CreateRandomMediaDeviceIDSalt()),
       media_stream_manager_(media_stream_manager),
       permission_checker_(base::MakeUnique<MediaDevicesPermissionChecker>()),
       weak_factory_(this) {
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
index 5c964576..1445e09 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
@@ -20,8 +20,8 @@
 #include "content/browser/renderer_host/media/media_stream_manager.h"
 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
 #include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/media_device_id.h"
-#include "content/public/test/mock_resource_context.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "media/audio/audio_device_description.h"
@@ -87,12 +87,8 @@
     media_stream_manager_ =
         base::MakeUnique<MediaStreamManager>(audio_system_.get());
 
-    MockResourceContext* mock_resource_context =
-        static_cast<MockResourceContext*>(
-            browser_context_.GetResourceContext());
-
     host_ = base::MakeUnique<MediaDevicesDispatcherHost>(
-        kProcessId, kRenderId, mock_resource_context->GetMediaDeviceIDSalt(),
+        kProcessId, kRenderId, browser_context_.GetMediaDeviceIDSalt(),
         media_stream_manager_.get());
   }
 
@@ -122,9 +118,9 @@
   void VideoInputCapabilitiesCallback(
       std::vector<::mojom::VideoInputDeviceCapabilitiesPtr> capabilities) {
     MockVideoInputCapabilitiesCallback();
-    std::string expected_first_device_id = GetHMACForMediaDeviceID(
-        browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), origin_,
-        kDefaultVideoDeviceID);
+    std::string expected_first_device_id =
+        GetHMACForMediaDeviceID(browser_context_.GetMediaDeviceIDSalt(),
+                                origin_, kDefaultVideoDeviceID);
     EXPECT_EQ(kNumFakeVideoDevices, capabilities.size());
     EXPECT_EQ(expected_first_device_id, capabilities[0]->device_id);
     for (const auto& capability : capabilities) {
@@ -200,8 +196,8 @@
         bool found_match = false;
         for (const auto& raw_device_info : physical_devices_[i]) {
           if (DoesMediaDeviceIDMatchHMAC(
-                  browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
-                  origin, device_info.device_id, raw_device_info.device_id)) {
+                  browser_context_.GetMediaDeviceIDSalt(), origin,
+                  device_info.device_id, raw_device_info.device_id)) {
             EXPECT_FALSE(found_match);
             found_match = true;
           }
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 485eae1..6e48377 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -27,9 +27,9 @@
 #include "content/browser/renderer_host/media/video_capture_manager.h"
 #include "content/common/media/media_stream_messages.h"
 #include "content/common/media/media_stream_options.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/media_device_id.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/test/mock_resource_context.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/test_content_browser_client.h"
@@ -257,12 +257,8 @@
     media_stream_manager_ = base::MakeUnique<MediaStreamManager>(
         audio_system_.get(), std::move(mock_video_capture_provider));
 
-    MockResourceContext* mock_resource_context =
-        static_cast<MockResourceContext*>(
-            browser_context_.GetResourceContext());
-
     host_ = new MockMediaStreamDispatcherHost(
-        mock_resource_context->GetMediaDeviceIDSalt(),
+        browser_context_.GetMediaDeviceIDSalt(),
         base::ThreadTaskRunnerHandle::Get(), media_stream_manager_.get());
 
     // Use the fake content client and browser.
@@ -409,18 +405,16 @@
           audio_device_descriptions_.begin();
       for (; audio_it != audio_device_descriptions_.end(); ++audio_it) {
         if (content::DoesMediaDeviceIDMatchHMAC(
-                browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
-                origin,
-                devices[i].device.id,
-                audio_it->unique_id)) {
+                browser_context_.GetMediaDeviceIDSalt(), origin,
+                devices[i].device.id, audio_it->unique_id)) {
           EXPECT_FALSE(found_match);
           found_match = true;
         }
       }
       for (const std::string& device_id : stub_video_device_ids_) {
         if (content::DoesMediaDeviceIDMatchHMAC(
-                browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
-                origin, devices[i].device.id, device_id)) {
+                browser_context_.GetMediaDeviceIDSalt(), origin,
+                devices[i].device.id, device_id)) {
           EXPECT_FALSE(found_match);
           found_match = true;
         }
@@ -509,8 +503,7 @@
   // We specify to generate both audio and video stream.
   StreamControls controls(true, true);
   std::string source_id = content::GetHMACForMediaDeviceID(
-      browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), origin_,
-      kDepthVideoDeviceId);
+      browser_context_.GetMediaDeviceIDSalt(), origin_, kDepthVideoDeviceId);
   // |source_id| corresponds to the depth device. As we can generate only one
   // video stream using GenerateStreamAndWaitForResult, we use
   // controls.video.source_id to specify that the stream is depth video.
@@ -663,9 +656,7 @@
       audio_device_descriptions_.begin();
   for (; audio_it != audio_device_descriptions_.end(); ++audio_it) {
     std::string source_id = content::GetHMACForMediaDeviceID(
-        browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
-        origin_,
-        audio_it->unique_id);
+        browser_context_.GetMediaDeviceIDSalt(), origin_, audio_it->unique_id);
     ASSERT_FALSE(source_id.empty());
     StreamControls controls(true, true);
     controls.audio.device_id = source_id;
@@ -677,8 +668,7 @@
 
   for (const std::string& device_id : stub_video_device_ids_) {
     std::string source_id = content::GetHMACForMediaDeviceID(
-        browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), origin_,
-        device_id);
+        browser_context_.GetMediaDeviceIDSalt(), origin_, device_id);
     ASSERT_FALSE(source_id.empty());
     StreamControls controls(true, true);
     controls.video.device_id = source_id;
diff --git a/content/browser/renderer_host/media/video_capture_unittest.cc b/content/browser/renderer_host/media/video_capture_unittest.cc
index c8ea3c0..9cb9347e 100644
--- a/content/browser/renderer_host/media/video_capture_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -24,7 +24,6 @@
 #include "content/browser/renderer_host/media/video_capture_manager.h"
 #include "content/common/media/media_devices.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/test/mock_resource_context.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/test_content_browser_client.h"
@@ -165,10 +164,9 @@
       devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
       media_stream_manager_->media_devices_manager()->EnumerateDevices(
           devices_to_enumerate,
-          base::Bind(
-              &VideoInputDevicesEnumerated, run_loop.QuitClosure(),
-              browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
-              security_origin, &video_devices));
+          base::Bind(&VideoInputDevicesEnumerated, run_loop.QuitClosure(),
+                     browser_context_.GetMediaDeviceIDSalt(), security_origin,
+                     &video_devices));
       run_loop.Run();
     }
     ASSERT_FALSE(video_devices.empty());
@@ -179,9 +177,9 @@
       StreamDeviceInfo opened_device;
       media_stream_manager_->OpenDevice(
           &stream_requester_, render_process_id, render_frame_id,
-          browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
-          page_request_id, video_devices[0].device_id,
-          MEDIA_DEVICE_VIDEO_CAPTURE, security_origin);
+          browser_context_.GetMediaDeviceIDSalt(), page_request_id,
+          video_devices[0].device_id, MEDIA_DEVICE_VIDEO_CAPTURE,
+          security_origin);
       EXPECT_CALL(stream_requester_,
                   DeviceOpened(render_frame_id, page_request_id, _, _))
           .Times(1)
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index bb9d311..1884d92a 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1056,9 +1056,8 @@
   scoped_refptr<net::URLRequestContextGetter> media_request_context(
       GetStoragePartition()->GetMediaURLRequestContext());
 
-  ResourceMessageFilter::GetContextsCallback get_contexts_callback(
-      base::Bind(&GetContexts, browser_context->GetResourceContext(),
-                 request_context, media_request_context));
+  ResourceMessageFilter::GetContextsCallback get_contexts_callback(base::Bind(
+      &GetContexts, resource_context, request_context, media_request_context));
 
   // Several filters need the Blob storage context, so fetch it in advance.
   scoped_refptr<ChromeBlobStorageContext> blob_storage_context =
@@ -1087,7 +1086,7 @@
   audio_renderer_host_ = new AudioRendererHost(
       GetID(), audio_manager, BrowserMainLoop::GetInstance()->audio_system(),
       AudioMirroringManager::GetInstance(), media_stream_manager,
-      browser_context->GetResourceContext()->GetMediaDeviceIDSalt());
+      browser_context->GetMediaDeviceIDSalt());
   AddFilter(audio_renderer_host_.get());
   AddFilter(
       new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_service()));
@@ -1102,8 +1101,7 @@
       GetID(), webrtc_eventlog_host_.GetWeakPtr());
   AddFilter(peer_connection_tracker_host_.get());
   AddFilter(new MediaStreamDispatcherHost(
-      GetID(), browser_context->GetResourceContext()->GetMediaDeviceIDSalt(),
-      media_stream_manager));
+      GetID(), browser_context->GetMediaDeviceIDSalt(), media_stream_manager));
   AddFilter(new MediaStreamTrackMetricsHost());
 #endif
 #if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/content/browser/resource_context_impl.cc b/content/browser/resource_context_impl.cc
index 93e2890d..a9718edb 100644
--- a/content/browser/resource_context_impl.cc
+++ b/content/browser/resource_context_impl.cc
@@ -6,11 +6,9 @@
 
 #include <stdint.h>
 
-#include "base/base64.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "base/rand_util.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader/resource_request_info_impl.h"
@@ -28,27 +26,13 @@
 const char kStreamContextKeyName[] = "content_stream_context";
 const char kURLDataManagerBackendKeyName[] = "url_data_manager_backend";
 
-ResourceContext::ResourceContext()
-    : media_device_id_salt_(CreateRandomMediaDeviceIDSalt()) {
-}
+ResourceContext::ResourceContext() {}
 
 ResourceContext::~ResourceContext() {
   if (ResourceDispatcherHostImpl::Get())
     ResourceDispatcherHostImpl::Get()->CancelRequestsForContext(this);
 }
 
-std::string ResourceContext::GetMediaDeviceIDSalt() {
-  return media_device_id_salt_;
-}
-
-// static
-std::string ResourceContext::CreateRandomMediaDeviceIDSalt() {
-  std::string salt;
-  base::Base64Encode(base::RandBytesAsString(16), &salt);
-  DCHECK(!salt.empty());
-  return salt;
-}
-
 ChromeBlobStorageContext* GetChromeBlobStorageContextForResourceContext(
     const ResourceContext* resource_context) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 2bf03fab..531f5bd 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -2256,14 +2256,8 @@
   EXPECT_EQ(1, GetRequestCount(kPageUrl));
 }
 
-// Flaky on Win/Mac: http://crbug.com/533631
-#if defined(OS_WIN) || defined(OS_MACOSX)
-#define MAYBE_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure DISABLED_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure
-#else
-#define MAYBE_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure ResponseFromHTTPSServiceWorkerIsMarkedAsSecure
-#endif
 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
-                       MAYBE_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure) {
+                       ResponseFromHTTPSServiceWorkerIsMarkedAsSecure) {
   StartServerAndNavigateToSetup();
   const char kPageUrl[] = "/service_worker/fetch_event_blob.html";
   const char kWorkerUrl[] = "/service_worker/fetch_event_blob.js";
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h
index 89461daa..7bc69b6 100644
--- a/content/public/browser/browser_context.h
+++ b/content/public/browser/browser_context.h
@@ -10,6 +10,7 @@
 
 #include <map>
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "base/callback_forward.h"
@@ -171,6 +172,8 @@
   static ServiceManagerConnection* GetServiceManagerConnectionFor(
       BrowserContext* browser_context);
 
+  BrowserContext();
+
   ~BrowserContext() override;
 
   // Shuts down the storage partitions associated to this browser context.
@@ -251,6 +254,18 @@
   // Registers per-browser-context services to be loaded in the browser process
   // by the Service Manager.
   virtual void RegisterInProcessServices(StaticServiceMap* services) {}
+
+  // Returns a random salt string that is used for creating media device IDs.
+  // Returns a random string by default.
+  virtual std::string GetMediaDeviceIDSalt();
+
+  // Utility function useful for embedders. Only needs to be called if
+  // 1) The embedder needs to use a new salt, and
+  // 2) The embedder saves its salt across restarts.
+  static std::string CreateRandomMediaDeviceIDSalt();
+
+ private:
+  const std::string media_device_id_salt_;
 };
 
 }  // namespace content
diff --git a/content/public/browser/resource_context.h b/content/public/browser/resource_context.h
index 602f935..44b829b 100644
--- a/content/public/browser/resource_context.h
+++ b/content/public/browser/resource_context.h
@@ -5,14 +5,7 @@
 #ifndef CONTENT_PUBLIC_BROWSER_RESOURCE_CONTEXT_H_
 #define CONTENT_PUBLIC_BROWSER_RESOURCE_CONTEXT_H_
 
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
 #include "base/supports_user_data.h"
-#include "build/build_config.h"
 #include "content/common/content_export.h"
 
 namespace net {
@@ -25,6 +18,7 @@
 // ResourceContext contains the relevant context information required for
 // resource loading. It lives on the IO thread, although it is constructed on
 // the UI thread. It must be destructed on the IO thread.
+// TODO(mmenke):  Get rid of this class.
 class CONTENT_EXPORT ResourceContext : public base::SupportsUserData {
  public:
   ResourceContext();
@@ -35,18 +29,6 @@
   // storage partitioning. This getter returns the default context associated
   // with a BrowsingContext.
   virtual net::URLRequestContext* GetRequestContext() = 0;
-
-  // Returns a random salt string that is used for creating media device IDs.
-  // Returns a random string by default.
-  virtual std::string GetMediaDeviceIDSalt();
-
-  // Utility function useful for embedders. Only needs to be called if
-  // 1) The embedder needs to use a new salt, and
-  // 2) The embedder saves its salt across restarts.
-  static std::string CreateRandomMediaDeviceIDSalt();
-
- private:
-  const std::string media_device_id_salt_;
 };
 
 }  // namespace content
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index f2743d81..397c86e 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -706,7 +706,7 @@
 
       int aria_colcount = src.AriaColumnCount();
       if (aria_colcount)
-        dst->AddIntAttribute(ui::AX_ATTR_ARIA_COL_COUNT, aria_colcount);
+        dst->AddIntAttribute(ui::AX_ATTR_ARIA_COLUMN_COUNT, aria_colcount);
 
       int aria_rowcount = src.AriaRowCount();
       if (aria_rowcount)
@@ -742,13 +742,15 @@
                              src.CellRowSpan());
 
         int aria_colindex = src.AriaColumnIndex();
-        if (aria_colindex)
-          dst->AddIntAttribute(ui::AX_ATTR_ARIA_COL_INDEX, aria_colindex);
+        if (aria_colindex) {
+          dst->AddIntAttribute(ui::AX_ATTR_ARIA_CELL_COLUMN_INDEX,
+                               aria_colindex);
+        }
       }
 
       int aria_rowindex = src.AriaRowIndex();
       if (aria_rowindex)
-        dst->AddIntAttribute(ui::AX_ATTR_ARIA_ROW_INDEX, aria_rowindex);
+        dst->AddIntAttribute(ui::AX_ATTR_ARIA_CELL_ROW_INDEX, aria_rowindex);
     }
 
     if ((dst->role == ui::AX_ROLE_ROW_HEADER ||
diff --git a/content/renderer/android/synchronous_compositor_frame_sink.cc b/content/renderer/android/synchronous_compositor_frame_sink.cc
index ad0e358..be2a840 100644
--- a/content/renderer/android/synchronous_compositor_frame_sink.cc
+++ b/content/renderer/android/synchronous_compositor_frame_sink.cc
@@ -288,7 +288,7 @@
     auto* surface_quad =
         embed_render_pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
     shared_quad_state->SetAll(
-        child_transform, child_size, gfx::Rect(child_size),
+        child_transform, gfx::Rect(child_size), gfx::Rect(child_size),
         gfx::Rect() /* clip_rect */, false /* is_clipped */, 1.f /* opacity */,
         SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
     surface_quad->SetNew(
diff --git a/content/renderer/media/render_media_log.cc b/content/renderer/media/render_media_log.cc
index 981e38d..66708ecf 100644
--- a/content/renderer/media/render_media_log.cc
+++ b/content/renderer/media/render_media_log.cc
@@ -92,15 +92,16 @@
         last_duration_changed_event_.swap(event);
         break;
 
-      // Hold onto the most recent PIPELINE_ERROR and MEDIA_LOG_ERROR_ENTRY for
-      // use in GetLastErrorMessage().
+      // Hold onto the most recent PIPELINE_ERROR and the first, if any,
+      // MEDIA_LOG_ERROR_ENTRY for use in GetErrorMessage().
       case media::MediaLogEvent::PIPELINE_ERROR:
         queued_media_events_.push_back(*event);
         last_pipeline_error_.swap(event);
         break;
       case media::MediaLogEvent::MEDIA_ERROR_LOG_ENTRY:
         queued_media_events_.push_back(*event);
-        last_media_error_log_entry_.swap(event);
+        if (!cached_media_error_for_message_)
+          cached_media_error_for_message_ = std::move(event);
         break;
 
       // Just enqueue all other event types for throttled transmission.
@@ -134,18 +135,25 @@
       base::Bind(&RenderMediaLog::SendQueuedMediaEvents, weak_this_));
 }
 
-std::string RenderMediaLog::GetLastErrorMessage() {
+std::string RenderMediaLog::GetErrorMessage() {
   base::AutoLock auto_lock(lock_);
 
-  // Return the conditional concatenation of the last pipeline error and the
-  // last media error log.
+  // Keep message structure in sync with
+  // HTMLMediaElement::BuildElementErrorMessage().
+
   std::stringstream result;
-  if (last_pipeline_error_) {
-    result << MediaEventToLogString(*last_pipeline_error_)
-           << (last_media_error_log_entry_ ? ", " : "");
+  if (last_pipeline_error_)
+    result << MediaEventToMessageString(*last_pipeline_error_);
+
+  if (cached_media_error_for_message_) {
+    DCHECK(last_pipeline_error_)
+        << "Message with detail should be associated with a pipeline error";
+    // This ':' lets web apps extract the UA-specific-error-code from the
+    // MediaError.message prefix.
+    result << ": "
+           << MediaEventToMessageString(*cached_media_error_for_message_);
   }
-  if (last_media_error_log_entry_)
-    result << MediaEventToLogString(*last_media_error_log_entry_);
+
   return result.str();
 }
 
diff --git a/content/renderer/media/render_media_log.h b/content/renderer/media/render_media_log.h
index 825125f..f13e021 100644
--- a/content/renderer/media/render_media_log.h
+++ b/content/renderer/media/render_media_log.h
@@ -39,7 +39,7 @@
 
   // MediaLog implementation.
   void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override;
-  std::string GetLastErrorMessage() override;
+  std::string GetErrorMessage() override;
   void RecordRapporWithSecurityOrigin(const std::string& metric) override;
 
   // Will reset |last_ipc_send_time_| with the value of NowTicks().
@@ -60,7 +60,7 @@
   // |lock_| protects access to all of the following member variables.  It
   // allows any render process thread to AddEvent(), while preserving their
   // sequence for throttled send on |task_runner_| and coherent retrieval by
-  // GetLastErrorMessage().
+  // GetErrorMessage().
   mutable base::Lock lock_;
   std::unique_ptr<base::TickClock> tick_clock_;
   base::TimeTicks last_ipc_send_time_;
@@ -73,8 +73,12 @@
   std::unique_ptr<media::MediaLogEvent> last_buffered_extents_changed_event_;
   std::unique_ptr<media::MediaLogEvent> last_duration_changed_event_;
 
-  // Holds a copy of the most recent MEDIA_ERROR_LOG_ENTRY, if any.
-  std::unique_ptr<media::MediaLogEvent> last_media_error_log_entry_;
+  // Holds the earliest MEDIA_ERROR_LOG_ENTRY event added to this log. This is
+  // most likely to contain the most specific information available describing
+  // any eventual fatal error.
+  // TODO(wolenetz): Introduce a reset method to clear this in cases like
+  // non-fatal error recovery like decoder fallback.
+  std::unique_ptr<media::MediaLogEvent> cached_media_error_for_message_;
 
   // Holds a copy of the most recent PIPELINE_ERROR, if any.
   std::unique_ptr<media::MediaLogEvent> last_pipeline_error_;
diff --git a/content/renderer/media/webmediaplayer_ms.cc b/content/renderer/media/webmediaplayer_ms.cc
index 6d48707..711a1be 100644
--- a/content/renderer/media/webmediaplayer_ms.cc
+++ b/content/renderer/media/webmediaplayer_ms.cc
@@ -422,8 +422,8 @@
   return ready_state_;
 }
 
-blink::WebString WebMediaPlayerMS::GetErrorMessage() {
-  return blink::WebString::FromUTF8(media_log_->GetLastErrorMessage());
+blink::WebString WebMediaPlayerMS::GetErrorMessage() const {
+  return blink::WebString::FromUTF8(media_log_->GetErrorMessage());
 }
 
 blink::WebTimeRanges WebMediaPlayerMS::Buffered() const {
diff --git a/content/renderer/media/webmediaplayer_ms.h b/content/renderer/media/webmediaplayer_ms.h
index debec32..7cfca3df 100644
--- a/content/renderer/media/webmediaplayer_ms.h
+++ b/content/renderer/media/webmediaplayer_ms.h
@@ -130,7 +130,7 @@
   blink::WebMediaPlayer::NetworkState GetNetworkState() const override;
   blink::WebMediaPlayer::ReadyState GetReadyState() const override;
 
-  blink::WebString GetErrorMessage() override;
+  blink::WebString GetErrorMessage() const override;
   bool DidLoadingProgress() override;
 
   bool HasSingleSecurityOrigin() const override;
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
index 52c6b77f..376ab1a 100644
--- a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
@@ -56,7 +56,10 @@
   double CurrentTime() const override { return 0.0; }
   NetworkState GetNetworkState() const override { return kNetworkStateEmpty; }
   ReadyState GetReadyState() const override { return kReadyStateHaveNothing; }
-  blink::WebString GetErrorMessage() override { return blink::WebString(); }
+  blink::WebString GetErrorMessage() const override {
+    return blink::WebString();
+  }
+
   bool DidLoadingProgress() override { return true; }
   bool HasSingleSecurityOrigin() const override { return true; }
   bool DidPassCORSAccessCheck() const override { return true; }
diff --git a/content/test/data/accessibility/aria/aria-col-attr-expected-blink.txt b/content/test/data/accessibility/aria/aria-col-attr-expected-blink.txt
index c96566df..501678c4 100644
--- a/content/test/data/accessibility/aria/aria-col-attr-expected-blink.txt
+++ b/content/test/data/accessibility/aria/aria-col-attr-expected-blink.txt
@@ -1,26 +1,26 @@
 rootWebArea
-++grid ariaColCount=5
+++grid ariaColumnCount=5
 ++++row
-++++++columnHeader name='cell 2' ariaColIndex=2
+++++++columnHeader name='cell 2' ariaCellColumnIndex=2
 ++++++++staticText name='cell 2'
 ++++++++++inlineTextBox name='cell 2'
-++++++columnHeader name='cell 4' ariaColIndex=4
+++++++columnHeader name='cell 4' ariaCellColumnIndex=4
 ++++++++staticText name='cell 4'
 ++++++++++inlineTextBox name='cell 4'
-++++++columnHeader name='cell 5' ariaColIndex=5
+++++++columnHeader name='cell 5' ariaCellColumnIndex=5
 ++++++++staticText name='cell 5'
 ++++++++++inlineTextBox name='cell 5'
 ++++row
-++++++cell name='cell 2' ariaColIndex=2
+++++++cell name='cell 2' ariaCellColumnIndex=2
 ++++++++staticText name='cell 2'
 ++++++++++inlineTextBox name='cell 2'
-++++++cell name='cell 3' ariaColIndex=3
+++++++cell name='cell 3' ariaCellColumnIndex=3
 ++++++++staticText name='cell 3'
 ++++++++++inlineTextBox name='cell 3'
-++++++cell name='cell 4' ariaColIndex=4
+++++++cell name='cell 4' ariaCellColumnIndex=4
 ++++++++staticText name='cell 4'
 ++++++++++inlineTextBox name='cell 4'
-++++++cell name='cell 5' ariaColIndex=5
+++++++cell name='cell 5' ariaCellColumnIndex=5
 ++++++++staticText name='cell 5'
 ++++++++++inlineTextBox name='cell 5'
 ++++column
diff --git a/content/test/data/accessibility/aria/aria-col-attr.html b/content/test/data/accessibility/aria/aria-col-attr.html
index a77b5f63..a4782a6 100644
--- a/content/test/data/accessibility/aria/aria-col-attr.html
+++ b/content/test/data/accessibility/aria/aria-col-attr.html
@@ -3,7 +3,8 @@
 @WIN-ALLOW:colindex*
 @WIN-ALLOW:colspan*
 @MAC-ALLOW:AXARIAColumn*
-@BLINK-ALLOW:ariaCol*
+@BLINK-ALLOW:ariaColumn*
+@BLINK-ALLOW:ariaCellColumn*
 -->
 <div role="grid" aria-colcount="5">
   <div role="row">
diff --git a/content/test/data/accessibility/aria/aria-row-attr-expected-blink.txt b/content/test/data/accessibility/aria/aria-row-attr-expected-blink.txt
index 9440ddd..03705172 100644
--- a/content/test/data/accessibility/aria/aria-row-attr-expected-blink.txt
+++ b/content/test/data/accessibility/aria/aria-row-attr-expected-blink.txt
@@ -1,20 +1,20 @@
 rootWebArea
 ++grid ariaRowCount=5
 ++++row
-++++++columnHeader name='cell 2' ariaRowIndex=3
+++++++columnHeader name='cell 2' ariaCellRowIndex=3
 ++++++++staticText name='cell 2'
 ++++++++++inlineTextBox name='cell 2'
-++++++columnHeader name='cell 3' ariaRowIndex=3
+++++++columnHeader name='cell 3' ariaCellRowIndex=3
 ++++++++staticText name='cell 3'
 ++++++++++inlineTextBox name='cell 3'
-++++++columnHeader name='cell 4' ariaRowIndex=3
+++++++columnHeader name='cell 4' ariaCellRowIndex=3
 ++++++++staticText name='cell 4'
 ++++++++++inlineTextBox name='cell 4'
-++++row ariaRowIndex=4
-++++++cell name='cell 2' ariaRowIndex=4
+++++row ariaCellRowIndex=4
+++++++cell name='cell 2' ariaCellRowIndex=4
 ++++++++staticText name='cell 2'
 ++++++++++inlineTextBox name='cell 2'
-++++++cell name='cell 3' ariaRowIndex=4
+++++++cell name='cell 3' ariaCellRowIndex=4
 ++++++++staticText name='cell 3'
 ++++++++++inlineTextBox name='cell 3'
 ++++column
diff --git a/content/test/data/accessibility/aria/aria-row-attr.html b/content/test/data/accessibility/aria/aria-row-attr.html
index d6b47f04..1b5e6299 100644
--- a/content/test/data/accessibility/aria/aria-row-attr.html
+++ b/content/test/data/accessibility/aria/aria-row-attr.html
@@ -4,6 +4,7 @@
 @WIN-ALLOW:rowspan*
 @MAC-ALLOW:AXARIARow*
 @BLINK-ALLOW:ariaRow*
+@BLINK-ALLOW:ariaCellRow*
 -->
 <div role="grid" aria-rowcount="5">
   <div role="row">
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index d7c17ce..9ca488f 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -220,7 +220,9 @@
     # Fails on all GPU types.
     self.Fail('conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html',
               ['mac'], bug=709351)
-
+    self.Fail('conformance2/rendering/' +
+        'blitframebuffer-resolve-to-back-buffer.html',
+        ['mac'], bug=699566)
     self.Fail('conformance2/rendering/' +
         'framebuffer-completeness-unaffected.html',
         ['mac'], bug=630800)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
index 57413a2d..489b476 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
+++ b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
@@ -1,3 +1,3 @@
 # AUTOGENERATED FILE - DO NOT EDIT
 # SEE roll_webgl_conformance.py
-Current webgl revision 73fd432435e8a8563f2117737c7639331761bddd
+Current webgl revision 40d75ac0e565191d93ff3c4e8fd19f8b2df7f617
diff --git a/docs/android_cast_build_instructions.md b/docs/android_cast_build_instructions.md
index f6d0287d..b0658182 100644
--- a/docs/android_cast_build_instructions.md
+++ b/docs/android_cast_build_instructions.md
@@ -234,8 +234,8 @@
 As drawback, the shell runs in non-production rendering mode only.
 
 ```shell
-ninja -C out/Release android_webview_apk
-build/android/adb_install_apk.py out/Release/apks/AndroidWebView.apk
+ninja -C out/Release webview_instrumentation_apk
+build/android/adb_install_apk.py out/Release/apks/WebViewInstrumentation.apk
 ```
 
 If, instead, you want to build the complete Android WebView framework component and test the effect of your chromium changes in other Android app using the WebView, you should follow the [Android AOSP + chromium WebView instructions](https://www.chromium.org/developers/how-tos/build-instructions-android-webview)
diff --git a/docs/android_test_instructions.md b/docs/android_test_instructions.md
index b941118..0fedc0d 100644
--- a/docs/android_test_instructions.md
+++ b/docs/android_test_instructions.md
@@ -121,7 +121,7 @@
     typically belong in either `<top-level directory>_javatests` or `<top-level
     directory>_test_java`. Regardless, they'll wind up getting packaged into one
     of a few test APKs:
-    -   `android_webview_test_apk` for anything in `//android_webview`
+    -   `webview_instrumentation_test_apk` for anything in `//android_webview`
     -   `content_shell_test_apk` for anything in `//content` or below
     -   `chrome_public_test_apk` for most things in `//chrome`
     -   `chrome_sync_shell_test_apk` in a few exceptional cases
@@ -270,9 +270,9 @@
 AndroidWebView tests:
 
 ```shell
-ninja -C out/Release android_webview_apk
-ninja -C out/Release android_webview_test_apk
-out/Release/bin/run_android_webview_test_apk [-vv]
+ninja -C out/Release webview_instrumentation_apk
+ninja -C out/Release webview_instrumentation_test_apk
+out/Release/bin/run_webview_instrumentation_test_apk [-vv]
 ```
 
 In order to run a subset of tests, use -f to filter based on test class/method
diff --git a/extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc b/extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc
index 7e768073e..05457ce 100644
--- a/extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc
+++ b/extensions/browser/api/webcam_private/webcam_private_api_chromeos.cc
@@ -120,9 +120,7 @@
 
   return content::GetMediaDeviceIDForHMAC(
       content::MEDIA_DEVICE_VIDEO_CAPTURE,
-      browser_context_->GetResourceContext()->GetMediaDeviceIDSalt(),
-      security_origin,
-      webcam_id,
+      browser_context_->GetMediaDeviceIDSalt(), security_origin, webcam_id,
       device_id);
 }
 
@@ -132,8 +130,7 @@
       extensions::Extension::GetBaseURLFromExtensionId(extension_id));
 
   return content::GetHMACForMediaDeviceID(
-      browser_context_->GetResourceContext()->GetMediaDeviceIDSalt(),
-      security_origin, device_id);
+      browser_context_->GetMediaDeviceIDSalt(), security_origin, device_id);
 }
 
 WebcamResource* WebcamPrivateAPI::FindWebcamResource(
diff --git a/extensions/renderer/argument_spec.cc b/extensions/renderer/argument_spec.cc
index da9b4e7..fd3e1a97 100644
--- a/extensions/renderer/argument_spec.cc
+++ b/extensions/renderer/argument_spec.cc
@@ -20,11 +20,14 @@
 bool ParseFundamentalValueHelper(v8::Local<v8::Value> arg,
                                  v8::Local<v8::Context> context,
                                  const base::Optional<int>& minimum,
+                                 const base::Optional<int>& maximum,
                                  std::unique_ptr<base::Value>* out_value) {
   T val;
   if (!gin::Converter<T>::FromV8(context->GetIsolate(), arg, &val))
     return false;
-  if (minimum && val < minimum.value())
+  if (minimum && val < *minimum)
+    return false;
+  if (maximum && val > *maximum)
     return false;
   if (out_value)
     *out_value = base::MakeUnique<base::Value>(val);
@@ -92,6 +95,10 @@
   if (dict->GetInteger("minimum", &min))
     minimum_ = min;
 
+  int max = 0;
+  if (dict->GetInteger("maximum", &max))
+    maximum_ = max;
+
   int min_length = 0;
   if (dict->GetInteger("minLength", &min_length) ||
       dict->GetInteger("minItems", &min_length)) {
@@ -241,10 +248,10 @@
   switch (type_) {
     case ArgumentType::INTEGER:
       return ParseFundamentalValueHelper<int32_t>(value, context, minimum_,
-                                                  out_value);
+                                                  maximum_, out_value);
     case ArgumentType::DOUBLE:
       return ParseFundamentalValueHelper<double>(value, context, minimum_,
-                                                 out_value);
+                                                 maximum_, out_value);
     case ArgumentType::STRING: {
       if (!value->IsString())
         return false;
diff --git a/extensions/renderer/argument_spec.h b/extensions/renderer/argument_spec.h
index f264e25e..66b87a1 100644
--- a/extensions/renderer/argument_spec.h
+++ b/extensions/renderer/argument_spec.h
@@ -131,8 +131,9 @@
   // type in its prototype chain.
   base::Optional<std::string> instance_of_;
 
-  // A minimum, if any.
+  // A minimum and maximum for integer and double values, if any.
   base::Optional<int> minimum_;
+  base::Optional<int> maximum_;
 
   // A minimium length for strings or arrays.
   base::Optional<size_t> min_length_;
diff --git a/extensions/renderer/argument_spec_unittest.cc b/extensions/renderer/argument_spec_unittest.cc
index 5cf0706..4bf8d25 100644
--- a/extensions/renderer/argument_spec_unittest.cc
+++ b/extensions/renderer/argument_spec_unittest.cc
@@ -159,6 +159,13 @@
   }
 
   {
+    ArgumentSpec spec(*ValueFromString("{'type': 'integer', 'maximum': 10}"));
+    ExpectSuccess(spec, "10", "10");
+    ExpectSuccess(spec, "1", "1");
+    ExpectFailure(spec, "11");
+  }
+
+  {
     ArgumentSpec spec(*ValueFromString("{'type': 'string'}"));
     ExpectSuccess(spec, "'foo'", "'foo'");
     ExpectSuccess(spec, "''", "''");
diff --git a/ios/chrome/browser/payments/cells/BUILD.gn b/ios/chrome/browser/payments/cells/BUILD.gn
index 123a96a..5dfd08d 100644
--- a/ios/chrome/browser/payments/cells/BUILD.gn
+++ b/ios/chrome/browser/payments/cells/BUILD.gn
@@ -4,6 +4,8 @@
 
 source_set("cells") {
   sources = [
+    "accepted_payment_methods_item.h",
+    "accepted_payment_methods_item.mm",
     "autofill_profile_item.h",
     "autofill_profile_item.mm",
     "page_info_item.h",
@@ -31,6 +33,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "accepted_payment_methods_item_unittest.mm",
     "autofill_profile_item_unittest.mm",
     "page_info_item_unittest.mm",
     "payment_method_item_unittest.mm",
diff --git a/ios/chrome/browser/payments/cells/accepted_payment_methods_item.h b/ios/chrome/browser/payments/cells/accepted_payment_methods_item.h
new file mode 100644
index 0000000..85e09f47
--- /dev/null
+++ b/ios/chrome/browser/payments/cells/accepted_payment_methods_item.h
@@ -0,0 +1,43 @@
+// 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 IOS_CHROME_BROWSER_PAYMENTS_CELLS_ACCEPTED_PAYMENT_METHODS_ITEM_H_
+#define IOS_CHROME_BROWSER_PAYMENTS_CELLS_ACCEPTED_PAYMENT_METHODS_ITEM_H_
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
+#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h"
+
+// AcceptedPaymentMethodsItem is the model class corresponding to
+// AcceptedPaymentMethodsCell.
+@interface AcceptedPaymentMethodsItem : CollectionViewItem
+
+// The message to be displayed alongside the icons for the accepted payment
+// method types.
+@property(nonatomic, copy) NSString* message;
+
+// An array of icons corresponding to the accepted payment method types.
+@property(nonatomic, strong) NSArray<UIImage*>* methodTypeIcons;
+
+@end
+
+// AcceptedPaymentMethodsCell implements an MDCCollectionViewCell subclass
+// containing one text label and a list of icons representing the accepted
+// payment method types. The text label is laid out on the leading edge of the
+// cell up to the trailing edge of the cell. Below that, icon are laid out in a
+// row from the leading edge of the cell up to the trailing edge of the cell.
+// The text label is wrapped as needed to fit in the cell.
+@interface AcceptedPaymentMethodsCell : MDCCollectionViewCell
+
+// UILabel corresponding to |message|.
+@property(nonatomic, readonly, strong) UILabel* messageLabel;
+
+// An array of UIImageView objects containing the icons for the accepted payment
+// method types.
+@property(nonatomic, strong) NSArray<UIImageView*>* methodTypeIconViews;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_PAYMENTS_CELLS_ACCEPTED_PAYMENT_METHODS_ITEM_H_
diff --git a/ios/chrome/browser/payments/cells/accepted_payment_methods_item.mm b/ios/chrome/browser/payments/cells/accepted_payment_methods_item.mm
new file mode 100644
index 0000000..8fdf969
--- /dev/null
+++ b/ios/chrome/browser/payments/cells/accepted_payment_methods_item.mm
@@ -0,0 +1,174 @@
+// 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.
+
+#import "ios/chrome/browser/payments/cells/accepted_payment_methods_item.h"
+
+#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
+#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// Padding of the top and bottom edges of the cell.
+const CGFloat kVerticalPadding = 12;
+
+// Spacing between the icons.
+const CGFloat kHorizontalSpacingBetweenIcons = 5;
+}  // namespace
+
+@implementation AcceptedPaymentMethodsItem
+
+@synthesize message = _message;
+@synthesize methodTypeIcons = _methodTypeIcons;
+
+#pragma mark CollectionViewItem
+
+- (instancetype)initWithType:(NSInteger)type {
+  self = [super initWithType:type];
+  if (self) {
+    self.cellClass = [AcceptedPaymentMethodsCell class];
+  }
+  return self;
+}
+
+- (void)configureCell:(AcceptedPaymentMethodsCell*)cell {
+  [super configureCell:cell];
+  cell.messageLabel.text = self.message;
+
+  NSMutableArray* methodTypeIconViews = [NSMutableArray array];
+  for (UIImage* methodTypeIcon in self.methodTypeIcons) {
+    UIImageView* methodTypeIconView =
+        [[UIImageView alloc] initWithFrame:CGRectZero];
+    methodTypeIconView.image = methodTypeIcon;
+    methodTypeIconView.accessibilityLabel = methodTypeIcon.accessibilityLabel;
+    methodTypeIconView.layer.borderColor =
+        [UIColor colorWithWhite:0.9 alpha:1.0].CGColor;
+    methodTypeIconView.layer.borderWidth = 1.0;
+    [methodTypeIconViews addObject:methodTypeIconView];
+  }
+  cell.methodTypeIconViews = methodTypeIconViews;
+}
+
+@end
+
+@implementation AcceptedPaymentMethodsCell {
+  UIStackView* _stackView;
+}
+
+@synthesize messageLabel = _messageLabel;
+@synthesize methodTypeIconViews = _methodTypeIconViews;
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    self.isAccessibilityElement = YES;
+    [self addSubviews];
+    [self setDefaultViewStyling];
+    [self setViewConstraints];
+  }
+  return self;
+}
+
+// Create and add subviews.
+- (void)addSubviews {
+  UIView* contentView = self.contentView;
+  contentView.clipsToBounds = YES;
+
+  _messageLabel = [[UILabel alloc] init];
+  _messageLabel.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:_messageLabel];
+
+  _stackView = [[UIStackView alloc] initWithArrangedSubviews:@[]];
+  _stackView.axis = UILayoutConstraintAxisHorizontal;
+  _stackView.layoutMarginsRelativeArrangement = YES;
+  _stackView.layoutMargins =
+      UIEdgeInsetsMake(kVerticalPadding, 0, kVerticalPadding, 0);
+  _stackView.spacing = kHorizontalSpacingBetweenIcons;
+  _stackView.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:_stackView];
+}
+
+// Set default font and text colors for labels.
+- (void)setDefaultViewStyling {
+  _messageLabel.font = [MDCTypography body2Font];
+  _messageLabel.textColor = [[MDCPalette greyPalette] tint600];
+  _messageLabel.numberOfLines = 0;
+  _messageLabel.lineBreakMode = NSLineBreakByWordWrapping;
+}
+
+// Set constraints on subviews.
+- (void)setViewConstraints {
+  [NSLayoutConstraint activateConstraints:@[
+    [_messageLabel.topAnchor constraintEqualToAnchor:self.contentView.topAnchor
+                                            constant:kVerticalPadding],
+    [_messageLabel.leadingAnchor
+        constraintEqualToAnchor:self.contentView.leadingAnchor],
+    [_messageLabel.trailingAnchor
+        constraintEqualToAnchor:self.contentView.trailingAnchor],
+    [_messageLabel.bottomAnchor constraintEqualToAnchor:_stackView.topAnchor],
+    [_stackView.leadingAnchor
+        constraintEqualToAnchor:self.contentView.leadingAnchor],
+    [_stackView.trailingAnchor
+        constraintLessThanOrEqualToAnchor:self.contentView.trailingAnchor],
+    [_stackView.bottomAnchor
+        constraintEqualToAnchor:self.contentView.bottomAnchor],
+  ]];
+}
+
+- (void)setMethodTypeIconViews:(NSArray<UIImageView*>*)methodTypeIconViews {
+  // Remove the old UIImageViews.
+  for (UIImageView* methodTypeIconView in _methodTypeIconViews)
+    [methodTypeIconView removeFromSuperview];
+
+  _methodTypeIconViews = methodTypeIconViews;
+
+  // Add the new UIImageViews.
+  for (UIImageView* methodTypeIconView in _methodTypeIconViews)
+    [_stackView addArrangedSubview:methodTypeIconView];
+}
+
+#pragma mark - UIView
+
+// Implement -layoutSubviews as per instructions in documentation for
+// +[MDCCollectionViewCell cr_preferredHeightForWidth:forItem:].
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // Adjust preferredMaxLayoutWidth of _messageLabel when the parent's width
+  // changes, for instance on screen rotation.
+  CGFloat parentWidth = CGRectGetWidth(self.contentView.frame);
+  _messageLabel.preferredMaxLayoutWidth = parentWidth;
+
+  // Re-layout with the new preferred width to allow the label to adjust its
+  // height.
+  [super layoutSubviews];
+}
+
+#pragma mark - UICollectionReusableView
+
+- (void)prepareForReuse {
+  [super prepareForReuse];
+  self.messageLabel.text = nil;
+  self.methodTypeIconViews = nil;
+}
+
+#pragma mark - NSObject(Accessibility)
+
+- (NSString*)accessibilityLabel {
+  NSMutableString* accessibilityLabel =
+      [NSMutableString stringWithString:self.messageLabel.text];
+  NSArray* iconsAccessibilityLabels =
+      [self.methodTypeIconViews valueForKeyPath:@"accessibilityLabel"];
+  NSString* concatenatedAccessibilityLabel =
+      [iconsAccessibilityLabels componentsJoinedByString:@", "];
+  if (concatenatedAccessibilityLabel.length) {
+    [accessibilityLabel appendFormat:@", %@", concatenatedAccessibilityLabel];
+  }
+  return accessibilityLabel;
+}
+
+@end
diff --git a/ios/chrome/browser/payments/cells/accepted_payment_methods_item_unittest.mm b/ios/chrome/browser/payments/cells/accepted_payment_methods_item_unittest.mm
new file mode 100644
index 0000000..13f144b3
--- /dev/null
+++ b/ios/chrome/browser/payments/cells/accepted_payment_methods_item_unittest.mm
@@ -0,0 +1,47 @@
+// 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.
+
+#import "ios/chrome/browser/payments/cells/accepted_payment_methods_item.h"
+
+#import "ios/chrome/browser/ui/collection_view/cells/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+// Tests that the label and the images are set properly after a call to
+// |configureCell:|.
+TEST(PaymentRequestAcceptedPaymentMethodsItemTest, TextLabelsAndImages) {
+  AcceptedPaymentMethodsItem* item = [[AcceptedPaymentMethodsItem alloc] init];
+
+  NSString* message = @"Lorem ipsum dolor sit amet";
+  NSArray* methodTypeIcons = @[
+    ios_internal::CollectionViewTestImage(),
+    ios_internal::CollectionViewTestImage()
+  ];
+
+  item.message = message;
+  item.methodTypeIcons = methodTypeIcons;
+
+  id cell = [[[item cellClass] alloc] init];
+  ASSERT_TRUE([cell isMemberOfClass:[AcceptedPaymentMethodsCell class]]);
+
+  AcceptedPaymentMethodsCell* acceptedPaymentMethodsCell = cell;
+  EXPECT_FALSE(acceptedPaymentMethodsCell.messageLabel.text);
+  EXPECT_EQ(nil, acceptedPaymentMethodsCell.methodTypeIconViews);
+
+  [item configureCell:acceptedPaymentMethodsCell];
+  EXPECT_NSEQ(message, acceptedPaymentMethodsCell.messageLabel.text);
+  ASSERT_EQ(2UL, acceptedPaymentMethodsCell.methodTypeIconViews.count);
+  EXPECT_NSEQ(methodTypeIcons[0],
+              acceptedPaymentMethodsCell.methodTypeIconViews[0].image);
+  EXPECT_NSEQ(methodTypeIcons[1],
+              acceptedPaymentMethodsCell.methodTypeIconViews[1].image);
+}
+
+}  // namespace
diff --git a/ios/chrome/browser/payments/cells/autofill_profile_item_unittest.mm b/ios/chrome/browser/payments/cells/autofill_profile_item_unittest.mm
index b12ce451..82e00a54 100644
--- a/ios/chrome/browser/payments/cells/autofill_profile_item_unittest.mm
+++ b/ios/chrome/browser/payments/cells/autofill_profile_item_unittest.mm
@@ -16,7 +16,7 @@
 
 // Tests that the labels are set properly after a call to |configureCell:|.
 TEST(PaymentRequestAutofillProfileItemTest, TextLabels) {
-  AutofillProfileItem* item = [[AutofillProfileItem alloc] initWithType:0];
+  AutofillProfileItem* item = [[AutofillProfileItem alloc] init];
 
   NSString* name = @"Jon Doe";
   NSString* address = @"123 Main St, Anytown, USA";
diff --git a/ios/chrome/browser/payments/cells/page_info_item_unittest.mm b/ios/chrome/browser/payments/cells/page_info_item_unittest.mm
index 1030c67..63d457ee 100644
--- a/ios/chrome/browser/payments/cells/page_info_item_unittest.mm
+++ b/ios/chrome/browser/payments/cells/page_info_item_unittest.mm
@@ -17,7 +17,7 @@
 // Tests that the labels and image are set properly after a call to
 // |configureCell:|.
 TEST(PaymentRequestPageInfoItemTest, TextLabels) {
-  PageInfoItem* item = [[PageInfoItem alloc] initWithType:0];
+  PageInfoItem* item = [[PageInfoItem alloc] init];
 
   UIImage* pageFavicon = ios_internal::CollectionViewTestImage();
   NSString* pageTitle = @"The Greatest Website Ever";
diff --git a/ios/chrome/browser/payments/cells/payment_method_item_unittest.mm b/ios/chrome/browser/payments/cells/payment_method_item_unittest.mm
index c2ed3b5..cabfb3b 100644
--- a/ios/chrome/browser/payments/cells/payment_method_item_unittest.mm
+++ b/ios/chrome/browser/payments/cells/payment_method_item_unittest.mm
@@ -17,7 +17,7 @@
 // Tests that the labels and image are set properly after a call to
 // |configureCell:|.
 TEST(PaymentRequestPaymentMethodItemTest, TextLabels) {
-  PaymentMethodItem* item = [[PaymentMethodItem alloc] initWithType:0];
+  PaymentMethodItem* item = [[PaymentMethodItem alloc] init];
 
   NSString* methodID = @"BobPay - ****-6789";
   NSString* methodDetail = @"Bobs Your Uncle III, esq.";
diff --git a/ios/chrome/browser/payments/cells/payments_text_item_unittest.mm b/ios/chrome/browser/payments/cells/payments_text_item_unittest.mm
index 9c40280..b9f8e13 100644
--- a/ios/chrome/browser/payments/cells/payments_text_item_unittest.mm
+++ b/ios/chrome/browser/payments/cells/payments_text_item_unittest.mm
@@ -17,7 +17,7 @@
 // Tests that the text label and the image are set properly after a call to
 // |configureCell:|.
 TEST(PaymentRequestPaymentsTextItemTest, TextLabelAndImage) {
-  PaymentsTextItem* item = [[PaymentsTextItem alloc] initWithType:0];
+  PaymentsTextItem* item = [[PaymentsTextItem alloc] init];
 
   NSString* text = @"Lorem ipsum";
   NSString* detailText = @"Dolor sit amet";
diff --git a/ios/chrome/browser/payments/cells/price_item_unittest.mm b/ios/chrome/browser/payments/cells/price_item_unittest.mm
index 4b05f2f..5a4b872 100644
--- a/ios/chrome/browser/payments/cells/price_item_unittest.mm
+++ b/ios/chrome/browser/payments/cells/price_item_unittest.mm
@@ -16,7 +16,7 @@
 
 // Tests that the labels are set properly after a call to |configureCell:|.
 TEST(PaymentRequestPriceItemTest, TextLabels) {
-  PriceItem* priceItem = [[PriceItem alloc] initWithType:0];
+  PriceItem* priceItem = [[PriceItem alloc] init];
 
   NSString* item = @"Total";
   NSString* notification = @"Updated";
diff --git a/ios/chrome/browser/payments/credit_card_edit_mediator.mm b/ios/chrome/browser/payments/credit_card_edit_mediator.mm
index 9a9bdb99..2766890 100644
--- a/ios/chrome/browser/payments/credit_card_edit_mediator.mm
+++ b/ios/chrome/browser/payments/credit_card_edit_mediator.mm
@@ -12,6 +12,7 @@
 #import "components/autofill/ios/browser/credit_card_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/application_context.h"
+#import "ios/chrome/browser/payments/cells/accepted_payment_methods_item.h"
 #import "ios/chrome/browser/payments/cells/payment_method_item.h"
 #include "ios/chrome/browser/payments/payment_request.h"
 #import "ios/chrome/browser/payments/payment_request_editor_field.h"
@@ -27,9 +28,11 @@
 
 namespace {
 using ::AutofillUITypeFromAutofillType;
+using ::autofill::data_util::GetCardTypeForBasicCardPaymentType;
+using ::autofill::data_util::GetPaymentRequestData;
 using ::payment_request_util::GetBillingAddressLabelFromAutofillProfile;
 
-const CGFloat kCardTypeIconDimension = 25.0;
+const CGFloat kCardTypeIconDimension = 20.0;
 }  // namespace
 
 @interface CreditCardEditViewControllerMediator ()
@@ -66,6 +69,7 @@
 }
 
 - (CollectionViewItem*)serverCardSummaryItem {
+  // Return nil if creating or editing a local card.
   if (!_creditCard || autofill::IsCreditCardLocal(*_creditCard))
     return nil;
 
@@ -81,6 +85,35 @@
   return cardSummaryItem;
 }
 
+- (CollectionViewItem*)acceptedPaymentMethodsItem {
+  // Return nil if a server card is being edited.
+  if (_creditCard && !autofill::IsCreditCardLocal(*_creditCard))
+    return nil;
+
+  NSMutableArray* cardTypeIcons = [NSMutableArray array];
+  for (const auto& supportedNetwork :
+       _paymentRequest->supported_card_networks()) {
+    const std::string cardType =
+        GetCardTypeForBasicCardPaymentType(supportedNetwork);
+    const autofill::data_util::PaymentRequestData& cardData =
+        GetPaymentRequestData(cardType);
+    UIImage* cardTypeIcon =
+        ResizeImage(NativeImage(cardData.icon_resource_id),
+                    CGSizeMake(kCardTypeIconDimension, kCardTypeIconDimension),
+                    ProjectionMode::kAspectFillNoClipping);
+    cardTypeIcon.accessibilityLabel =
+        l10n_util::GetNSString(cardData.a11y_label_resource_id);
+    [cardTypeIcons addObject:cardTypeIcon];
+  }
+
+  AcceptedPaymentMethodsItem* acceptedMethodsItem =
+      [[AcceptedPaymentMethodsItem alloc] init];
+  acceptedMethodsItem.message =
+      l10n_util::GetNSString(IDS_PAYMENTS_ACCEPTED_CARDS_LABEL);
+  acceptedMethodsItem.methodTypeIcons = cardTypeIcons;
+  return acceptedMethodsItem;
+}
+
 - (NSString*)billingAddressLabelForProfileWithGUID:(NSString*)profileGUID {
   DCHECK(profileGUID);
   autofill::AutofillProfile* profile =
diff --git a/ios/chrome/browser/payments/credit_card_edit_view_controller.h b/ios/chrome/browser/payments/credit_card_edit_view_controller.h
index 0e0dd13..5fc5f39 100644
--- a/ios/chrome/browser/payments/credit_card_edit_view_controller.h
+++ b/ios/chrome/browser/payments/credit_card_edit_view_controller.h
@@ -21,10 +21,13 @@
 @protocol CreditCardEditViewControllerDataSource<
     PaymentRequestEditViewControllerDataSource>
 
-// Returns an item that identifies the server card being edited. Returns nil for
-// local cards or when a card is being created.
+// Returns an item that identifies the credit card being edited. May return nil.
 - (CollectionViewItem*)serverCardSummaryItem;
 
+// Returns an item that displays a list of payment method type icons for the
+// accepted payment methods. May return nil.
+- (CollectionViewItem*)acceptedPaymentMethodsItem;
+
 // Returns the billing address label from an autofill profile with the given
 // guid. Returns nil if the profile does not have an address.
 - (NSString*)billingAddressLabelForProfileWithGUID:(NSString*)profileGUID;
diff --git a/ios/chrome/browser/payments/credit_card_edit_view_controller.mm b/ios/chrome/browser/payments/credit_card_edit_view_controller.mm
index 3233778a7..89e15e8b 100644
--- a/ios/chrome/browser/payments/credit_card_edit_view_controller.mm
+++ b/ios/chrome/browser/payments/credit_card_edit_view_controller.mm
@@ -32,13 +32,15 @@
     @"kCreditCardEditCollectionViewId";
 
 typedef NS_ENUM(NSInteger, SectionIdentifier) {
-  SectionIdentifierCardSummary = kSectionIdentifierEnumStart,
+  SectionIdentifierAcceptedMethods = kSectionIdentifierEnumStart,
+  SectionIdentifierCardSummary,
   SectionIdentifierBillingAddress,
   SectionIdentifierSaveCard,
 };
 
 typedef NS_ENUM(NSInteger, ItemType) {
-  ItemTypeCardSummary = kItemTypeEnumStart,
+  ItemTypeAcceptedMethods = kItemTypeEnumStart,
+  ItemTypeCardSummary,
   ItemTypeBillingAddress,
   ItemTypeSaveCard,
 };
@@ -171,6 +173,16 @@
     [model addItem:serverCardSummaryItem
         toSectionWithIdentifier:SectionIdentifierCardSummary];
   }
+
+  // Accepted payment methods section.
+  CollectionViewItem* acceptedMethodsItem =
+      [_dataSource acceptedPaymentMethodsItem];
+  if (acceptedMethodsItem) {
+    [model addSectionWithIdentifier:SectionIdentifierAcceptedMethods];
+    acceptedMethodsItem.type = ItemTypeAcceptedMethods;
+    [model addItem:acceptedMethodsItem
+        toSectionWithIdentifier:SectionIdentifierAcceptedMethods];
+  }
 }
 
 - (void)loadFooterItems {
@@ -285,6 +297,7 @@
   CollectionViewItem* item =
       [self.collectionViewModel itemAtIndexPath:indexPath];
   switch (item.type) {
+    case ItemTypeAcceptedMethods:
     case ItemTypeCardSummary:
     case ItemTypeSaveCard:
       break;
@@ -306,6 +319,7 @@
   switch (item.type) {
     case ItemTypeBillingAddress:
       return MDCCellDefaultOneLineHeight;
+    case ItemTypeAcceptedMethods:
     case ItemTypeCardSummary:
     case ItemTypeSaveCard:
       return [MDCCollectionViewCell
@@ -321,6 +335,7 @@
     hidesInkViewAtIndexPath:(NSIndexPath*)indexPath {
   NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
   switch (type) {
+    case ItemTypeAcceptedMethods:
     case ItemTypeCardSummary:
     case ItemTypeSaveCard:
       return YES;
@@ -330,6 +345,18 @@
   }
 }
 
+- (BOOL)collectionView:(UICollectionView*)collectionView
+    shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath {
+  NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
+  switch (type) {
+    case ItemTypeAcceptedMethods:
+      return YES;
+    default:
+      return [super collectionView:collectionView
+          shouldHideItemBackgroundAtIndexPath:indexPath];
+  }
+}
+
 #pragma mark Switch Actions
 
 - (void)saveCardSwitchToggled:(UISwitch*)sender {
diff --git a/ios/chrome/browser/payments/credit_card_edit_view_controller_unittest.mm b/ios/chrome/browser/payments/credit_card_edit_view_controller_unittest.mm
index 66d4588..9c8507b1 100644
--- a/ios/chrome/browser/payments/credit_card_edit_view_controller_unittest.mm
+++ b/ios/chrome/browser/payments/credit_card_edit_view_controller_unittest.mm
@@ -7,6 +7,7 @@
 #include "base/mac/foundation_util.h"
 #include "base/memory/ptr_util.h"
 #include "components/autofill/core/browser/field_types.h"
+#import "ios/chrome/browser/payments/cells/accepted_payment_methods_item.h"
 #import "ios/chrome/browser/payments/cells/payment_method_item.h"
 #import "ios/chrome/browser/payments/payment_request_editor_field.h"
 #include "ios/chrome/browser/payments/payment_request_test_util.h"
@@ -35,6 +36,10 @@
   return [[PaymentMethodItem alloc] init];
 }
 
+- (CollectionViewItem*)acceptedPaymentMethodsItem {
+  return [[AcceptedPaymentMethodsItem alloc] init];
+}
+
 - (NSArray<EditorField*>*)editorFields {
   return @[
     [[EditorField alloc] initWithAutofillUIType:AutofillUITypeCreditCardNumber
@@ -96,10 +101,12 @@
       setState:CreditCardEditViewControllerStateEdit];
   [GetCreditCardEditViewController() loadModel];
 
-  // There is one section for every textfield (there are four textfields in
-  // total), one for the server card summary section, one for the footer, and
-  // one for the billing address ID item.
-  ASSERT_EQ(7, NumberOfSections());
+  // There is one section containing the credit card type icons for the accepted
+  // payment methods. In addition to that, there is one section for every
+  // textfield (there are four textfields in total), one for the server card
+  // summary section, one for the footer, and one for the billing address ID
+  // item.
+  ASSERT_EQ(8, NumberOfSections());
 
   // The server card summary section is the first section and has one item of
   // the type PaymentMethodItem.
@@ -107,11 +114,13 @@
   id item = GetCollectionViewItem(0, 0);
   EXPECT_TRUE([item isMemberOfClass:[PaymentMethodItem class]]);
 
-  // The next four sections have only one item of the type AutofillEditItem.
+  // The next section is the accepted payment methods section and has one item
+  // of the type AcceptedPaymentMethodsItem.
   ASSERT_EQ(1U, static_cast<unsigned int>(NumberOfItemsInSection(1)));
   item = GetCollectionViewItem(1, 0);
-  EXPECT_TRUE([item isMemberOfClass:[AutofillEditItem class]]);
+  EXPECT_TRUE([item isMemberOfClass:[AcceptedPaymentMethodsItem class]]);
 
+  // The next four sections have only one item of the type AutofillEditItem.
   ASSERT_EQ(1U, static_cast<unsigned int>(NumberOfItemsInSection(2)));
   item = GetCollectionViewItem(2, 0);
   EXPECT_TRUE([item isMemberOfClass:[AutofillEditItem class]]);
@@ -124,10 +133,14 @@
   item = GetCollectionViewItem(4, 0);
   EXPECT_TRUE([item isMemberOfClass:[AutofillEditItem class]]);
 
-  // The billing address section contains one item which is of the type
-  // CollectionViewDetailItem.
   ASSERT_EQ(1U, static_cast<unsigned int>(NumberOfItemsInSection(5)));
   item = GetCollectionViewItem(5, 0);
+  EXPECT_TRUE([item isMemberOfClass:[AutofillEditItem class]]);
+
+  // The billing address section contains one item which is of the type
+  // CollectionViewDetailItem.
+  ASSERT_EQ(1U, static_cast<unsigned int>(NumberOfItemsInSection(6)));
+  item = GetCollectionViewItem(6, 0);
   EXPECT_TRUE([item isMemberOfClass:[CollectionViewDetailItem class]]);
   CollectionViewDetailItem* billing_address_item = item;
   EXPECT_EQ(MDCCollectionViewCellAccessoryDisclosureIndicator,
@@ -135,8 +148,8 @@
 
   // The footer section contains one item which is of the type
   // CollectionViewFooterItem.
-  ASSERT_EQ(1U, static_cast<unsigned int>(NumberOfItemsInSection(6)));
-  item = GetCollectionViewItem(6, 0);
+  ASSERT_EQ(1U, static_cast<unsigned int>(NumberOfItemsInSection(7)));
+  item = GetCollectionViewItem(7, 0);
   EXPECT_TRUE([item isMemberOfClass:[CollectionViewFooterItem class]]);
 }
 
@@ -153,12 +166,12 @@
 
   // There is an extra section containing a switch that allows the user to save
   // the credit card locally.
-  ASSERT_EQ(8, NumberOfSections());
+  ASSERT_EQ(9, NumberOfSections());
 
   // The switch section is the last section before the footer and has one item
   // of the type CollectionViewSwitchItem. The switch is on by defualt.
-  ASSERT_EQ(1U, static_cast<unsigned int>(NumberOfItemsInSection(6)));
-  id item = GetCollectionViewItem(6, 0);
+  ASSERT_EQ(1U, static_cast<unsigned int>(NumberOfItemsInSection(7)));
+  id item = GetCollectionViewItem(7, 0);
   EXPECT_TRUE([item isMemberOfClass:[CollectionViewSwitchItem class]]);
   CollectionViewSwitchItem* switch_item = item;
   EXPECT_EQ(YES, [switch_item isOn]);
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn
index dab645e4..405fd269 100644
--- a/ios/chrome/browser/ui/infobars/BUILD.gn
+++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 source_set("infobars") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "infobar_view.h",
     "infobar_view.mm",
diff --git a/ios/chrome/browser/ui/infobars/infobar_view.h b/ios/chrome/browser/ui/infobars/infobar_view.h
index 57be604..583552f3 100644
--- a/ios/chrome/browser/ui/infobars/infobar_view.h
+++ b/ios/chrome/browser/ui/infobars/infobar_view.h
@@ -21,7 +21,7 @@
 @property(nonatomic, assign) CGFloat visibleHeight;
 
 // Label text with links initialized with |stringAsLink:|.
-@property(nonatomic, readonly) NSString* markedLabel;
+@property(nonatomic, strong, readonly) NSString* markedLabel;
 
 // Stops propagating events to delegate.
 - (void)resetDelegate;
diff --git a/ios/chrome/browser/ui/infobars/infobar_view.mm b/ios/chrome/browser/ui/infobars/infobar_view.mm
index 88d913b..dc3471dd 100644
--- a/ios/chrome/browser/ui/infobars/infobar_view.mm
+++ b/ios/chrome/browser/ui/infobars/infobar_view.mm
@@ -9,7 +9,6 @@
 
 #include "base/format_macros.h"
 #include "base/i18n/rtl.h"
-#include "base/ios/weak_nsobject.h"
 #include "base/logging.h"
 #include "base/mac/foundation_util.h"
 #include "base/strings/sys_string_conversions.h"
@@ -26,6 +25,10 @@
 #import "ui/gfx/ios/uikit_util.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 const char kChromeInfobarURL[] = "chromeinternal://infobar/";
@@ -82,16 +85,15 @@
 @end
 
 @implementation SwitchView {
-  base::scoped_nsobject<UILabel> label_;
-  base::scoped_nsobject<UISwitch> switch_;
+  UILabel* label_;
+  UISwitch* switch_;
   CGFloat preferredTotalWidth_;
   CGFloat preferredLabelWidth_;
 }
 
 - (id)initWithLabel:(NSString*)labelText isOn:(BOOL)isOn {
   // Creates switch and label.
-  base::scoped_nsobject<UILabel> tempLabel(
-      [[UILabel alloc] initWithFrame:CGRectZero]);
+  UILabel* tempLabel = [[UILabel alloc] initWithFrame:CGRectZero];
   [tempLabel setTextAlignment:NSTextAlignmentNatural];
   [tempLabel setFont:[MDCTypography body1Font]];
   [tempLabel setText:labelText];
@@ -99,8 +101,7 @@
   [tempLabel setLineBreakMode:NSLineBreakByWordWrapping];
   [tempLabel setNumberOfLines:0];
   [tempLabel setAdjustsFontSizeToFitWidth:NO];
-  base::scoped_nsobject<UISwitch> tempSwitch(
-      [[UISwitch alloc] initWithFrame:CGRectZero]);
+  UISwitch* tempSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
   [tempSwitch setExclusiveTouch:YES];
   [tempSwitch setAccessibilityLabel:labelText];
   [tempSwitch setOnTintColor:[[MDCPalette cr_bluePalette] tint500]];
@@ -117,8 +118,8 @@
   self = [super initWithFrame:frameRect];
   if (!self)
     return nil;
-  label_.reset([tempLabel retain]);
-  switch_.reset([tempSwitch retain]);
+  label_ = tempLabel;
+  switch_ = tempSwitch;
 
   // Sets the position of the label and the switch. The label is left aligned
   // and the switch is right aligned. Both are vertically centered.
@@ -223,37 +224,37 @@
 
 @implementation InfoBarView {
   // Delegates UIView events.
-  InfoBarViewDelegate* delegate_;  // weak
+  InfoBarViewDelegate* delegate_;  // weak.
   // The current height of this infobar (used for animations where part of the
   // infobar is hidden).
   CGFloat visibleHeight_;
   // The height of this infobar when fully visible.
   CGFloat targetHeight_;
   // View containing |imageView_|. Exists to apply drop shadows to the view.
-  base::scoped_nsobject<UIView> imageViewContainer_;
+  UIView* imageViewContainer_;
   // View containing the icon.
-  base::scoped_nsobject<UIImageView> imageView_;
+  UIImageView* imageView_;
   // Close button.
-  base::scoped_nsobject<UIButton> closeButton_;
+  UIButton* closeButton_;
   // View containing the switch and its label.
-  base::scoped_nsobject<SwitchView> switchView_;
+  SwitchView* switchView_;
   // We are using a LabelLinkController with an UILabel to be able to have
   // parts of the label underlined and clickable. This label_ may be nil if
   // the delegate returns an empty string for GetMessageText().
-  base::scoped_nsobject<LabelLinkController> labelLinkController_;
-  UILabel* label_;  // Weak.
+  LabelLinkController* labelLinkController_;
+  UILabel* label_;
   // Array of range information. The first element of the pair is the tag of
   // the action and the second element is the range defining the link.
   std::vector<std::pair<NSUInteger, NSRange>> linkRanges_;
   // Text for the label with link markers included.
-  base::scoped_nsobject<NSString> markedLabel_;
+  NSString* markedLabel_;
   // Buttons.
   // button1_ is tagged with ConfirmInfoBarDelegate::BUTTON_OK .
   // button2_ is tagged with ConfirmInfoBarDelegate::BUTTON_CANCEL .
-  base::scoped_nsobject<UIButton> button1_;
-  base::scoped_nsobject<UIButton> button2_;
+  UIButton* button1_;
+  UIButton* button2_;
   // Drop shadow.
-  base::scoped_nsobject<UIImageView> shadow_;
+  UIImageView* shadow_;
 }
 
 @synthesize visibleHeight = visibleHeight_;
@@ -265,7 +266,7 @@
     delegate_ = delegate;
     // Make the drop shadow.
     UIImage* shadowImage = [UIImage imageNamed:@"infobar_shadow"];
-    shadow_.reset([[UIImageView alloc] initWithImage:shadowImage]);
+    shadow_ = [[UIImageView alloc] initWithImage:shadowImage];
     [self addSubview:shadow_];
     [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth |
                               UIViewAutoresizingFlexibleHeight];
@@ -274,9 +275,6 @@
   return self;
 }
 
-- (void)dealloc {
-  [super dealloc];
-}
 
 - (NSString*)markedLabel {
   return markedLabel_;
@@ -663,7 +661,7 @@
   NSString* imagePath =
       [[NSBundle mainBundle] pathForResource:@"infobar_close" ofType:@"png"];
   UIImage* image = [UIImage imageWithContentsOfFile:imagePath];
-  closeButton_.reset([[UIButton buttonWithType:UIButtonTypeCustom] retain]);
+  closeButton_ = [UIButton buttonWithType:UIButtonTypeCustom];
   [closeButton_ setExclusiveTouch:YES];
   [closeButton_ setImage:image forState:UIControlStateNormal];
   [closeButton_ addTarget:target
@@ -679,17 +677,17 @@
                        tag:(NSInteger)tag
                     target:(id)target
                     action:(SEL)action {
-  switchView_.reset([[SwitchView alloc] initWithLabel:label isOn:isOn]);
+  switchView_ = [[SwitchView alloc] initWithLabel:label isOn:isOn];
   [switchView_ setTag:tag target:target action:action];
   [self addSubview:switchView_];
 }
 
 - (void)addLeftIcon:(UIImage*)image {
   if (!imageViewContainer_) {
-    imageViewContainer_.reset([[UIView alloc] init]);
+    imageViewContainer_ = [[UIView alloc] init];
     [self addSubview:imageViewContainer_];
   }
-  imageView_.reset([[UIImageView alloc] initWithImage:image]);
+  imageView_ = [[UIImageView alloc] initWithImage:image];
   [imageViewContainer_ addSubview:imageView_];
 }
 
@@ -726,7 +724,7 @@
         [string rangeOfString:[[InfoBarView openingMarkerForLink]
                                   stringByAppendingString:@"("]];
     if (!startingRange.length)
-      return [[string copy] autorelease];
+      return [string copy];
     // Read the tag.
     NSUInteger beginTag = NSMaxRange(startingRange);
     NSRange closingParenthesis = [string
@@ -734,13 +732,13 @@
               options:NSLiteralSearch
                 range:NSMakeRange(beginTag, [string length] - beginTag)];
     if (closingParenthesis.location == NSNotFound)
-      return [[string copy] autorelease];
+      return [string copy];
     NSInteger tag = [[string
         substringWithRange:NSMakeRange(beginTag, closingParenthesis.location -
                                                      beginTag)] integerValue];
     // If the parsing fails, |tag| is 0. Negative values are not allowed.
     if (tag <= 0)
-      return [[string copy] autorelease];
+      return [string copy];
     // Find the closing marker.
     startingRange.length =
         closingParenthesis.location - startingRange.location + 1;
@@ -768,21 +766,21 @@
 }
 
 - (void)addLabel:(NSString*)text action:(void (^)(NSUInteger))action {
-  markedLabel_.reset([text copy]);
+  markedLabel_ = [text copy];
   if (action)
     text = [self stripMarkersFromString:text];
   if ([label_ superview]) {
     [label_ removeFromSuperview];
   }
 
-  label_ = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
+  label_ = [[UILabel alloc] initWithFrame:CGRectZero];
 
   UIFont* font = [MDCTypography subheadFont];
 
   [label_ setBackgroundColor:[UIColor clearColor]];
 
   NSMutableParagraphStyle* paragraphStyle =
-      [[[NSMutableParagraphStyle alloc] init] autorelease];
+      [[NSMutableParagraphStyle alloc] init];
   paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
   paragraphStyle.lineSpacing = kLabelLineSpacing;
   NSDictionary* attributes = @{
@@ -791,16 +789,16 @@
   };
   [label_ setNumberOfLines:0];
 
-  [label_ setAttributedText:[[[NSAttributedString alloc]
-                                initWithString:text
-                                    attributes:attributes] autorelease]];
+  [label_
+      setAttributedText:[[NSAttributedString alloc] initWithString:text
+                                                        attributes:attributes]];
 
   [self addSubview:label_];
 
   if (linkRanges_.empty())
     return;
 
-  labelLinkController_.reset([[LabelLinkController alloc]
+  labelLinkController_ = [[LabelLinkController alloc]
       initWithLabel:label_
              action:^(const GURL& gurl) {
                if (action) {
@@ -808,7 +806,7 @@
                      gurl.ExtractFileName()) integerValue];
                  action(actionTag);
                }
-             }]);
+             }];
 
   [labelLinkController_ setLinkUnderlineStyle:NSUnderlineStyleSingle];
   [labelLinkController_ setLinkColor:[UIColor blackColor]];
@@ -829,20 +827,20 @@
               tag2:(NSInteger)tag2
             target:(id)target
             action:(SEL)action {
-  button1_.reset([[self infoBarButton:title1
-                              palette:[MDCPalette cr_bluePalette]
-                     customTitleColor:[UIColor whiteColor]
-                                  tag:tag1
-                               target:target
-                               action:action] retain]);
+  button1_ = [self infoBarButton:title1
+                         palette:[MDCPalette cr_bluePalette]
+                customTitleColor:[UIColor whiteColor]
+                             tag:tag1
+                          target:target
+                          action:action];
   [self addSubview:button1_];
 
-  button2_.reset([[self infoBarButton:title2
-                              palette:nil
-                     customTitleColor:UIColorFromRGB(kButton2TitleColor)
-                                  tag:tag2
-                               target:target
-                               action:action] retain]);
+  button2_ = [self infoBarButton:title2
+                         palette:nil
+                customTitleColor:UIColorFromRGB(kButton2TitleColor)
+                             tag:tag2
+                          target:target
+                          action:action];
   [self addSubview:button2_];
 }
 
@@ -852,12 +850,12 @@
            action:(SEL)action {
   if (![title length])
     return;
-  button1_.reset([[self infoBarButton:title
-                              palette:[MDCPalette cr_bluePalette]
-                     customTitleColor:[UIColor whiteColor]
-                                  tag:tag
-                               target:target
-                               action:action] retain]);
+  button1_ = [self infoBarButton:title
+                         palette:[MDCPalette cr_bluePalette]
+                customTitleColor:[UIColor whiteColor]
+                             tag:tag
+                          target:target
+                          action:action];
   [self addSubview:button1_];
 }
 
@@ -869,19 +867,19 @@
                        tag:(NSInteger)tag
                     target:(id)target
                     action:(SEL)action {
-  base::scoped_nsobject<MDCFlatButton> button([[MDCFlatButton alloc] init]);
-  button.get().inkColor = [[palette tint300] colorWithAlphaComponent:0.5f];
+  MDCFlatButton* button = [[MDCFlatButton alloc] init];
+  button.inkColor = [[palette tint300] colorWithAlphaComponent:0.5f];
   [button setBackgroundColor:[palette tint500] forState:UIControlStateNormal];
   [button setBackgroundColor:[UIColor colorWithWhite:0.8f alpha:1.0f]
                     forState:UIControlStateDisabled];
   if (palette)
-    button.get().hasOpaqueBackground = YES;
+    button.hasOpaqueBackground = YES;
   if (customTitleColor) {
-    button.get().tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
-    button.get().customTitleColor = customTitleColor;
+    button.tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
+    button.customTitleColor = customTitleColor;
   }
-  button.get().titleLabel.adjustsFontSizeToFitWidth = YES;
-  button.get().titleLabel.minimumScaleFactor = 0.6f;
+  button.titleLabel.adjustsFontSizeToFitWidth = YES;
+  button.titleLabel.minimumScaleFactor = 0.6f;
   [button setTitle:message forState:UIControlStateNormal];
   [button setTag:tag];
   [button addTarget:target
@@ -890,7 +888,7 @@
   // Without the call to layoutIfNeeded, |button| returns an incorrect
   // titleLabel the first time it is accessed in |narrowestWidthOfButton|.
   [button layoutIfNeeded];
-  return button.autorelease();
+  return button;
 }
 
 - (CGRect)frameOfCloseButton:(BOOL)singleLineMode {
diff --git a/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm b/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
index df84898..a16a34a 100644
--- a/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
@@ -10,6 +10,7 @@
 #include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/grit/components_scaled_resources.h"
+#import "ios/chrome/browser/payments/cells/accepted_payment_methods_item.h"
 #import "ios/chrome/browser/payments/cells/autofill_profile_item.h"
 #import "ios/chrome/browser/payments/cells/payments_text_item.h"
 #import "ios/chrome/browser/payments/cells/price_item.h"
@@ -56,6 +57,7 @@
   SectionIdentifierNativeAppCell,
   SectionIdentifierAutofill,
   SectionIdentifierPayments,
+  SectionIdentifierPaymentsNoBackground,
   SectionIdentifierAccountCell,
   SectionIdentifierAccountControlCell,
   SectionIdentifierFooters,
@@ -97,6 +99,9 @@
 // Image fixed horizontal size.
 const CGFloat kHorizontalImageFixedSize = 40;
 
+// Credit Card icon size.
+const CGFloat kCardTypeIconDimension = 25.0;
+
 }  // namespace
 
 @implementation MaterialCellCatalogViewController
@@ -258,6 +263,7 @@
   [model addSectionWithIdentifier:SectionIdentifierPayments];
   [model addItem:[self paymentsItemWithWrappingTextandOptionalImage]
       toSectionWithIdentifier:SectionIdentifierPayments];
+
   PriceItem* priceItem1 =
       [[PriceItem alloc] initWithType:ItemTypePaymentsSingleLine];
   priceItem1.item = @"Total";
@@ -306,6 +312,11 @@
   [model addItem:profileItem3
       toSectionWithIdentifier:SectionIdentifierPayments];
 
+  // Payments cells with no background.
+  [model addSectionWithIdentifier:SectionIdentifierPaymentsNoBackground];
+  [model addItem:[self acceptedPaymentMethodsItem]
+      toSectionWithIdentifier:SectionIdentifierPaymentsNoBackground];
+
   // Account cells.
   [model addSectionWithIdentifier:SectionIdentifierAccountCell];
   [model addItem:[self accountItemDetailWithError]
@@ -407,6 +418,7 @@
   NSInteger sectionIdentifier =
       [self.collectionViewModel sectionIdentifierForSection:indexPath.section];
   switch (sectionIdentifier) {
+    case SectionIdentifierPaymentsNoBackground:
     case SectionIdentifierFooters:
       // Display the Learn More footer without any background image or
       // shadowing.
@@ -557,6 +569,31 @@
   return item;
 }
 
+- (CollectionViewItem*)acceptedPaymentMethodsItem {
+  AcceptedPaymentMethodsItem* item = [[AcceptedPaymentMethodsItem alloc]
+      initWithType:ItemTypePaymentsDynamicHeight];
+  item.message = @"Cards accepted:";
+
+  NSMutableArray* cardTypeIcons = [NSMutableArray array];
+  const char* cardTypes[]{autofill::kVisaCard,
+                          autofill::kMasterCard,
+                          autofill::kAmericanExpressCard,
+                          autofill::kJCBCard,
+                          autofill::kDinersCard,
+                          autofill::kDiscoverCard};
+  for (const std::string& cardType : cardTypes) {
+    autofill::data_util::PaymentRequestData data =
+        autofill::data_util::GetPaymentRequestData(cardType);
+    UIImage* cardTypeIcon =
+        ResizeImage(NativeImage(data.icon_resource_id),
+                    CGSizeMake(kCardTypeIconDimension, kCardTypeIconDimension),
+                    ProjectionMode::kAspectFillNoClipping);
+    [cardTypeIcons addObject:cardTypeIcon];
+  }
+  item.methodTypeIcons = cardTypeIcons;
+  return item;
+}
+
 - (CollectionViewItem*)autofillItemWithMainAndTrailingText {
   AutofillDataItem* item =
       [[AutofillDataItem alloc] initWithType:ItemTypeAutofillDynamicHeight];
diff --git a/ios/clean/chrome/browser/ui/tools/menu_view_controller.h b/ios/clean/chrome/browser/ui/tools/menu_view_controller.h
index 757167b..1f815bc4 100644
--- a/ios/clean/chrome/browser/ui/tools/menu_view_controller.h
+++ b/ios/clean/chrome/browser/ui/tools/menu_view_controller.h
@@ -10,6 +10,7 @@
 #import "ios/clean/chrome/browser/ui/tools/tools_consumer.h"
 
 @protocol FindInPageVisibilityCommands;
+@protocol NavigationCommands;
 @protocol ToolsMenuCommands;
 
 // View controller that displays a vertical list of buttons to act as a menu.
@@ -18,8 +19,9 @@
 @interface MenuViewController : UIViewController<ToolsConsumer>
 
 // The dispatcher for this view controller.
-@property(nonatomic, weak) id<FindInPageVisibilityCommands, ToolsMenuCommands>
-    dispatcher;
+@property(nonatomic, weak)
+    id<FindInPageVisibilityCommands, NavigationCommands, ToolsMenuCommands>
+        dispatcher;
 
 @end
 
diff --git a/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm b/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm
index 3810f1c..cbe9f76 100644
--- a/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm
@@ -6,9 +6,11 @@
 
 #include "base/i18n/rtl.h"
 #import "base/logging.h"
+#import "base/mac/foundation_util.h"
 #import "base/macros.h"
 #import "ios/chrome/browser/ui/rtl_geometry.h"
 #import "ios/clean/chrome/browser/ui/commands/find_in_page_visibility_commands.h"
+#import "ios/clean/chrome/browser/ui/commands/navigation_commands.h"
 #import "ios/clean/chrome/browser/ui/commands/tools_menu_commands.h"
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_button.h"
 #import "ios/clean/chrome/browser/ui/tools/menu_overflow_controls_stackview.h"
@@ -26,6 +28,7 @@
 }
 
 @interface MenuViewController ()<ToolsActions>
+@property(nonatomic, strong) UIStackView* menuStackView;
 @property(nonatomic, strong) NSArray<ToolsMenuItem*>* menuItems;
 @property(nonatomic, strong)
     MenuOverflowControlsStackView* toolbarOverflowStackView;
@@ -35,6 +38,7 @@
 @implementation MenuViewController
 @synthesize dispatcher = _dispatcher;
 @synthesize menuItems = _menuItems;
+@synthesize menuStackView = _menuStackView;
 @synthesize toolbarOverflowStackView = _toolbarOverflowStackView;
 @synthesize displayOverflowControls = _displayOverflowControls;
 
@@ -52,6 +56,7 @@
   NSMutableArray<UIButton*>* buttons =
       [[NSMutableArray alloc] initWithCapacity:_menuItems.count];
 
+  // Load menu items.
   for (ToolsMenuItem* item in _menuItems) {
     UIButton* menuButton = [UIButton buttonWithType:UIButtonTypeSystem];
     menuButton.translatesAutoresizingMaskIntoConstraints = NO;
@@ -60,11 +65,12 @@
     [menuButton setContentEdgeInsets:UIEdgeInsetsMakeDirected(0, 10.0f, 0, 0)];
     [menuButton.titleLabel setFont:[MDCTypography subheadFont]];
     [menuButton.titleLabel setTextAlignment:NSTextAlignmentNatural];
-    [menuButton addTarget:self
-                   action:@selector(closeToolsMenu:)
+    [menuButton addTarget:self.dispatcher
+                   action:@selector(closeToolsMenu)
          forControlEvents:UIControlEventTouchUpInside];
     if (item.action) {
-      id target = (item.action == @selector(showFindInPage)) ? self : nil;
+      id target =
+          (item.action == @selector(showFindInPage)) ? self.dispatcher : nil;
       [menuButton addTarget:target
                      action:item.action
            forControlEvents:UIControlEventTouchUpInside];
@@ -73,50 +79,61 @@
   }
 
   // Placeholder stack view to hold menu contents.
-  UIStackView* menu = [[UIStackView alloc] initWithArrangedSubviews:buttons];
-  menu.translatesAutoresizingMaskIntoConstraints = NO;
-  menu.axis = UILayoutConstraintAxisVertical;
-  menu.distribution = UIStackViewDistributionFillEqually;
-  menu.alignment = UIStackViewAlignmentLeading;
+  self.menuStackView = [[UIStackView alloc] initWithArrangedSubviews:buttons];
+  self.menuStackView.translatesAutoresizingMaskIntoConstraints = NO;
+  self.menuStackView.axis = UILayoutConstraintAxisVertical;
+  self.menuStackView.distribution = UIStackViewDistributionFillEqually;
+  self.menuStackView.alignment = UIStackViewAlignmentLeading;
 
   // Stack view to hold overflow ToolbarButtons.
   if (self.traitCollection.horizontalSizeClass ==
           UIUserInterfaceSizeClassCompact &&
       self.displayOverflowControls) {
-    self.toolbarOverflowStackView =
-        [[MenuOverflowControlsStackView alloc] init];
-    // PLACEHOLDER: ToolsMenuButton might end up being part of the MenuVC's view
-    // instead of the StackView. We are waiting confirmation on this.
-    [self.toolbarOverflowStackView.toolsMenuButton
-               addTarget:nil
-                  action:@selector(closeToolsMenu:)
-        forControlEvents:UIControlEventTouchUpInside];
-    [menu insertArrangedSubview:self.toolbarOverflowStackView atIndex:0];
-    [NSLayoutConstraint activateConstraints:@[
-      [self.toolbarOverflowStackView.leadingAnchor
-          constraintEqualToAnchor:menu.leadingAnchor],
-      [self.toolbarOverflowStackView.trailingAnchor
-          constraintEqualToAnchor:menu.trailingAnchor],
-    ]];
+    [self setUpOverFlowControlsStackView];
   }
 
-  [self.view addSubview:menu];
+  // Setup constraints.
+  [self.view addSubview:self.menuStackView];
   [NSLayoutConstraint activateConstraints:@[
-    [menu.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
-    [menu.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
-    [menu.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
-    [menu.topAnchor constraintEqualToAnchor:self.view.topAnchor],
+    [self.menuStackView.leadingAnchor
+        constraintEqualToAnchor:self.view.leadingAnchor],
+    [self.menuStackView.trailingAnchor
+        constraintEqualToAnchor:self.view.trailingAnchor],
+    [self.menuStackView.bottomAnchor
+        constraintEqualToAnchor:self.view.bottomAnchor],
+    [self.menuStackView.topAnchor constraintEqualToAnchor:self.view.topAnchor],
   ]];
 }
 
-#pragma mark - ToolsMenuCommands
+- (void)setUpOverFlowControlsStackView {
+  self.toolbarOverflowStackView = [[MenuOverflowControlsStackView alloc] init];
+  // PLACEHOLDER: ToolsMenuButton might end up being part of the MenuVC's view
+  // instead of the StackView. We are waiting confirmation on this.
+  for (UIView* view in self.toolbarOverflowStackView.arrangedSubviews) {
+    if ([view isKindOfClass:[ToolbarButton class]]) {
+      ToolbarButton* button = base::mac::ObjCCastStrict<ToolbarButton>(view);
+      [button addTarget:self.dispatcher
+                    action:@selector(closeToolsMenu)
+          forControlEvents:UIControlEventTouchUpInside];
+    }
+  }
+  [self.toolbarOverflowStackView.reloadButton
+             addTarget:self.dispatcher
+                action:@selector(reloadPage)
+      forControlEvents:UIControlEventTouchUpInside];
+  [self.toolbarOverflowStackView.stopButton
+             addTarget:self.dispatcher
+                action:@selector(stopLoadingPage)
+      forControlEvents:UIControlEventTouchUpInside];
 
-- (void)closeToolsMenu:(id)sender {
-  [self.dispatcher closeToolsMenu];
-}
-
-- (void)showFindInPage {
-  [self.dispatcher showFindInPage];
+  [self.menuStackView insertArrangedSubview:self.toolbarOverflowStackView
+                                    atIndex:0];
+  [NSLayoutConstraint activateConstraints:@[
+    [self.toolbarOverflowStackView.leadingAnchor
+        constraintEqualToAnchor:self.menuStackView.leadingAnchor],
+    [self.toolbarOverflowStackView.trailingAnchor
+        constraintEqualToAnchor:self.menuStackView.trailingAnchor],
+  ]];
 }
 
 #pragma mark - Tools Consumer
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
index 2c55462..89a7434 100644
--- a/ipc/ipc_mojo_bootstrap.cc
+++ b/ipc/ipc_mojo_bootstrap.cc
@@ -788,6 +788,12 @@
     if (!endpoint)
       return;
 
+    // Careful, if the endpoint is detached its members are cleared. Check for
+    // that before dereferencing.
+    mojo::InterfaceEndpointClient* client = endpoint->client();
+    if (!client)
+      return;
+
     DCHECK(endpoint->task_runner()->BelongsToCurrentThread());
     MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
 
@@ -796,10 +802,6 @@
     if (message_wrapper.value().IsNull())
       return;
 
-    mojo::InterfaceEndpointClient* client = endpoint->client();
-    if (!client)
-      return;
-
     bool result = false;
     {
       base::AutoUnlock unlocker(lock_);
diff --git a/media/base/media_log.cc b/media/base/media_log.cc
index 76b6b40d..6d3140ce 100644
--- a/media/base/media_log.cc
+++ b/media/base/media_log.cc
@@ -8,6 +8,7 @@
 
 #include "base/atomic_sequence_num.h"
 #include "base/json/json_writer.h"
+#include "base/strings/string_util.h"
 #include "base/values.h"
 
 namespace media {
@@ -168,42 +169,32 @@
 }
 
 std::string MediaLog::PipelineStatusToString(PipelineStatus status) {
+#define STRINGIFY_STATUS_CASE(status) \
+  case status:                        \
+    return #status
+
   switch (status) {
-    case PIPELINE_OK:
-      return "pipeline: ok";
-    case PIPELINE_ERROR_NETWORK:
-      return "pipeline: network error";
-    case PIPELINE_ERROR_DECODE:
-      return "pipeline: decode error";
-    case PIPELINE_ERROR_ABORT:
-      return "pipeline: abort";
-    case PIPELINE_ERROR_INITIALIZATION_FAILED:
-      return "pipeline: initialization failed";
-    case PIPELINE_ERROR_COULD_NOT_RENDER:
-      return "pipeline: could not render";
-    case PIPELINE_ERROR_EXTERNAL_RENDERER_FAILED:
-      return "pipeline: external renderer failed";
-    case PIPELINE_ERROR_READ:
-      return "pipeline: read error";
-    case PIPELINE_ERROR_INVALID_STATE:
-      return "pipeline: invalid state";
-    case DEMUXER_ERROR_COULD_NOT_OPEN:
-      return "demuxer: could not open";
-    case DEMUXER_ERROR_COULD_NOT_PARSE:
-      return "demuxer: could not parse";
-    case DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
-      return "demuxer: no supported streams";
-    case DECODER_ERROR_NOT_SUPPORTED:
-      return "decoder: not supported";
-    case CHUNK_DEMUXER_ERROR_APPEND_FAILED:
-      return "chunk demuxer: append failed";
-    case CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR:
-      return "chunk demuxer: application requested decode error on eos";
-    case CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR:
-      return "chunk demuxer: application requested network error on eos";
-    case AUDIO_RENDERER_ERROR:
-      return "audio renderer: output device reported an error";
+    STRINGIFY_STATUS_CASE(PIPELINE_OK);
+    STRINGIFY_STATUS_CASE(PIPELINE_ERROR_NETWORK);
+    STRINGIFY_STATUS_CASE(PIPELINE_ERROR_DECODE);
+    STRINGIFY_STATUS_CASE(PIPELINE_ERROR_ABORT);
+    STRINGIFY_STATUS_CASE(PIPELINE_ERROR_INITIALIZATION_FAILED);
+    STRINGIFY_STATUS_CASE(PIPELINE_ERROR_COULD_NOT_RENDER);
+    STRINGIFY_STATUS_CASE(PIPELINE_ERROR_EXTERNAL_RENDERER_FAILED);
+    STRINGIFY_STATUS_CASE(PIPELINE_ERROR_READ);
+    STRINGIFY_STATUS_CASE(PIPELINE_ERROR_INVALID_STATE);
+    STRINGIFY_STATUS_CASE(DEMUXER_ERROR_COULD_NOT_OPEN);
+    STRINGIFY_STATUS_CASE(DEMUXER_ERROR_COULD_NOT_PARSE);
+    STRINGIFY_STATUS_CASE(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
+    STRINGIFY_STATUS_CASE(DECODER_ERROR_NOT_SUPPORTED);
+    STRINGIFY_STATUS_CASE(CHUNK_DEMUXER_ERROR_APPEND_FAILED);
+    STRINGIFY_STATUS_CASE(CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR);
+    STRINGIFY_STATUS_CASE(CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR);
+    STRINGIFY_STATUS_CASE(AUDIO_RENDERER_ERROR);
   }
+
+#undef STRINGIFY_STATUS_CASE
+
   NOTREACHED();
   return NULL;
 }
@@ -218,11 +209,33 @@
     PipelineStatus status = static_cast<PipelineStatus>(error_code);
     return EventTypeToString(event.type) + " " + PipelineStatusToString(status);
   }
+
   std::string params_json;
   base::JSONWriter::Write(event.params, &params_json);
   return EventTypeToString(event.type) + " " + params_json;
 }
 
+std::string MediaLog::MediaEventToMessageString(const MediaLogEvent& event) {
+  switch (event.type) {
+    case MediaLogEvent::PIPELINE_ERROR: {
+      int error_code = 0;
+      event.params.GetInteger("pipeline_error", &error_code);
+      DCHECK_NE(error_code, 0);
+      return PipelineStatusToString(static_cast<PipelineStatus>(error_code));
+    }
+    case MediaLogEvent::MEDIA_ERROR_LOG_ENTRY: {
+      std::string result = "";
+      if (event.params.GetString(MediaLogLevelToString(MEDIALOG_ERROR),
+                                 &result))
+        base::ReplaceChars(result, "\n", " ", &result);
+      return result;
+    }
+    default:
+      NOTREACHED();
+      return "";
+  }
+}
+
 std::string MediaLog::BufferingStateToString(BufferingState state) {
   switch (state) {
     case BUFFERING_HAVE_NOTHING:
@@ -240,7 +253,7 @@
 
 void MediaLog::AddEvent(std::unique_ptr<MediaLogEvent> event) {}
 
-std::string MediaLog::GetLastErrorMessage() {
+std::string MediaLog::GetErrorMessage() {
   return "";
 }
 
diff --git a/media/base/media_log.h b/media/base/media_log.h
index 0ab19ef..49efd18 100644
--- a/media/base/media_log.h
+++ b/media/base/media_log.h
@@ -36,11 +36,21 @@
   static std::string MediaLogLevelToString(MediaLogLevel level);
   static MediaLogEvent::Type MediaLogLevelToEventType(MediaLogLevel level);
   static std::string EventTypeToString(MediaLogEvent::Type type);
+
+  // Returns a string version of the status, unique to each PipelineStatus, and
+  // not including any ':'. This makes it suitable for usage in
+  // MediaError.message as the UA-specific-error-code.
   static std::string PipelineStatusToString(PipelineStatus status);
+
   static std::string BufferingStateToString(BufferingState state);
 
   static std::string MediaEventToLogString(const MediaLogEvent& event);
 
+  // Returns a string usable as part of a MediaError.message, for only
+  // PIPELINE_ERROR or MEDIA_ERROR_LOG_ENTRY events, with any newlines replaced
+  // with whitespace in the latter kind of events.
+  static std::string MediaEventToMessageString(const MediaLogEvent& event);
+
   MediaLog();
   virtual ~MediaLog();
 
@@ -48,8 +58,12 @@
   // with it.
   virtual void AddEvent(std::unique_ptr<MediaLogEvent> event);
 
-  // Retrieve an error message, if any.
-  virtual std::string GetLastErrorMessage();
+  // Returns a string usable as the contents of a MediaError.message.
+  // This method returns an incomplete message if it is called before the
+  // pertinent events for the error have been added to the log.
+  // Note: The base class definition only produces empty messages. See
+  // RenderMediaLog for where this method is meaningful.
+  virtual std::string GetErrorMessage();
 
   // Records the domain and registry of the current frame security origin to a
   // Rappor privacy-preserving metric. See:
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index af8d74c1..f2ba41b4 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -784,9 +784,9 @@
   return ready_state_;
 }
 
-blink::WebString WebMediaPlayerImpl::GetErrorMessage() {
+blink::WebString WebMediaPlayerImpl::GetErrorMessage() const {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
-  return blink::WebString::FromUTF8(media_log_->GetLastErrorMessage());
+  return blink::WebString::FromUTF8(media_log_->GetErrorMessage());
 }
 
 blink::WebTimeRanges WebMediaPlayerImpl::Buffered() const {
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index d154f00..6a2e541 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -158,7 +158,7 @@
   blink::WebMediaPlayer::NetworkState GetNetworkState() const override;
   blink::WebMediaPlayer::ReadyState GetReadyState() const override;
 
-  blink::WebString GetErrorMessage() override;
+  blink::WebString GetErrorMessage() const override;
   bool DidLoadingProgress() override;
 
   bool HasSingleSecurityOrigin() const override;
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java
index 3d30f1da..c2ab234f 100644
--- a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java
+++ b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java
@@ -379,6 +379,16 @@
         if (mExposureMode == AndroidMeteringMode.NONE
                 || mExposureMode == AndroidMeteringMode.FIXED) {
             requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_OFF);
+
+            // We need to configure by hand the exposure time when AE mode is off.  Set it to the
+            // middle of the allowed range. Further tuning will be done via |mIso|.
+            final CameraCharacteristics cameraCharacteristics =
+                    getCameraCharacteristics(mContext, mId);
+            Range<Long> range = cameraCharacteristics.get(
+                    CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
+            requestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME,
+                    range.getLower() + (range.getUpper() + range.getLower()) / 2 /* nanoseconds*/);
+
         } else {
             requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
             requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, mAeFpsRange);
diff --git a/media/test/data/player.html b/media/test/data/player.html
index 7577d86..1f891b0 100644
--- a/media/test/data/player.html
+++ b/media/test/data/player.html
@@ -1,11 +1,18 @@
 <html>
 <body onload="RunTest();">
 <div id="player_container"></div>
+<div id="logs"></div>
 </body>
 
 <script type="text/javascript">
 // <audio> or <video> player element.
 var player;
+var logs = document.getElementById('logs');
+
+function Log(message) {
+  logs.innerHTML = message + '<br>' + logs.innerHTML;
+  console.log(message);
+}
 
 // Listen for |event| from |element|, set document.title = |event| upon event.
 function InstallTitleEventHandler(element, event) {
@@ -14,6 +21,28 @@
   }, false);
 }
 
+function InstallTitleErrorEventHandler(element, error_substr) {
+  element.addEventListener('error', function(e) {
+    // Element's error attribute must be populated.
+    var mediaError = element.error;
+    if (mediaError == null) {
+      Log('ERROR: Null element error attribute while handling error event.');
+      Failed();
+      return;
+    }
+
+    Log('INFO: Element error message is ' + mediaError.message);
+
+    if (error_substr != null && !mediaError.message.includes(error_substr)) {
+      Log('ERROR: Element error message (' + mediaError.message +
+          ') does not contain expected substring (' + error_substr + ')');
+      Failed();
+      return;
+    }
+    document.title = 'ERROR';
+  }, false);
+}
+
 function Failed() {
   document.title = 'FAILED';
   return false;
@@ -39,14 +68,17 @@
 
 // Uses URL query parameters to create an audio or video element using a given
 // source.  URL must be of the form:
-// "player.html?[tag]=[media_url][&loop=[true/false]]".
+// "player.html?[tag]=[media_url][&loop=[true/false]][&error_substr=substr]".
 //
 // Plays the media and waits for X seconds of playback or the ended event, at
 // which point the test seeks near the end of the file and resumes playback.
 // Test completes when the second ended event occurs or an error event occurs at
 // any time.
-// There is an optional loop query parameter which when set to true, will cause
+// There is an optional loop query parameter, which when set to true will cause
 // the created media element to loop.
+// There is an optional error_substr query parameter, which when set will cause
+// any error event handling to fail if the MediaError.message does not contain
+// the specified substring resulting from decodeURIComponent().
 function RunTest() {
   var url_parts = window.location.href.split('?');
   if (url_parts.length != 2)
@@ -55,6 +87,7 @@
   var tag = '';
   var media_url = '';
   var loop = false;
+  var error_substr = null;
 
   var query_params = url_parts[1].split('&');
   for (var query_param in query_params) {
@@ -73,6 +106,11 @@
       loop = (query_parts[1] == 'true');
       continue;
     }
+
+    if (query_parts[0] == 'error_substr') {
+      error_substr = decodeURIComponent(query_parts[1]);
+      continue;
+    }
   }
 
   if (tag != 'audio' && tag != 'video') {
@@ -98,8 +136,9 @@
   player.addEventListener('ended', SeekTestStep, false);
   player.addEventListener('timeupdate', SeekTestTimeoutSetup, false);
 
-  // Ensure we percolate up any error events.
-  InstallTitleEventHandler(player, 'error');
+  // Ensure we percolate up any error events, and optionally verify they contain
+  // the expected error substring in their message.
+  InstallTitleErrorEventHandler(player, error_substr);
 
   // Starts the player.
   player.loop = loop;
diff --git a/net/BUILD.gn b/net/BUILD.gn
index db6cb35..4e2e034 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -5735,6 +5735,20 @@
   ]
 }
 
+fuzzer_test("net_http_security_headers_expect_ct_fuzzer") {
+  sources = [
+    "http/http_security_headers_expect_ct_fuzzer.cc",
+  ]
+  deps = [
+    ":net_fuzzer_test_support",
+    "//base",
+    "//net",
+    "//url",
+  ]
+  dict = "data/fuzzer_dictionaries/net_http_security_headers_fuzzer.dict"
+  seed_corpus = "data/fuzzer_data/http_security_headers/"
+}
+
 fuzzer_test("net_http_security_headers_hsts_fuzzer") {
   sources = [
     "http/http_security_headers_hsts_fuzzer.cc",
@@ -5744,6 +5758,7 @@
     "//net",
   ]
   dict = "data/fuzzer_dictionaries/net_http_security_headers_fuzzer.dict"
+  seed_corpus = "data/fuzzer_data/http_security_headers/"
 }
 
 fuzzer_test("net_http_security_headers_hpkp_fuzzer") {
@@ -5757,6 +5772,7 @@
     "//url",
   ]
   dict = "data/fuzzer_dictionaries/net_http_security_headers_fuzzer.dict"
+  seed_corpus = "data/fuzzer_data/http_security_headers/"
 }
 
 fuzzer_test("net_http_security_headers_hpkp_report_only_fuzzer") {
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_000.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_000.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_000.txt
@@ -0,0 +1 @@
+
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_001.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_001.txt
new file mode 100644
index 0000000..163b4d3f
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_001.txt
@@ -0,0 +1 @@
+    
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_002.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_002.txt
new file mode 100644
index 0000000..7edb2fa
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_002.txt
@@ -0,0 +1 @@
+,
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_003.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_003.txt
new file mode 100644
index 0000000..3ec3bff9
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_003.txt
@@ -0,0 +1 @@
+,,,, ,,,
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_004.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_004.txt
new file mode 100644
index 0000000..092bc2b0
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_004.txt
@@ -0,0 +1 @@
+;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_005.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_005.txt
new file mode 100644
index 0000000..3178536
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_005.txt
@@ -0,0 +1 @@
+;;;; ;;;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_006.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_006.txt
new file mode 100644
index 0000000..8baef1b4
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_006.txt
@@ -0,0 +1 @@
+abc
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_007.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_007.txt
new file mode 100644
index 0000000..03e48feb
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_007.txt
@@ -0,0 +1 @@
+  abc
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_008.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_008.txt
new file mode 100644
index 0000000..9b620e17
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_008.txt
@@ -0,0 +1 @@
+  abc   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_009.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_009.txt
new file mode 100644
index 0000000..356662a
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_009.txt
@@ -0,0 +1 @@
+amax-age=3488923
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_010.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_010.txt
new file mode 100644
index 0000000..a291793
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_010.txt
@@ -0,0 +1 @@
+animal="squirrel, distinguished", enFoRce, max-age=123
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_011.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_011.txt
new file mode 100644
index 0000000..8d49100
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_011.txt
@@ -0,0 +1 @@
+animal="squirrel; distinguished"; incLudesUbdOmains; max-age=123
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_012.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_012.txt
new file mode 100644
index 0000000..48d58eb
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_012.txt
@@ -0,0 +1 @@
+enFoRCE, max-age=123
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_013.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_013.txt
new file mode 100644
index 0000000..cd1a197
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_013.txt
@@ -0,0 +1 @@
+   enFORce, max-age=123
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_014.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_014.txt
new file mode 100644
index 0000000..9f450b3
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_014.txt
@@ -0,0 +1 @@
+   enFORcE, max-age=123, pumpkin=kitten
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_015.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_015.txt
new file mode 100644
index 0000000..b76690e
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_015.txt
@@ -0,0 +1 @@
+enfORce   , max-age=394082038 ,,
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_016.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_016.txt
new file mode 100644
index 0000000..995307e5
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_016.txt
@@ -0,0 +1 @@
+enforce, max-age=999, enforce
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_017.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_017.txt
new file mode 100644
index 0000000..46a25b5
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_017.txt
@@ -0,0 +1 @@
+enforce,report-uri="https://foo.test",max-age=123
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_018.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_018.txt
new file mode 100644
index 0000000..948ee83
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_018.txt
@@ -0,0 +1 @@
+   includeSubDomains,  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_019.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_019.txt
new file mode 100644
index 0000000..4ece532
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_019.txt
@@ -0,0 +1 @@
+   includeSubDomains;  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_020.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_020.txt
new file mode 100644
index 0000000..a24f029
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_020.txt
@@ -0,0 +1 @@
+,,,, includeSubDomains,,,
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_021.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_021.txt
new file mode 100644
index 0000000..453c561e6
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_021.txt
@@ -0,0 +1 @@
+;;;; includeSubDomains;;;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_022.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_022.txt
new file mode 100644
index 0000000..636af266
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_022.txt
@@ -0,0 +1 @@
+includesubdomains; max-age=10000
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_023.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_023.txt
new file mode 100644
index 0000000..c54db3c
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_023.txt
@@ -0,0 +1 @@
+   incLudesUbdOmains; max-age=123
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_024.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_024.txt
new file mode 100644
index 0000000..76601119
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_024.txt
@@ -0,0 +1 @@
+incLudesUbdOmains; max-age=123
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_025.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_025.txt
new file mode 100644
index 0000000..b41da86
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_025.txt
@@ -0,0 +1 @@
+   incLudesUbdOmains; max-age=123; pumpkin=kitten
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_026.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_026.txt
new file mode 100644
index 0000000..7542756
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_026.txt
@@ -0,0 +1 @@
+incLudesUbdOmains   ; max-age=394082038 ;;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_027.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_027.txt
new file mode 100644
index 0000000..44f9844
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_027.txt
@@ -0,0 +1 @@
+includeSubDOMAINS;pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="  ; mAx-aGe    = 890      
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_028.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_028.txt
new file mode 100644
index 0000000..d5efe33
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_028.txt
@@ -0,0 +1 @@
+max-ag=3488923
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_029.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_029.txt
new file mode 100644
index 0000000..93a2bfe
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_029.txt
@@ -0,0 +1 @@
+max-ag=3488923pins=pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=",pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_030.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_030.txt
new file mode 100644
index 0000000..49c98321
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_030.txt
@@ -0,0 +1 @@
+   max-age=
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_031.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_031.txt
new file mode 100644
index 0000000..68577fc
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_031.txt
@@ -0,0 +1 @@
+   max-age=   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_032.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_032.txt
new file mode 100644
index 0000000..bc3bceb
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_032.txt
@@ -0,0 +1 @@
+   max-age  =
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_033.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_033.txt
new file mode 100644
index 0000000..4d924a2
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_033.txt
@@ -0,0 +1 @@
+   max-age  =     
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_034.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_034.txt
new file mode 100644
index 0000000..f07939f
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_034.txt
@@ -0,0 +1 @@
+  max-age
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_035.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_035.txt
new file mode 100644
index 0000000..81cf934
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_035.txt
@@ -0,0 +1 @@
+  max-age  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_036.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_036.txt
new file mode 100644
index 0000000..0f51aed
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_036.txt
@@ -0,0 +1 @@
+max-age
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_037.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_037.txt
new file mode 100644
index 0000000..aa188dbf
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_037.txt
@@ -0,0 +1 @@
+max-age=
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_038.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_038.txt
new file mode 100644
index 0000000..40948f69
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_038.txt
@@ -0,0 +1 @@
+max-age, ,
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_039.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_039.txt
new file mode 100644
index 0000000..2cc668d3
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_039.txt
@@ -0,0 +1 @@
+max-age; ;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_040.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_040.txt
new file mode 100644
index 0000000..163fbaf
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_040.txt
@@ -0,0 +1 @@
+  max-age=0  ,  enforce   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_041.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_041.txt
new file mode 100644
index 0000000..b6dfffd
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_041.txt
@@ -0,0 +1 @@
+  max-age=0  ;  incLudesUbdOmains   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_042.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_042.txt
new file mode 100644
index 0000000..0d117dc
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_042.txt
@@ -0,0 +1 @@
+  max-age=0 ; includeSubdomains;  pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_043.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_043.txt
new file mode 100644
index 0000000..17f2c80
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_043.txt
@@ -0,0 +1 @@
+  max-age=0  ;  pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_044.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_044.txt
new file mode 100644
index 0000000..16a45c23
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_044.txt
@@ -0,0 +1 @@
+max-age = 0; pin-sha256="AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_045.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_045.txt
new file mode 100644
index 0000000..3777e61
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_045.txt
@@ -0,0 +1 @@
+max-age = 10000; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="; pin-sha256="AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_046.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_046.txt
new file mode 100644
index 0000000..d4c61c4
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_046.txt
@@ -0,0 +1 @@
+max-age = 10000; pin-sha256="AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_047.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_047.txt
new file mode 100644
index 0000000..8f39993
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_047.txt
@@ -0,0 +1 @@
+max-age = 10000; pin-sha256="AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";report-uri="http://google.com/"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_048.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_048.txt
new file mode 100644
index 0000000..2be7704
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_048.txt
@@ -0,0 +1 @@
+max-age = 10000; pin-sha256="AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE="; pin-sha256="AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_049.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_049.txt
new file mode 100644
index 0000000..0fc77f9
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_049.txt
@@ -0,0 +1 @@
+max-age=123,enFoRce
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_050.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_050.txt
new file mode 100644
index 0000000..7fd69b0d
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_050.txt
@@ -0,0 +1 @@
+max-age=123;incLudesUbdOmains
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_051.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_051.txt
new file mode 100644
index 0000000..8d949de76
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_051.txt
@@ -0,0 +1 @@
+max-age=13####
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_052.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_052.txt
new file mode 100644
index 0000000..97b2d6f4
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_052.txt
@@ -0,0 +1 @@
+max-age=18446744073709551615####
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_053.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_053.txt
new file mode 100644
index 0000000..9cef2790
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_053.txt
@@ -0,0 +1 @@
+max-age=243
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_054.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_054.txt
new file mode 100644
index 0000000..d61b8c63
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_054.txt
@@ -0,0 +1 @@
+max-age=243; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_055.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_055.txt
new file mode 100644
index 0000000..b52d4a4
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_055.txt
@@ -0,0 +1 @@
+max-age=243; pin-sha256=AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=;pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_056.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_056.txt
new file mode 100644
index 0000000..5d0c8f7
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_056.txt
@@ -0,0 +1 @@
+max-age=243; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";report-uri=;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_057.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_057.txt
new file mode 100644
index 0000000..055c3c8
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_057.txt
@@ -0,0 +1 @@
+max-age=243; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";report-uri=''
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_058.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_058.txt
new file mode 100644
index 0000000..8ad5258
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_058.txt
@@ -0,0 +1 @@
+max-age=243; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="; report-uri= "http://example.test/foo"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_059.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_059.txt
new file mode 100644
index 0000000..2b00599
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_059.txt
@@ -0,0 +1 @@
+max-age=243; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";report-uri=http://foo.com;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_060.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_060.txt
new file mode 100644
index 0000000..c0404d9
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_060.txt
@@ -0,0 +1 @@
+max-age==3488923
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_061.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_061.txt
new file mode 100644
index 0000000..85b2515
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_061.txt
@@ -0,0 +1 @@
+max-age=-3488923
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_062.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_062.txt
new file mode 100644
index 0000000..b061913
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_062.txt
@@ -0,0 +1 @@
+max-age=+3488923
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_063.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_063.txt
new file mode 100644
index 0000000..2299d9e
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_063.txt
@@ -0,0 +1 @@
+max-age=34889.23
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_064.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_064.txt
new file mode 100644
index 0000000..75beac7
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_064.txt
@@ -0,0 +1 @@
+max-age=3488923;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_065.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_065.txt
new file mode 100644
index 0000000..66e19b0
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_065.txt
@@ -0,0 +1 @@
+max-age=3488923     e
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_066.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_066.txt
new file mode 100644
index 0000000..42e657d
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_066.txt
@@ -0,0 +1 @@
+max-age=3488923     includesubdomain
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_067.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_067.txt
new file mode 100644
index 0000000..70f928df
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_067.txt
@@ -0,0 +1 @@
+max-age=3488923 includesubdomain=
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_068.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_068.txt
new file mode 100644
index 0000000..a13e0062
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_068.txt
@@ -0,0 +1 @@
+max-age=3488923includesubdomains
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_069.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_069.txt
new file mode 100644
index 0000000..c0f3b3f
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_069.txt
@@ -0,0 +1 @@
+max-age=34889.23 includesubdomains
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_070.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_070.txt
new file mode 100644
index 0000000..57e1e8c
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_070.txt
@@ -0,0 +1 @@
+max-age=3488923=includesubdomains
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_071.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_071.txt
new file mode 100644
index 0000000..284c9771
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_071.txt
@@ -0,0 +1 @@
+max-age=3488923 includesubdomainsx
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_072.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_072.txt
new file mode 100644
index 0000000..f4118a6
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_072.txt
@@ -0,0 +1 @@
+max-age=3488923 includesubdomains x
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_073.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_073.txt
new file mode 100644
index 0000000..47fdac7
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_073.txt
@@ -0,0 +1 @@
+max-age=3488923 includesubdomain=true
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_074.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_074.txt
new file mode 100644
index 0000000..8cc4f06
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_074.txt
@@ -0,0 +1 @@
+max-age=3488923 includesubdomainx
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_075.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_075.txt
new file mode 100644
index 0000000..1a421bd
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_075.txt
@@ -0,0 +1 @@
+max-age=3488923;pins=pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=",pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="report-uri="http://foo.com"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_076.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_076.txt
new file mode 100644
index 0000000..665e3750
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_076.txt
@@ -0,0 +1 @@
+max-age=3488923     report-uri="http://foo.com"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_077.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_077.txt
new file mode 100644
index 0000000..5a22117
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_077.txt
@@ -0,0 +1 @@
+max-age=34889 includesubdomains
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_078.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_078.txt
new file mode 100644
index 0000000..b340a86
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_078.txt
@@ -0,0 +1 @@
+   max-age  =     3488a923
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_079.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_079.txt
new file mode 100644
index 0000000..8f3938da
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_079.txt
@@ -0,0 +1 @@
+max-age=3488a923  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_080.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_080.txt
new file mode 100644
index 0000000..2d3d39d
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_080.txt
@@ -0,0 +1 @@
+max-age=39408038  ;    cybers=39408038  ;  includeSubdomains; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_081.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_081.txt
new file mode 100644
index 0000000..0f24a7c
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_081.txt
@@ -0,0 +1 @@
+,, max-age=394082038  ,
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_082.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_082.txt
new file mode 100644
index 0000000..0748e1f
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_082.txt
@@ -0,0 +1 @@
+;; max-age=394082038  ;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_083.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_083.txt
new file mode 100644
index 0000000..f6d52ea
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_083.txt
@@ -0,0 +1 @@
+,,    , , max-age=394082038,,, enforce     ,,  ,
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_084.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_084.txt
new file mode 100644
index 0000000..3775571b
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_084.txt
@@ -0,0 +1 @@
+,, max-age=394082038  , enfoRce, ,
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_085.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_085.txt
new file mode 100644
index 0000000..8af7429
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_085.txt
@@ -0,0 +1 @@
+;;    ; ; max-age=394082038;;; includeSubdomains     ;;  ;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_086.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_086.txt
new file mode 100644
index 0000000..dc06126f
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_086.txt
@@ -0,0 +1 @@
+;; max-age=394082038  ; incLudesUbdOmains; ;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_087.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_087.txt
new file mode 100644
index 0000000..5ff825a
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_087.txt
@@ -0,0 +1 @@
+max-age=394082038  ; incLudesUbdOmains
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_088.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_088.txt
new file mode 100644
index 0000000..0de25fc
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_088.txt
@@ -0,0 +1 @@
+max-age=394082038  ; incLudesUbdOmains;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_089.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_089.txt
new file mode 100644
index 0000000..f30e993
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_089.txt
@@ -0,0 +1 @@
+max-age=39408299  ,enforce
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_090.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_090.txt
new file mode 100644
index 0000000..be86f8e
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_090.txt
@@ -0,0 +1 @@
+max-age=39408299  ;incLudesUbdOmains
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_091.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_091.txt
new file mode 100644
index 0000000..a792193
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_091.txt
@@ -0,0 +1 @@
+max-age=39408299  ;pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_092.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_092.txt
new file mode 100644
index 0000000..a0ca43b
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_092.txt
@@ -0,0 +1 @@
+max-age=394082,  enforce
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_093.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_093.txt
new file mode 100644
index 0000000..817e596
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_093.txt
@@ -0,0 +1 @@
+max-age=394082;  incLudesUbdOmains
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_094.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_094.txt
new file mode 100644
index 0000000..2f4dd70
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_094.txt
@@ -0,0 +1 @@
+max-age=394082;pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_095.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_095.txt
new file mode 100644
index 0000000..09c7242
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_095.txt
@@ -0,0 +1 @@
+  Max-agE    = 567
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_096.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_096.txt
new file mode 100644
index 0000000..c72cc38
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_096.txt
@@ -0,0 +1 @@
+  mAx-aGe    = 890      
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_097.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_097.txt
new file mode 100644
index 0000000..6e9fed1
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_097.txt
@@ -0,0 +1 @@
+max-age=9223372036854775807#####
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_098.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_098.txt
new file mode 100644
index 0000000..a9a1631
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_098.txt
@@ -0,0 +1 @@
+max-age="999
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_099.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_099.txt
new file mode 100644
index 0000000..e42f391
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_099.txt
@@ -0,0 +1 @@
+max-age=999999999999999999999999$.&#!
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_100.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_100.txt
new file mode 100644
index 0000000..1e4e13a2
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_100.txt
@@ -0,0 +1 @@
+  max-age=999999999999999999999999999999999999999999999  ,  enforce   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_101.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_101.txt
new file mode 100644
index 0000000..9ac2eab
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_101.txt
@@ -0,0 +1 @@
+  max-age=999999999999999999999999999999999999999999999  ;  incLudesUbdOmains   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_102.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_102.txt
new file mode 100644
index 0000000..164b17d
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_102.txt
@@ -0,0 +1 @@
+  max-age=999999999999999999999999999999999999999999999  ;  pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_103.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_103.txt
new file mode 100644
index 0000000..e09ef4b
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_103.txt
@@ -0,0 +1 @@
+  max-age=999999999999999999999999999999999999999999999  ;  pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";   report-uri="http://example.test/foo"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_104.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_104.txt
new file mode 100644
index 0000000..ad90e56
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_104.txt
@@ -0,0 +1 @@
+max-age=999, enforce, max-age=99999
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_105.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_105.txt
new file mode 100644
index 0000000..6a95056
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_105.txt
@@ -0,0 +1 @@
+max-age=999, enforce=true
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_106.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_106.txt
new file mode 100644
index 0000000..85d4b5f5
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_106.txt
@@ -0,0 +1 @@
+  max-age=999;  pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_107.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_107.txt
new file mode 100644
index 0000000..49cfecd
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_107.txt
@@ -0,0 +1 @@
+max-age='999'; pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_108.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_108.txt
new file mode 100644
index 0000000..7c376c1c
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_108.txt
@@ -0,0 +1 @@
+max-age=999; pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="; report-uri="foo;bar'
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_109.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_109.txt
new file mode 100644
index 0000000..47ae525
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_109.txt
@@ -0,0 +1 @@
+max-age=999; pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="; report-uri="http://foo;bar'
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_110.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_110.txt
new file mode 100644
index 0000000..1dba8c4
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_110.txt
@@ -0,0 +1 @@
+max-age=999; pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="; report-uri="http://foo.com/"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_111.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_111.txt
new file mode 100644
index 0000000..eb731eb
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_111.txt
@@ -0,0 +1 @@
+max-age=999; pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="; report-uri='http://foo.com\'\a'
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_112.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_112.txt
new file mode 100644
index 0000000..2235e5a
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_112.txt
@@ -0,0 +1 @@
+max-age=999; pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="; report-uri="http://foo.com/?;bar"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_113.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_113.txt
new file mode 100644
index 0000000..1ab4843a
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_113.txt
@@ -0,0 +1 @@
+  max-age=999;  pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";pin-sha256="AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM=";   
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_114.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_114.txt
new file mode 100644
index 0000000..1b2f126
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_114.txt
@@ -0,0 +1 @@
+max-age=999, report-uri=""
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_115.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_115.txt
new file mode 100644
index 0000000..b1968e4
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_115.txt
@@ -0,0 +1 @@
+max-age=999, report-uri="foo;bar"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_116.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_116.txt
new file mode 100644
index 0000000..bc7614a8
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_116.txt
@@ -0,0 +1 @@
+max-age=999, report-uri=http://blah
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_117.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_117.txt
new file mode 100644
index 0000000..6c4b5e4
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_117.txt
@@ -0,0 +1 @@
+max-age=999, report-uri="http://foo;bar'
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_118.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_118.txt
new file mode 100644
index 0000000..b966c15
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_118.txt
@@ -0,0 +1 @@
+max-aged=3488923
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_119.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_119.txt
new file mode 100644
index 0000000..864d9ad
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_119.txt
@@ -0,0 +1 @@
+max-aged=3488923; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_120.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_120.txt
new file mode 100644
index 0000000..8915a797
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_120.txt
@@ -0,0 +1 @@
+max-aged=3488923; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_121.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_121.txt
new file mode 100644
index 0000000..940b5116
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_121.txt
@@ -0,0 +1 @@
+max-aged=3488923; pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_122.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_122.txt
new file mode 100644
index 0000000..67f560a
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_122.txt
@@ -0,0 +1 @@
+max-aged=3488923pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_123.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_123.txt
new file mode 100644
index 0000000..587874f1
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_123.txt
@@ -0,0 +1 @@
+max-aged=3488923; pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_124.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_124.txt
new file mode 100644
index 0000000..11e4b77
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_124.txt
@@ -0,0 +1 @@
+   max-age  =     xy
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_125.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_125.txt
new file mode 100644
index 0000000..1d44b1f
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_125.txt
@@ -0,0 +1 @@
+pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=";pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="; max-age=123;IGNORED;
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_126.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_126.txt
new file mode 100644
index 0000000..fc519f7
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_126.txt
@@ -0,0 +1 @@
+   pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="; pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="  ; Max-agE    = 567; repOrT-URi = "http://example.test/foo"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_127.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_127.txt
new file mode 100644
index 0000000..b27979fc
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_127.txt
@@ -0,0 +1 @@
+pin-sha256="BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ="; pin-sha256="AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI="; report-uri='http://foo.com'
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_128.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_128.txt
new file mode 100644
index 0000000..cc8ce2a4
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_128.txt
@@ -0,0 +1 @@
+   pumpkin=894; incLudesUbdOmains; max-age=123  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_129.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_129.txt
new file mode 100644
index 0000000..3dfde27
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_129.txt
@@ -0,0 +1 @@
+   pumpkin=894, report-uri=     "https://bar", enFORce, max-age=123  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_130.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_130.txt
new file mode 100644
index 0000000..dd89a45
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_130.txt
@@ -0,0 +1 @@
+   pumpkin, enforce, max-age="123"  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_131.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_131.txt
new file mode 100644
index 0000000..af618bf
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_131.txt
@@ -0,0 +1 @@
+   pumpkin, enFoRcE, max-age=123  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_132.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_132.txt
new file mode 100644
index 0000000..7b343eb5
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_132.txt
@@ -0,0 +1 @@
+   pumpkin; incLudesUbdOmains; max-age="123"  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_133.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_133.txt
new file mode 100644
index 0000000..5889c4cc
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_133.txt
@@ -0,0 +1 @@
+   pumpkin; incLudesUbdOmains; max-age=123  
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_134.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_134.txt
new file mode 100644
index 0000000..c638e287
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_134.txt
@@ -0,0 +1 @@
+report-uri="http://foo", max-age=999, enforce, report-uri="http://foo"
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_135.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_135.txt
new file mode 100644
index 0000000..ee9b6a8d
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_135.txt
@@ -0,0 +1 @@
+report-uri="https://foo.test",   enFORce, max-age=123
diff --git a/net/data/fuzzer_data/http_security_headers/http_security_header_136.txt b/net/data/fuzzer_data/http_security_headers/http_security_header_136.txt
new file mode 100644
index 0000000..9d5fce0
--- /dev/null
+++ b/net/data/fuzzer_data/http_security_headers/http_security_header_136.txt
@@ -0,0 +1 @@
+report-uri="https://foo.test",max-age=123
diff --git a/net/data/fuzzer_dictionaries/net_http_security_headers_fuzzer.dict b/net/data/fuzzer_dictionaries/net_http_security_headers_fuzzer.dict
index 0003e60..ed58b06 100644
--- a/net/data/fuzzer_dictionaries/net_http_security_headers_fuzzer.dict
+++ b/net/data/fuzzer_dictionaries/net_http_security_headers_fuzzer.dict
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# HSTS and HPKP header parts
+# HSTS, HPKP, Expect-CT header parts
 "max-age"
 "pin-"
 "sha256"
@@ -10,9 +10,11 @@
 "report-uri"
 "includeSubdomains"
 "pin"
+"enforce"
 "="
 ";"
 "\""
+","
 
 # base64
 "+"
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index dbe1154f..542cd2a 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -218,7 +218,7 @@
     : command_sent_(COMMAND_NONE),
       io_callback_(base::Bind(&FtpNetworkTransaction::OnIOComplete,
                               base::Unretained(this))),
-      request_(NULL),
+      request_(nullptr),
       resolver_(resolver),
       read_ctrl_buf_(new IOBuffer(kCtrlBufLen)),
       read_data_buf_len_(0),
@@ -232,15 +232,23 @@
       data_connection_port_(0),
       socket_factory_(socket_factory),
       next_state_(STATE_NONE),
-      state_after_data_connect_complete_(STATE_NONE) {
-}
+      state_after_data_connect_complete_(STATE_NONE) {}
 
 FtpNetworkTransaction::~FtpNetworkTransaction() {
 }
 
 int FtpNetworkTransaction::Stop(int error) {
-  if (command_sent_ == COMMAND_QUIT)
-    return error;
+  if (command_sent_ == COMMAND_QUIT) {
+    if (error != ERR_EMPTY_RESPONSE)
+      return error;
+
+    // For empty responses, if this is propagating an error, then it will return
+    // the error. If the error occurred during a QUIT command, then this will
+    // return OK since there was no previous error. Some FTP servers are lazy
+    // and do not bother responding to QUIT commands.
+    // See https://crbug.com/633841
+    return last_error_;
+  }
 
   next_state_ = STATE_CTRL_WRITE_QUIT;
   last_error_ = error;
@@ -253,7 +261,7 @@
   net_log_ = net_log;
   request_ = request_info;
 
-  ctrl_response_buffer_.reset(new FtpCtrlResponseBuffer(net_log_));
+  ctrl_response_buffer_ = base::MakeUnique<FtpCtrlResponseBuffer>(net_log_);
 
   if (request_->url.has_username()) {
     base::string16 username;
@@ -339,8 +347,8 @@
   user_callback_.Reset();
   response_ = FtpResponseInfo();
   read_ctrl_buf_ = new IOBuffer(kCtrlBufLen);
-  ctrl_response_buffer_.reset(new FtpCtrlResponseBuffer(net_log_));
-  read_data_buf_ = NULL;
+  ctrl_response_buffer_ = base::MakeUnique<FtpCtrlResponseBuffer>(net_log_);
+  read_data_buf_ = nullptr;
   read_data_buf_len_ = 0;
   if (write_buf_.get())
     write_buf_->SetOffset(0);
@@ -667,7 +675,7 @@
 int FtpNetworkTransaction::DoCtrlConnect() {
   next_state_ = STATE_CTRL_CONNECT_COMPLETE;
   ctrl_socket_ = socket_factory_->CreateTransportClientSocket(
-      addresses_, NULL, net_log_.net_log(), net_log_.source());
+      addresses_, nullptr, net_log_.net_log(), net_log_.source());
   net_log_.AddEvent(
       NetLogEventType::FTP_CONTROL_CONNECTION,
       ctrl_socket_->NetLog().source().ToEventParametersCallback());
@@ -740,8 +748,8 @@
   write_buf_->DidConsume(result);
   if (write_buf_->BytesRemaining() == 0) {
     // Clear the write buffer.
-    write_buf_ = NULL;
-    write_command_buf_ = NULL;
+    write_buf_ = nullptr;
+    write_command_buf_ = nullptr;
 
     next_state_ = STATE_CTRL_READ;
   } else {
@@ -1220,7 +1228,7 @@
   data_address = AddressList::CreateFromIPAddress(
       ip_endpoint.address(), data_connection_port_);
   data_socket_ = socket_factory_->CreateTransportClientSocket(
-      data_address, NULL, net_log_.net_log(), net_log_.source());
+      data_address, nullptr, net_log_.net_log(), net_log_.source());
   net_log_.AddEvent(
       NetLogEventType::FTP_DATA_CONNECTION,
       data_socket_->NetLog().source().ToEventParametersCallback());
@@ -1253,7 +1261,7 @@
   DCHECK(read_data_buf_.get());
   DCHECK_GT(read_data_buf_len_, 0);
 
-  if (data_socket_ == NULL || !data_socket_->IsConnected()) {
+  if (!data_socket_ || !data_socket_->IsConnected()) {
     // If we don't destroy the data socket completely, some servers will wait
     // for us (http://crbug.com/21127). The half-closed TCP connection needs
     // to be closed on our side too.
diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h
index 02c45c2..9731ae7 100644
--- a/net/ftp/ftp_network_transaction.h
+++ b/net/ftp/ftp_network_transaction.h
@@ -248,7 +248,7 @@
 
   uint16_t data_connection_port_;
 
-  ClientSocketFactory* socket_factory_;
+  ClientSocketFactory* const socket_factory_;
 
   std::unique_ptr<StreamSocket> ctrl_socket_;
   std::unique_ptr<StreamSocket> data_socket_;
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc
index bf7b29e9..7159c76 100644
--- a/net/ftp/ftp_network_transaction_unittest.cc
+++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -1705,6 +1705,15 @@
   ExecuteTransaction(&ctrl_socket, "ftp://host/", ERR_INVALID_RESPONSE);
 }
 
+// Test case for https://crbug.com/633841 - similar to the ExtraQuitResponses
+// test case, but with an empty response.
+TEST_P(FtpNetworkTransactionTest, EmptyQuitResponse) {
+  FtpSocketDataProviderDirectoryListing ctrl_socket;
+  ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_QUIT,
+                            FtpSocketDataProvider::QUIT, "");
+  ExecuteTransaction(&ctrl_socket, "ftp://host/", OK);
+}
+
 TEST_P(FtpNetworkTransactionTest, InvalidRemoteDirectory) {
   FtpSocketDataProviderFileDownload ctrl_socket;
   TransactionFailHelper(
diff --git a/net/http/http_security_headers.cc b/net/http/http_security_headers.cc
index 8225385..9df02cf 100644
--- a/net/http/http_security_headers.cc
+++ b/net/http/http_security_headers.cc
@@ -365,4 +365,78 @@
                              include_subdomains, hashes, report_uri);
 }
 
+// "Expect-CT" ":"
+//     "max-age" "=" delta-seconds
+//     [ "," "enforce" ]
+//     [ "," "report-uri" "=" uri-reference ]
+bool ParseExpectCTHeader(const std::string& value,
+                         base::TimeDelta* max_age,
+                         bool* enforce,
+                         GURL* report_uri) {
+  bool parsed_max_age = false;
+  bool enforce_candidate = false;
+  bool has_report_uri = false;
+  uint32_t max_age_candidate = 0;
+  GURL parsed_report_uri;
+
+  HttpUtil::NameValuePairsIterator name_value_pairs(
+      value.begin(), value.end(), ',',
+      HttpUtil::NameValuePairsIterator::Values::NOT_REQUIRED,
+      // Use STRICT_QUOTES because "UAs must not attempt to fix malformed header
+      // fields."
+      HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
+
+  while (name_value_pairs.GetNext()) {
+    base::StringPiece name(name_value_pairs.name_begin(),
+                           name_value_pairs.name_end());
+    if (base::LowerCaseEqualsASCII(name, "max-age")) {
+      // "A given directive MUST NOT appear more than once in a given header
+      // field."
+      if (parsed_max_age)
+        return false;
+      if (!MaxAgeToLimitedInt(name_value_pairs.value_begin(),
+                              name_value_pairs.value_end(), kMaxExpectCTAgeSecs,
+                              &max_age_candidate)) {
+        return false;
+      }
+      parsed_max_age = true;
+    } else if (base::LowerCaseEqualsASCII(name, "enforce")) {
+      // "A given directive MUST NOT appear more than once in a given header
+      // field."
+      if (enforce_candidate)
+        return false;
+      if (!name_value_pairs.value().empty())
+        return false;
+      enforce_candidate = true;
+    } else if (base::LowerCaseEqualsASCII(name, "report-uri")) {
+      // "A given directive MUST NOT appear more than once in a given header
+      // field."
+      if (has_report_uri)
+        return false;
+      // report-uris are always quoted.
+      if (!name_value_pairs.value_is_quoted())
+        return false;
+
+      has_report_uri = true;
+      parsed_report_uri = GURL(base::StringPiece(name_value_pairs.value_begin(),
+                                                 name_value_pairs.value_end()));
+      if (parsed_report_uri.is_empty() || !parsed_report_uri.is_valid())
+        return false;
+    } else {
+      // Silently ignore unknown directives for forward compatibility.
+    }
+  }
+
+  if (!name_value_pairs.valid())
+    return false;
+
+  if (!parsed_max_age)
+    return false;
+
+  *max_age = base::TimeDelta::FromSeconds(max_age_candidate);
+  *enforce = enforce_candidate;
+  *report_uri = parsed_report_uri;
+  return true;
+}
+
 }  // namespace net
diff --git a/net/http/http_security_headers.h b/net/http/http_security_headers.h
index 34f37b9..9c63798 100644
--- a/net/http/http_security_headers.h
+++ b/net/http/http_security_headers.h
@@ -24,6 +24,10 @@
 // http://tools.ietf.org/html/rfc7469#section-4.1
 const uint32_t kMaxHPKPAgeSecs = 86400 * 60;  // 60 days
 
+// https://tools.ietf.org/html/draft-ietf-httpbis-expect-ct-00 suggests a
+// conservative maximum max-age, at least while Expect-CT is new.
+const uint32_t kMaxExpectCTAgeSecs = 86400 * 30;  // 30 days
+
 // Parses |value| as a Strict-Transport-Security header value. If successful,
 // returns true and sets |*max_age| and |*include_subdomains|.
 // Otherwise returns false and leaves the output parameters unchanged.
@@ -79,6 +83,22 @@
                                                   bool* include_subdomains,
                                                   HashValueVector* hashes,
                                                   GURL* report_uri);
+
+// Parses |value| as an Expect-CT header value. If successful, returns true and
+// populates the |*max_age|, |*enforce|, and |*report_uri| values. Otherwise
+// returns false and leaves the output parameters unchanged.
+//
+// |value| is the right-hand side of:
+// "Expect-CT" ":"
+//     "max-age" "=" delta-seconds
+//     [ "," "enforce" ]
+//     [ "," "report-uri" "=" uri-reference ]
+//
+bool NET_EXPORT_PRIVATE ParseExpectCTHeader(const std::string& value,
+                                            base::TimeDelta* max_age,
+                                            bool* enforce,
+                                            GURL* report_uri);
+
 }  // namespace net
 
 #endif  // NET_HTTP_HTTP_SECURITY_HEADERS_H_
diff --git a/net/http/http_security_headers_expect_ct_fuzzer.cc b/net/http/http_security_headers_expect_ct_fuzzer.cc
new file mode 100644
index 0000000..4eade8b
--- /dev/null
+++ b/net/http/http_security_headers_expect_ct_fuzzer.cc
@@ -0,0 +1,21 @@
+// 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 <stddef.h>
+#include <stdint.h>
+#include <string>
+
+#include "base/time/time.h"
+#include "net/http/http_security_headers.h"
+#include "url/gurl.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  std::string input(data, data + size);
+  base::TimeDelta max_age;
+  bool enforce;
+  GURL report_uri;
+
+  net::ParseExpectCTHeader(input, &max_age, &enforce, &report_uri);
+  return 0;
+}
diff --git a/net/http/http_security_headers_unittest.cc b/net/http/http_security_headers_unittest.cc
index 9203781..5cfbd55 100644
--- a/net/http/http_security_headers_unittest.cc
+++ b/net/http/http_security_headers_unittest.cc
@@ -905,4 +905,291 @@
                 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log));
 }
 
+TEST_F(HttpSecurityHeadersTest, BogusExpectCTHeaders) {
+  base::TimeDelta max_age;
+  bool enforce = false;
+  GURL report_uri;
+  EXPECT_FALSE(
+      ParseExpectCTHeader(std::string(), &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("    ", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("abc", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("  abc", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("  abc   ", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("  max-age", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("  max-age  ", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("max-age=", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("   max-age=", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("   max-age  =", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("   max-age=   ", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("   max-age  =     ", &max_age, &enforce,
+                                   &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("   max-age  =     xy", &max_age, &enforce,
+                                   &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("   max-age  =     3488a923", &max_age,
+                                   &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=3488a923  ", &max_age, &enforce,
+                                   &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("max-ag=3488923", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("max-aged=3488923", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("max-age==3488923", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("amax-age=3488923", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("max-age=-3488923", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("max-age=+3488923", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("max-age=13####", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=9223372036854775807#####", &max_age,
+                                   &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=18446744073709551615####", &max_age,
+                                   &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=999999999999999999999999$.&#!",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=3488923     e", &max_age, &enforce,
+                                   &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=3488923     includesubdomain",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=3488923includesubdomains", &max_age,
+                                   &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=3488923=includesubdomains",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=3488923 includesubdomainx",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader(
+      "max-age=3488923 includesubdomain=", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=3488923 includesubdomain=true",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=3488923 includesubdomainsx",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=3488923 includesubdomains x",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=34889.23 includesubdomains",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=34889 includesubdomains", &max_age,
+                                   &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader(",,,, ,,,", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader(",,,, includeSubDomains,,,", &max_age,
+                                   &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("   includeSubDomains,  ", &max_age,
+                                   &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader(",", &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("max-age, ,", &max_age, &enforce, &report_uri));
+
+  // Test that the parser rejects misquoted or invalid report-uris.
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=999, report-uri=\"http://foo;bar\'",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=999, report-uri=\"foo;bar\"",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=999, report-uri=http://blah",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=999, report-uri=\"\"", &max_age,
+                                   &enforce, &report_uri));
+
+  // Test that the parser does not fix up misquoted values.
+  EXPECT_FALSE(
+      ParseExpectCTHeader("max-age=\"999", &max_age, &enforce, &report_uri));
+
+  // Test that the parser rejects headers that contain duplicate directives.
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=999, enforce, max-age=99999",
+                                   &max_age, &enforce, &report_uri));
+  EXPECT_FALSE(ParseExpectCTHeader("enforce, max-age=999, enforce", &max_age,
+                                   &enforce, &report_uri));
+  EXPECT_FALSE(
+      ParseExpectCTHeader("report-uri=\"http://foo\", max-age=999, enforce, "
+                          "report-uri=\"http://foo\"",
+                          &max_age, &enforce, &report_uri));
+
+  // Test that the parser rejects headers with values for the valueless
+  // 'enforce' directive.
+  EXPECT_FALSE(ParseExpectCTHeader("max-age=999, enforce=true", &max_age,
+                                   &enforce, &report_uri));
+
+  // Check the out args were not updated by checking the default
+  // values for its predictable fields.
+  EXPECT_EQ(0, max_age.InSeconds());
+  EXPECT_FALSE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+}
+
+TEST_F(HttpSecurityHeadersTest, ValidExpectCTHeaders) {
+  base::TimeDelta max_age;
+  bool enforce = false;
+  GURL report_uri;
+
+  EXPECT_TRUE(
+      ParseExpectCTHeader("max-age=243", &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(243), max_age);
+  EXPECT_FALSE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  EXPECT_TRUE(ParseExpectCTHeader("  Max-agE    = 567", &max_age, &enforce,
+                                  &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(567), max_age);
+  EXPECT_FALSE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  EXPECT_TRUE(ParseExpectCTHeader("  mAx-aGe    = 890      ", &max_age,
+                                  &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(890), max_age);
+  EXPECT_FALSE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  EXPECT_TRUE(ParseExpectCTHeader("max-age=123,enFoRce", &max_age, &enforce,
+                                  &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader("enFoRCE, max-age=123", &max_age, &enforce,
+                                  &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader("   enFORce, max-age=123", &max_age, &enforce,
+                                  &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader(
+      "report-uri=\"https://foo.test\",   enFORce, max-age=123", &max_age,
+      &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_EQ(GURL("https://foo.test"), report_uri);
+
+  enforce = false;
+  report_uri = GURL();
+  EXPECT_TRUE(
+      ParseExpectCTHeader("enforce,report-uri=\"https://foo.test\",max-age=123",
+                          &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_EQ(GURL("https://foo.test"), report_uri);
+
+  report_uri = GURL();
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader("report-uri=\"https://foo.test\",max-age=123",
+                                  &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_FALSE(enforce);
+  EXPECT_EQ(GURL("https://foo.test"), report_uri);
+
+  report_uri = GURL();
+  EXPECT_TRUE(ParseExpectCTHeader("   enFORcE, max-age=123, pumpkin=kitten",
+                                  &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader(
+      "   pumpkin=894, report-uri=     \"https://bar\", enFORce, max-age=123  ",
+      &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_EQ(GURL("https://bar"), report_uri);
+
+  enforce = false;
+  report_uri = GURL();
+  EXPECT_TRUE(ParseExpectCTHeader("   pumpkin, enFoRcE, max-age=123  ",
+                                  &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader("   pumpkin, enforce, max-age=\"123\"  ",
+                                  &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader(
+      "animal=\"squirrel, distinguished\", enFoRce, max-age=123", &max_age,
+      &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(123), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader("max-age=394082,  enforce", &max_age,
+                                  &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(394082), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader("max-age=39408299  ,enforce", &max_age,
+                                  &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(kMaxExpectCTAgeSecs), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  // Per RFC 7230, "a recipient MUST parse and ignore a reasonable number of
+  // empty list elements".
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader(",, max-age=394082038  , enfoRce, ,",
+                                  &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(kMaxExpectCTAgeSecs), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader(",, max-age=394082038  ,", &max_age, &enforce,
+                                  &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(kMaxExpectCTAgeSecs), max_age);
+  EXPECT_FALSE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  EXPECT_TRUE(
+      ParseExpectCTHeader(",,    , , max-age=394082038,,, enforce     ,,  ,",
+                          &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(kMaxExpectCTAgeSecs), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader("enfORce   , max-age=394082038 ,,", &max_age,
+                                  &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(kMaxExpectCTAgeSecs), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader("  max-age=0  ,  enforce   ", &max_age,
+                                  &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(0), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+
+  enforce = false;
+  EXPECT_TRUE(ParseExpectCTHeader(
+      "  max-age=999999999999999999999999999999999999999999999  ,"
+      "  enforce   ",
+      &max_age, &enforce, &report_uri));
+  EXPECT_EQ(base::TimeDelta::FromSeconds(kMaxExpectCTAgeSecs), max_age);
+  EXPECT_TRUE(enforce);
+  EXPECT_TRUE(report_uri.is_empty());
+}
+
 };    // namespace net
diff --git a/remoting/client/ios/app/BUILD.gn b/remoting/client/ios/app/BUILD.gn
index f775b25b..51f79c1 100644
--- a/remoting/client/ios/app/BUILD.gn
+++ b/remoting/client/ios/app/BUILD.gn
@@ -60,7 +60,7 @@
 }
 
 ios_app_bundle("ios_remoting_app") {
-  output_name = "remoting-ios"
+  output_name = "$remoting_ios_executable_name"
 
   entitlements_path = "resources/Remoting.entitlements"
   info_plist_target = ":tweak_info_plist"
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc
index 9f6c0fe..6c695ba 100644
--- a/services/ui/ws/frame_generator.cc
+++ b/services/ui/ws/frame_generator.cc
@@ -144,8 +144,8 @@
     gfx::Size scaled_bounds = gfx::ScaleToCeiledSize(
         pixel_size_, window_manager_surface_info_.device_scale_factor(),
         window_manager_surface_info_.device_scale_factor());
-    shared_state->SetAll(gfx::Transform(), scaled_bounds, bounds, bounds, false,
-                         1.f, SkBlendMode::kSrcOver, 0);
+    shared_state->SetAll(gfx::Transform(), gfx::Rect(scaled_bounds), bounds,
+                         bounds, false, 1.f, SkBlendMode::kSrcOver, 0);
     auto* quad = invert_pass->CreateAndAppendDrawQuad<cc::RenderPassDrawQuad>();
     frame.render_pass_list.back()->filters.Append(
         cc::FilterOperation::CreateInvertFilter(1.f));
@@ -186,11 +186,11 @@
 
   // TODO(fsamuel): These clipping and visible rects are incorrect. They need
   // to be populated from CompositorFrame structs.
-  sqs->SetAll(quad_to_target_transform, scaled_bounds /* layer_bounds */,
-              bounds_at_origin /* visible_layer_bounds */,
-              bounds_at_origin /* clip_rect */, false /* is_clipped */,
-              1.0f /* opacity */, SkBlendMode::kSrcOver,
-              0 /* sorting-context_id */);
+  sqs->SetAll(
+      quad_to_target_transform, gfx::Rect(scaled_bounds) /* layer_rect */,
+      bounds_at_origin /* visible_layer_bounds */,
+      bounds_at_origin /* clip_rect */, false /* is_clipped */,
+      1.0f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting-context_id */);
   auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
   quad->SetAll(sqs, bounds_at_origin /* rect */, gfx::Rect() /* opaque_rect */,
                bounds_at_origin /* visible_rect */, true /* needs_blending*/,
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index 05e61de..f8182da 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -289,7 +289,8 @@
 # external/wpt/mediasession [ Pass ]
 ## Owners: chcunningham@chromium.org,mlamouri@chromium.org
 # external/wpt/media-capabilities
-external/wpt/media-source [ Skip ]
+## Owners: chcunningham@chromium.org,wolenetz@chromium.org
+# external/wpt/media-source [ Pass ]
 ## Owners: mcasas@chromium.org
 # external/wpt/mediacapture-record [ Pass ]
 ## Owners: phoglund@chromium.org
diff --git a/third_party/WebKit/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash-expected.txt b/third_party/WebKit/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash-expected.txt
index 497ac08..6412203 100644
--- a/third_party/WebKit/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash-expected.txt
+++ b/third_party/WebKit/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash-expected.txt
@@ -1,6 +1,6 @@
 a
 a
-In certain cases removing a decendent from an anonymous block element does not update the parent chain correctly. This can cause a crash.
+In certain cases removing a descendant from an anonymous block element does not update the parent chain correctly. This can cause a crash.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
diff --git a/third_party/WebKit/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash.html b/third_party/WebKit/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash.html
index 02cc1399..4380a955 100644
--- a/third_party/WebKit/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash.html
+++ b/third_party/WebKit/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash.html
@@ -7,12 +7,12 @@
         document.getElementById('div').removeChild(document.getElementById('div').children[2]);
     }
 
-    function queryIsEnabledOnDecendants(accessibilityObject) {
+    function queryIsEnabledOnDescendants(accessibilityObject) {
         accessibilityObject.isEnabled
 
         var count = accessibilityObject.childrenCount;
         for (var i = 0; i < count; ++i)
-            queryIsEnabledOnDecendants(accessibilityObject.childAtIndex(i));
+            queryIsEnabledOnDescendants(accessibilityObject.childAtIndex(i));
     }
 </script>
 <script src="../resources/js-test.js"></script>
@@ -31,18 +31,18 @@
 <div id="console"></div>
 
 <script>
-    description("In certain cases removing a decendent from an anonymous block element does not update the parent chain correctly. This can cause a crash.");
+    description("In certain cases removing a descendant from an anonymous block element does not update the parent chain correctly. This can cause a crash.");
 
     if (window.accessibilityController) {
         // First build up full accessibility tree.
         document.body.focus();
-        queryIsEnabledOnDecendants(accessibilityController.focusedElement);
-        
+        queryIsEnabledOnDescendants(accessibilityController.focusedElement);
+
         removeElement()
-        
+
         // Now call isEnabled on each accessibility object.
         document.body.focus();
-        queryIsEnabledOnDecendants(accessibilityController.focusedElement);
+        queryIsEnabledOnDescendants(accessibilityController.focusedElement);
     }
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb_webworkers.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb_webworkers.htm
index dba3a93f..9c29d00 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb_webworkers.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb_webworkers.htm
@@ -8,6 +8,7 @@
 <script>
     var db, count = 0,
       t = async_test();
+      t.add_cleanup(function() { indexedDB.deleteDatabase('webworker101'); });
 
     t.step(function() {
         var worker = new Worker("idbworker.js");
@@ -27,7 +28,4 @@
 
         worker.postMessage(1);
     })
-
 </script>
-
-<div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance-continue-async.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance-continue-async.htm
index d1b6af3..ccadb7f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance-continue-async.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance-continue-async.htm
@@ -7,180 +7,175 @@
 
 <script>
 
-    var db, open;
+function upgrade_func(t, db, tx) {
+  var objStore = db.createObjectStore("test");
+  objStore.createIndex("index", "");
 
-    setup(function() {
-        open = indexedDB.open('testdb-' + new Date().getTime());
-        open.onupgradeneeded = function(e) {
-            db = e.target.result;
-            var objStore = db.createObjectStore("test");
-            objStore.createIndex("index", "");
+  objStore.add("data",  1);
+  objStore.add("data2", 2);
+}
 
-            objStore.add("data",  1);
-            objStore.add("data2", 2);
-        };
-    },
-    { explicit_done: true });
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").openCursor();
 
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 2, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-    open.onsuccess = function() {
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "data")
+          assert_equals(cursor.key, 1)
+          cursor.advance(1)
+          assert_equals(cursor.value, "data")
+          assert_equals(cursor.key, 1)
+          break
 
+        case 1:
+          assert_equals(cursor.value, "data2")
+          assert_equals(cursor.key, 2)
+          cursor.advance(1)
+          assert_equals(cursor.value, "data2")
+          assert_equals(cursor.key, 2)
+          break
 
-        async_test(document.title + " - advance").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").openCursor();
+        default:
+          assert_unreached("Unexpected count: " + count)
+      }
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 2, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - advance"
+);
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "data")
-                        assert_equals(cursor.key, 1)
-                        cursor.advance(1)
-                        assert_equals(cursor.value, "data")
-                        assert_equals(cursor.key, 1)
-                        break
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
 
-                    case 1:
-                        assert_equals(cursor.value, "data2")
-                        assert_equals(cursor.key, 2)
-                        cursor.advance(1)
-                        assert_equals(cursor.value, "data2")
-                        assert_equals(cursor.key, 2)
-                        break
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 2, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-                    default:
-                        assert_unreached("Unexpected count: " + count)
-                }
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "data")
+          assert_equals(cursor.key,   "data")
+          assert_equals(cursor.primaryKey, 1)
+          cursor.continue("data2")
+          assert_equals(cursor.value, "data")
+          assert_equals(cursor.key,   "data")
+          assert_equals(cursor.primaryKey, 1)
+          break
 
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+        case 1:
+          assert_equals(cursor.value, "data2")
+          assert_equals(cursor.key,   "data2")
+          assert_equals(cursor.primaryKey, 2)
+          cursor.continue()
+          assert_equals(cursor.value, "data2")
+          assert_equals(cursor.key,   "data2")
+          assert_equals(cursor.primaryKey, 2)
+          break
 
+        default:
+          assert_unreached("Unexpected count: " + count)
+      }
 
-        async_test(document.title + " - continue").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - continue"
+);
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 2, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "data")
-                        assert_equals(cursor.key,   "data")
-                        assert_equals(cursor.primaryKey, 1)
-                        cursor.continue("data2")
-                        assert_equals(cursor.value, "data")
-                        assert_equals(cursor.key,   "data")
-                        assert_equals(cursor.primaryKey, 1)
-                        break
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 2, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
+      cursor.advance(1)
 
-                    case 1:
-                        assert_equals(cursor.value, "data2")
-                        assert_equals(cursor.key,   "data2")
-                        assert_equals(cursor.primaryKey, 2)
-                        cursor.continue()
-                        assert_equals(cursor.value, "data2")
-                        assert_equals(cursor.key,   "data2")
-                        assert_equals(cursor.primaryKey, 2)
-                        break
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "data")
+          assert_equals(cursor.key,   "data")
+          assert_equals(cursor.primaryKey, 1)
+          break
 
-                    default:
-                        assert_unreached("Unexpected count: " + count)
-                }
+        case 1:
+          assert_equals(cursor.value, "data2")
+          assert_equals(cursor.key,   "data2")
+          assert_equals(cursor.primaryKey, 2)
+          break
 
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+        default:
+          assert_unreached("Unexpected count: " + count)
+      }
 
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - fresh advance still async"
+);
 
-        async_test(document.title + " - fresh advance still async").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").openCursor();
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 2, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
-                cursor.advance(1)
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 2, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
+      cursor.continue()
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "data")
-                        assert_equals(cursor.key,   "data")
-                        assert_equals(cursor.primaryKey, 1)
-                        break
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "data")
+          assert_equals(cursor.key, 1)
+          break
 
-                    case 1:
-                        assert_equals(cursor.value, "data2")
-                        assert_equals(cursor.key,   "data2")
-                        assert_equals(cursor.primaryKey, 2)
-                        break
+        case 1:
+          assert_equals(cursor.value, "data2")
+          assert_equals(cursor.key, 2)
+          break
 
-                    default:
-                        assert_unreached("Unexpected count: " + count)
-                }
+        default:
+          assert_unreached("Unexpected count: " + count)
+      }
 
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
-
-
-        async_test(document.title + " - fresh continue still async").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").openCursor();
-
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 2, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
-                cursor.continue()
-
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "data")
-                        assert_equals(cursor.key, 1)
-                        break
-
-                    case 1:
-                        assert_equals(cursor.value, "data2")
-                        assert_equals(cursor.key, 2)
-                        break
-
-                    default:
-                        assert_unreached("Unexpected count: " + count)
-                }
-
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
-
-        // Stop blocking the testing system from hereon
-        done();
-    }
-
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - fresh continue still async"
+);
 </script>
-
-<div id=log></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance-invalid.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance-invalid.htm
index dda216b..ee911cc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance-invalid.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance-invalid.htm
@@ -13,176 +13,180 @@
 
 <script>
 
-    var db, open;
+function upgrade_func(t, db, tx) {
+  var objStore = db.createObjectStore("test");
+  objStore.createIndex("index", "");
 
-    setup(function() {
-        open = indexedDB.open('testdb-' + new Date().getTime());
-        open.onupgradeneeded = function(e) {
-            db = e.target.result;
-            var objStore = db.createObjectStore("test");
-            objStore.createIndex("index", "");
+  objStore.add("data",  1);
+  objStore.add("data2", 2);
+}
 
-            objStore.add("data",  1);
-            objStore.add("data2", 2);
-        };
-    },
-    { explicit_done: true });
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
 
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 2, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-    open.onsuccess = function() {
+      cursor.advance(1);
 
-        async_test(document.title + " - attempt to call advance twice").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
-
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 2, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
-
-                cursor.advance(1);
-
-                // Second try
-                assert_throws('InvalidStateError',
+      // Second try
+      assert_throws('InvalidStateError',
                     function() { cursor.advance(1); }, 'second advance');
 
-                assert_throws('InvalidStateError',
+      assert_throws('InvalidStateError',
                     function() { cursor.advance(3); }, 'third advance');
 
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - attempt to call advance twice"
+);
 
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
 
-        async_test(document.title + " - pass something other than number").step(function(e) {
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+    rq.onsuccess = t.step_func(function(e) {
+      var cursor = e.target.result;
 
-            rq.onsuccess = this.step_func(function(e) {
-                var cursor = e.target.result;
-
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(document); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance({}); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance([]); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(""); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance("1 2"); });
 
-                this.done();
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      t.done();
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - pass something other than number"
+);
 
 
-        async_test(document.title + " - pass null/undefined").step(function(e) {
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
 
-            rq.onsuccess = this.step_func(function(e) {
-                var cursor = e.target.result;
+    rq.onsuccess = t.step_func(function(e) {
+      var cursor = e.target.result;
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(null); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(undefined); });
 
-                var myvar = null;
-                assert_throws({ name: "TypeError" },
+      var myvar = null;
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(myvar); });
 
-                this.done();
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      t.done();
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - pass null/undefined"
+);
 
 
-        async_test(document.title + " - missing argument").step(function(e) {
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
 
-            rq.onsuccess = this.step_func(function(e) {
-                var cursor = e.target.result;
+    rq.onsuccess = t.step_func(function(e) {
+      var cursor = e.target.result;
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(); });
 
-                this.done();
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      t.done();
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - missing argument"
+);
 
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
 
-        async_test(document.title + " - pass negative numbers").step(function(e) {
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+    rq.onsuccess = t.step_func(function(e) {
+      var cursor = e.target.result;
 
-            rq.onsuccess = this.step_func(function(e) {
-                var cursor = e.target.result;
-
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(-1); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(NaN); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(0); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(-0); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(Infinity); });
 
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(-Infinity); });
 
-                var myvar = -999999;
-                assert_throws({ name: "TypeError" },
+      var myvar = -999999;
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(myvar); });
 
-                this.done();
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      t.done();
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - pass negative numbers"
+);
 
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
 
-        async_test(document.title + " - got value not set on exception").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+    rq.onsuccess = t.step_func(function(e) {
+      var cursor = e.target.result;
+      if (!cursor)
+        {
+          assert_equals(count, 2, "count runs");
+          t.done();
+          return;
+        }
 
-            rq.onsuccess = this.step_func(function(e) {
-                var cursor = e.target.result;
-                if (!cursor)
-                {
-                    assert_equals(count, 2, "count runs");
-                    this.done();
-                    return;
-                }
-
-                assert_throws({ name: "TypeError" },
+      assert_throws({ name: "TypeError" },
                     function() { cursor.advance(0); });
 
-                cursor.advance(1);
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
-
-
-        // Stop blocking the testing system from hereon
-        done();
-    }
+      cursor.advance(1);
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - got value not set on exception"
+);
 
 </script>
-
-<div id=log></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance.htm
index f4ecbc0..f08a259 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-advance.htm
@@ -7,237 +7,241 @@
 
 <script>
 
-    var db, open;
+function upgrade_func(t, db, tx) {
+  var objStore = db.createObjectStore("test");
+  objStore.createIndex("index", "");
 
-    setup(function() {
-        open = indexedDB.open("testdb-" + new Date().getTime());
-        open.onupgradeneeded = function(e) {
-            db = e.target.result;
-            var objStore = db.createObjectStore("test");
-            objStore.createIndex("index", "");
+  objStore.add("cupcake", 5);
+  objStore.add("pancake", 3); // Yes, it is intended
+  objStore.add("pie",     1);
+  objStore.add("pie",     4);
+  objStore.add("taco",    2);
+}
 
-            objStore.add("cupcake", 5);
-            objStore.add("pancake", 3); // Yes, it is intended
-            objStore.add("pie",     1);
-            objStore.add("pie",     4);
-            objStore.add("taco",    2);
-        };
-    },
-    { explicit_done: true });
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
 
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 3, "count");
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-    open.onsuccess = function() {
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "cupcake");
+          assert_equals(cursor.primaryKey, 5);
+          break;
 
-        async_test(document.title + " - advances").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+        case 1:
+          assert_equals(cursor.value, "pie");
+          assert_equals(cursor.primaryKey, 1);
+          break;
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 3, "count");
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+        case 2:
+          assert_equals(cursor.value, "taco");
+          assert_equals(cursor.primaryKey, 2);
+          break;
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "cupcake");
-                        assert_equals(cursor.primaryKey, 5);
-                        break;
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
-                    case 1:
-                        assert_equals(cursor.value, "pie");
-                        assert_equals(cursor.primaryKey, 1);
-                        break;
+      count++;
+      cursor.advance(2);
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - advances"
+);
 
-                    case 2:
-                        assert_equals(cursor.value, "taco");
-                        assert_equals(cursor.primaryKey, 2);
-                        break;
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor(null, "prev");
 
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 3, "count");
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-                count++;
-                cursor.advance(2);
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "taco");
+          assert_equals(cursor.primaryKey, 2);
+          break;
 
-        async_test(document.title + " - advances backwards").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor(null, "prev");
+        case 1:
+          assert_equals(cursor.value, "pie");
+          assert_equals(cursor.primaryKey, 1);
+          break;
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 3, "count");
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+        case 2:
+          assert_equals(cursor.value, "cupcake");
+          assert_equals(cursor.primaryKey, 5);
+          break;
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "taco");
-                        assert_equals(cursor.primaryKey, 2);
-                        break;
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
-                    case 1:
-                        assert_equals(cursor.value, "pie");
-                        assert_equals(cursor.primaryKey, 1);
-                        break;
+      count++;
+      cursor.advance(2);
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - advances backwards"
+);
 
-                    case 2:
-                        assert_equals(cursor.value, "cupcake");
-                        assert_equals(cursor.primaryKey, 5);
-                        break;
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index")
+               .openCursor();
 
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 1, "count");
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-                count++;
-                cursor.advance(2);
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "cupcake");
+          assert_equals(cursor.primaryKey, 5);
+          break;
 
-        async_test(document.title + " - skip far forward").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index")
-                       .openCursor();
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 1, "count");
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+      count++;
+      cursor.advance(100000);
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - skip far forward"
+);
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "cupcake");
-                        assert_equals(cursor.primaryKey, 5);
-                        break;
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index")
+               .openCursor(IDBKeyRange.lowerBound("cupcake", true));
 
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 2, "count");
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-                count++;
-                cursor.advance(100000);
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "pancake");
+          assert_equals(cursor.primaryKey, 3);
+          break;
 
+        case 1:
+          assert_equals(cursor.value, "pie");
+          assert_equals(cursor.primaryKey, 4);
+          break;
 
-        async_test(document.title + " - within range").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index")
-                       .openCursor(IDBKeyRange.lowerBound("cupcake", true));
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 2, "count");
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+      count++;
+      cursor.advance(2);
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - within range"
+);
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "pancake");
-                        assert_equals(cursor.primaryKey, 3);
-                        break;
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index")
+               .openCursor("pancake");
 
-                    case 1:
-                        assert_equals(cursor.value, "pie");
-                        assert_equals(cursor.primaryKey, 4);
-                        break;
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 1, "count");
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "pancake");
+          assert_equals(cursor.primaryKey, 3);
+          break;
 
-                count++;
-                cursor.advance(2);
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
+      count++;
+      cursor.advance(1);
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - within single key range"
+);
 
-        async_test(document.title + " - within single key range").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index")
-                       .openCursor("pancake");
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index")
+               .openCursor("pie");
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 1, "count");
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 2, "count");
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "pancake");
-                        assert_equals(cursor.primaryKey, 3);
-                        break;
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "pie");
+          assert_equals(cursor.primaryKey, 1);
+          break;
 
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
+        case 1:
+          assert_equals(cursor.value, "pie");
+          assert_equals(cursor.primaryKey, 4);
+          break;
 
-                count++;
-                cursor.advance(1);
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
-
-        async_test(document.title + " - within single key range, with several results").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index")
-                       .openCursor("pie");
-
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 2, "count");
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
-
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "pie");
-                        assert_equals(cursor.primaryKey, 1);
-                        break;
-
-                    case 1:
-                        assert_equals(cursor.value, "pie");
-                        assert_equals(cursor.primaryKey, 4);
-                        break;
-
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
-
-                count++;
-                cursor.advance(1);
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
-
-
-        // Stop blocking the testing system from hereon
-        done();
-    }
+      count++;
+      cursor.advance(1);
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - within single key range, with several results"
+);
 
 </script>
-
-<div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continue.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continue.htm
index 968cd9c..372d452 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continue.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continue.htm
@@ -9,232 +9,240 @@
 
 <script>
 
-    var db, open;
-    var store = [ { value: "cupcake", key: 5 },
-                  { value: "pancake", key: 3 },
-                  { value: "pie",     key: 1 },
-                  { value: "pie",     key: 4 },
-                  { value: "taco",    key: 2 } ];
+var store = [ { value: "cupcake", key: 5 },
+              { value: "pancake", key: 3 },
+              { value: "pie",     key: 1 },
+              { value: "pie",     key: 4 },
+              { value: "taco",    key: 2 } ];
 
-    setup(function() {
-        open = indexedDB.open('testdb-' + new Date().getTime());
-        open.onupgradeneeded = function(e) {
-            var os, i;
-            db = e.target.result;
-            os = db.createObjectStore("test");
-            os.createIndex("index", "");
+function upgrade_func(t, db, tx) {
+  var db, open;
 
-            for (i = 0; i < store.length; i++)
-                os.add(store[i].value, store[i].key);
-        };
-    },
-    { explicit_done: true });
+  var os, i;
+  os = db.createObjectStore("test");
+  os.createIndex("index", "");
+
+  for (i = 0; i < store.length; i++)
+    os.add(store[i].value, store[i].key);
+}
+
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 5, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
+
+      assert_equals(cursor.value, store[count].value);
+      assert_equals(cursor.primaryKey, store[count].key);
+
+      cursor.continue();
+
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - continues"
+);
 
 
-    open.onsuccess = function() {
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 3, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
+
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "cupcake");
+          assert_equals(cursor.primaryKey, 5);
+          cursor.continue("pie");
+          break;
+
+        case 1:
+          assert_equals(cursor.value, "pie");
+          assert_equals(cursor.primaryKey, 1);
+          cursor.continue("taco");
+          break;
+
+        case 2:
+          assert_equals(cursor.value, "taco");
+          assert_equals(cursor.primaryKey, 2);
+          cursor.continue();
+          break;
+
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
+
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error")
+  },
+  document.title + " - with given key"
+);
 
 
-        async_test(document.title + " - continues").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index")
+               .openCursor();
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 5, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 1, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-                assert_equals(cursor.value, store[count].value);
-                assert_equals(cursor.primaryKey, store[count].key);
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "cupcake");
+          assert_equals(cursor.primaryKey, 5);
+          break;
 
-                cursor.continue();
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      count++;
+      cursor.continue([]); // Arrays are always bigger than strings
+
+    });
+    rq.onerror = t.unreached_func("unexpected error2")
+  },
+  document.title + " - skip far forward"
+);
 
 
-        async_test(document.title + " - with given key").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index")
+               .openCursor(IDBKeyRange.lowerBound("cupcake", true));
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 3, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 2, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "cupcake");
-                        assert_equals(cursor.primaryKey, 5);
-                        cursor.continue("pie");
-                        break;
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "pancake");
+          assert_equals(cursor.primaryKey, 3);
+          cursor.continue("pie");
+          break;
 
-                    case 1:
-                        assert_equals(cursor.value, "pie");
-                        assert_equals(cursor.primaryKey, 1);
-                        cursor.continue("taco");
-                        break;
+        case 1:
+          assert_equals(cursor.value, "pie");
+          assert_equals(cursor.primaryKey, 1);
+          cursor.continue("zzz");
+          break;
 
-                    case 2:
-                        assert_equals(cursor.value, "taco");
-                        assert_equals(cursor.primaryKey, 2);
-                        cursor.continue();
-                        break;
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
-
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error")
-        });
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error1")
+  },
+  document.title + " - within range"
+);
 
 
-        async_test(document.title + " - skip far forward").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index")
-                       .openCursor();
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index")
+               .openCursor("pancake");
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 1, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 1, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "cupcake");
-                        assert_equals(cursor.primaryKey, 5);
-                        break;
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "pancake");
+          assert_equals(cursor.primaryKey, 3);
+          cursor.continue("pie");
+          break;
 
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
-                count++;
-                cursor.continue([]); // Arrays are always bigger than strings
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error1")
+  },
+  document.title + " - within single key range"
+);
 
-            });
-            rq.onerror = fail(this, "unexpected error2")
-        });
+indexeddb_test(
+  upgrade_func,
+  function(t, db) {
+    var count = 0;
+    var rq = db.transaction("test").objectStore("test").index("index")
+               .openCursor("pie");
 
+    rq.onsuccess = t.step_func(function(e) {
+      if (!e.target.result) {
+        assert_equals(count, 2, 'count');
+        t.done();
+        return;
+      }
+      var cursor = e.target.result;
 
-        async_test(document.title + " - within range").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index")
-                       .openCursor(IDBKeyRange.lowerBound("cupcake", true));
+      switch(count) {
+        case 0:
+          assert_equals(cursor.value, "pie");
+          assert_equals(cursor.primaryKey, 1);
+          cursor.continue();
+          break;
 
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 2, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
+        case 1:
+          assert_equals(cursor.value, "pie");
+          assert_equals(cursor.primaryKey, 4);
+          cursor.continue();
+          break;
 
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "pancake");
-                        assert_equals(cursor.primaryKey, 3);
-                        cursor.continue("pie");
-                        break;
+        default:
+          assert_unreached("Unexpected count: " + count);
+      }
 
-                    case 1:
-                        assert_equals(cursor.value, "pie");
-                        assert_equals(cursor.primaryKey, 1);
-                        cursor.continue("zzz");
-                        break;
-
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
-
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error1")
-        });
-
-
-        async_test(document.title + " - within single key range").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index")
-                       .openCursor("pancake");
-
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 1, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
-
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "pancake");
-                        assert_equals(cursor.primaryKey, 3);
-                        cursor.continue("pie");
-                        break;
-
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
-
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error1")
-        });
-
-
-        async_test(document.title + " - within single key range, with several results").step(function(e) {
-            var count = 0;
-            var rq = db.transaction("test").objectStore("test").index("index")
-                       .openCursor("pie");
-
-            rq.onsuccess = this.step_func(function(e) {
-                if (!e.target.result) {
-                    assert_equals(count, 2, 'count');
-                    this.done();
-                    return;
-                }
-                var cursor = e.target.result;
-
-                switch(count) {
-                    case 0:
-                        assert_equals(cursor.value, "pie");
-                        assert_equals(cursor.primaryKey, 1);
-                        cursor.continue();
-                        break;
-
-                    case 1:
-                        assert_equals(cursor.value, "pie");
-                        assert_equals(cursor.primaryKey, 4);
-                        cursor.continue();
-                        break;
-
-                    default:
-                        assert_unreached("Unexpected count: " + count);
-                }
-
-                count++;
-            });
-            rq.onerror = fail(this, "unexpected error1")
-        });
-
-
-        // Stop blocking the testing system from hereon
-        done();
-    }
+      count++;
+    });
+    rq.onerror = t.unreached_func("unexpected error1")
+  },
+  document.title + " - within single key range, with several results"
+);
 
 </script>
-
-<div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm
index 0d35218..56a23a1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm
@@ -45,12 +45,12 @@
 
             store.deleteIndex("idx");
         });
-        txn.oncomplete = function() {
+        txn.oncomplete = t.step_func(function() {
             assert_throws("TransactionInactiveError", function() {
                 cursor.continuePrimaryKey("A", 4);
             }, "transaction-state check should precede deletion check");
             t.done();
-        };
+        });
     },
     null,
     "TransactionInactiveError v.s. InvalidStateError(deleted index)"
@@ -378,5 +378,3 @@
     "DataError(keys are larger then current one) in 'prev' direction"
 );
 </script>
-
-<div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey-exceptions.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey-exceptions.htm
index d678513..9393e2fb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey-exceptions.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-continuePrimaryKey-exceptions.htm
@@ -16,6 +16,10 @@
 
     open.onupgradeneeded = t.step_func(function() {
         var db = open.result;
+        t.add_cleanup(function() {
+            db.close();
+            indexedDB.deleteDatabase(db.name);
+        });
         var store = db.createObjectStore('store');
         store.put('a', 1).onerror = t.unreached_func('put should not fail');
         var request = store.openCursor();
@@ -60,6 +64,10 @@
 
         open.onupgradeneeded = t.step_func(function() {
             var db = open.result;
+            t.add_cleanup(function() {
+                db.close();
+                indexedDB.deleteDatabase(db.name);
+            });
             var store = db.createObjectStore('store', {keyPath: 'pk'});
             var index = store.createIndex('index', 'ik', {multiEntry: true});
             store.put({pk: 'a', ik: [1,2,3]}).onerror =
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-index-keyrange.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-index-keyrange.htm
index e0f0c6d0..2de3854 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-index-keyrange.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-index-keyrange.htm
@@ -15,69 +15,46 @@
 <script src="support.js"></script>
 
 <script>
-    var records = [ 1337, "Alice", "Bob", "Bob", "Greg", "Åke", ["Anne"] ];
-    var directions = ["next", "prev", "nextunique", "prevunique"];
-    var tests = {};
-
-    directions.forEach(function(dir) {
-        tests[dir] = async_test(document.title + ' - ' + dir);
-    });
-
-    var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
-
-    open_rq.onupgradeneeded = function(e) {
-        var objStore = e.target.result.createObjectStore("test");
-        objStore.createIndex("idx", "name");
-
-        for (var i = 0; i < records.length; i++)
-            objStore.add({ name: records[i] }, i);
-    };
-
-    open_rq.onsuccess = function(e) {
-        var db = e.target.result;
-        db.onerror = fail_helper("db.onerror");
+var records = [ 1337, "Alice", "Bob", "Bob", "Greg", "Åke", ["Anne"] ];
+var cases = [
+  {dir: 'next', expect: ['Alice:1', 'Bob:2', 'Bob:3', 'Greg:4']},
+  {dir: 'prev', expect: ['Greg:4',  'Bob:3', 'Bob:2', 'Alice:1']},
+  {dir: 'nextunique', expect: ['Alice:1', 'Bob:2', 'Greg:4']},
+  {dir: 'prevunique', expect: ['Greg:4',  'Bob:2', 'Alice:1']}
+];
 
 
-        // The tests
-        testdir('next',       ['Alice:1', 'Bob:2', 'Bob:3', 'Greg:4']);
-        testdir('prev',       ['Greg:4',  'Bob:3', 'Bob:2', 'Alice:1']);
-        testdir('nextunique', ['Alice:1', 'Bob:2', 'Greg:4']);
-        testdir('prevunique', ['Greg:4',  'Bob:2', 'Alice:1']);
+cases.forEach(function(testcase) {
+  var dir = testcase.dir;
+  var expect = testcase.expect;
+  indexeddb_test(
+    function(t, db, tx) {
+      var objStore = db.createObjectStore("test");
+      objStore.createIndex("idx", "name");
 
-
-        // Test function
-        function testdir(dir, expect) {
-            var count = 0;
-            var t = tests[dir];
-            var rq = db.transaction("test").objectStore("test").index("idx").openCursor(IDBKeyRange.bound("AA", "ZZ"), dir);
-            rq.onsuccess = t.step_func(function(e) {
-                var cursor = e.target.result;
-                if (!cursor) {
-                    assert_equals(count, expect.length, "cursor runs");
-                    t.done();
-                }
-                assert_equals(cursor.value.name + ":" + cursor.primaryKey, expect[count], "cursor.value");
-                count++;
-                cursor.continue();
-            });
-            rq.onerror = t.step_func(function(e) {
-                e.preventDefault();
-                e.stopPropagation();
-                assert_unreached("rq.onerror - " + e.message);
-            });
+      for (var i = 0; i < records.length; i++)
+        objStore.add({ name: records[i] }, i);
+    },
+    function(t, db) {
+      var count = 0;
+      var rq = db.transaction("test").objectStore("test").index("idx").openCursor(IDBKeyRange.bound("AA", "ZZ"), dir);
+      rq.onsuccess = t.step_func(function(e) {
+        var cursor = e.target.result;
+        if (!cursor) {
+          assert_equals(count, expect.length, "cursor runs");
+          t.done();
         }
-    };
-
-    // Fail handling
-    function fail_helper(name) {
-        return function() {
-            directions.forEach(function(dir) {
-                tests[dir].step(function() { assert_unreached(name); });
-            });
-        };
-    }
-    open_rq.onblocked = fail_helper('open_rq.onblocked');
-    open_rq.onerror = fail_helper('open_rq.onerror');
+        assert_equals(cursor.value.name + ":" + cursor.primaryKey, expect[count], "cursor.value");
+        count++;
+        cursor.continue();
+      });
+      rq.onerror = t.step_func(function(e) {
+        e.preventDefault();
+        e.stopPropagation();
+        assert_unreached("rq.onerror - " + e.message);
+      });
+    },
+    document.title + ' - ' + dir
+  )
+});
 </script>
-
-<div id=log> </div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-index.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-index.htm
index 39afcb2..0eb926d9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-index.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-index.htm
@@ -13,69 +13,45 @@
 <script src="support.js"></script>
 
 <script>
-    var records = [ "Alice", "Bob", "Bob", "Greg" ];
-    var directions = ["next", "prev", "nextunique", "prevunique"];
-    var tests = {};
+var records = [ "Alice", "Bob", "Bob", "Greg" ];
+var cases = [
+  {dir: 'next', expect: ['Alice:0', 'Bob:1', 'Bob:2', 'Greg:3']},
+  {dir: 'prev', expect: ['Greg:3',  'Bob:2', 'Bob:1', 'Alice:0']},
+  {dir: 'nextunique', expect: ['Alice:0', 'Bob:1', 'Greg:3']},
+  {dir: 'prevunique', expect: ['Greg:3',  'Bob:1', 'Alice:0']},
+];
 
-    directions.forEach(function(dir) {
-        tests[dir] = async_test(document.title + ' - ' + dir);
-    });
+cases.forEach(function(testcase) {
+  var dir = testcase.dir;
+  var expect = testcase.expect;
+  indexeddb_test(
+    function(t, db, tx) {
+      var objStore = db.createObjectStore("test");
+      objStore.createIndex("idx", "name");
 
-    var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
-
-    open_rq.onupgradeneeded = function(e) {
-        var objStore = e.target.result.createObjectStore("test");
-        objStore.createIndex("idx", "name");
-
-        for (var i = 0; i < records.length; i++)
-            objStore.add({ name: records[i] }, i);
-    };
-
-    open_rq.onsuccess = function(e) {
-        var db = e.target.result;
-        db.onerror = fail_helper("db.onerror");
-
-
-        // The tests
-        testdir('next',       ['Alice:0', 'Bob:1', 'Bob:2', 'Greg:3']);
-        testdir('prev',       ['Greg:3',  'Bob:2', 'Bob:1', 'Alice:0']);
-        testdir('nextunique', ['Alice:0', 'Bob:1', 'Greg:3']);
-        testdir('prevunique', ['Greg:3',  'Bob:1', 'Alice:0']);
-
-
-        // Test function
-        function testdir(dir, expect) {
-            var count = 0;
-            var t = tests[dir];
-            var rq = db.transaction("test").objectStore("test").index("idx").openCursor(undefined, dir);
-            rq.onsuccess = t.step_func(function(e) {
-                var cursor = e.target.result;
-                if (!cursor) {
-                    assert_equals(count, expect.length, "cursor runs");
-                    t.done();
-                }
-                assert_equals(cursor.value.name + ":" + cursor.primaryKey, expect[count], "cursor.value");
-                count++;
-                cursor.continue();
-            });
-            rq.onerror = t.step_func(function(e) {
-                e.preventDefault();
-                e.stopPropagation();
-                assert_unreached("rq.onerror - " + e.message);
-            });
+      for (var i = 0; i < records.length; i++)
+        objStore.add({ name: records[i] }, i);
+    },
+    function(t, db) {
+      var count = 0;
+      var rq = db.transaction("test").objectStore("test").index("idx").openCursor(undefined, dir);
+      rq.onsuccess = t.step_func(function(e) {
+        var cursor = e.target.result;
+        if (!cursor) {
+          assert_equals(count, expect.length, "cursor runs");
+          t.done();
         }
-    };
-
-    // Fail handling
-    function fail_helper(name) {
-        return function() {
-            directions.forEach(function(dir) {
-                tests[dir].step(function() { assert_unreached(name); });
-            });
-        };
-    }
-    open_rq.onblocked = fail_helper('open_rq.onblocked');
-    open_rq.onerror = fail_helper('open_rq.onerror');
+        assert_equals(cursor.value.name + ":" + cursor.primaryKey, expect[count], "cursor.value");
+        count++;
+        cursor.continue();
+      });
+      rq.onerror = t.step_func(function(e) {
+        e.preventDefault();
+        e.stopPropagation();
+        assert_unreached("rq.onerror - " + e.message);
+      });
+    },
+    document.title + ' - ' + dir
+  );
+});
 </script>
-
-<div id=log> </div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-objectstore-keyrange.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-objectstore-keyrange.htm
index 7bcb971..96f92a0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-objectstore-keyrange.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-objectstore-keyrange.htm
@@ -11,68 +11,44 @@
 <script src="support.js"></script>
 
 <script>
-    var records = [ 1337, "Alice", "Bob", "Greg", "Åke", ["Anne"] ];
-    var directions = ["next", "prev", "nextunique", "prevunique"];
-    var tests = {};
+var records = [ 1337, "Alice", "Bob", "Greg", "Åke", ["Anne"] ];
+var directions = ["next", "prev", "nextunique", "prevunique"];
+var cases = [
+  {dir: 'next', expect: ['Alice', 'Bob', 'Greg']},
+  {dir: 'prev', expect: ['Greg', 'Bob', 'Alice']},
+  {dir: 'nextunique', expect: ['Alice', 'Bob', 'Greg']},
+  {dir: 'prevunique', expect: ['Greg', 'Bob', 'Alice']},
+];
 
-    directions.forEach(function(dir) {
-        tests[dir] = async_test(document.title + ' - ' + dir);
-    });
-
-    var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
-
-    open_rq.onupgradeneeded = function(e) {
-        var objStore = e.target.result.createObjectStore("test");
-
+cases.forEach(function(testcase) {
+  var dir = testcase.dir;
+  var expect = testcase.expect;
+  indexeddb_test(
+    function(t, db, tx) {
+        var objStore = db.createObjectStore("test");
         for (var i = 0; i < records.length; i++)
-            objStore.add(records[i], records[i]);
-    };
-
-    open_rq.onsuccess = function(e) {
-        var db = e.target.result;
-        db.onerror = fail_helper("db.onerror");
-
-
-        // The tests
-        testdir('next',       ['Alice', 'Bob', 'Greg']);
-        testdir('prev',       ['Greg', 'Bob', 'Alice']);
-        testdir('nextunique', ['Alice', 'Bob', 'Greg']);
-        testdir('prevunique', ['Greg', 'Bob', 'Alice']);
-
-
-        // Test function
-        function testdir(dir, expect) {
-            var count = 0;
-            var t = tests[dir];
-            var rq = db.transaction("test").objectStore("test").openCursor(IDBKeyRange.bound("AA", "ZZ"), dir);
-            rq.onsuccess = t.step_func(function(e) {
-                var cursor = e.target.result;
-                if (!cursor) {
-                    assert_equals(count, expect.length, "cursor runs");
-                    t.done();
-                }
-                assert_equals(cursor.value, expect[count], "cursor.value");
-                count++;
-                cursor.continue();
-            });
-            rq.onerror = t.step_func(function(e) {
-                e.preventDefault();
-                e.stopPropagation();
-                assert_unreached("rq.onerror - " + e.message);
-            });
+          objStore.add(records[i], records[i]);
+    },
+    function(t, db) {
+      var count = 0;
+      var rq = db.transaction("test").objectStore("test").openCursor(IDBKeyRange.bound("AA", "ZZ"), dir);
+      rq.onsuccess = t.step_func(function(e) {
+        var cursor = e.target.result;
+        if (!cursor) {
+          assert_equals(count, expect.length, "cursor runs");
+          t.done();
         }
-    };
-
-    // Fail handling
-    function fail_helper(name) {
-        return function() {
-            directions.forEach(function(dir) {
-                tests[dir].step(function() { assert_unreached(name); });
-            });
-        };
-    }
-    open_rq.onblocked = fail_helper('open_rq.onblocked');
-    open_rq.onerror = fail_helper('open_rq.onerror');
+        assert_equals(cursor.value, expect[count], "cursor.value");
+        count++;
+        cursor.continue();
+      });
+      rq.onerror = t.step_func(function(e) {
+        e.preventDefault();
+        e.stopPropagation();
+        assert_unreached("rq.onerror - " + e.message);
+      });
+    },
+    document.title + ' - ' + dir
+  );
+});
 </script>
-
-<div id=log> </div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-objectstore.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-objectstore.htm
index c0235539..85088ee 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-objectstore.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction-objectstore.htm
@@ -13,68 +13,44 @@
 <script src="support.js"></script>
 
 <script>
-    var records = [ "Alice", "Bob", "Greg" ];
-    var directions = ["next", "prev", "nextunique", "prevunique"];
-    var tests = {};
+var records = [ "Alice", "Bob", "Greg" ];
+var directions = ["next", "prev", "nextunique", "prevunique"];
+var cases = [
+  {dir: 'next', expect: ['Alice', 'Bob', 'Greg']},
+  {dir: 'prev', expect: ['Greg', 'Bob', 'Alice']},
+  {dir: 'nextunique', expect: ['Alice', 'Bob', 'Greg']},
+  {dir: 'prevunique', expect: ['Greg', 'Bob', 'Alice']},
+];
 
-    directions.forEach(function(dir) {
-        tests[dir] = async_test(document.title + ' - ' + dir);
-    });
-
-    var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
-
-    open_rq.onupgradeneeded = function(e) {
-        var objStore = e.target.result.createObjectStore("test");
-
-        for (var i = 0; i < records.length; i++)
-            objStore.add(records[i], records[i]);
-    };
-
-    open_rq.onsuccess = function(e) {
-        var db = e.target.result;
-        db.onerror = fail_helper("db.onerror");
-
-
-        // The tests
-        testdir('next',       ['Alice', 'Bob', 'Greg']);
-        testdir('prev',       ['Greg', 'Bob', 'Alice']);
-        testdir('nextunique', ['Alice', 'Bob', 'Greg']);
-        testdir('prevunique', ['Greg', 'Bob', 'Alice']);
-
-
-        // Test function
-        function testdir(dir, expect) {
-            var count = 0;
-            var t = tests[dir];
-            var rq = db.transaction("test").objectStore("test").openCursor(undefined, dir);
-            rq.onsuccess = t.step_func(function(e) {
-                var cursor = e.target.result;
-                if (!cursor) {
-                    assert_equals(count, expect.length, "cursor runs");
-                    t.done();
-                }
-                assert_equals(cursor.value, expect[count], "cursor.value");
-                count++;
-                cursor.continue();
-            });
-            rq.onerror = t.step_func(function(e) {
-                e.preventDefault();
-                e.stopPropagation();
-                assert_unreached("rq.onerror - " + e.message);
-            });
+cases.forEach(function(testcase) {
+  var dir = testcase.dir;
+  var expect = testcase.expect;
+  indexeddb_test(
+    function(t, db, tx) {
+      var objStore = db.createObjectStore("test");
+      for (var i = 0; i < records.length; i++)
+        objStore.add(records[i], records[i]);
+    },
+    function(t, db) {
+      var count = 0;
+      var rq = db.transaction("test").objectStore("test").openCursor(undefined, dir);
+      rq.onsuccess = t.step_func(function(e) {
+        var cursor = e.target.result;
+        if (!cursor) {
+          assert_equals(count, expect.length, "cursor runs");
+          t.done();
         }
-    };
-
-    // Fail handling
-    function fail_helper(name) {
-        return function() {
-            directions.forEach(function(dir) {
-                tests[dir].step(function() { assert_unreached(name); });
-            });
-        };
-    }
-    open_rq.onblocked = fail_helper('open_rq.onblocked');
-    open_rq.onerror = fail_helper('open_rq.onerror');
+        assert_equals(cursor.value, expect[count], "cursor.value");
+        count++;
+        cursor.continue();
+      });
+      rq.onerror = t.step_func(function(e) {
+        e.preventDefault();
+        e.stopPropagation();
+        assert_unreached("rq.onerror - " + e.message);
+      });
+    },
+    document.title + ' - ' + dir
+  );
+});
 </script>
-
-<div id=log> </div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction.htm
index b50eded..246cd79 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-direction.htm
@@ -17,6 +17,11 @@
 
         open_rq.onupgradeneeded = function(e) {
             db = e.target.result;
+            t.add_cleanup(function() {
+                db.close();
+                indexedDB.deleteDatabase(db.name);
+            });
+
             var objStore = db.createObjectStore("test");
 
             objStore.add("data", "key");
@@ -69,5 +74,3 @@
     cursor_direction("prevunique", "prevunique");
 
 </script>
-
-<div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-source.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-source.htm
index 7e3746a..b23551c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-source.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor-source.htm
@@ -6,63 +6,61 @@
 <script src="support.js"></script>
 
 <script>
-    setup({ explicit_done: true });
+function cursor_source_test(test_name, name, stringified_object, cursor_rq_func) {
+  indexeddb_test(
+    function(t, db, tx) {
+      var objStore = db.createObjectStore("my_objectstore");
+      objStore.createIndex("my_index", "");
 
-    var db;
-    var open_rq = indexedDB.open('testdb-' + new Date().getTime());
-    open_rq.onupgradeneeded = function(e) {
-        db = e.target.result;
-        var objStore = db.createObjectStore("my_objectstore");
-        objStore.createIndex("my_index", "");
+      objStore.add("data",  1);
+      objStore.add("data2", 2);
+    },
+    function(t, db) {
+      var cursor_rq = cursor_rq_func(db);
 
-        objStore.add("data",  1);
-        objStore.add("data2", 2);
-    };
+      cursor_rq.onsuccess = t.step_func(function(e) {
+        if (!e.target.result) {
+          return;
+        }
+        var cursor = e.target.result;
+        assert_readonly(cursor, 'source');
 
-    function cursor_source(name, stringified_object, cursor_rq) {
-        var cursor;
+        // Direct try
+        assert_true(cursor.source instanceof Object, "source isobject");
+        assert_equals(cursor.source + "", stringified_object, "source");
+        assert_equals(cursor.source.name, name, "name");
 
-        cursor_rq.onsuccess = this.step_func(function(e) {
-            if (!e.target.result) {
-                return;
-            }
-            cursor = e.target.result;
-            assert_readonly(cursor, 'source');
+        cursor.continue();
+      });
 
-            // Direct try
-            assert_true(cursor.source instanceof Object, "source isobject");
-            assert_equals(cursor.source + "", stringified_object, "source");
-            assert_equals(cursor.source.name, name, "name");
+      cursor_rq.transaction.oncomplete = t.step_func(function(e) {
+        t.done();
+      });
 
-            cursor.continue();
-        });
+      cursor_rq.transaction.onerror = t.step_func(function(e) {
+        assert_unreached("Transaction got error. " + (e.target.error ? e.target.error.name : "unknown"));
+      });
+    },
+    test_name
+  );
+}
 
-        cursor_rq.transaction.oncomplete = this.step_func(function(e) {
-            this.done();
-         });
+cursor_source_test(
+  document.title + ' - IDBObjectStore',
+  "my_objectstore",
+  "[object IDBObjectStore]",
+  function(db) { return db.transaction("my_objectstore")
+                          .objectStore("my_objectstore")
+                          .openCursor(); }
+);
 
-        cursor_rq.transaction.onerror = this.step_func(function(e) {
-            assert_unreached("Transaction got error. " + (e.target.error ? e.target.error.name : "unknown"));
-        });
-    }
-
-    open_rq.onsuccess = function() {
-        async_test(document.title + ' - IDBObjectStore').step(function() {
-            cursor_source.call(this, "my_objectstore", "[object IDBObjectStore]", db.transaction("my_objectstore")
-                                                       .objectStore("my_objectstore")
-                                                       .openCursor());
-        });
-
-        async_test(document.title + ' - IDBIndex').step(function() {
-            cursor_source.call(this, "my_index", "[object IDBIndex]", db.transaction("my_objectstore")
-                                                 .objectStore("my_objectstore")
-                                                 .index("my_index")
-                                                 .openCursor());
-        });
-
-        done();
-    };
-
+cursor_source_test(
+  document.title + ' - IDBIndex',
+  "my_index",
+  "[object IDBIndex]",
+  function(db) { return db.transaction("my_objectstore")
+                          .objectStore("my_objectstore")
+                          .index("my_index")
+                          .openCursor(); }
+);
 </script>
-
-<div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating.htm
index fd3cd0a..df663eff 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating.htm
@@ -13,6 +13,7 @@
     var open_rq = createdb(t);
     open_rq.onupgradeneeded = function(e) {
         db = e.target.result;
+        t.add_cleanup(function() { db.close(); indexedDB.delete(db.name); });
         var objStore = db.createObjectStore("test", { keyPath: "key" });
 
         for (var i = 0; i < 500; i++)
@@ -106,5 +107,3 @@
         });
     };
 </script>
-
-<div id="log"> </div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating_objectstore.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating_objectstore.htm
index db66c4d..28270df 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating_objectstore.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating_objectstore.htm
@@ -18,6 +18,7 @@
     var open_rq = createdb(t);
     open_rq.onupgradeneeded = function(e) {
         db = e.target.result;
+        t.add_cleanup(function() { db.close(); indexedDB.delete(db.name); });
         var objStore = db.createObjectStore("test", {keyPath:"pKey"});
 
         for (var i = 0; i < records.length; i++)
@@ -47,5 +48,3 @@
         });
     };
 </script>
-
-<div id="log"> </div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating_objectstore2.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating_objectstore2.htm
index 2374a85..e80fe35 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating_objectstore2.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbcursor_iterating_objectstore2.htm
@@ -18,6 +18,7 @@
     var open_rq = createdb(t);
     open_rq.onupgradeneeded = function(e) {
         db = e.target.result;
+        t.add_cleanup(function() { db.close(); indexedDB.delete(db.name); });
         var objStore = db.createObjectStore("test", {keyPath:"pKey"});
 
         for (var i = 0; i < records.length; i++)
@@ -47,5 +48,3 @@
         });
     };
 </script>
-
-<div id="log"> </div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex_getAll.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex_getAll.html
index 507b6c9..2b07b4b2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex_getAll.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex_getAll.html
@@ -2,26 +2,14 @@
 <title>IndexedDB: Test IDBIndex.getAll.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
 <script>
-setup({explicit_done: true});
-
 var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
 var ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
 
-function doSetup(dbName, dbVersion, onsuccess) {
-  var delete_request = indexedDB.deleteDatabase(dbName);
-  delete_request.onerror = function() {
-    assert_unreached('deleteDatabase should not fail');
-  };
-  delete_request.onsuccess = function(e) {
-    var req = indexedDB.open(dbName, dbVersion);
-    req.onsuccess = onsuccess;
-    req.onerror = function() {
-      assert_unreached('open should not fail');
-    };
-    req.onupgradeneeded = function(evt) {
-      var connection = evt.target.result;
-
+function getall_test(func, name) {
+  indexeddb_test(
+    function(t, connection, tx) {
       var store = connection.createObjectStore('generated',
             {autoIncrement: true, keyPath: 'id'});
       var index = store.createIndex('test_idx', 'upper');
@@ -61,8 +49,10 @@
 
       store = connection.createObjectStore('empty', null);
       index = store.createIndex('test_idx', 'upper');
-    };
-  };
+    },
+    func,
+    name
+  );
 }
 
 function createGetAllRequest(t, storeName, connection, range, maxCount) {
@@ -74,9 +64,7 @@
     return req;
 }
 
-doSetup(location.pathname + '-IDBIndex.getAll', 1, function(evt) {
-    var connection = evt.target.result;
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection, 'C');
       req.onsuccess = t.step_func(function(evt) {
           var data = evt.target.result;
@@ -87,7 +75,7 @@
       });
     }, 'Single item get');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'empty', connection);
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result, [],
@@ -96,7 +84,7 @@
       });
     }, 'Empty object store');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection);
       req.onsuccess = t.step_func(function(evt) {
           var data = evt.target.result;
@@ -107,7 +95,7 @@
       });
     }, 'Get all keys');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection, undefined,
                                     10);
       req.onsuccess = t.step_func(function(evt) {
@@ -119,7 +107,7 @@
       });
     }, 'maxCount=10');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('G', 'M'));
       req.onsuccess = t.step_func(function(evt) {
@@ -130,7 +118,7 @@
       });
     }, 'Get bound range');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('G', 'M'), 3);
       req.onsuccess = t.step_func(function(evt) {
@@ -142,7 +130,7 @@
       });
     }, 'Get bound range with maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
           IDBKeyRange.bound('G', 'K', false, true));
       req.onsuccess = t.step_func(function(evt) {
@@ -154,7 +142,7 @@
       });
     }, 'Get upper excluded');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
           IDBKeyRange.bound('G', 'K', true, false));
       req.onsuccess = t.step_func(function(evt) {
@@ -166,7 +154,7 @@
       });
     }, 'Get lower excluded');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'generated',
           connection, IDBKeyRange.bound(4, 15), 3);
       req.onsuccess = t.step_func(function(evt) {
@@ -177,7 +165,7 @@
       });
     }, 'Get bound range (generated) with maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line',
           connection, "Doesn't exist");
       req.onsuccess = t.step_func(function(evt) {
@@ -188,7 +176,7 @@
       });
     }, 'Non existent key');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
           undefined, 0);
       req.onsuccess = t.step_func(function(evt) {
@@ -200,7 +188,7 @@
       });
     }, 'maxCount=0');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line-not-unique', connection,
                                     'first');
       req.onsuccess = t.step_func(function(evt) {
@@ -212,7 +200,7 @@
       });
     }, 'Retrieve multiEntry key');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line-multi', connection,
                                     'vowel');
       req.onsuccess = t.step_func(function(evt) {
@@ -225,8 +213,4 @@
       });
     }, 'Retrieve one key multiple values');
 
-    // Explicit done needed in case async_test body fails synchronously.
-    done();
-});
-
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex_getAllKeys.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex_getAllKeys.html
index 7653a51..a882312 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex_getAllKeys.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex_getAllKeys.html
@@ -2,25 +2,14 @@
 <title>IndexedDB: Test IDBIndex.getAllKeys.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
 <script>
-setup({explicit_done: true});
 
 var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
 
-function doSetup(dbName, dbVersion, onsuccess) {
-  var delete_request = indexedDB.deleteDatabase(dbName);
-  delete_request.onerror = function() {
-    assert_unreached('deleteDatabase should not fail');
-  };
-  delete_request.onsuccess = function(e) {
-    var req = indexedDB.open(dbName, dbVersion);
-    req.onsuccess = onsuccess;
-    req.onerror = function() {
-      assert_unreached('open should not fail');
-    };
-    req.onupgradeneeded = function(evt) {
-      var connection = evt.target.result;
-
+function getall_test(func, name) {
+  indexeddb_test(
+    function(t, connection, tx) {
       var store = connection.createObjectStore('generated',
             {autoIncrement: true, keyPath: 'id'});
       var index = store.createIndex('test_idx', 'upper');
@@ -51,8 +40,10 @@
 
       store = connection.createObjectStore('empty', null);
       index = store.createIndex('test_idx', 'upper');
-    };
-  };
+    },
+    func,
+    name
+  );
 }
 
 function createGetAllKeysRequest(t, storeName, connection, range, maxCount) {
@@ -64,9 +55,7 @@
     return req;
 }
 
-doSetup(location.pathname + '-IDBIndex.getAllKeys', 1, function(evt) {
-    var connection = evt.target.result;
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection, 'C');
       req.onsuccess = t.step_func(function(evt) {
           var data = evt.target.result;
@@ -75,7 +64,7 @@
       });
     }, 'Single item get');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'empty', connection);
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result, [],
@@ -84,7 +73,7 @@
       });
     }, 'Empty object store');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection);
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result, alphabet,
@@ -93,7 +82,7 @@
       });
     }, 'Get all keys');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'generated', connection);
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result,
@@ -104,7 +93,7 @@
       });
     }, 'Get all generated keys');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection, undefined,
                                     10);
       req.onsuccess = t.step_func(function(evt) {
@@ -115,7 +104,7 @@
       });
     }, 'maxCount=10');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('G', 'M'));
       req.onsuccess = t.step_func(function(evt) {
@@ -126,7 +115,7 @@
       });
     }, 'Get bound range');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('G', 'M'), 3);
       req.onsuccess = t.step_func(function(evt) {
@@ -137,7 +126,7 @@
       });
     }, 'Get bound range with maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
           IDBKeyRange.bound('G', 'K', false, true));
       req.onsuccess = t.step_func(function(evt) {
@@ -148,7 +137,7 @@
       });
     }, 'Get upper excluded');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
           IDBKeyRange.bound('G', 'K', true, false));
       req.onsuccess = t.step_func(function(evt) {
@@ -159,7 +148,7 @@
       });
     }, 'Get lower excluded');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'generated',
           connection, IDBKeyRange.bound(4, 15), 3);
       req.onsuccess = t.step_func(function(evt) {
@@ -169,7 +158,7 @@
       });
     }, 'Get bound range (generated) with maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line',
           connection, "Doesn't exist");
       req.onsuccess = t.step_func(function(evt) {
@@ -180,7 +169,7 @@
       });
     }, 'Non existent key');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
           undefined, 0);
       req.onsuccess = t.step_func(function(evt) {
@@ -190,7 +179,7 @@
       });
     }, 'maxCount=0');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line-multi', connection,
                                         'vowel');
       req.onsuccess = t.step_func(function(evt) {
@@ -200,8 +189,4 @@
       req.onerror = t.unreached_func('getAllKeys request should succeed');
     }, 'Retrieve multiEntry keys');
 
-    // Explicit done needed in case async_test body fails synchronously.
-    done();
-});
-
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getAll.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getAll.html
index f81e4caf..c9d29d3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getAll.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getAll.html
@@ -2,25 +2,14 @@
 <title>IndexedDB: Test IDBObjectStore.getAll.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
 <script>
-setup({explicit_done: true});
 
 var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
 
-function doSetup(dbName, dbVersion, onsuccess) {
-  var delete_request = indexedDB.deleteDatabase(dbName);
-  delete_request.onerror = function() {
-    assert_unreached('deleteDatabase should not fail');
-  };
-  delete_request.onsuccess = function(e) {
-    var req = indexedDB.open(dbName, dbVersion);
-    req.onsuccess = onsuccess;
-    req.onerror = function() {
-      assert_unreached('open should not fail');
-    };
-    req.onupgradeneeded = function(evt) {
-      var connection = evt.target.result;
-
+function getall_test(func, name) {
+  indexeddb_test(
+    function(t, connection, tx) {
       var store = connection.createObjectStore('generated',
             {autoIncrement: true, keyPath: 'id'});
       alphabet.forEach(function(letter) {
@@ -33,8 +22,10 @@
       });
 
       store = connection.createObjectStore('empty', null);
-    };
-  };
+    },
+    func,
+    name
+  );
 }
 
 function createGetAllRequest(t, storeName, connection, range, maxCount) {
@@ -45,9 +36,7 @@
     return req;
 }
 
-doSetup(location.pathname + '-IDBObjectStore.getAll', 1, function(evt) {
-    var connection = evt.target.result;
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection, 'c');
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result, ['value-c']);
@@ -55,7 +44,7 @@
       });
     }, 'Single item get');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'generated', connection, 3);
       req.onsuccess = t.step_func(function(evt) {
           var data = evt.target.result;
@@ -67,7 +56,7 @@
       });
     }, 'Single item get (generated key)');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'empty', connection);
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result, [],
@@ -76,7 +65,7 @@
       });
     }, 'getAll on empty object store');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection);
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result,
@@ -85,7 +74,7 @@
       });
     }, 'Get all values');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection, undefined,
                                     10);
       req.onsuccess = t.step_func(function(evt) {
@@ -95,7 +84,7 @@
       });
     }, 'Test maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('g', 'm'));
       req.onsuccess = t.step_func(function(evt) {
@@ -105,7 +94,7 @@
       });
     }, 'Get bound range');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('g', 'm'), 3);
       req.onsuccess = t.step_func(function(evt) {
@@ -115,7 +104,7 @@
       });
     }, 'Get bound range with maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('g', 'k', false, true));
       req.onsuccess = t.step_func(function(evt) {
@@ -125,7 +114,7 @@
       });
     }, 'Get upper excluded');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('g', 'k', true, false));
       req.onsuccess = t.step_func(function(evt) {
@@ -135,7 +124,7 @@
       });
     }, 'Get lower excluded');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'generated', connection,
                                     IDBKeyRange.bound(4, 15), 3);
       req.onsuccess = t.step_func(function(evt) {
@@ -147,7 +136,7 @@
       });
     }, 'Get bound range (generated) with maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection,
                                     "Doesn't exist");
       req.onsuccess = t.step_func(function(evt) {
@@ -158,7 +147,7 @@
       req.onerror = t.unreached_func('getAll request should succeed');
     }, 'Non existent key');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllRequest(t, 'out-of-line', connection, undefined, 0);
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result,
@@ -167,8 +156,4 @@
       });
     }, 'zero maxCount');
 
-    // Explicit done needed in case async_test body fails synchronously.
-    done();
-});
-
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getAllKeys.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getAllKeys.html
index f4d317d..896d4df 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getAllKeys.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getAllKeys.html
@@ -2,25 +2,14 @@
 <title>IndexedDB: Test IDBObjectStore.getAllKeys.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
 <script>
-setup({explicit_done: true});
 
 var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
 
-function doSetup(dbName, dbVersion, onsuccess) {
-  var delete_request = indexedDB.deleteDatabase(dbName);
-  delete_request.onerror = function() {
-    assert_unreached('deleteDatabase should not fail');
-  };
-  delete_request.onsuccess = function(e) {
-    var req = indexedDB.open(dbName, dbVersion);
-    req.onsuccess = onsuccess;
-    req.onerror = function() {
-      assert_unreached('open should not fail');
-    };
-    req.onupgradeneeded = function(evt) {
-      var connection = evt.target.result;
-
+function getall_test(func, name) {
+  indexeddb_test(
+    function(t, connection, tx) {
       var store = connection.createObjectStore('generated',
             {autoIncrement: true, keyPath: 'id'});
       alphabet.forEach(function(letter) {
@@ -33,8 +22,10 @@
       });
 
       store = connection.createObjectStore('empty', null);
-    };
-  };
+    },
+    func,
+    name
+  );
 }
 
 function createGetAllKeysRequest(t, storeName, connection, range, maxCount) {
@@ -45,9 +36,7 @@
     return req;
 }
 
-doSetup(location.pathname + '-IDBObjectStore.getAllKeys', 1, function(evt) {
-    var connection = evt.target.result;
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection, 'c');
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result, ['c']);
@@ -55,7 +44,7 @@
       });
     }, 'Single item get');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'generated', connection, 3);
       req.onsuccess = t.step_func(function(evt) {
           var data = evt.target.result;
@@ -65,7 +54,7 @@
       });
     }, 'Single item get (generated key)');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'empty', connection);
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result, [],
@@ -75,7 +64,7 @@
       });
     }, 'getAllKeys on empty object store');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection);
       req.onsuccess = t.step_func(function(evt) {
           assert_array_equals(evt.target.result, alphabet);
@@ -83,7 +72,7 @@
       });
     }, 'Get all values');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection, undefined,
                                     10);
       req.onsuccess = t.step_func(function(evt) {
@@ -92,7 +81,7 @@
       });
     }, 'Test maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('g', 'm'));
       req.onsuccess = t.step_func(function(evt) {
@@ -101,7 +90,7 @@
       });
     }, 'Get bound range');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('g', 'm'), 3);
       req.onsuccess = t.step_func(function(evt) {
@@ -110,7 +99,7 @@
       });
     }, 'Get bound range with maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('g', 'k', false, true));
       req.onsuccess = t.step_func(function(evt) {
@@ -119,7 +108,7 @@
       });
     }, 'Get upper excluded');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
                                     IDBKeyRange.bound('g', 'k', true, false));
       req.onsuccess = t.step_func(function(evt) {
@@ -128,7 +117,7 @@
       });
     }, 'Get lower excluded');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'generated', connection,
                                     IDBKeyRange.bound(4, 15), 3);
       req.onsuccess = t.step_func(function(evt) {
@@ -139,7 +128,7 @@
       });
     }, 'Get bound range (generated) with maxCount');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection,
                                     "Doesn't exist");
       req.onsuccess = t.step_func(function(evt) {
@@ -151,7 +140,7 @@
       req.onerror = t.unreached_func('getAllKeys request should succeed');
     }, 'Non existent key');
 
-    async_test(function(t) {
+getall_test(function(t, connection) {
       var req = createGetAllKeysRequest(t, 'out-of-line', connection, undefined,
           0);
       req.onsuccess = t.step_func(function(evt) {
@@ -160,8 +149,4 @@
       });
     }, 'zero maxCount');
 
-    // Explicit done needed in case async_test body fails synchronously.
-    done();
-});
-
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getKey.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getKey.html
index 19229456..ddb78b1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getKey.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_getKey.html
@@ -4,17 +4,12 @@
 <meta name=timeout content=long>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
 <script>
 
 function getkey_test(func, name) {
-    return async_test(function(t) {
-        var del = indexedDB.deleteDatabase(name);
-        del.onerror = t.unreached_func('deleteDatabase failed');
-        var open = indexedDB.open(name);
-        open.onerror = t.unreached_func('open failed');
-        open.onupgradeneeded = t.step_func(function() {
-            var db = open.result;
-
+    indexeddb_test(
+        function(t, db, tx) {
             var basic = db.createObjectStore('basic');
             var key_path_store = db.createObjectStore('key path',
                 {keyPath: 'id'});
@@ -30,12 +25,10 @@
                 key_generator_store.put('value: ' + i);
                 key_generator_and_path_store.put({});
             }
-        });
-        open.onsuccess = t.step_func(function() {
-            var db = open.result;
-            func(t, db);
-        });
-    }, name);
+        },
+        func,
+        name
+    );
 }
 
 getkey_test(function(t, db) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_openCursor_invalid.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_openCursor_invalid.htm
index 698e7998..a142a3a4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_openCursor_invalid.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_openCursor_invalid.htm
@@ -4,28 +4,17 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="support.js"></script>
-
 <script>
 
-    var db, open;
-
-    setup(function() {
-        open = indexedDB.open('testdb-' + new Date().getTime());
-        open.onupgradeneeded = function(e) {
-            db = e.target.result;
+indexeddb_test(
+  function(t, db, tx) {
             var objStore = db.createObjectStore("test");
             objStore.createIndex("index", "");
 
             objStore.add("data",  1);
             objStore.add("data2", 2);
-        };
-    },
-    { explicit_done: true });
-
-
-    open.onsuccess = function() {
-
-        async_test(document.title + " - pass something other than number").step(function(e) {
+  },
+  function(t, db, tx) {
             var idx = db.transaction("test").objectStore("test").index("index");
 
             assert_throws("DataError",
@@ -37,14 +26,8 @@
             assert_throws("DataError",
                 function() { idx.openCursor({ lower: "a", lowerOpen: false, upper: null, upperOpen: false }); });
 
-            this.done();
-        });
-
-
-        // Stop blocking the testing system from hereon
-        done();
-    }
-
+            t.done();
+  },
+  document.title + " - pass something other than number"
+);
 </script>
-
-<div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_openKeyCursor.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_openKeyCursor.htm
index 9dc547c..3458459 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_openKeyCursor.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore_openKeyCursor.htm
@@ -2,26 +2,20 @@
 <title>IDBObjectStore.openKeyCursor()</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
 <script>
 function store_test(func, name) {
-    async_test(function(t) {
-        var del = indexedDB.deleteDatabase(name);
-        del.onerror = t.unreached_func("deleteDatabase failed");
-        var open = indexedDB.open(name);
-        open.onupgradeneeded = t.step_func(function() {
-            var db = open.result;
-            var store = db.createObjectStore("store");
-            for (var i = 0; i < 10; ++i) {
-                store.put("value: " + i, i);
-            }
-        });
-
-        open.onsuccess = t.step_func(function() {
-            var db = open.result;
-            var tx = db.transaction("store");
-            var store = tx.objectStore("store");
-            func(t, db, tx, store);
-        });
+  indexeddb_test(
+    function(t, db, tx) {
+      var store = db.createObjectStore("store");
+      for (var i = 0; i < 10; ++i) {
+        store.put("value: " + i, i);
+      }
+    },
+    function(t, db) {
+      var tx = db.transaction("store");
+      var store = tx.objectStore("store");
+      func(t, db, tx, store);
     }, name);
 }
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbrequest-onupgradeneeded.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbrequest-onupgradeneeded.htm
index 9e94cc3..a84d3b1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbrequest-onupgradeneeded.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbrequest-onupgradeneeded.htm
@@ -16,6 +16,10 @@
       var open_request = indexedDB.open(dbName);
 
       open_request.onupgradeneeded = t.step_func(function() {
+        t.add_cleanup(function() {
+          open_request.result.close(),
+          indexedDB.deleteDatabase(dbName);
+        });
         upgrade_func(t, open_request);
       });
       open_request.onsuccess = t.step_func(function() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbtransaction.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbtransaction.htm
index 8a34845..5baa3db5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbtransaction.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbtransaction.htm
@@ -6,41 +6,54 @@
 <script src="support.js"></script>
 
 <script>
-    var db,
-      t = async_test(document.title + " - request gotten by the handler"),
-      open_t = async_test(document.title + " - request returned by open()"),
+async_test(function(t) {
+  var open_rq = indexedDB.open("idbtransaction-" + document.location + t.name);
 
-    open_rq = indexedDB.open("idbtransaction-" + new Date().getTime() + Math.random());
+  open_rq.onblocked = t.unreached_func('open_rq.onblocked');
+  open_rq.onerror = t.unreached_func('open_rq.onerror');
 
-    open_t.step(function() {
-        assert_equals(open_rq.transaction, null, "IDBOpenDBRequest.transaction");
-        assert_equals(open_rq.source, null, "IDBOpenDBRequest.source");
-        assert_equals(open_rq.readyState, "pending", "IDBOpenDBRequest.readyState");
-
-        assert_true(open_rq instanceof IDBOpenDBRequest, "open_rq instanceof IDBOpenDBRequest");
-        assert_equals(open_rq + "", "[object IDBOpenDBRequest]", "IDBOpenDBRequest (open_rq)");
-
-        open_t.done();
+  open_rq.onupgradeneeded = t.step_func(function(e) {
+    t.add_cleanup(function() {
+      open_rq.onerror = function(e) {
+        e.preventDefault();
+      };
+      open_rq.result.close();
+      indexedDB.deleteDatabase(open_rq.result.name);
     });
 
-    open_rq.onupgradeneeded = t.step_func(function(e) {
-        assert_equals(e.target, open_rq, "e.target is reusing the same IDBOpenDBRequest");
-        assert_equals(e.target.transaction, open_rq.transaction, "IDBOpenDBRequest.transaction");
+    assert_equals(e.target, open_rq, "e.target is reusing the same IDBOpenDBRequest");
+    assert_equals(e.target.transaction, open_rq.transaction, "IDBOpenDBRequest.transaction");
 
-        assert_true(e.target.transaction instanceof IDBTransaction, "transaction instanceof IDBTransaction");
-        t.done();
+    assert_true(e.target.transaction instanceof IDBTransaction, "transaction instanceof IDBTransaction");
+    t.done();
+  });
+
+}, document.title + " - request gotten by the handler");
+
+async_test(function(t) {
+  var open_rq = indexedDB.open("idbtransaction-" + document.location + t.name);
+
+  assert_equals(open_rq.transaction, null, "IDBOpenDBRequest.transaction");
+  assert_equals(open_rq.source, null, "IDBOpenDBRequest.source");
+  assert_equals(open_rq.readyState, "pending", "IDBOpenDBRequest.readyState");
+
+  assert_true(open_rq instanceof IDBOpenDBRequest, "open_rq instanceof IDBOpenDBRequest");
+  assert_equals(open_rq + "", "[object IDBOpenDBRequest]", "IDBOpenDBRequest (open_rq)");
+
+  open_rq.onblocked = t.unreached_func('open_rq.onblocked');
+  open_rq.onerror = t.unreached_func('open_rq.onerror');
+
+  open_rq.onupgradeneeded = t.step_func(function() {
+    t.add_cleanup(function() {
+      open_rq.onerror = function(e) {
+        e.preventDefault();
+      };
+      open_rq.result.close();
+      indexedDB.deleteDatabase(open_rq.result.name);
     });
+    t.done();
+  });
 
+}, document.title + " - request returned by open()");
 
-    // Not plausible conditions...
-    function fail_helper(name) {
-        return function() {
-            t.step(function() { assert_unreached(name); });
-            open_t.step(function() { assert_unreached(name); });
-        };
-    }
-    open_rq.onblocked = fail_helper('open_rq.onblocked');
-    open_rq.onerror = fail_helper('open_rq.onerror');
 </script>
-
-<div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support.js
index cf3aa4d..7cab067f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support.js
@@ -106,30 +106,34 @@
 
 function indexeddb_test(upgrade_func, open_func, description, options) {
   async_test(function(t) {
-    var options = Object.assign({upgrade_will_abort: false}, options);
+    options = Object.assign({upgrade_will_abort: false}, options);
     var dbname = document.location + '-' + t.name;
     var del = indexedDB.deleteDatabase(dbname);
     del.onerror = t.unreached_func('deleteDatabase should succeed');
     var open = indexedDB.open(dbname, 1);
-    if (!options.upgrade_will_abort) {
-      open.onsuccess = t.unreached_func('open should not succeed');
-    } else {
-      open.onerror = t.unreached_func('open should succeed');
-    }
     open.onupgradeneeded = t.step_func(function() {
       var db = open.result;
-      var tx = open.transaction;
-      upgrade_func(t, db, tx);
-    });
-    open.onsuccess = t.step_func(function() {
-      var db = open.result;
       t.add_cleanup(function() {
+        // If open didn't succeed already, ignore the error.
+        open.onerror = function(e) {
+          e.preventDefault();
+        };
         db.close();
         indexedDB.deleteDatabase(db.name);
       });
-      if (open_func)
-        open_func(t, db);
+      var tx = open.transaction;
+      upgrade_func(t, db, tx);
     });
+    if (options.upgrade_will_abort) {
+      open.onsuccess = t.unreached_func('open should not succeed');
+    } else {
+      open.onerror = t.unreached_func('open should succeed');
+      open.onsuccess = t.step_func(function() {
+        var db = open.result;
+        if (open_func)
+          open_func(t, db);
+      });
+    }
   }, description);
 }
 
diff --git a/third_party/WebKit/LayoutTests/media/video-error-does-not-exist.html b/third_party/WebKit/LayoutTests/media/video-error-does-not-exist.html
index 85e7e7040..51bcec0 100644
--- a/third_party/WebKit/LayoutTests/media/video-error-does-not-exist.html
+++ b/third_party/WebKit/LayoutTests/media/video-error-does-not-exist.html
@@ -14,6 +14,9 @@
         assert_not_equals(video.error, null);
         assert_equals(video.error.code, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
 
+        // Actual message can vary greatly, so we only verify the attribute's type.
+        assert_equals(typeof video.error.message, 'string', 'MediaError.message type');
+
         assert_equals(video.networkState, HTMLMediaElement.NETWORK_NO_SOURCE);
 
         assert_true(isNaN(video.duration));
@@ -25,4 +28,4 @@
 
     video.src = "content/does-not-exist.mpeg";
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
index a3882ca..dbc8b68 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -531,7 +531,6 @@
     method fill
     method fillRect
     method fillText
-    method getContextAttributes
     method getImageData
     method getLineDash
     method isPointInPath
@@ -3290,6 +3289,7 @@
     attribute MEDIA_ERR_NETWORK
     attribute MEDIA_ERR_SRC_NOT_SUPPORTED
     getter code
+    getter message
     method constructor
 interface MediaKeyMessageEvent : Event
     attribute @@toStringTag
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
index 6b7862c..0931f24a 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -460,7 +460,6 @@
     method fill
     method fillRect
     method fillText
-    method getContextAttributes
     method getImageData
     method getLineDash
     method isPointInPath
@@ -3219,6 +3218,7 @@
     attribute MEDIA_ERR_NETWORK
     attribute MEDIA_ERR_SRC_NOT_SUPPORTED
     getter code
+    getter message
     method constructor
 interface MediaKeyMessageEvent : Event
     attribute @@toStringTag
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
index dc46af42..e0ff71e 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -3973,6 +3973,7 @@
     attribute MEDIA_ERR_NETWORK
     attribute MEDIA_ERR_SRC_NOT_SUPPORTED
     getter code
+    getter message
     method constructor
 interface MediaKeyMessageEvent : Event
     attribute @@toStringTag
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index e29d2d3..6d9b897 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -3973,6 +3973,7 @@
     attribute MEDIA_ERR_NETWORK
     attribute MEDIA_ERR_SRC_NOT_SUPPORTED
     getter code
+    getter message
     method constructor
 interface MediaKeyMessageEvent : Event
     attribute @@toStringTag
diff --git a/third_party/WebKit/Source/bindings/modules/v8/generated.gni b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
index 77336079..ca9f4c06 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/generated.gni
+++ b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
@@ -32,6 +32,10 @@
   "$bindings_modules_v8_output_dir/ClientOrServiceWorkerOrMessagePort.h",
   "$bindings_modules_v8_output_dir/CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvas.cpp",
   "$bindings_modules_v8_output_dir/CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvas.h",
+  "$bindings_modules_v8_output_dir/DecodeErrorCallback.cpp",
+  "$bindings_modules_v8_output_dir/DecodeErrorCallback.h",
+  "$bindings_modules_v8_output_dir/DecodeSuccessCallback.cpp",
+  "$bindings_modules_v8_output_dir/DecodeSuccessCallback.h",
   "$bindings_modules_v8_output_dir/DictionaryOrString.cpp",
   "$bindings_modules_v8_output_dir/DictionaryOrString.h",
   "$bindings_modules_v8_output_dir/DoubleOrConstrainDoubleRange.cpp",
diff --git a/third_party/WebKit/Source/core/css/StyleRule.cpp b/third_party/WebKit/Source/core/css/StyleRule.cpp
index 95c1c64e..bcc1c054 100644
--- a/third_party/WebKit/Source/core/css/StyleRule.cpp
+++ b/third_party/WebKit/Source/core/css/StyleRule.cpp
@@ -211,16 +211,16 @@
 StyleRule::StyleRule(CSSSelectorList selector_list,
                      StylePropertySet* properties)
     : StyleRuleBase(kStyle),
+      should_consider_for_matching_rules_(kConsiderIfNonEmpty),
       selector_list_(std::move(selector_list)),
-      properties_(properties),
-      should_consider_for_matching_rules_(kConsiderIfNonEmpty) {}
+      properties_(properties) {}
 
 StyleRule::StyleRule(CSSSelectorList selector_list,
                      CSSLazyPropertyParser* lazy_property_parser)
     : StyleRuleBase(kStyle),
+      should_consider_for_matching_rules_(kAlwaysConsider),
       selector_list_(std::move(selector_list)),
-      lazy_property_parser_(lazy_property_parser),
-      should_consider_for_matching_rules_(kAlwaysConsider) {}
+      lazy_property_parser_(lazy_property_parser) {}
 
 const StylePropertySet& StyleRule::Properties() const {
   if (!properties_) {
@@ -232,9 +232,9 @@
 
 StyleRule::StyleRule(const StyleRule& o)
     : StyleRuleBase(o),
+      should_consider_for_matching_rules_(kConsiderIfNonEmpty),
       selector_list_(o.selector_list_.Copy()),
-      properties_(o.Properties().MutableCopy()),
-      should_consider_for_matching_rules_(kConsiderIfNonEmpty) {}
+      properties_(o.Properties().MutableCopy()) {}
 
 StyleRule::~StyleRule() {}
 
diff --git a/third_party/WebKit/Source/core/css/StyleRule.h b/third_party/WebKit/Source/core/css/StyleRule.h
index 3d971e0..2965c92 100644
--- a/third_party/WebKit/Source/core/css/StyleRule.h
+++ b/third_party/WebKit/Source/core/css/StyleRule.h
@@ -132,10 +132,6 @@
   StyleRule(CSSSelectorList, CSSLazyPropertyParser*);
   StyleRule(const StyleRule&);
 
-  CSSSelectorList selector_list_;
-  mutable Member<StylePropertySet> properties_;
-  mutable Member<CSSLazyPropertyParser> lazy_property_parser_;
-
   // Whether or not we should consider this for matching rules. Usually we try
   // to avoid considering empty property sets, as an optimization. This is
   // not possible for lazy properties, which always need to be considered. The
@@ -146,6 +142,10 @@
     kConsiderIfNonEmpty,
   };
   mutable ConsiderForMatching should_consider_for_matching_rules_;
+
+  CSSSelectorList selector_list_;
+  mutable Member<StylePropertySet> properties_;
+  mutable Member<CSSLazyPropertyParser> lazy_property_parser_;
 };
 
 class StyleRuleFontFace : public StyleRuleBase {
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp
index 16095d2..d5e93c8 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -153,7 +153,7 @@
 
 // Updating the selection is considered side-effect of the event and so it
 // doesn't impact the handled state.
-bool SelectionController::HandleMousePressEventSingleClick(
+bool SelectionController::HandleSingleClick(
     const MouseEventWithHitTestResults& event) {
   TRACE_EVENT0("blink",
                "SelectionController::handleMousePressEventSingleClick");
@@ -737,7 +737,7 @@
       kCharacterGranularity, HandleVisibility::kVisible);
 }
 
-bool SelectionController::HandleMousePressEventDoubleClick(
+bool SelectionController::HandleDoubleClick(
     const MouseEventWithHitTestResults& event) {
   TRACE_EVENT0("blink",
                "SelectionController::handleMousePressEventDoubleClick");
@@ -746,7 +746,7 @@
     return false;
 
   if (!mouse_down_allows_multi_click_)
-    return HandleMousePressEventSingleClick(event);
+    return HandleSingleClick(event);
 
   if (event.Event().button != WebPointerProperties::Button::kLeft)
     return false;
@@ -764,7 +764,7 @@
   return true;
 }
 
-bool SelectionController::HandleMousePressEventTripleClick(
+bool SelectionController::HandleTripleClick(
     const MouseEventWithHitTestResults& event) {
   TRACE_EVENT0("blink",
                "SelectionController::handleMousePressEventTripleClick");
@@ -775,7 +775,7 @@
   }
 
   if (!mouse_down_allows_multi_click_)
-    return HandleMousePressEventSingleClick(event);
+    return HandleSingleClick(event);
 
   if (event.Event().button != WebPointerProperties::Button::kLeft)
     return false;
@@ -807,8 +807,10 @@
                         : HandleVisibility::kNotVisible);
 }
 
-void SelectionController::HandleMousePressEvent(
+bool SelectionController::HandleMousePressEvent(
     const MouseEventWithHitTestResults& event) {
+  TRACE_EVENT0("blink", "SelectionController::handleMousePressEvent");
+
   // If we got the event back, that must mean it wasn't prevented,
   // so it's allowed to start a drag or selection if it wasn't in a scrollbar.
   mouse_down_may_start_select_ =
@@ -818,16 +820,21 @@
   if (!Selection().IsAvailable()) {
     // "gesture-tap-frame-removed.html" reaches here.
     mouse_down_allows_multi_click_ = !event.Event().FromTouch();
-    return;
+  } else {
+    // Avoid double-tap touch gesture confusion by restricting multi-click side
+    // effects, e.g., word selection, to editable regions.
+    mouse_down_allows_multi_click_ =
+        !event.Event().FromTouch() ||
+        Selection()
+            .ComputeVisibleSelectionInDOMTreeDeprecated()
+            .HasEditableStyle();
   }
 
-  // Avoid double-tap touch gesture confusion by restricting multi-click side
-  // effects, e.g., word selection, to editable regions.
-  mouse_down_allows_multi_click_ =
-      !event.Event().FromTouch() ||
-      Selection()
-          .ComputeVisibleSelectionInDOMTreeDeprecated()
-          .HasEditableStyle();
+  if (event.Event().click_count >= 3)
+    return HandleTripleClick(event);
+  if (event.Event().click_count == 2)
+    return HandleDoubleClick(event);
+  return HandleSingleClick(event);
 }
 
 void SelectionController::HandleMouseDraggedEvent(
@@ -836,6 +843,8 @@
     const LayoutPoint& drag_start_pos,
     Node* mouse_press_node,
     const IntPoint& last_known_mouse_position) {
+  TRACE_EVENT0("blink", "SelectionController::handleMouseDraggedEvent");
+
   if (!Selection().IsAvailable())
     return;
   if (selection_state_ != SelectionState::kExtendedSelection) {
@@ -873,6 +882,8 @@
 bool SelectionController::HandleMouseReleaseEvent(
     const MouseEventWithHitTestResults& event,
     const LayoutPoint& drag_start_pos) {
+  TRACE_EVENT0("blink", "SelectionController::handleMouseReleaseEvent");
+
   if (!Selection().IsAvailable())
     return false;
 
@@ -956,8 +967,9 @@
 }
 
 bool SelectionController::HandleGestureLongPress(
-    const WebGestureEvent& gesture_event,
     const HitTestResult& hit_test_result) {
+  TRACE_EVENT0("blink", "SelectionController::handleGestureLongPress");
+
   if (!Selection().IsAvailable())
     return false;
   if (hit_test_result.IsLiveLink())
@@ -984,11 +996,15 @@
 
 void SelectionController::HandleGestureTwoFingerTap(
     const GestureEventWithHitTestResults& targeted_event) {
+  TRACE_EVENT0("blink", "SelectionController::handleGestureTwoFingerTap");
+
   SetCaretAtHitTestResult(targeted_event.GetHitTestResult());
 }
 
 void SelectionController::HandleGestureLongTap(
     const GestureEventWithHitTestResults& targeted_event) {
+  TRACE_EVENT0("blink", "SelectionController::handleGestureLongTap");
+
   SetCaretAtHitTestResult(targeted_event.GetHitTestResult());
 }
 
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.h b/third_party/WebKit/Source/core/editing/SelectionController.h
index 1fc5b82..ba17143 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.h
+++ b/third_party/WebKit/Source/core/editing/SelectionController.h
@@ -51,10 +51,7 @@
   virtual ~SelectionController();
   DECLARE_TRACE();
 
-  void HandleMousePressEvent(const MouseEventWithHitTestResults&);
-  bool HandleMousePressEventSingleClick(const MouseEventWithHitTestResults&);
-  bool HandleMousePressEventDoubleClick(const MouseEventWithHitTestResults&);
-  bool HandleMousePressEventTripleClick(const MouseEventWithHitTestResults&);
+  bool HandleMousePressEvent(const MouseEventWithHitTestResults&);
   void HandleMouseDraggedEvent(const MouseEventWithHitTestResults&,
                                const IntPoint&,
                                const LayoutPoint&,
@@ -63,7 +60,7 @@
   bool HandleMouseReleaseEvent(const MouseEventWithHitTestResults&,
                                const LayoutPoint&);
   bool HandlePasteGlobalSelection(const WebMouseEvent&);
-  bool HandleGestureLongPress(const WebGestureEvent&, const HitTestResult&);
+  bool HandleGestureLongPress(const HitTestResult&);
   void HandleGestureTwoFingerTap(const GestureEventWithHitTestResults&);
   void HandleGestureLongTap(const GestureEventWithHitTestResults&);
 
@@ -128,6 +125,10 @@
   // changed.
   void ContextDestroyed(Document*) final;
 
+  bool HandleSingleClick(const MouseEventWithHitTestResults&);
+  bool HandleDoubleClick(const MouseEventWithHitTestResults&);
+  bool HandleTripleClick(const MouseEventWithHitTestResults&);
+
   Member<LocalFrame> const frame_;
   // TODO(yosin): We should use |PositionWIthAffinityInFlatTree| since we
   // should reduce usage of |VisibleSelectionInFlatTree|.
diff --git a/third_party/WebKit/Source/core/editing/SelectionControllerTest.cpp b/third_party/WebKit/Source/core/editing/SelectionControllerTest.cpp
index 6bef62b5..a31b2810 100644
--- a/third_party/WebKit/Source/core/editing/SelectionControllerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionControllerTest.cpp
@@ -114,7 +114,6 @@
   GetDocument().body()->AppendChild(script);
   GetDocument().View()->UpdateAllLifecyclePhases();
   GetFrame().GetEventHandler().GetSelectionController().HandleGestureLongPress(
-      WebGestureEvent(),
       GetFrame().GetEventHandler().HitTestResultAtPoint(IntPoint(8, 8)));
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index ca26c8a..20ef17a0 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -888,24 +888,6 @@
   return true;
 }
 
-namespace {
-
-class UnacceleratedSurfaceFactory
-    : public RecordingImageBufferFallbackSurfaceFactory {
- public:
-  virtual std::unique_ptr<ImageBufferSurface> CreateSurface(
-      const IntSize& size,
-      OpacityMode opacity_mode,
-      const CanvasColorParams& color_params) {
-    return WTF::WrapUnique(new UnacceleratedImageBufferSurface(
-        size, opacity_mode, kInitializeImagePixels, color_params));
-  }
-
-  virtual ~UnacceleratedSurfaceFactory() {}
-};
-
-}  // namespace
-
 bool HTMLCanvasElement::ShouldUseDisplayList() {
   // Rasterization of web contents will blend in the output space. Only embed
   // the canvas as a display list if it intended to do output space blending as
@@ -928,8 +910,8 @@
   // If 3d, but the use of the canvas will be for non-accelerated content
   // then make a non-accelerated ImageBuffer. This means copying the internal
   // Image will require a pixel readback, but that is unavoidable in this case.
-  auto surface = WTF::WrapUnique(new AcceleratedImageBufferSurface(
-      size(), opacity_mode, context_->color_params()));
+  auto surface = WTF::MakeUnique<AcceleratedImageBufferSurface>(
+      size(), opacity_mode, context_->color_params());
   if (surface->IsValid())
     return std::move(surface);
   return nullptr;
@@ -956,10 +938,9 @@
   if (context_provider->IsSoftwareRendering())
     return nullptr;  // Don't use accelerated canvas with swiftshader.
 
-  std::unique_ptr<ImageBufferSurface> surface =
-      WTF::WrapUnique(new Canvas2DImageBufferSurface(
-          std::move(context_provider), size(), *msaa_sample_count, opacity_mode,
-          Canvas2DLayerBridge::kEnableAcceleration, context_->color_params()));
+  auto surface = WTF::MakeUnique<Canvas2DImageBufferSurface>(
+      std::move(context_provider), size(), *msaa_sample_count, opacity_mode,
+      Canvas2DLayerBridge::kEnableAcceleration, context_->color_params());
   if (!surface->IsValid()) {
     CanvasMetrics::CountCanvasContextUsage(
         CanvasMetrics::kGPUAccelerated2DCanvasImageBufferCreationFailed);
@@ -968,16 +949,15 @@
 
   CanvasMetrics::CountCanvasContextUsage(
       CanvasMetrics::kGPUAccelerated2DCanvasImageBufferCreated);
-  return surface;
+  return std::move(surface);
 }
 
 std::unique_ptr<ImageBufferSurface>
 HTMLCanvasElement::CreateUnacceleratedImageBufferSurface(
     OpacityMode opacity_mode) {
   if (ShouldUseDisplayList()) {
-    auto surface = WTF::WrapUnique(new RecordingImageBufferSurface(
-        size(), WTF::WrapUnique(new UnacceleratedSurfaceFactory), opacity_mode,
-        context_->color_params()));
+    auto surface = WTF::MakeUnique<RecordingImageBufferSurface>(
+        size(), opacity_mode, context_->color_params());
     if (surface->IsValid()) {
       CanvasMetrics::CountCanvasContextUsage(
           CanvasMetrics::kDisplayList2DCanvasImageBufferCreated);
@@ -987,13 +967,12 @@
     // here.
   }
 
-  auto surface_factory = WTF::MakeUnique<UnacceleratedSurfaceFactory>();
-  auto surface = surface_factory->CreateSurface(size(), opacity_mode,
-                                                context_->color_params());
+  auto surface = WTF::MakeUnique<UnacceleratedImageBufferSurface>(
+      size(), opacity_mode, kInitializeImagePixels, context_->color_params());
   if (surface->IsValid()) {
     CanvasMetrics::CountCanvasContextUsage(
         CanvasMetrics::kUnaccelerated2DCanvasImageBufferCreated);
-    return surface;
+    return std::move(surface);
   }
 
   CanvasMetrics::CountCanvasContextUsage(
@@ -1479,7 +1458,7 @@
     layer_tree_view =
         frame->GetPage()->GetChromeClient().GetWebLayerTreeView(frame);
     surface_layer_bridge_ =
-        WTF::WrapUnique(new CanvasSurfaceLayerBridge(this, layer_tree_view));
+        WTF::MakeUnique<CanvasSurfaceLayerBridge>(this, layer_tree_view);
     // Creates a placeholder layer first before Surface is created.
     surface_layer_bridge_->CreateSolidColorLayer();
   }
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index b7dad162..a76c7d2 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -217,6 +217,19 @@
     map.erase(it);
 }
 
+String BuildElementErrorMessage(const String& error) {
+  // Prepend a UA-specific-error code before the first ':', to enable better
+  // collection and aggregation of UA-specific-error codes from
+  // MediaError.message by web apps. WebMediaPlayer::GetErrorMessage() should
+  // similarly conform to this format.
+  DEFINE_STATIC_LOCAL(const String, element_error_prefix,
+                      ("MEDIA_ELEMENT_ERROR: "));
+  StringBuilder builder;
+  builder.Append(element_error_prefix);
+  builder.Append(error);
+  return builder.ToString();
+}
+
 class AudioSourceProviderClientLockScope {
   STACK_ALLOCATED();
 
@@ -1059,15 +1072,18 @@
   // If the src attribute's value is the empty string ... jump down to the
   // failed step below
   if (src_value.IsEmpty()) {
-    MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError);
-    BLINK_MEDIA_LOG << "loadSourceFromAttribute(" << (void*)this
+    BLINK_MEDIA_LOG << "LoadSourceFromAttribute(" << (void*)this
                     << "), empty 'src'";
+    MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError,
+                       BuildElementErrorMessage("Empty src attribute"));
     return;
   }
 
   KURL media_url = GetDocument().CompleteURL(src_value);
   if (!IsSafeToLoadURL(media_url, kComplain)) {
-    MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError);
+    MediaLoadingFailed(
+        WebMediaPlayer::kNetworkStateFormatError,
+        BuildElementErrorMessage("Media load rejected by URL safety check"));
     return;
   }
 
@@ -1104,7 +1120,9 @@
 
   LocalFrame* frame = GetDocument().GetFrame();
   if (!frame) {
-    MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError);
+    MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError,
+                       BuildElementErrorMessage(
+                           "Resource load failure: document has no frame"));
     return;
   }
 
@@ -1162,7 +1180,11 @@
       StartPlayerLoad();
     }
   } else {
-    MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError);
+    MediaLoadingFailed(
+        WebMediaPlayer::kNetworkStateFormatError,
+        BuildElementErrorMessage(attempt_load
+                                     ? "Unable to load URL due to content type"
+                                     : "Unable to attach MediaSource"));
   }
 
   // If there is no poster to display, allow the media engine to render video
@@ -1208,14 +1230,18 @@
   // TODO(srirama.m): Figure out how frame can be null when
   // coming from executeDeferredLoad()
   if (!frame) {
-    MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError);
+    MediaLoadingFailed(
+        WebMediaPlayer::kNetworkStateFormatError,
+        BuildElementErrorMessage("Player load failure: document has no frame"));
     return;
   }
 
   web_media_player_ =
       frame->Loader().Client()->CreateWebMediaPlayer(*this, source, this);
   if (!web_media_player_) {
-    MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError);
+    MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError,
+                       BuildElementErrorMessage(
+                           "Player load failure: error creating media player"));
     return;
   }
 
@@ -1458,8 +1484,9 @@
     GetLayoutObject()->UpdateFromElement();
 }
 
-void HTMLMediaElement::NoneSupported() {
-  BLINK_MEDIA_LOG << "noneSupported(" << (void*)this << ")";
+void HTMLMediaElement::NoneSupported(const String& message) {
+  BLINK_MEDIA_LOG << "NoneSupported(" << (void*)this << ", message='" << message
+                  << "')";
 
   StopPeriodicTimers();
   load_state_ = kWaitingForSource;
@@ -1470,7 +1497,7 @@
 
   // 1 - Set the error attribute to a new MediaError object whose code attribute
   // is set to MEDIA_ERR_SRC_NOT_SUPPORTED.
-  error_ = MediaError::Create(MediaError::kMediaErrSrcNotSupported);
+  error_ = MediaError::Create(MediaError::kMediaErrSrcNotSupported, message);
 
   // 2 - Forget the media element's media-resource-specific text tracks.
   ForgetResourceSpecificTracks();
@@ -1539,7 +1566,12 @@
   SetNetworkState(GetWebMediaPlayer()->GetNetworkState());
 }
 
-void HTMLMediaElement::MediaLoadingFailed(WebMediaPlayer::NetworkState error) {
+void HTMLMediaElement::MediaLoadingFailed(WebMediaPlayer::NetworkState error,
+                                          const String& message) {
+  BLINK_MEDIA_LOG << "MediaLoadingFailed(" << (void*)this << ", "
+                  << static_cast<int>(error) << ", message='" << message
+                  << "')";
+
   StopPeriodicTimers();
 
   // If we failed while trying to load a <source> element, the movie was never
@@ -1579,13 +1611,21 @@
 
   if (error == WebMediaPlayer::kNetworkStateNetworkError &&
       ready_state_ >= kHaveMetadata) {
-    MediaEngineError(MediaError::Create(MediaError::kMediaErrNetwork));
+    MediaEngineError(MediaError::Create(MediaError::kMediaErrNetwork, message));
   } else if (error == WebMediaPlayer::kNetworkStateDecodeError) {
-    MediaEngineError(MediaError::Create(MediaError::kMediaErrDecode));
+    MediaEngineError(MediaError::Create(MediaError::kMediaErrDecode, message));
   } else if ((error == WebMediaPlayer::kNetworkStateFormatError ||
               error == WebMediaPlayer::kNetworkStateNetworkError) &&
              load_state_ == kLoadingFromSrcAttr) {
-    NoneSupported();
+    if (message.IsEmpty()) {
+      // Generate a more meaningful error message to differentiate the two types
+      // of MEDIA_SRC_ERR_NOT_SUPPORTED.
+      NoneSupported(BuildElementErrorMessage(
+          error == WebMediaPlayer::kNetworkStateFormatError ? "Format error"
+                                                            : "Network error"));
+    } else {
+      NoneSupported(message);
+    }
   }
 
   UpdateDisplayState();
@@ -1605,7 +1645,7 @@
   if (state == WebMediaPlayer::kNetworkStateFormatError ||
       state == WebMediaPlayer::kNetworkStateNetworkError ||
       state == WebMediaPlayer::kNetworkStateDecodeError) {
-    MediaLoadingFailed(state);
+    MediaLoadingFailed(state, web_media_player_->GetErrorMessage());
     return;
   }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
index b313f69..c79fcd1 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -452,7 +452,7 @@
   void ClearMediaPlayer();
   void ClearMediaPlayerAndAudioSourceProviderClientWithoutLocking();
   bool HavePotentialSourceChild();
-  void NoneSupported();
+  void NoneSupported(const String&);
   void MediaEngineError(MediaError*);
   void CancelPendingEventsAndCallbacks();
   void WaitForSourceChange();
@@ -460,7 +460,7 @@
 
   KURL SelectNextSourceChild(String* content_type, InvalidURLAction);
 
-  void MediaLoadingFailed(WebMediaPlayer::NetworkState);
+  void MediaLoadingFailed(WebMediaPlayer::NetworkState, const String&);
 
   // deferred loading (preload=none)
   bool LoadIsDeferred() const;
diff --git a/third_party/WebKit/Source/core/html/media/MediaError.h b/third_party/WebKit/Source/core/html/media/MediaError.h
index 8580a06..1d41800 100644
--- a/third_party/WebKit/Source/core/html/media/MediaError.h
+++ b/third_party/WebKit/Source/core/html/media/MediaError.h
@@ -29,11 +29,13 @@
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "core/CoreExport.h"
 #include "platform/heap/Handle.h"
+#include "platform/wtf/text/WTFString.h"
 
 namespace blink {
 
-class CORE_EXPORT MediaError final : public GarbageCollected<MediaError>,
-                                     public ScriptWrappable {
+class CORE_EXPORT MediaError final
+    : public GarbageCollectedFinalized<MediaError>,
+      public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -44,16 +46,24 @@
     kMediaErrSrcNotSupported,
   };
 
-  static MediaError* Create(ErrorCode code) { return new MediaError(code); }
+  static MediaError* Create(ErrorCode code, const String& message) {
+    return new MediaError(code, message);
+  }
 
   ErrorCode code() const { return code_; }
 
+  // Returns either an empty string, or a human readable string describing
+  // additional error detail.
+  String message() const { return message_; }
+
   DEFINE_INLINE_TRACE() {}
 
  private:
-  MediaError(ErrorCode code) : code_(code) {}
+  MediaError(ErrorCode code, const String& message)
+      : code_(code), message_(message) {}
 
   ErrorCode code_;
+  String message_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/media/MediaError.idl b/third_party/WebKit/Source/core/html/media/MediaError.idl
index e43026e..cd551b6 100644
--- a/third_party/WebKit/Source/core/html/media/MediaError.idl
+++ b/third_party/WebKit/Source/core/html/media/MediaError.idl
@@ -31,4 +31,5 @@
     const unsigned short MEDIA_ERR_DECODE = 3;
     const unsigned short MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
     readonly attribute unsigned short code;
+    readonly attribute DOMString message;
 };
diff --git a/third_party/WebKit/Source/core/input/GestureManager.cpp b/third_party/WebKit/Source/core/input/GestureManager.cpp
index 8babf0f..131f5d8 100644
--- a/third_party/WebKit/Source/core/input/GestureManager.cpp
+++ b/third_party/WebKit/Source/core/input/GestureManager.cpp
@@ -331,8 +331,7 @@
 
   Node* inner_node = hit_test_result.InnerNode();
   if (inner_node && inner_node->GetLayoutObject() &&
-      selection_controller_->HandleGestureLongPress(gesture_event,
-                                                    hit_test_result)) {
+      selection_controller_->HandleGestureLongPress(hit_test_result)) {
     mouse_event_manager_->FocusDocumentView();
     return WebInputEventResult::kHandledSystem;
   }
diff --git a/third_party/WebKit/Source/core/input/MouseEventManager.cpp b/third_party/WebKit/Source/core/input/MouseEventManager.cpp
index 7c03ad6a..bb88304 100644
--- a/third_party/WebKit/Source/core/input/MouseEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/MouseEventManager.cpp
@@ -585,9 +585,6 @@
   mouse_down_may_start_drag_ =
       single_click && !IsLinkSelection(event) && !IsExtendingSelection(event);
 
-  frame_->GetEventHandler().GetSelectionController().HandleMousePressEvent(
-      event);
-
   mouse_down_ = event.Event();
 
   if (frame_->GetDocument()->IsSVGDocument() &&
@@ -613,22 +610,11 @@
   frame_->GetDocument()->SetSequentialFocusNavigationStartingPoint(inner_node);
   drag_start_pos_ = FlooredIntPoint(event.Event().PositionInRootFrame());
 
-  bool swallow_event = false;
   mouse_pressed_ = true;
 
-  if (event.Event().click_count == 2) {
-    swallow_event = frame_->GetEventHandler()
-                        .GetSelectionController()
-                        .HandleMousePressEventDoubleClick(event);
-  } else if (event.Event().click_count >= 3) {
-    swallow_event = frame_->GetEventHandler()
-                        .GetSelectionController()
-                        .HandleMousePressEventTripleClick(event);
-  } else {
-    swallow_event = frame_->GetEventHandler()
-                        .GetSelectionController()
-                        .HandleMousePressEventSingleClick(event);
-  }
+  bool swallow_event =
+      frame_->GetEventHandler().GetSelectionController().HandleMousePressEvent(
+          event);
 
   mouse_down_may_start_autoscroll_ =
       frame_->GetEventHandler()
diff --git a/third_party/WebKit/Source/modules/app_banner/AppBannerPromptResult.cpp b/third_party/WebKit/Source/modules/app_banner/AppBannerPromptResult.cpp
index ce259c1..9df48c9 100644
--- a/third_party/WebKit/Source/modules/app_banner/AppBannerPromptResult.cpp
+++ b/third_party/WebKit/Source/modules/app_banner/AppBannerPromptResult.cpp
@@ -17,7 +17,7 @@
       return "dismissed";
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return "";
 }
 
diff --git a/third_party/WebKit/Source/modules/audio_output_devices/SetSinkIdCallbacks.cpp b/third_party/WebKit/Source/modules/audio_output_devices/SetSinkIdCallbacks.cpp
index e6089dd..96cdd96 100644
--- a/third_party/WebKit/Source/modules/audio_output_devices/SetSinkIdCallbacks.cpp
+++ b/third_party/WebKit/Source/modules/audio_output_devices/SetSinkIdCallbacks.cpp
@@ -26,7 +26,7 @@
       return DOMException::Create(kNotSupportedError,
                                   "Operation not supported");
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return DOMException::Create(kAbortError, "Invalid error code");
   }
 }
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl
index 6ab34b38..fcd7a1dc2 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl
@@ -134,7 +134,7 @@
     // Should be merged with WebGL counterpart in CanvasRenderingContext, once no-longer experimental
     [RuntimeEnabled=ExperimentalCanvasFeatures] boolean isContextLost();
 
-    [MeasureAs=GetCanvas2DContextAttributes] CanvasRenderingContext2DSettings getContextAttributes();
+    [RuntimeEnabled=ExperimentalCanvasFeatures, MeasureAs=GetCanvas2DContextAttributes] CanvasRenderingContext2DSettings getContextAttributes();
 
     // FIXME: factor out to CanvasDrawingStyles
     // line caps/joins
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
index 1105d69..f74ae06 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -259,13 +259,12 @@
 
 //============================================================================
 
-class FakeAcceleratedImageBufferSurfaceForTesting
+class FakeAcceleratedImageBufferSurface
     : public UnacceleratedImageBufferSurface {
  public:
-  FakeAcceleratedImageBufferSurfaceForTesting(const IntSize& size,
-                                              OpacityMode mode)
+  FakeAcceleratedImageBufferSurface(const IntSize& size, OpacityMode mode)
       : UnacceleratedImageBufferSurface(size, mode), is_accelerated_(true) {}
-  ~FakeAcceleratedImageBufferSurfaceForTesting() override {}
+  ~FakeAcceleratedImageBufferSurface() override {}
   bool IsAccelerated() const override { return is_accelerated_; }
   void SetIsAccelerated(bool is_accelerated) {
     if (is_accelerated != is_accelerated_)
@@ -296,8 +295,8 @@
 
 #define TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS)                                \
   std::unique_ptr<MockImageBufferSurfaceForOverwriteTesting> mock_surface =    \
-      WTF::WrapUnique(new MockImageBufferSurfaceForOverwriteTesting(           \
-          IntSize(10, 10), kNonOpaque));                                       \
+      WTF::MakeUnique<MockImageBufferSurfaceForOverwriteTesting>(              \
+          IntSize(10, 10), kNonOpaque);                                        \
   MockImageBufferSurfaceForOverwriteTesting* surface_ptr = mock_surface.get(); \
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(                     \
       std::move(mock_surface));                                                \
@@ -344,40 +343,6 @@
 
 //============================================================================
 
-class MockSurfaceFactory : public RecordingImageBufferFallbackSurfaceFactory {
- public:
-  enum FallbackExpectation { kExpectFallback, kExpectNoFallback };
-  static std::unique_ptr<MockSurfaceFactory> Create(
-      FallbackExpectation expectation) {
-    return WTF::WrapUnique(new MockSurfaceFactory(expectation));
-  }
-
-  std::unique_ptr<ImageBufferSurface> CreateSurface(
-      const IntSize& size,
-      OpacityMode mode,
-      const CanvasColorParams& color_params) override {
-    EXPECT_EQ(kExpectFallback, expectation_);
-    did_fallback_ = true;
-    return WTF::WrapUnique(new UnacceleratedImageBufferSurface(
-        size, mode, kInitializeImagePixels, color_params));
-  }
-
-  ~MockSurfaceFactory() override {
-    if (expectation_ == kExpectFallback) {
-      EXPECT_TRUE(did_fallback_);
-    }
-  }
-
- private:
-  MockSurfaceFactory(FallbackExpectation expectation)
-      : expectation_(expectation), did_fallback_(false) {}
-
-  FallbackExpectation expectation_;
-  bool did_fallback_;
-};
-
-//============================================================================
-
 TEST_F(CanvasRenderingContext2DTest, detectOverdrawWithFillRect) {
   CreateContext(kNonOpaque);
 
@@ -554,22 +519,19 @@
 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionByDefault) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionUnderOverdrawLimit) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->setGlobalAlpha(0.5f);  // To prevent overdraw optimization
@@ -580,15 +542,14 @@
   }
 
   EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, LayerPromotionOverOverdrawLimit) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->setGlobalAlpha(0.5f);  // To prevent overdraw optimization
@@ -599,15 +560,14 @@
   }
 
   EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited());
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionUnderImageSizeRatioLimit) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   NonThrowableExceptionState exception_state;
@@ -634,15 +594,14 @@
   EXPECT_FALSE(exception_state.HadException());
 
   EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, LayerPromotionOverImageSizeRatioLimit) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   NonThrowableExceptionState exception_state;
@@ -670,16 +629,15 @@
   EXPECT_FALSE(exception_state.HadException());
 
   EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited());
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest,
        NoLayerPromotionUnderExpensivePathPointCount) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -695,16 +653,15 @@
   Context2d()->fill();
 
   EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest,
        LayerPromotionOverExpensivePathPointCount) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -720,15 +677,14 @@
   Context2d()->fill();
 
   EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited());
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, LayerPromotionWhenPathIsConcave) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -743,15 +699,14 @@
   } else {
     EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
   }
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionWithRectangleClip) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -760,15 +715,14 @@
   Context2d()->fillRect(0, 0, 4, 4);
 
   EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, LayerPromotionWithComplexClip) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -784,15 +738,14 @@
   } else {
     EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
   }
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, LayerPromotionWithBlurredShadow) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->setShadowColor(String("red"));
@@ -804,15 +757,14 @@
   } else {
     EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
   }
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionWithSharpShadow) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->setShadowColor(String("red"));
@@ -820,18 +772,17 @@
   Context2d()->fillRect(1, 1, 1, 1);
 
   EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, NoFallbackWithSmallState) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
-  Context2d()->fillRect(0, 0, 1, 1);  // To have a non-empty dirty rect
+  Context2d()->fillRect(0, 0, 1, 1);  // To have a non-empty dirty rect.
   for (int i = 0;
        i <
        ExpensiveCanvasHeuristicParameters::kExpensiveRecordingStackDepth - 1;
@@ -839,26 +790,28 @@
     Context2d()->save();
     Context2d()->translate(1.0f, 0.0f);
   }
-  CanvasElement().FinalizeFrame();  // To close the current frame
+  CanvasElement().FinalizeFrame();  // To close the current frame.
+
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, FallbackWithLargeState) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
-  Context2d()->fillRect(0, 0, 1, 1);  // To have a non-empty dirty rect
+  Context2d()->fillRect(0, 0, 1, 1);  // To have a non-empty dirty rect.
   for (int i = 0;
        i < ExpensiveCanvasHeuristicParameters::kExpensiveRecordingStackDepth;
        ++i) {
     Context2d()->save();
     Context2d()->translate(1.0f, 0.0f);
   }
-  CanvasElement().FinalizeFrame();  // To close the current frame
+  CanvasElement().FinalizeFrame();  // To close the current frame.
+
+  EXPECT_FALSE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, OpaqueDisplayListFallsBackForText) {
@@ -868,27 +821,27 @@
   // does not support pixel geometry settings.
   // See: crbug.com/583809
   CreateContext(kOpaque);
-  std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectFallback),
-          kOpaque));
+  auto surface =
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->fillText("Text", 0, 5);
+
+  EXPECT_FALSE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest,
        NonOpaqueDisplayListDoesNotFallBackForText) {
   CreateContext(kNonOpaque);
   std::unique_ptr<RecordingImageBufferSurface> surface =
-      WTF::WrapUnique(new RecordingImageBufferSurface(
-          IntSize(10, 10),
-          MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque));
+      WTF::MakeUnique<RecordingImageBufferSurface>(IntSize(10, 10), kNonOpaque);
+  auto* surface_ptr = surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->fillText("Text", 0, 5);
+
+  EXPECT_TRUE(surface_ptr->IsRecording());
 }
 
 TEST_F(CanvasRenderingContext2DTest, ImageResourceLifetime) {
@@ -921,11 +874,10 @@
 TEST_F(CanvasRenderingContext2DTest, GPUMemoryUpdateForAcceleratedCanvas) {
   CreateContext(kNonOpaque);
 
-  std::unique_ptr<FakeAcceleratedImageBufferSurfaceForTesting>
-      fake_accelerate_surface =
-          WTF::WrapUnique(new FakeAcceleratedImageBufferSurfaceForTesting(
-              IntSize(10, 10), kNonOpaque));
-  FakeAcceleratedImageBufferSurfaceForTesting* fake_accelerate_surface_ptr =
+  std::unique_ptr<FakeAcceleratedImageBufferSurface> fake_accelerate_surface =
+      WTF::MakeUnique<FakeAcceleratedImageBufferSurface>(IntSize(10, 10),
+                                                         kNonOpaque);
+  FakeAcceleratedImageBufferSurface* fake_accelerate_surface_ptr =
       fake_accelerate_surface.get();
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(
       std::move(fake_accelerate_surface));
@@ -950,10 +902,9 @@
   EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount());
 
   // Creating a different accelerated image buffer
-  std::unique_ptr<FakeAcceleratedImageBufferSurfaceForTesting>
-      fake_accelerate_surface2 =
-          WTF::WrapUnique(new FakeAcceleratedImageBufferSurfaceForTesting(
-              IntSize(10, 5), kNonOpaque));
+  auto fake_accelerate_surface2 =
+      WTF::MakeUnique<FakeAcceleratedImageBufferSurface>(IntSize(10, 5),
+                                                         kNonOpaque);
   std::unique_ptr<ImageBuffer> image_buffer2 =
       ImageBuffer::Create(std::move(fake_accelerate_surface2));
   EXPECT_EQ(800, GetCurrentGPUMemoryUsage());
@@ -1117,10 +1068,9 @@
        IsAccelerationOptimalForCanvasContentHeuristic) {
   CreateContext(kNonOpaque);
 
-  std::unique_ptr<FakeAcceleratedImageBufferSurfaceForTesting>
-      fake_accelerate_surface =
-          WTF::WrapUnique(new FakeAcceleratedImageBufferSurfaceForTesting(
-              IntSize(10, 10), kNonOpaque));
+  auto fake_accelerate_surface =
+      WTF::MakeUnique<FakeAcceleratedImageBufferSurface>(IntSize(10, 10),
+                                                         kNonOpaque);
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(
       std::move(fake_accelerate_surface));
 
@@ -1152,10 +1102,9 @@
 TEST_F(CanvasRenderingContext2DTest, DisableAcceleration) {
   CreateContext(kNonOpaque);
 
-  std::unique_ptr<FakeAcceleratedImageBufferSurfaceForTesting>
-      fake_accelerate_surface =
-          WTF::WrapUnique(new FakeAcceleratedImageBufferSurfaceForTesting(
-              IntSize(10, 10), kNonOpaque));
+  auto fake_accelerate_surface =
+      WTF::MakeUnique<FakeAcceleratedImageBufferSurface>(IntSize(10, 10),
+                                                         kNonOpaque);
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(
       std::move(fake_accelerate_surface));
   CanvasRenderingContext2D* context = Context2d();
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp
index b19b158..c0293a7 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp
@@ -85,7 +85,7 @@
     case kParseFailed:
       return false;
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return false;
   }
 }
@@ -121,7 +121,7 @@
           flags, AffineTransformToSkMatrix(GetCanvasPattern()->GetTransform()));
       break;
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
   }
 }
 
diff --git a/third_party/WebKit/Source/modules/crypto/CryptoHistograms.cpp b/third_party/WebKit/Source/modules/crypto/CryptoHistograms.cpp
index 9b2fc096..a7f40b3 100644
--- a/third_party/WebKit/Source/modules/crypto/CryptoHistograms.cpp
+++ b/third_party/WebKit/Source/modules/crypto/CryptoHistograms.cpp
@@ -48,7 +48,7 @@
       return UseCounter::kCryptoAlgorithmPbkdf2;
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return static_cast<UseCounter::Feature>(0);
 }
 
diff --git a/third_party/WebKit/Source/modules/crypto/CryptoKey.cpp b/third_party/WebKit/Source/modules/crypto/CryptoKey.cpp
index 8e69bbf..7da91dab 100644
--- a/third_party/WebKit/Source/modules/crypto/CryptoKey.cpp
+++ b/third_party/WebKit/Source/modules/crypto/CryptoKey.cpp
@@ -51,7 +51,7 @@
     case kWebCryptoKeyTypePrivate:
       return "private";
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return 0;
 }
 
@@ -82,7 +82,7 @@
     if (kKeyUsageMappings[i].value == usage)
       return kKeyUsageMappings[i].name;
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp b/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp
index 0883422..91cd427 100644
--- a/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp
+++ b/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp
@@ -115,7 +115,7 @@
       return kV8TypeError;
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return 0;
 }
 
diff --git a/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp b/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
index f5120fab..e67d9159 100644
--- a/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
+++ b/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp
@@ -987,7 +987,7 @@
       context.Add("Pbkdf2Params");
       return ParsePbkdf2Params(raw, params, context, error);
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return false;
 }
 
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
index 9a11dc0c..24ae327d 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
@@ -90,9 +90,8 @@
   DCHECK(layout_object.GetNode());
 
   PaintRenderingContext2D* rendering_context = PaintRenderingContext2D::Create(
-      ImageBuffer::Create(WTF::WrapUnique(
-          new RecordingImageBufferSurface(size, nullptr /* fallbackFactory */,
-                                          has_alpha_ ? kNonOpaque : kOpaque))),
+      ImageBuffer::Create(WTF::WrapUnique(new RecordingImageBufferSurface(
+          size, has_alpha_ ? kNonOpaque : kOpaque))),
       has_alpha_, zoom);
   PaintSize* paint_size = PaintSize::Create(specified_size);
   StylePropertyMapReadonly* style_map =
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index 7a09ee1..de2bc0b 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -281,7 +281,6 @@
                     "vr/VRStageParameters.idl",
                     "webaudio/AnalyserNode.idl",
                     "webaudio/AudioBuffer.idl",
-                    "webaudio/AudioBufferCallback.idl",
                     "webaudio/AudioBufferSourceNode.idl",
                     "webaudio/AudioContext.idl",
                     "webaudio/AudioDestinationNode.idl",
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp
index 9d3e718..f078654b 100644
--- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp
+++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp
@@ -180,7 +180,7 @@
       return declined_handler;
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return String();
 }
 
diff --git a/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp b/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp
index 21a6d6b..d0f4b57 100644
--- a/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp
+++ b/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp
@@ -36,7 +36,7 @@
     case kWebConnectionTypeUnknown:
       return "unknown";
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return "none";
 }
 
diff --git a/third_party/WebKit/Source/modules/permissions/PermissionStatus.cpp b/third_party/WebKit/Source/modules/permissions/PermissionStatus.cpp
index b5963faa..ab6e5fca 100644
--- a/third_party/WebKit/Source/modules/permissions/PermissionStatus.cpp
+++ b/third_party/WebKit/Source/modules/permissions/PermissionStatus.cpp
@@ -81,7 +81,7 @@
       return "prompt";
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return "denied";
 }
 
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
index c2d82a6..90d0d36 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
+++ b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
@@ -62,7 +62,7 @@
       return terminated_value;
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return terminated_value;
 }
 
@@ -81,7 +81,7 @@
       return went_away_value;
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return error_value;
 }
 
@@ -346,7 +346,7 @@
     case kBinaryTypeArrayBuffer:
       return "arraybuffer";
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return String();
 }
 
@@ -359,7 +359,7 @@
     binary_type_ = kBinaryTypeArrayBuffer;
     return;
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
 }
 
 void PresentationConnection::DidReceiveTextMessage(const WebString& message) {
@@ -388,7 +388,7 @@
       DispatchEvent(MessageEvent::Create(buffer));
       return;
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
 }
 
 WebPresentationConnectionState PresentationConnection::GetState() {
diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
index 9e4ef79..d66c1f1d 100644
--- a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
+++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
@@ -35,7 +35,7 @@
       return disconnected_value;
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return disconnected_value;
 }
 
diff --git a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.cpp b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.cpp
index 2b9d61fb..341149d 100644
--- a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.cpp
+++ b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.cpp
@@ -73,7 +73,7 @@
       return orientation_map[i].name;
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return g_null_atom;
 }
 
@@ -87,7 +87,7 @@
           orientation_map[i].orientation);
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return kWebScreenOrientationLockDefault;
 }
 
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
index 24e284ff..9582f59 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
@@ -99,7 +99,7 @@
   switch (handle_->ServiceWorker()->GetState()) {
     case kWebServiceWorkerStateUnknown:
       // The web platform should never see this internal state
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return "unknown";
     case kWebServiceWorkerStateInstalling:
       return "installing";
@@ -112,7 +112,7 @@
     case kWebServiceWorkerStateRedundant:
       return "redundant";
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return g_null_atom;
   }
 }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp
index 595a92c..e54315d6 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp
@@ -30,10 +30,10 @@
     case kWebServiceWorkerClientTypeSharedWorker:
       return ServiceWorkerClient::Create(*web_client);
     case kWebServiceWorkerClientTypeLast:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return nullptr;
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return nullptr;
 }
 
@@ -61,7 +61,7 @@
       return "top-level";
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return String();
 }
 
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp
index b2d60e8..ee7a500 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp
@@ -58,7 +58,7 @@
     return kWebServiceWorkerClientTypeSharedWorker;
   if (type == "all")
     return kWebServiceWorkerClientTypeAll;
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return kWebServiceWorkerClientTypeWindow;
 }
 
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
index 25504131..1067a81 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
@@ -78,7 +78,7 @@
                              web_error.message);
     case WebServiceWorkerError::kErrorTypeNavigation:
       // ErrorTypeNavigation should have bailed out before calling this.
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return ExceptionParams(kUnknownError);
     case WebServiceWorkerError::kErrorTypeNetwork:
       return ExceptionParams(kNetworkError,
@@ -108,10 +108,10 @@
                              web_error.message);
     case WebServiceWorkerError::kErrorTypeType:
       // ErrorTypeType should have been handled before reaching this point.
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return ExceptionParams(kUnknownError);
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return ExceptionParams(kUnknownError);
 }
 
diff --git a/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp b/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp
index e5fb8d3..3491497 100644
--- a/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp
+++ b/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp
@@ -49,7 +49,7 @@
       return "language-not-supported";
   }
 
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return String();
 }
 
diff --git a/third_party/WebKit/Source/modules/speech/SpeechSynthesis.cpp b/third_party/WebKit/Source/modules/speech/SpeechSynthesis.cpp
index fd97662a3..9f6c6fa 100644
--- a/third_party/WebKit/Source/modules/speech/SpeechSynthesis.cpp
+++ b/third_party/WebKit/Source/modules/speech/SpeechSynthesis.cpp
@@ -179,7 +179,7 @@
                 char_index, sentence_boundary_string);
       break;
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
   }
 }
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp
index c43bcff..d2ba5b2 100644
--- a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp
@@ -24,9 +24,11 @@
  */
 
 #include "modules/webaudio/AsyncAudioDecoder.h"
+
+#include "bindings/modules/v8/DecodeErrorCallback.h"
+#include "bindings/modules/v8/DecodeSuccessCallback.h"
 #include "core/dom/DOMArrayBuffer.h"
 #include "modules/webaudio/AudioBuffer.h"
-#include "modules/webaudio/AudioBufferCallback.h"
 #include "modules/webaudio/BaseAudioContext.h"
 #include "platform/CrossThreadFunctional.h"
 #include "platform/audio/AudioBus.h"
@@ -40,8 +42,8 @@
 
 void AsyncAudioDecoder::DecodeAsync(DOMArrayBuffer* audio_data,
                                     float sample_rate,
-                                    AudioBufferCallback* success_callback,
-                                    AudioBufferCallback* error_callback,
+                                    DecodeSuccessCallback* success_callback,
+                                    DecodeErrorCallback* error_callback,
                                     ScriptPromiseResolver* resolver,
                                     BaseAudioContext* context) {
   DCHECK(IsMainThread());
@@ -62,8 +64,8 @@
 void AsyncAudioDecoder::DecodeOnBackgroundThread(
     DOMArrayBuffer* audio_data,
     float sample_rate,
-    AudioBufferCallback* success_callback,
-    AudioBufferCallback* error_callback,
+    DecodeSuccessCallback* success_callback,
+    DecodeErrorCallback* error_callback,
     ScriptPromiseResolver* resolver,
     BaseAudioContext* context) {
   DCHECK(!IsMainThread());
@@ -89,8 +91,8 @@
 }
 
 void AsyncAudioDecoder::NotifyComplete(DOMArrayBuffer*,
-                                       AudioBufferCallback* success_callback,
-                                       AudioBufferCallback* error_callback,
+                                       DecodeSuccessCallback* success_callback,
+                                       DecodeErrorCallback* error_callback,
                                        AudioBus* audio_bus,
                                        ScriptPromiseResolver* resolver,
                                        BaseAudioContext* context) {
diff --git a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h
index e5ba089..a5d739111 100644
--- a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h
+++ b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h
@@ -34,8 +34,9 @@
 
 class BaseAudioContext;
 class AudioBuffer;
-class AudioBufferCallback;
 class AudioBus;
+class DecodeErrorCallback;
+class DecodeSuccessCallback;
 class DOMArrayBuffer;
 class ScriptPromiseResolver;
 
@@ -58,8 +59,8 @@
   // appropriately when finished.
   void DecodeAsync(DOMArrayBuffer* audio_data,
                    float sample_rate,
-                   AudioBufferCallback* success_callback,
-                   AudioBufferCallback* error_callback,
+                   DecodeSuccessCallback*,
+                   DecodeErrorCallback*,
                    ScriptPromiseResolver*,
                    BaseAudioContext*);
 
@@ -67,13 +68,13 @@
   AudioBuffer* CreateAudioBufferFromAudioBus(AudioBus*);
   static void DecodeOnBackgroundThread(DOMArrayBuffer* audio_data,
                                        float sample_rate,
-                                       AudioBufferCallback* success_callback,
-                                       AudioBufferCallback* error_callback,
+                                       DecodeSuccessCallback*,
+                                       DecodeErrorCallback*,
                                        ScriptPromiseResolver*,
                                        BaseAudioContext*);
   static void NotifyComplete(DOMArrayBuffer* audio_data,
-                             AudioBufferCallback* success_callback,
-                             AudioBufferCallback* error_callback,
+                             DecodeSuccessCallback*,
+                             DecodeErrorCallback*,
                              AudioBus*,
                              ScriptPromiseResolver*,
                              BaseAudioContext*);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBufferCallback.h b/third_party/WebKit/Source/modules/webaudio/AudioBufferCallback.h
deleted file mode 100644
index e8ccc98..0000000
--- a/third_party/WebKit/Source/modules/webaudio/AudioBufferCallback.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2011, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1.  Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
-
-#ifndef AudioBufferCallback_h
-#define AudioBufferCallback_h
-
-#include "platform/heap/Handle.h"
-#include "platform/wtf/build_config.h"
-
-namespace blink {
-
-class AudioBuffer;
-class DOMException;
-
-class AudioBufferCallback
-    : public GarbageCollectedFinalized<AudioBufferCallback> {
- public:
-  virtual ~AudioBufferCallback() {}
-  DEFINE_INLINE_VIRTUAL_TRACE() {}
-  virtual void handleEvent(AudioBuffer*) = 0;
-  virtual void handleEvent(DOMException*) = 0;
-};
-
-}  // namespace blink
-
-#endif  // AudioBufferCallback_h
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBufferCallback.idl b/third_party/WebKit/Source/modules/webaudio/AudioBufferCallback.idl
deleted file mode 100644
index 83b627d..0000000
--- a/third_party/WebKit/Source/modules/webaudio/AudioBufferCallback.idl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1.  Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
-
-callback interface AudioBufferCallback {
-    void handleEvent(AudioBuffer audioBuffer);
-    void handleEvent(DOMException exception);
-};
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
index be3e301..d588778 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
@@ -13,7 +13,6 @@
 #include "core/frame/UseCounter.h"
 #include "core/timing/DOMWindowPerformance.h"
 #include "core/timing/Performance.h"
-#include "modules/webaudio/AudioBufferCallback.h"
 #include "modules/webaudio/AudioContextOptions.h"
 #include "modules/webaudio/AudioTimestamp.h"
 #include "modules/webaudio/DefaultAudioDestinationNode.h"
diff --git a/third_party/WebKit/Source/modules/webaudio/BUILD.gn b/third_party/WebKit/Source/modules/webaudio/BUILD.gn
index b10d919..8cfcd64 100644
--- a/third_party/WebKit/Source/modules/webaudio/BUILD.gn
+++ b/third_party/WebKit/Source/modules/webaudio/BUILD.gn
@@ -16,7 +16,6 @@
     "AudioBasicProcessorHandler.h",
     "AudioBuffer.cpp",
     "AudioBuffer.h",
-    "AudioBufferCallback.h",
     "AudioBufferSourceNode.cpp",
     "AudioBufferSourceNode.h",
     "AudioContext.cpp",
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
index aa91dff6e..c7090d8f 100644
--- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
@@ -30,6 +30,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "bindings/core/v8/ScriptState.h"
+#include "bindings/modules/v8/DecodeErrorCallback.h"
+#include "bindings/modules/v8/DecodeSuccessCallback.h"
 #include "core/dom/DOMException.h"
 #include "core/dom/Document.h"
 #include "core/dom/ExceptionCode.h"
@@ -41,7 +43,6 @@
 #include "modules/mediastream/MediaStream.h"
 #include "modules/webaudio/AnalyserNode.h"
 #include "modules/webaudio/AudioBuffer.h"
-#include "modules/webaudio/AudioBufferCallback.h"
 #include "modules/webaudio/AudioBufferSourceNode.h"
 #include "modules/webaudio/AudioContext.h"
 #include "modules/webaudio/AudioListener.h"
@@ -272,8 +273,25 @@
 ScriptPromise BaseAudioContext::decodeAudioData(
     ScriptState* script_state,
     DOMArrayBuffer* audio_data,
-    AudioBufferCallback* success_callback,
-    AudioBufferCallback* error_callback,
+    ExceptionState& exception_state) {
+  return decodeAudioData(script_state, audio_data, nullptr, nullptr,
+                         exception_state);
+}
+
+ScriptPromise BaseAudioContext::decodeAudioData(
+    ScriptState* script_state,
+    DOMArrayBuffer* audio_data,
+    DecodeSuccessCallback* success_callback,
+    ExceptionState& exception_state) {
+  return decodeAudioData(script_state, audio_data, success_callback, nullptr,
+                         exception_state);
+}
+
+ScriptPromise BaseAudioContext::decodeAudioData(
+    ScriptState* script_state,
+    DOMArrayBuffer* audio_data,
+    DecodeSuccessCallback* success_callback,
+    DecodeErrorCallback* error_callback,
     ExceptionState& exception_state) {
   DCHECK(IsMainThread());
   DCHECK(audio_data);
@@ -292,7 +310,7 @@
         kDataCloneError, "Cannot decode detached ArrayBuffer");
     resolver->Reject(error);
     if (error_callback) {
-      error_callback->handleEvent(error);
+      error_callback->call(this, error);
     }
   } else {
     // Detach the audio array buffer from the main thread and start
@@ -312,22 +330,22 @@
 void BaseAudioContext::HandleDecodeAudioData(
     AudioBuffer* audio_buffer,
     ScriptPromiseResolver* resolver,
-    AudioBufferCallback* success_callback,
-    AudioBufferCallback* error_callback) {
+    DecodeSuccessCallback* success_callback,
+    DecodeErrorCallback* error_callback) {
   DCHECK(IsMainThread());
 
   if (audio_buffer) {
     // Resolve promise successfully and run the success callback
     resolver->Resolve(audio_buffer);
     if (success_callback)
-      success_callback->handleEvent(audio_buffer);
+      success_callback->call(this, audio_buffer);
   } else {
     // Reject the promise and run the error callback
     DOMException* error =
         DOMException::Create(kEncodingError, "Unable to decode audio data");
     resolver->Reject(error);
     if (error_callback)
-      error_callback->handleEvent(error);
+      error_callback->call(this, error);
   }
 
   // We've resolved the promise.  Remove it now.
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
index 67b43b0..5f9c053e 100644
--- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
+++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
@@ -51,7 +51,6 @@
 
 class AnalyserNode;
 class AudioBuffer;
-class AudioBufferCallback;
 class AudioBufferSourceNode;
 class AudioContextOptions;
 class AudioListener;
@@ -62,6 +61,8 @@
 class ConstantSourceNode;
 class ConvolverNode;
 class DelayNode;
+class DecodeErrorCallback;
+class DecodeSuccessCallback;
 class Document;
 class DynamicsCompressorNode;
 class ExceptionState;
@@ -169,16 +170,25 @@
   // Asynchronous audio file data decoding.
   ScriptPromise decodeAudioData(ScriptState*,
                                 DOMArrayBuffer* audio_data,
-                                AudioBufferCallback* success_callback,
-                                AudioBufferCallback* error_callback,
+                                DecodeSuccessCallback*,
+                                DecodeErrorCallback*,
+                                ExceptionState&);
+
+  ScriptPromise decodeAudioData(ScriptState*,
+                                DOMArrayBuffer* audio_data,
+                                ExceptionState&);
+
+  ScriptPromise decodeAudioData(ScriptState*,
+                                DOMArrayBuffer* audio_data,
+                                DecodeSuccessCallback*,
                                 ExceptionState&);
 
   // Handles the promise and callbacks when |decodeAudioData| is finished
   // decoding.
   void HandleDecodeAudioData(AudioBuffer*,
                              ScriptPromiseResolver*,
-                             AudioBufferCallback* success_callback,
-                             AudioBufferCallback* error_callback);
+                             DecodeSuccessCallback*,
+                             DecodeErrorCallback*);
 
   AudioListener* listener() { return listener_; }
 
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.idl b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.idl
index d8d4d6d..f058169 100644
--- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.idl
+++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.idl
@@ -3,12 +3,16 @@
 // found in the LICENSE file.
 
 // See https://webaudio.github.io/web-audio-api/#BaseAudioContext
+
 enum AudioContextState {
     "suspended",
     "running",
     "closed"
 };
 
+callback DecodeErrorCallback = void (DOMException error);
+callback DecodeSuccessCallback = void (AudioBuffer decodedData);
+
 [
     ActiveScriptWrappable,
     DependentLifetime,
@@ -31,7 +35,7 @@
     [RaisesException] AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long numberOfFrames, float sampleRate);
 
     // Asynchronous audio file data decoding.
-    [RaisesException, MeasureAs=AudioContextDecodeAudioData, CallWith=ScriptState] Promise<AudioBuffer> decodeAudioData(ArrayBuffer audioData, optional AudioBufferCallback successCallback, optional AudioBufferCallback errorCallback);
+    [RaisesException, MeasureAs=AudioContextDecodeAudioData, CallWith=ScriptState] Promise<AudioBuffer> decodeAudioData(ArrayBuffer audioData, optional DecodeSuccessCallback successCallback, optional DecodeErrorCallback  errorCallback);
 
     // Sources
     [RaisesException, MeasureAs=AudioContextCreateBufferSource] AudioBufferSourceNode createBufferSource();
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
index a509517..89531ff 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -453,7 +453,7 @@
       }
       break;
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return false;
   }
   return true;
@@ -4525,7 +4525,7 @@
       return WebGLAny(script_state, bool_result);
     }
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return ScriptValue::CreateNull(script_state);
   }
 }
@@ -5098,7 +5098,7 @@
       bound_uniform_buffer_ = buffer;
       break;
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       break;
   }
 
@@ -5168,7 +5168,7 @@
       }
       break;
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       break;
   }
 
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index a77833a8..b1115150 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -1545,7 +1545,7 @@
     // succeed because cases where canvas()-buffer() is not accelerated are
     // handle before reaching this point.  If that assumption ever stops holding
     // true, we may need to implement a fallback right here.
-    ASSERT_NOT_REACHED();
+    NOTREACHED();
     return false;
   }
 
@@ -1711,7 +1711,7 @@
       bound_vertex_array_object_->SetElementArrayBuffer(buffer);
       break;
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return false;
   }
 
@@ -3799,7 +3799,7 @@
           return WebGLAny(script_state, DOMUint32Array::Create(uint_value, 4));
         }
         default:
-          ASSERT_NOT_REACHED();
+          NOTREACHED();
           break;
       }
       return ScriptValue::CreateNull(script_state);
@@ -7067,7 +7067,7 @@
                         "ArrayBufferView is not NULL");
       return false;
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
   }
 
   unsigned total_bytes_required, skip_bytes;
diff --git a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
index a2ee4c8..5079e42 100644
--- a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
@@ -65,7 +65,7 @@
     case UsbTransferStatus::SHORT_PACKET:
       return nullptr;
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return nullptr;
   }
 }
@@ -80,7 +80,7 @@
     case UsbTransferStatus::BABBLE:
       return "babble";
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return "";
   }
 }
@@ -660,7 +660,7 @@
 
   switch (error) {
     case UsbOpenDeviceError::ALREADY_OPEN:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
     // fall through
     case UsbOpenDeviceError::OK:
       OnDeviceOpenedOrClosed(true /* opened */);
diff --git a/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp b/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp
index 81f7a50d..3f63ecd 100644
--- a/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp
@@ -23,7 +23,7 @@
     case UsbTransferDirection::OUTBOUND:
       return "out";
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return "";
   }
 }
@@ -37,7 +37,7 @@
     case UsbTransferType::ISOCHRONOUS:
       return "isochronous";
     default:
-      ASSERT_NOT_REACHED();
+      NOTREACHED();
       return "";
   }
 }
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
index bb1a4cc..99379a0 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -525,35 +525,15 @@
   }
 }
 
-namespace {
-
-class UnacceleratedSurfaceFactory
-    : public RecordingImageBufferFallbackSurfaceFactory {
- public:
-  virtual std::unique_ptr<ImageBufferSurface> CreateSurface(
-      const IntSize& size,
-      OpacityMode opacity_mode,
-      const CanvasColorParams& color_params) {
-    return WTF::WrapUnique(new UnacceleratedImageBufferSurface(
-        size, opacity_mode, kInitializeImagePixels, color_params));
-  }
-
-  virtual ~UnacceleratedSurfaceFactory() {}
-};
-
-}  // namespace
-
 void ImageBuffer::DisableAcceleration() {
   if (!IsAccelerated())
     return;
 
   // Create and configure a recording (unaccelerated) surface.
-  std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory> surface_factory =
-      WTF::MakeUnique<UnacceleratedSurfaceFactory>();
   std::unique_ptr<ImageBufferSurface> surface =
       WTF::WrapUnique(new RecordingImageBufferSurface(
-          surface_->size(), std::move(surface_factory),
-          surface_->GetOpacityMode(), surface_->color_params()));
+          surface_->size(), surface_->GetOpacityMode(),
+          surface_->color_params()));
   SetSurface(std::move(surface));
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
index 9e849684..0d87eec 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
@@ -228,7 +228,7 @@
   pass->SetNew(kRenderPassId, bounds, bounds, gfx::Transform());
 
   cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
-  sqs->SetAll(gfx::Transform(), bounds.size(), bounds, bounds, false, 1.f,
+  sqs->SetAll(gfx::Transform(), bounds, bounds, bounds, false, 1.f,
               SkBlendMode::kSrcOver, 0);
 
   cc::TransferableResource resource;
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
index 4b0bb49..11f0991e 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
@@ -5,11 +5,13 @@
 #include "platform/graphics/RecordingImageBufferSurface.h"
 
 #include <memory>
+
 #include "platform/Histogram.h"
 #include "platform/graphics/CanvasMetrics.h"
 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h"
 #include "platform/graphics/GraphicsContext.h"
 #include "platform/graphics/ImageBuffer.h"
+#include "platform/graphics/UnacceleratedImageBufferSurface.h"
 #include "platform/graphics/paint/PaintRecorder.h"
 #include "platform/wtf/PassRefPtr.h"
 #include "platform/wtf/PtrUtil.h"
@@ -18,8 +20,6 @@
 
 RecordingImageBufferSurface::RecordingImageBufferSurface(
     const IntSize& size,
-    std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory>
-        fallback_factory,
     OpacityMode opacity_mode,
     const CanvasColorParams& color_params)
     : ImageBufferSurface(size, opacity_mode, color_params),
@@ -29,8 +29,7 @@
       frame_was_cleared_(true),
       did_record_draw_commands_in_current_frame_(false),
       current_frame_has_expensive_op_(false),
-      previous_frame_has_expensive_op_(false),
-      fallback_factory_(std::move(fallback_factory)) {
+      previous_frame_has_expensive_op_(false) {
   InitializeCurrentFrame();
 }
 
@@ -68,10 +67,9 @@
                                               int x,
                                               int y) {
   if (!fallback_surface_) {
-    if (x <= 0 && y <= 0 && x + orig_info.width() >= size().Width() &&
-        y + orig_info.height() >= size().Height()) {
+    IntRect write_rect(x, y, orig_info.width(), orig_info.height());
+    if (write_rect.Contains(IntRect(IntPoint(), size())))
       WillOverwriteCanvas();
-    }
     FallBackToRasterCanvas(kFallbackReasonWritePixels);
   }
   return fallback_surface_->WritePixels(orig_info, pixels, row_bytes, x, y);
@@ -79,7 +77,6 @@
 
 void RecordingImageBufferSurface::FallBackToRasterCanvas(
     FallbackReason reason) {
-  DCHECK(fallback_factory_);
   CHECK(reason != kFallbackReasonUnknown);
 
   if (fallback_surface_) {
@@ -93,8 +90,8 @@
                                kFallbackReasonCount));
   canvas_fallback_histogram.Count(reason);
 
-  fallback_surface_ = fallback_factory_->CreateSurface(size(), GetOpacityMode(),
-                                                       color_params());
+  fallback_surface_ = WTF::WrapUnique(new UnacceleratedImageBufferSurface(
+      size(), GetOpacityMode(), kInitializeImagePixels, color_params()));
   fallback_surface_->SetImageBuffer(image_buffer_);
 
   if (previous_frame_) {
@@ -230,8 +227,6 @@
   FallbackReason fallback_reason = kFallbackReasonUnknown;
   bool can_use_record = FinalizeFrameInternal(&fallback_reason);
 
-  DCHECK(can_use_record || fallback_factory_);
-
   if (can_use_record) {
     return previous_frame_;
   }
@@ -320,9 +315,8 @@
     return false;
   }
 
-  if (fallback_factory_ &&
-      current_frame_->getRecordingCanvas()->getSaveCount() - 1 >
-          ExpensiveCanvasHeuristicParameters::kExpensiveRecordingStackDepth) {
+  if (current_frame_->getRecordingCanvas()->getSaveCount() - 1 >
+      ExpensiveCanvasHeuristicParameters::kExpensiveRecordingStackDepth) {
     // (getSaveCount() decremented to account  for the intial recording canvas
     // save frame.)
     *fallback_reason = kFallbackReasonRunawayStateStack;
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.h b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.h
index a0b8f493..8ed5756c8 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.h
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.h
@@ -16,20 +16,7 @@
 namespace blink {
 
 class ImageBuffer;
-class RecordingImageBufferSurfaceTest;
-
-class RecordingImageBufferFallbackSurfaceFactory {
-  USING_FAST_MALLOC(RecordingImageBufferFallbackSurfaceFactory);
-  WTF_MAKE_NONCOPYABLE(RecordingImageBufferFallbackSurfaceFactory);
-
- public:
-  virtual std::unique_ptr<ImageBufferSurface>
-  CreateSurface(const IntSize&, OpacityMode, const CanvasColorParams&) = 0;
-  virtual ~RecordingImageBufferFallbackSurfaceFactory() {}
-
- protected:
-  RecordingImageBufferFallbackSurfaceFactory() {}
-};
+class UnacceleratedImageBufferSurface;
 
 class PLATFORM_EXPORT RecordingImageBufferSurface : public ImageBufferSurface {
   WTF_MAKE_NONCOPYABLE(RecordingImageBufferSurface);
@@ -42,8 +29,6 @@
   // Only #getRecord should be used to access the resulting frame.
   RecordingImageBufferSurface(
       const IntSize&,
-      std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory>
-          fallback_factory = nullptr,
       OpacityMode = kNonOpaque,
       const CanvasColorParams& = CanvasColorParams());
   ~RecordingImageBufferSurface() override;
@@ -116,7 +101,6 @@
   };
 
  private:
-  friend class RecordingImageBufferSurfaceTest;  // for unit testing
   void FallBackToRasterCanvas(FallbackReason);
   void InitializeCurrentFrame();
   bool FinalizeFrameInternal(FallbackReason*);
@@ -124,7 +108,7 @@
 
   std::unique_ptr<PaintRecorder> current_frame_;
   sk_sp<PaintRecord> previous_frame_;
-  std::unique_ptr<ImageBufferSurface> fallback_surface_;
+  std::unique_ptr<UnacceleratedImageBufferSurface> fallback_surface_;
   ImageBuffer* image_buffer_;
   int initial_save_count_;
   int current_frame_pixel_count_;
@@ -133,7 +117,6 @@
   bool did_record_draw_commands_in_current_frame_;
   bool current_frame_has_expensive_op_;
   bool previous_frame_has_expensive_op_;
-  std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory> fallback_factory_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
index b37d903..e4d44dc 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
@@ -25,60 +25,23 @@
 
 namespace blink {
 
-class MockSurfaceFactory : public RecordingImageBufferFallbackSurfaceFactory {
- public:
-  MockSurfaceFactory() : create_surface_count_(0) {}
-
-  virtual std::unique_ptr<ImageBufferSurface> CreateSurface(
-      const IntSize& size,
-      OpacityMode opacity_mode,
-      const CanvasColorParams& color_params) {
-    create_surface_count_++;
-    return WTF::WrapUnique(new UnacceleratedImageBufferSurface(
-        size, opacity_mode, kInitializeImagePixels, color_params));
-  }
-
-  virtual ~MockSurfaceFactory() {}
-
-  int CreateSurfaceCount() { return create_surface_count_; }
-
- private:
-  int create_surface_count_;
-};
-
 class RecordingImageBufferSurfaceTest : public Test {
  protected:
   RecordingImageBufferSurfaceTest() {
-    std::unique_ptr<MockSurfaceFactory> surface_factory =
-        WTF::MakeUnique<MockSurfaceFactory>();
-    surface_factory_ = surface_factory.get();
-    std::unique_ptr<RecordingImageBufferSurface> test_surface =
-        WTF::WrapUnique(new RecordingImageBufferSurface(
-            IntSize(10, 10), std::move(surface_factory), kNonOpaque));
+    auto test_surface = WTF::MakeUnique<RecordingImageBufferSurface>(
+        IntSize(10, 10), kNonOpaque);
     test_surface_ = test_surface.get();
-    // We create an ImageBuffer in order for the testSurface to be
+    // We create an ImageBuffer in order for the |test_surface| to be
     // properly initialized with a GraphicsContext
     image_buffer_ = ImageBuffer::Create(std::move(test_surface));
-    EXPECT_FALSE(!image_buffer_);
-    test_surface_->InitializeCurrentFrame();
+    EXPECT_TRUE(image_buffer_);
   }
 
  public:
   RecordingImageBufferSurface* TestSurface() { return test_surface_; }
-  int CreateSurfaceCount() { return surface_factory_->CreateSurfaceCount(); }
   PaintCanvas* Canvas() { return image_buffer_->Canvas(); }
 
-  void ExpectDisplayListEnabled(bool display_list_enabled) {
-    EXPECT_EQ(display_list_enabled, (bool)test_surface_->current_frame_.get());
-    EXPECT_EQ(!display_list_enabled,
-              (bool)test_surface_->fallback_surface_.get());
-    int expected_surface_creation_count = display_list_enabled ? 0 : 1;
-    EXPECT_EQ(expected_surface_creation_count,
-              surface_factory_->CreateSurfaceCount());
-  }
-
  private:
-  MockSurfaceFactory* surface_factory_;
   RecordingImageBufferSurface* test_surface_;
   std::unique_ptr<ImageBuffer> image_buffer_;
 };
@@ -86,13 +49,13 @@
 TEST_F(RecordingImageBufferSurfaceTest, testEmptyPicture) {
   sk_sp<PaintRecord> record = TestSurface()->GetRecord();
   EXPECT_TRUE(record.get());
-  ExpectDisplayListEnabled(true);
+  EXPECT_TRUE(TestSurface()->IsRecording());
 }
 
 TEST_F(RecordingImageBufferSurfaceTest, testNoFallbackWithClear) {
   TestSurface()->WillOverwriteCanvas();
   TestSurface()->GetRecord();
-  ExpectDisplayListEnabled(true);
+  EXPECT_TRUE(TestSurface()->IsRecording());
 }
 
 TEST_F(RecordingImageBufferSurfaceTest, testNonAnimatedCanvasUpdate) {
@@ -101,17 +64,16 @@
   TestSurface()->DidDraw(FloatRect(0, 0, 1, 1));
   TestSurface()->GetRecord();
   TestSurface()->GetRecord();
-  ExpectDisplayListEnabled(true);
+  EXPECT_TRUE(TestSurface()->IsRecording());
 }
 
 TEST_F(RecordingImageBufferSurfaceTest, testAnimatedWithoutClear) {
   TestSurface()->DidDraw(FloatRect(0, 0, 1, 1));
   TestSurface()->GetRecord();
-  EXPECT_EQ(0, CreateSurfaceCount());
-  ExpectDisplayListEnabled(true);  // first frame has an implicit clear
+  EXPECT_TRUE(TestSurface()->IsRecording());
   TestSurface()->DidDraw(FloatRect(0, 0, 1, 1));
   TestSurface()->GetRecord();
-  ExpectDisplayListEnabled(false);
+  EXPECT_FALSE(TestSurface()->IsRecording());
 }
 
 TEST_F(RecordingImageBufferSurfaceTest, testAnimatedWithClear) {
@@ -119,12 +81,12 @@
   TestSurface()->WillOverwriteCanvas();
   TestSurface()->DidDraw(FloatRect(0, 0, 1, 1));
   TestSurface()->GetRecord();
-  ExpectDisplayListEnabled(true);
-  // clear after use
+  EXPECT_TRUE(TestSurface()->IsRecording());
+  // Clear after use.
   TestSurface()->DidDraw(FloatRect(0, 0, 1, 1));
   TestSurface()->WillOverwriteCanvas();
   TestSurface()->GetRecord();
-  ExpectDisplayListEnabled(true);
+  EXPECT_TRUE(TestSurface()->IsRecording());
 }
 
 TEST_F(RecordingImageBufferSurfaceTest, testClearRect) {
@@ -136,7 +98,7 @@
                      clear_flags);
   TestSurface()->DidDraw(FloatRect(0, 0, 1, 1));
   TestSurface()->GetRecord();
-  ExpectDisplayListEnabled(true);
+  EXPECT_TRUE(TestSurface()->IsRecording());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.cpp b/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.cpp
index 2d46343..8c013b0 100644
--- a/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.cpp
+++ b/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.cpp
@@ -21,4 +21,8 @@
   return WebSize(0, 0);
 }
 
+WebString EmptyWebMediaPlayer::GetErrorMessage() const {
+  return WebString();
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.h b/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.h
index 5055b812..bbf9c32 100644
--- a/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.h
+++ b/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.h
@@ -37,7 +37,7 @@
   double CurrentTime() const override { return 0.0; }
   NetworkState GetNetworkState() const override { return kNetworkStateEmpty; }
   ReadyState GetReadyState() const override { return kReadyStateHaveNothing; }
-  WebString GetErrorMessage() override { return WebString(); }
+  WebString GetErrorMessage() const override;
   bool DidLoadingProgress() override { return false; }
   bool HasSingleSecurityOrigin() const override { return true; }
   bool DidPassCORSAccessCheck() const override { return true; }
diff --git a/third_party/WebKit/public/platform/WebMediaPlayer.h b/third_party/WebKit/public/platform/WebMediaPlayer.h
index 4f17e2e..a637b93 100644
--- a/third_party/WebKit/public/platform/WebMediaPlayer.h
+++ b/third_party/WebKit/public/platform/WebMediaPlayer.h
@@ -159,7 +159,12 @@
   virtual NetworkState GetNetworkState() const = 0;
   virtual ReadyState GetReadyState() const = 0;
 
-  virtual WebString GetErrorMessage() = 0;
+  // Returns an implementation-specific human readable error message, or an
+  // empty string if no message is available. The message should begin with a
+  // UA-specific-error-code (without any ':'), optionally followed by ': ' and
+  // further description of the error.
+  virtual WebString GetErrorMessage() const = 0;
+
   virtual bool DidLoadingProgress() = 0;
 
   virtual bool HasSingleSecurityOrigin() const = 0;
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js
index 0ce3d29..d5a52e2 100644
--- a/third_party/closure_compiler/externs/automation.js
+++ b/third_party/closure_compiler/externs/automation.js
@@ -723,27 +723,48 @@
 chrome.automation.AutomationNode.prototype.setSize;
 
 /**
- * The number of rows in this table.
+ * The number of rows in this table as specified in the DOM.
  * @type {(number|undefined)}
  * @see https://developer.chrome.com/extensions/automation#type-tableRowCount
  */
 chrome.automation.AutomationNode.prototype.tableRowCount;
 
 /**
- * The number of columns in this table.
+ * The number of rows in this table as specified by the page author.
+ * @type {(number|undefined)}
+ * @see https://developer.chrome.com/extensions/automation#type-ariaRowCount
+ */
+chrome.automation.AutomationNode.prototype.ariaRowCount;
+
+/**
+ * The number of columns in this table as specified in the DOM.
  * @type {(number|undefined)}
  * @see https://developer.chrome.com/extensions/automation#type-tableColumnCount
  */
 chrome.automation.AutomationNode.prototype.tableColumnCount;
 
 /**
- * The zero-based index of the column that this cell is in.
+ * The number of columns in this table as specified by the page author.
+ * @type {(number|undefined)}
+ * @see https://developer.chrome.com/extensions/automation#type-ariaColumnCount
+ */
+chrome.automation.AutomationNode.prototype.ariaColumnCount;
+
+/**
+ * The zero-based index of the column that this cell is in as specified in the DOM.
  * @type {(number|undefined)}
  * @see https://developer.chrome.com/extensions/automation#type-tableCellColumnIndex
  */
 chrome.automation.AutomationNode.prototype.tableCellColumnIndex;
 
 /**
+ * The ARIA column index as specified by the page author.
+ * @type {(number|undefined)}
+ * @see https://developer.chrome.com/extensions/automation#type-ariaCellColumnIndex
+ */
+chrome.automation.AutomationNode.prototype.ariaCellColumnIndex;
+
+/**
  * The number of columns that this cell spans (default is 1).
  * @type {(number|undefined)}
  * @see https://developer.chrome.com/extensions/automation#type-tableCellColumnSpan
@@ -751,13 +772,20 @@
 chrome.automation.AutomationNode.prototype.tableCellColumnSpan;
 
 /**
- * The zero-based index of the row that this cell is in.
+ * The zero-based index of the row that this cell is in as specified in the DOM.
  * @type {(number|undefined)}
  * @see https://developer.chrome.com/extensions/automation#type-tableCellRowIndex
  */
 chrome.automation.AutomationNode.prototype.tableCellRowIndex;
 
 /**
+ * The ARIA row index as specified by the page author.
+ * @type {(number|undefined)}
+ * @see https://developer.chrome.com/extensions/automation#type-ariaCellRowIndex
+ */
+chrome.automation.AutomationNode.prototype.ariaCellRowIndex;
+
+/**
  * The number of rows that this cell spans (default is 1).
  * @type {(number|undefined)}
  * @see https://developer.chrome.com/extensions/automation#type-tableCellRowSpan
diff --git a/third_party/flatbuffers/OWNERS b/third_party/flatbuffers/OWNERS
index 3bf39c13..94966f0 100644
--- a/third_party/flatbuffers/OWNERS
+++ b/third_party/flatbuffers/OWNERS
@@ -1,2 +1,3 @@
 battre@chromium.org
+csharrison@chromium.org
 engedy@chromium.org
diff --git a/tools/chrome_proxy/webdriver/decorator_smoke.py b/tools/chrome_proxy/webdriver/decorator_smoke.py
index bf2f82f..0441798c 100644
--- a/tools/chrome_proxy/webdriver/decorator_smoke.py
+++ b/tools/chrome_proxy/webdriver/decorator_smoke.py
@@ -3,6 +3,8 @@
 # found in the LICENSE file.
 
 from decorators import AndroidOnly
+from decorators import ChromeVersionAfterM
+from decorators import ChromeVersionBeforeM
 from common import ParseFlags
 from common import IntegrationTest
 
@@ -19,6 +21,15 @@
     if not ParseFlags().android:
       self.AndroidOnlyFunction()
 
+  @ChromeVersionBeforeM(0)
+  def testVersionBeforeDecorator(self):
+    self.fail('This function should not be called when the Chrome Milestone is '
+      'greater than 0')
+
+  @ChromeVersionAfterM(999999999)
+  def testVersionAfterDecorator(self):
+    self.fail('This function should not be called when the Chrome Milestone is '
+      'less than 999999999')
 
 if __name__ == '__main__':
   IntegrationTest.RunAllTests()
diff --git a/tools/chrome_proxy/webdriver/decorators.py b/tools/chrome_proxy/webdriver/decorators.py
index 5da3650..c04055f 100644
--- a/tools/chrome_proxy/webdriver/decorators.py
+++ b/tools/chrome_proxy/webdriver/decorators.py
@@ -2,7 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import re
+
 from common import ParseFlags
+from common import TestDriver
 
 
 # Platform-specific decorators.
@@ -72,3 +75,45 @@
     else:
       args[0].skipTest('This test does not run on Mac OS.')
   return wrapper
+
+chrome_version = None
+
+def GetChromeVersion():
+  with TestDriver() as t:
+    t.LoadURL('http://check.googlezip.net/connect')
+    ua = t.ExecuteJavascriptStatement('navigator.userAgent')
+    match = re.search('Chrome/[0-9\.]+', ua)
+    if not match:
+      raise Exception('Could not find Chrome version in User-Agent: %s' % ua)
+    chrome_version = ua[match.start():match.end()]
+    version = chrome_version[chrome_version.find('/') + 1:]
+    version_split = version.split('.')
+    milestone = int(version_split[0])
+    print 'Running on Chrome M%d (%s)' % (milestone, version)
+    return milestone
+
+def ChromeVersionBeforeM(milestone):
+  def puesdo_wrapper(func):
+    def wrapper(*args, **kwargs):
+      global chrome_version
+      if chrome_version == None:
+        chrome_version = GetChromeVersion()
+      if chrome_version < milestone:
+        func(*args, **kwargs)
+      else:
+        args[0].skipTest('This test does not run above M%d.' % milestone)
+    return wrapper
+  return puesdo_wrapper
+
+def ChromeVersionAfterM(milestone):
+  def puesdo_wrapper(func):
+    def wrapper(*args, **kwargs):
+      global chrome_version
+      if chrome_version == None:
+        chrome_version = GetChromeVersion()
+      if chrome_version >= milestone:
+        func(*args, **kwargs)
+      else:
+        args[0].skipTest('This test does not run below M%d.' % milestone)
+    return wrapper
+  return puesdo_wrapper
diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl
index ca638d2..cae796e 100644
--- a/ui/accessibility/ax_enums.idl
+++ b/ui/accessibility/ax_enums.idl
@@ -365,10 +365,10 @@
     text_sel_end,
 
     // aria_col* and aria_row* attributes
-    aria_col_count,
-    aria_col_index,
+    aria_column_count,
+    aria_cell_column_index,
     aria_row_count,
-    aria_row_index,
+    aria_cell_row_index,
 
     // Table attributes.
     table_row_count,
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index c150dee..0debb01 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -110,10 +110,10 @@
     case AX_ATTR_CHECKED_STATE:
     case AX_ATTR_TEXT_DIRECTION:
     case AX_ATTR_TEXT_STYLE:
-    case AX_ATTR_ARIA_COL_COUNT:
-    case AX_ATTR_ARIA_COL_INDEX:
+    case AX_ATTR_ARIA_COLUMN_COUNT:
+    case AX_ATTR_ARIA_CELL_COLUMN_INDEX:
     case AX_ATTR_ARIA_ROW_COUNT:
-    case AX_ATTR_ARIA_ROW_INDEX:
+    case AX_ATTR_ARIA_CELL_ROW_INDEX:
       return false;
   }
 
@@ -524,17 +524,17 @@
       case AX_ATTR_TEXT_SEL_END:
         result += " sel_end=" + value;
         break;
-      case AX_ATTR_ARIA_COL_COUNT:
-        result += " aria_col_count=" + value;
+      case AX_ATTR_ARIA_COLUMN_COUNT:
+        result += " aria_column_count=" + value;
         break;
-      case AX_ATTR_ARIA_COL_INDEX:
-        result += " aria_col_index=" + value;
+      case AX_ATTR_ARIA_CELL_COLUMN_INDEX:
+        result += " aria_cell_column_index=" + value;
         break;
       case AX_ATTR_ARIA_ROW_COUNT:
         result += " aria_row_count=" + value;
         break;
-      case AX_ATTR_ARIA_ROW_INDEX:
-        result += " aria_row_index=" + value;
+      case AX_ATTR_ARIA_CELL_ROW_INDEX:
+        result += " aria_cell_row_index=" + value;
         break;
       case AX_ATTR_TABLE_ROW_COUNT:
         result += " rows=" + value;
diff --git a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
index c955cb23..01920a8 100644
--- a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
+++ b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
@@ -82,7 +82,7 @@
 }  // namespace
 
 DrmGpuPlatformSupportHost::DrmGpuPlatformSupportHost(DrmCursor* cursor)
-    : cursor_(cursor) {}
+    : cursor_(cursor), weak_ptr_factory_(this) {}
 
 DrmGpuPlatformSupportHost::~DrmGpuPlatformSupportHost() {}
 
@@ -105,31 +105,23 @@
 
 void DrmGpuPlatformSupportHost::OnGpuProcessLaunched(
     int host_id,
+    scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
     scoped_refptr<base::SingleThreadTaskRunner> send_runner,
     const base::Callback<void(IPC::Message*)>& send_callback) {
+  DCHECK(!ui_runner->BelongsToCurrentThread());
+  ui_runner_ = std::move(ui_runner);
   TRACE_EVENT1("drm", "DrmGpuPlatformSupportHost::OnGpuProcessLaunched",
                "host_id", host_id);
   host_id_ = host_id;
-  send_runner_ = send_runner;
+  send_runner_ = std::move(send_runner);
   send_callback_ = send_callback;
 
   for (GpuThreadObserver& observer : gpu_thread_observers_)
     observer.OnGpuProcessLaunched();
-}
 
-void DrmGpuPlatformSupportHost::OnChannelEstablished() {
-  TRACE_EVENT0("drm", "DrmGpuPlatformSupportHost::OnChannelEstablished");
-  channel_established_ = true;
-
-  for (GpuThreadObserver& observer : gpu_thread_observers_)
-    observer.OnGpuThreadReady();
-
-  // The cursor is special since it will process input events on the IO thread
-  // and can by-pass the UI thread. This means that we need to special case it
-  // and notify it after all other observers/handlers are notified such that the
-  // (windowing) state on the GPU can be initialized before the cursor is
-  // allowed to IPC messages (which are targeted to a specific window).
-  cursor_->SetDrmCursorProxy(new CursorIPC(send_runner_, send_callback_));
+  ui_runner_->PostTask(
+      FROM_HERE, base::Bind(&DrmGpuPlatformSupportHost::OnChannelEstablished,
+                            weak_ptr_factory_.GetWeakPtr()));
 }
 
 void DrmGpuPlatformSupportHost::OnChannelDestroyed(int host_id) {
@@ -176,6 +168,21 @@
   display_manager_ = nullptr;
 }
 
+void DrmGpuPlatformSupportHost::OnChannelEstablished() {
+  TRACE_EVENT0("drm", "DrmGpuPlatformSupportHost::OnChannelEstablished");
+  channel_established_ = true;
+
+  for (GpuThreadObserver& observer : gpu_thread_observers_)
+    observer.OnGpuThreadReady();
+
+  // The cursor is special since it will process input events on the IO thread
+  // and can by-pass the UI thread. This means that we need to special case it
+  // and notify it after all other observers/handlers are notified such that the
+  // (windowing) state on the GPU can be initialized before the cursor is
+  // allowed to IPC messages (which are targeted to a specific window).
+  cursor_->SetDrmCursorProxy(new CursorIPC(send_runner_, send_callback_));
+}
+
 bool DrmGpuPlatformSupportHost::OnMessageReceivedForDrmDisplayHostManager(
     const IPC::Message& message) {
   bool handled = true;
diff --git a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
index f446d32b..37f7e45 100644
--- a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
+++ b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
@@ -30,15 +30,15 @@
                                   public GpuThreadAdapter,
                                   public IPC::Sender {
  public:
-  DrmGpuPlatformSupportHost(DrmCursor* cursor);
+  explicit DrmGpuPlatformSupportHost(DrmCursor* cursor);
   ~DrmGpuPlatformSupportHost() override;
 
   // GpuPlatformSupportHost:
   void OnGpuProcessLaunched(
       int host_id,
+      scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
       scoped_refptr<base::SingleThreadTaskRunner> send_runner,
       const base::Callback<void(IPC::Message*)>& send_callback) override;
-  void OnChannelEstablished() override;
   void OnChannelDestroyed(int host_id) override;
 
   // IPC::Listener:
@@ -95,6 +95,7 @@
                               const gfx::Rect& bounds) override;
 
  private:
+  void OnChannelEstablished();
   bool OnMessageReceivedForDrmDisplayHostManager(const IPC::Message& message);
   void OnUpdateNativeDisplays(
       const std::vector<DisplaySnapshot_Params>& displays);
@@ -113,6 +114,7 @@
   int host_id_ = -1;
   bool channel_established_ = false;
 
+  scoped_refptr<base::SingleThreadTaskRunner> ui_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> send_runner_;
   base::Callback<void(IPC::Message*)> send_callback_;
 
@@ -121,6 +123,9 @@
 
   DrmCursor* cursor_;                              // Not owned.
   base::ObserverList<GpuThreadObserver> gpu_thread_observers_;
+
+  base::WeakPtrFactory<DrmGpuPlatformSupportHost> weak_ptr_factory_;
+  DISALLOW_COPY_AND_ASSIGN(DrmGpuPlatformSupportHost);
 };
 
 }  // namespace ui
diff --git a/ui/ozone/public/gpu_platform_support_host.cc b/ui/ozone/public/gpu_platform_support_host.cc
index 5130301..a79c7b6a 100644
--- a/ui/ozone/public/gpu_platform_support_host.cc
+++ b/ui/ozone/public/gpu_platform_support_host.cc
@@ -17,11 +17,10 @@
   // GpuPlatformSupportHost:
   void OnGpuProcessLaunched(
       int host_id,
+      scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
       scoped_refptr<base::SingleThreadTaskRunner> send_runner,
       const base::Callback<void(IPC::Message*)>& send_callback) override {}
 
-  void OnChannelEstablished() override {}
-
   void OnChannelDestroyed(int host_id) override {}
   bool OnMessageReceived(const IPC::Message&) override { return false; }
 };
diff --git a/ui/ozone/public/gpu_platform_support_host.h b/ui/ozone/public/gpu_platform_support_host.h
index 6a1ef22..3fad9645 100644
--- a/ui/ozone/public/gpu_platform_support_host.h
+++ b/ui/ozone/public/gpu_platform_support_host.h
@@ -31,13 +31,10 @@
   // This is called from browser IO thread.
   virtual void OnGpuProcessLaunched(
       int host_id,
+      scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
       scoped_refptr<base::SingleThreadTaskRunner> send_runner,
       const base::Callback<void(IPC::Message*)>& sender) = 0;
 
-  // Called when the channel is established.
-  // This is called from browser UI thread.
-  virtual void OnChannelEstablished() = 0;
-
   // Called when the GPU process is destroyed.
   // This is called from browser UI thread.
   virtual void OnChannelDestroyed(int host_id) = 0;
diff --git a/ui/ozone/public/ozone_gpu_test_helper.cc b/ui/ozone/public/ozone_gpu_test_helper.cc
index a08b088..55fc4b4 100644
--- a/ui/ozone/public/ozone_gpu_test_helper.cc
+++ b/ui/ozone/public/ozone_gpu_test_helper.cc
@@ -84,13 +84,8 @@
 
     ui::OzonePlatform::GetInstance()
         ->GetGpuPlatformSupportHost()
-        ->OnGpuProcessLaunched(kGpuProcessHostId, gpu_io_task_runner_, sender);
-  }
-
-  void InitOnUI() {
-    ui::OzonePlatform::GetInstance()
-        ->GetGpuPlatformSupportHost()
-        ->OnChannelEstablished();
+        ->OnGpuProcessLaunched(kGpuProcessHostId, gpu_task_runner_,
+                               gpu_io_task_runner_, sender);
   }
 
  private:
@@ -124,7 +119,6 @@
                             base::Unretained(fake_gpu_process_host_.get())));
   io_helper_thread_->FlushForTesting();
 
-  fake_gpu_process_host_->InitOnUI();
   return true;
 }
 
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 7c3d7bbf..0332daf1 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -28,13 +28,6 @@
     "submenu_arrow.1x.icon",
     "submenu_arrow.icon",
   ]
-
-  if (is_mac) {
-    icons += [
-      "combobox_arrow_mac_enabled.icon",
-      "combobox_arrow_mac_disabled.icon",
-    ]
-  }
 }
 
 component("views") {
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index 24c5170..99d0253 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -452,7 +452,8 @@
     SetPaintToLayer();
     layer()->SetFillsBoundsOpaquely(false);
   } else {
-    arrow_image_ = PlatformStyle::CreateComboboxArrow(enabled(), style);
+    arrow_image_ = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+        IDR_MENU_DROPARROW);
   }
 }
 
@@ -550,12 +551,6 @@
   arrow_button_->SetBounds(arrow_button_x, 0, arrow_button_width, height());
 }
 
-void Combobox::OnEnabledChanged() {
-  View::OnEnabledChanged();
-  if (!UseMd())
-    arrow_image_ = PlatformStyle::CreateComboboxArrow(enabled(), style_);
-}
-
 void Combobox::OnNativeThemeChanged(const ui::NativeTheme* theme) {
   if (!UseMd())
     return;
@@ -1013,9 +1008,9 @@
 }
 
 int Combobox::GetArrowContainerWidth() const {
-  const int kMdPaddingWidth = 8;
-  int arrow_pad = UseMd() ? kMdPaddingWidth
-                          : PlatformStyle::kComboboxNormalArrowPadding;
+  constexpr int kMdPaddingWidth = 8;
+  constexpr int kNormalPaddingWidth = 7;
+  int arrow_pad = UseMd() ? kMdPaddingWidth : kNormalPaddingWidth;
   int padding = style_ == STYLE_NORMAL
                     ? arrow_pad * 2
                     : kActionLeftPadding + kActionRightPadding;
diff --git a/ui/views/controls/combobox/combobox.h b/ui/views/controls/combobox/combobox.h
index c06ddb9a..62ee4b9 100644
--- a/ui/views/controls/combobox/combobox.h
+++ b/ui/views/controls/combobox/combobox.h
@@ -101,7 +101,6 @@
   void OnBlur() override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void Layout() override;
-  void OnEnabledChanged() override;
   void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
 
   // Overridden from PrefixDelegate:
diff --git a/ui/views/style/platform_style.cc b/ui/views/style/platform_style.cc
index ca86255..bf6d767 100644
--- a/ui/views/style/platform_style.cc
+++ b/ui/views/style/platform_style.cc
@@ -36,7 +36,6 @@
 
 #if !defined(OS_MACOSX)
 
-const int PlatformStyle::kComboboxNormalArrowPadding = 7;
 const int PlatformStyle::kMinLabelButtonWidth = 70;
 const int PlatformStyle::kMinLabelButtonHeight = 33;
 const bool PlatformStyle::kDefaultLabelButtonHasBoldFont = true;
@@ -54,13 +53,6 @@
 const bool PlatformStyle::kMirrorBubbleArrowInRTLByDefault = true;
 
 // static
-gfx::ImageSkia PlatformStyle::CreateComboboxArrow(bool is_enabled,
-                                                  Combobox::Style style) {
-  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-  return *rb.GetImageSkiaNamed(IDR_MENU_DROPARROW);
-}
-
-// static
 std::unique_ptr<ScrollBar> PlatformStyle::CreateScrollBar(bool is_horizontal) {
 #if defined(OS_CHROMEOS)
   return base::MakeUnique<OverlayScrollBar>(is_horizontal);
diff --git a/ui/views/style/platform_style.h b/ui/views/style/platform_style.h
index 876dba5..ce39689 100644
--- a/ui/views/style/platform_style.h
+++ b/ui/views/style/platform_style.h
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/custom_button.h"
-#include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/views_export.h"
 
 namespace views {
@@ -26,10 +25,6 @@
   // Type used by LabelButton to map button states to text colors.
   using ButtonColorByState = SkColor[Button::STATE_COUNT];
 
-  // Padding to use on either side of the arrow for a Combobox when in
-  // Combobox::STYLE_NORMAL.
-  static const int kComboboxNormalArrowPadding;
-
   // Minimum size for platform-styled buttons (Button::STYLE_BUTTON).
   static const int kMinLabelButtonWidth;
   static const int kMinLabelButtonHeight;
@@ -71,13 +66,6 @@
   // opens in the opposite direction.
   static const bool kMirrorBubbleArrowInRTLByDefault;
 
-  // Creates an ImageSkia containing the image to use for the combobox arrow.
-  // The |is_enabled| argument is true if the control the arrow is for is
-  // enabled, and false if the control is disabled. The |style| argument is the
-  // style of the combobox the arrow is being drawn for.
-  static gfx::ImageSkia CreateComboboxArrow(bool is_enabled,
-                                            Combobox::Style style);
-
   // Creates the default scrollbar for the given orientation.
   static std::unique_ptr<ScrollBar> CreateScrollBar(bool is_horizontal);
 
diff --git a/ui/views/style/platform_style_mac.mm b/ui/views/style/platform_style_mac.mm
index 7ee1380..e18282bc 100644
--- a/ui/views/style/platform_style_mac.mm
+++ b/ui/views/style/platform_style_mac.mm
@@ -5,20 +5,15 @@
 #include "ui/views/style/platform_style.h"
 
 #include "base/memory/ptr_util.h"
-#include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_features.h"
 #include "ui/gfx/color_utils.h"
-#include "ui/gfx/paint_vector_icon.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/controls/button/label_button.h"
 #import "ui/views/controls/scrollbar/cocoa_scroll_bar.h"
-#include "ui/views/vector_icons.h"
 
 #import <Cocoa/Cocoa.h>
 
 namespace views {
 
-const int PlatformStyle::kComboboxNormalArrowPadding = 0;
 const int PlatformStyle::kMinLabelButtonWidth = 32;
 const int PlatformStyle::kMinLabelButtonHeight = 30;
 const bool PlatformStyle::kDefaultLabelButtonHasBoldFont = false;
@@ -46,21 +41,6 @@
 const bool PlatformStyle::kReturnClicksFocusedControl = false;
 
 // static
-gfx::ImageSkia PlatformStyle::CreateComboboxArrow(bool is_enabled,
-                                                  Combobox::Style style) {
-  // TODO(ellyjones): IDR_MENU_DROPARROW is a cross-platform image that doesn't
-  // look right on Mac. See https://crbug.com/384071.
-  if (style == Combobox::STYLE_ACTION) {
-    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-    return *rb.GetImageSkiaNamed(IDR_MENU_DROPARROW);
-  }
-  const int kComboboxArrowWidth = 24;
-  return gfx::CreateVectorIcon(
-      is_enabled ? kComboboxArrowMacEnabledIcon : kComboboxArrowMacDisabledIcon,
-      kComboboxArrowWidth, SK_ColorBLACK);
-}
-
-// static
 std::unique_ptr<ScrollBar> PlatformStyle::CreateScrollBar(bool is_horizontal) {
   return base::MakeUnique<CocoaScrollBar>(is_horizontal);
 }
diff --git a/ui/views/vector_icons/combobox_arrow_mac_disabled.icon b/ui/views/vector_icons/combobox_arrow_mac_disabled.icon
deleted file mode 100644
index f074091..0000000
--- a/ui/views/vector_icons/combobox_arrow_mac_disabled.icon
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 30,
-
-// Disabled arrows are a single stroke, the same weight as the lightest stroke
-// on enabled arrows, in flat grey.
-STROKE, 2,
-PATH_COLOR_ARGB, 0x7f, 0x21, 0x21, 0x21,
-MOVE_TO, 11, 12,
-LINE_TO, 15, 8,
-LINE_TO, 19, 12,
-MOVE_TO, 11, 18,
-LINE_TO, 15, 22,
-LINE_TO, 19, 18,
-END
diff --git a/ui/views/vector_icons/combobox_arrow_mac_enabled.icon b/ui/views/vector_icons/combobox_arrow_mac_enabled.icon
deleted file mode 100644
index cf4519e..0000000
--- a/ui/views/vector_icons/combobox_arrow_mac_enabled.icon
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 30,
-
-// The outer layer of the arrows is drawn in transparent-ish solid blue.
-STROKE, 3.5,
-PATH_COLOR_ARGB, 0x40, 0x00, 0x00, 0xff,
-MOVE_TO, 11, 12,
-LINE_TO, 15, 8,
-LINE_TO, 19, 12,
-MOVE_TO, 11, 18,
-LINE_TO, 15, 22,
-LINE_TO, 19, 18,
-
-// The inner layer is a narrower stroke of solid white.
-NEW_PATH,
-STROKE, 2,
-PATH_COLOR_ARGB, 0xff, 0xff, 0xff, 0xff,
-MOVE_TO, 11, 12,
-LINE_TO, 15, 8,
-LINE_TO, 19, 12,
-MOVE_TO, 11, 18,
-LINE_TO, 15, 22,
-LINE_TO, 19, 18,
-END