diff --git a/DEPS b/DEPS
index 37c93de..9f01522d8 100644
--- a/DEPS
+++ b/DEPS
@@ -145,11 +145,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': '4da34bf74723a55b0549f6fae960748a7685e64e',
+  'skia_revision': '6e86c1b05eeedc3b6be0e98001b7b5d6bab71b74',
   # 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': '11c60ffe95375a400b5465b615f1157901dc197a',
+  'v8_revision': '781babd0c9ef5d62a23b0a54ed64586c3236db6c',
   # 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.
@@ -157,7 +157,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '2613cdba80a3aca0f131b55af3c41cc62a43a31c',
+  'angle_revision': '8b2dfa0fc657d64903849421f7aa0885f39a0eb0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -165,7 +165,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'e858d1fb244dff2855ad86d30b5bc510371d896c',
+  'pdfium_revision': '12bc1c4dae87f210dc1b379d658a7f329c74d469',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -208,7 +208,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'e73fe02a406e7951c59fe328f63b29fb885d5d6d',
+  'catapult_revision': '2568b37b25f5447322a1f9943ddc35aa78522d97',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -280,7 +280,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '7b57c5bb770fb233cea6a4b6c70b54c4d98e71df',
+  'dawn_revision': '35ad5221fb556c7aa80961d42537e4d9c825bf49',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -809,7 +809,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '1157607f2f5497c37515fcd8b9a18f8cea9065e4',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '019109290b69be57b47b2e0cde3db2499d16edf5',
       'condition': 'checkout_linux',
   },
 
@@ -1207,7 +1207,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '968d1d819bc0146de28db8de796c98bf9d2a621f',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '6ce7935230e8bcd8e4da9f8ffd68df2e6fc581c0',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1416,7 +1416,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@42f9ab2813ad4a1515bbf7ec22c4dca3f678b61b',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b63730a701a417073edd4645d0330bf1c31cd5df',
     'condition': 'checkout_src_internal',
   },
 
@@ -2388,7 +2388,7 @@
     # Update the Mac toolchain if necessary.
     'name': 'mac_toolchain',
     'pattern': '.',
-    'condition': 'checkout_ios or checkout_mac',
+    'condition': 'checkout_mac',
     'action': ['python', 'src/build/mac_toolchain.py'],
   },
   # Pull binutils for linux, enabled debug fission for faster linking /
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index 1ba368a..fd51a2b 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -578,6 +578,8 @@
     "browser/js_java_interaction/js_api_handler_factory.h",
     "browser/js_java_interaction/js_java_configurator_host.cc",
     "browser/js_java_interaction/js_java_configurator_host.h",
+    "browser/memory_metrics_logger.cc",
+    "browser/memory_metrics_logger.h",
     "browser/net/android_stream_reader_url_request_job.cc",
     "browser/net/android_stream_reader_url_request_job.h",
     "browser/net/aw_cookie_change_dispatcher_wrapper.cc",
@@ -771,6 +773,8 @@
     "//net:extras",
     "//printing",
     "//services/preferences/tracked:tracked",
+    "//services/resource_coordinator/public/cpp/memory_instrumentation",
+    "//services/resource_coordinator/public/cpp/memory_instrumentation:browser",
     "//services/service_manager/public/cpp",
     "//storage/browser",
     "//storage/common",
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS
index 76c1634..f314dcca 100644
--- a/android_webview/browser/DEPS
+++ b/android_webview/browser/DEPS
@@ -58,6 +58,7 @@
   "+printing",
 
   "+services/network/public",
+  "+services/resource_coordinator/public/cpp",
   "+services/service_manager/public/cpp",
 
   # network service related unit tests
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index c665268..ed4a615e 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -20,7 +20,6 @@
 #include "android_webview/browser/aw_resource_context.h"
 #include "android_webview/browser/aw_web_ui_controller_factory.h"
 #include "android_webview/browser/cookie_manager.h"
-#include "android_webview/browser/net/aw_url_request_context_getter.h"
 #include "android_webview/browser/network_service/net_helpers.h"
 #include "android_webview/browser/safe_browsing/aw_safe_browsing_whitelist_manager.h"
 #include "base/base_paths_posix.h"
@@ -239,12 +238,6 @@
 void AwBrowserContext::PreMainMessageLoopRun() {
   CreateUserPrefService();
 
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    // TODO(amalova): Create a new instance for non-default profiles.
-    url_request_context_getter_ =
-        AwBrowserProcess::GetInstance()->GetAwURLRequestContext();
-  }
-
   scoped_refptr<base::SequencedTaskRunner> db_task_runner =
       base::CreateSequencedTaskRunnerWithTraits(
           {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
@@ -365,26 +358,6 @@
   return nullptr;
 }
 
-net::URLRequestContextGetter* AwBrowserContext::CreateRequestContext(
-    content::ProtocolHandlerMap* protocol_handlers,
-    content::URLRequestInterceptorScopedVector request_interceptors) {
-  DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
-  // This function cannot actually create the request context because
-  // there is a reentrant dependency on GetResourceContext() via
-  // content::StoragePartitionImplMap::Create(). This is not fixable
-  // until http://crbug.com/159193. Until then, assert that the context
-  // has already been allocated and just handle setting the protocol_handlers.
-  DCHECK(url_request_context_getter_);
-  url_request_context_getter_->SetHandlersAndInterceptors(
-      protocol_handlers, std::move(request_interceptors));
-  return url_request_context_getter_.get();
-}
-
-net::URLRequestContextGetter* AwBrowserContext::CreateMediaRequestContext() {
-  DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
-  return AwBrowserProcess::GetInstance()->GetAwURLRequestContext();
-}
-
 download::InProgressDownloadManager*
 AwBrowserContext::RetriveInProgressDownloadManager() {
   return new download::InProgressDownloadManager(
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h
index eb4e1937..6094df6 100644
--- a/android_webview/browser/aw_browser_context.h
+++ b/android_webview/browser/aw_browser_context.h
@@ -49,7 +49,6 @@
 
 class AwFormDatabaseService;
 class AwQuotaManagerBridge;
-class AwURLRequestContextGetter;
 
 class AwBrowserContext : public content::BrowserContext,
                          public visitedlink::VisitedLinkDelegate {
@@ -102,10 +101,6 @@
   content::BackgroundSyncController* GetBackgroundSyncController() override;
   content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
       override;
-  net::URLRequestContextGetter* CreateRequestContext(
-      content::ProtocolHandlerMap* protocol_handlers,
-      content::URLRequestInterceptorScopedVector request_interceptors) override;
-  net::URLRequestContextGetter* CreateMediaRequestContext() override;
   download::InProgressDownloadManager* RetriveInProgressDownloadManager()
       override;
 
@@ -127,7 +122,6 @@
   // The file path where data for this context is persisted.
   base::FilePath context_storage_path_;
 
-  scoped_refptr<AwURLRequestContextGetter> url_request_context_getter_;
   scoped_refptr<AwQuotaManagerBridge> quota_manager_bridge_;
   std::unique_ptr<AwFormDatabaseService> form_database_service_;
   std::unique_ptr<autofill::AutocompleteHistoryManager>
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index 5fda767..eef4a67 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -13,6 +13,7 @@
 #include "android_webview/browser/aw_browser_terminator.h"
 #include "android_webview/browser/aw_content_browser_client.h"
 #include "android_webview/browser/aw_metrics_service_client.h"
+#include "android_webview/browser/memory_metrics_logger.h"
 #include "android_webview/browser/net/aw_network_change_notifier_factory.h"
 #include "android_webview/common/aw_descriptors.h"
 #include "android_webview/common/aw_paths.h"
@@ -123,6 +124,7 @@
   AwBrowserContext* context = browser_client_->InitBrowserContext();
   context->PreMainMessageLoopRun();
   content::RenderFrameHost::AllowInjectingJavaScript();
+  metrics_logger_ = std::make_unique<MemoryMetricsLogger>();
 }
 
 bool AwBrowserMainParts::MainMessageLoopRun(int* result_code) {
diff --git a/android_webview/browser/aw_browser_main_parts.h b/android_webview/browser/aw_browser_main_parts.h
index f170dcac..e3bbc92 100644
--- a/android_webview/browser/aw_browser_main_parts.h
+++ b/android_webview/browser/aw_browser_main_parts.h
@@ -15,8 +15,9 @@
 
 namespace android_webview {
 
-class AwContentBrowserClient;
 class AwBrowserProcess;
+class AwContentBrowserClient;
+class MemoryMetricsLogger;
 
 class AwBrowserMainParts : public content::BrowserMainParts {
  public:
@@ -36,6 +37,8 @@
 
   AwContentBrowserClient* browser_client_;
 
+  std::unique_ptr<MemoryMetricsLogger> metrics_logger_;
+
   std::unique_ptr<AwBrowserProcess> browser_process_;
 
   DISALLOW_COPY_AND_ASSIGN(AwBrowserMainParts);
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
index 0709c658..bd1e1f3 100644
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -24,7 +24,7 @@
 #include "android_webview/browser/gfx/aw_picture.h"
 #include "android_webview/browser/gfx/browser_view_renderer.h"
 #include "android_webview/browser/gfx/child_frame.h"
-#include "android_webview/browser/gfx/deferred_gpu_command_service.h"
+#include "android_webview/browser/gfx/gpu_service_web_view.h"
 #include "android_webview/browser/gfx/java_browser_view_renderer_helper.h"
 #include "android_webview/browser/gfx/render_thread_manager.h"
 #include "android_webview/browser/gfx/scoped_app_gl_state_restore.h"
@@ -415,8 +415,9 @@
   // Make sure GPUInfo is collected. This will initialize GL bindings,
   // collect GPUInfo, and compute GpuFeatureInfo if they have not been
   // already done.
-  return DeferredGpuCommandService::GetInstance()
-      ->CanSupportThreadedTextureMailbox();
+  return GpuServiceWebView::GetInstance()
+      ->gpu_info()
+      .can_support_threaded_texture_mailbox;
 }
 
 static void JNI_AwContents_SetAwDrawSWFunctionTable(JNIEnv* env,
diff --git a/android_webview/browser/gfx/deferred_gpu_command_service.cc b/android_webview/browser/gfx/deferred_gpu_command_service.cc
index 61290137..ccdeecf 100644
--- a/android_webview/browser/gfx/deferred_gpu_command_service.cc
+++ b/android_webview/browser/gfx/deferred_gpu_command_service.cc
@@ -4,19 +4,9 @@
 
 #include "android_webview/browser/gfx/deferred_gpu_command_service.h"
 
-#include "android_webview/browser/gfx/render_thread_manager.h"
+#include "android_webview/browser/gfx/gpu_service_web_view.h"
 #include "android_webview/browser/gfx/task_forwarding_sequence.h"
 #include "android_webview/browser/gfx/task_queue_web_view.h"
-#include "base/no_destructor.h"
-#include "base/strings/string_number_conversions.h"
-#include "content/public/browser/gpu_data_manager.h"
-#include "content/public/browser/gpu_utils.h"
-#include "content/public/common/content_switches.h"
-#include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/mailbox_manager_factory.h"
-#include "gpu/command_buffer/service/sync_point_manager.h"
-#include "gpu/config/gpu_info.h"
-#include "gpu/config/gpu_util.h"
 #include "ui/gl/gl_share_group.h"
 
 namespace android_webview {
@@ -80,8 +70,4 @@
   return false;
 }
 
-bool DeferredGpuCommandService::CanSupportThreadedTextureMailbox() const {
-  return gpu_info().can_support_threaded_texture_mailbox;
-}
-
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/deferred_gpu_command_service.h b/android_webview/browser/gfx/deferred_gpu_command_service.h
index 1c12480..4188cc09 100644
--- a/android_webview/browser/gfx/deferred_gpu_command_service.h
+++ b/android_webview/browser/gfx/deferred_gpu_command_service.h
@@ -5,23 +5,13 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_GFX_DEFERRED_GPU_COMMAND_SERVICE_H_
 #define ANDROID_WEBVIEW_BROWSER_GFX_DEFERRED_GPU_COMMAND_SERVICE_H_
 
-#include <stddef.h>
-
-#include <memory>
-#include <utility>
-
-#include "android_webview/browser/gfx/gpu_service_web_view.h"
-#include "base/lazy_instance.h"
 #include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "base/threading/thread_local.h"
-#include "base/time/time.h"
-#include "gpu/config/gpu_info.h"
 #include "gpu/ipc/command_buffer_task_executor.h"
 
 namespace android_webview {
+
+class GpuServiceWebView;
 class TaskQueueWebView;
-class ScopedAllowGL;
 
 // Implementation for gpu service objects accessor for command buffer WebView.
 class DeferredGpuCommandService : public gpu::CommandBufferTaskExecutor {
@@ -36,15 +26,10 @@
   void ScheduleDelayedWork(base::OnceClosure task) override;
   void PostNonNestableToClient(base::OnceClosure callback) override;
 
-  const gpu::GPUInfo& gpu_info() const { return gpu_service_->gpu_info(); }
-
-  bool CanSupportThreadedTextureMailbox() const;
-
  protected:
   ~DeferredGpuCommandService() override;
 
  private:
-  friend class ScopedAllowGL;
   friend class TaskForwardingSequence;
 
   DeferredGpuCommandService(TaskQueueWebView* task_queue,
diff --git a/android_webview/browser/gfx/render_thread_manager.cc b/android_webview/browser/gfx/render_thread_manager.cc
index 51d45571..64e884f4 100644
--- a/android_webview/browser/gfx/render_thread_manager.cc
+++ b/android_webview/browser/gfx/render_thread_manager.cc
@@ -8,7 +8,7 @@
 
 #include "android_webview/browser/gfx/compositor_frame_producer.h"
 #include "android_webview/browser/gfx/compositor_id.h"
-#include "android_webview/browser/gfx/deferred_gpu_command_service.h"
+#include "android_webview/browser/gfx/gpu_service_web_view.h"
 #include "android_webview/browser/gfx/scoped_app_gl_state_restore.h"
 #include "android_webview/browser/gfx/task_queue_web_view.h"
 #include "android_webview/public/browser/draw_gl.h"
@@ -186,8 +186,7 @@
 void RenderThreadManager::DrawOnRT(bool save_restore,
                                    HardwareRendererDrawParams* params) {
   // Force GL binding init if it's not yet initialized.
-  // TODO(crbug.com/987265): Clean up usage of DeferredGpuCommandService.
-  DeferredGpuCommandService::GetInstance();
+  GpuServiceWebView::GetInstance();
   ScopedAppGLStateRestore state_restore(ScopedAppGLStateRestore::MODE_DRAW,
                                         save_restore);
   ScopedAllowGL allow_gl;
@@ -202,7 +201,7 @@
 }
 
 void RenderThreadManager::DestroyHardwareRendererOnRT(bool save_restore) {
-  DeferredGpuCommandService::GetInstance();
+  GpuServiceWebView::GetInstance();
   ScopedAppGLStateRestore state_restore(
       ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT, save_restore);
   ScopedAllowGL allow_gl;
diff --git a/android_webview/browser/memory_metrics_logger.cc b/android_webview/browser/memory_metrics_logger.cc
new file mode 100644
index 0000000..ef1ec918
--- /dev/null
+++ b/android_webview/browser/memory_metrics_logger.cc
@@ -0,0 +1,143 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/browser/memory_metrics_logger.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
+
+using memory_instrumentation::GetPrivateFootprintHistogramName;
+using memory_instrumentation::HistogramProcessType;
+
+namespace android_webview {
+namespace {
+
+MemoryMetricsLogger* g_instance = nullptr;
+
+// Called once the metrics have been determined. Does the actual logging.
+void RecordMemoryMetricsImpl(
+    MemoryMetricsLogger::RecordCallback done_callback,
+    bool success,
+    std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump) {
+  if (!success) {
+    if (done_callback)
+      std::move(done_callback).Run(false);
+    return;
+  }
+
+  for (const auto& process_dump : dump->process_dumps()) {
+    switch (process_dump.process_type()) {
+      case memory_instrumentation::mojom::ProcessType::BROWSER: {
+        MEMORY_METRICS_HISTOGRAM_MB(
+            GetPrivateFootprintHistogramName(HistogramProcessType::kBrowser),
+            process_dump.os_dump().private_footprint_kb / 1024);
+        break;
+      }
+      case memory_instrumentation::mojom::ProcessType::RENDERER: {
+        // On the desktop this may be attributed to an 'extension', but as
+        // android doesn't support extensions there is no checking.
+        MEMORY_METRICS_HISTOGRAM_MB(
+            GetPrivateFootprintHistogramName(HistogramProcessType::kRenderer),
+            process_dump.os_dump().private_footprint_kb / 1024);
+        break;
+      }
+
+      // WebView only supports the browser and possibly renderer process.
+      case memory_instrumentation::mojom::ProcessType::GPU:
+        FALLTHROUGH;
+      case memory_instrumentation::mojom::ProcessType::ARC:
+        FALLTHROUGH;
+      case memory_instrumentation::mojom::ProcessType::UTILITY:
+        FALLTHROUGH;
+      case memory_instrumentation::mojom::ProcessType::PLUGIN:
+        FALLTHROUGH;
+      case memory_instrumentation::mojom::ProcessType::OTHER:
+        NOTREACHED();
+        break;
+    }
+  }
+  if (done_callback)
+    std::move(done_callback).Run(true);
+}
+
+}  // namespace
+
+// State is used to trigger logging to stop. State is accessed on both the main
+// thread and the background task runner.
+struct MemoryMetricsLogger::State : public base::RefCountedThreadSafe<State> {
+  State() = default;
+
+  // MemoryInstrumentation requires a SequencedTaskRunner.
+  scoped_refptr<base::SequencedTaskRunner> task_runner;
+
+  bool stop_logging = false;
+
+ private:
+  friend class base::RefCountedThreadSafe<State>;
+
+  ~State() = default;
+
+  DISALLOW_COPY_AND_ASSIGN(State);
+};
+
+MemoryMetricsLogger::MemoryMetricsLogger()
+    : state_(base::MakeRefCounted<State>()) {
+  g_instance = this;
+  state_->task_runner = base::CreateSequencedTaskRunner({base::ThreadPool()});
+  state_->task_runner->PostTask(
+      FROM_HERE,
+      base::BindOnce(&MemoryMetricsLogger::RecordMemoryMetricsAfterDelay,
+                     state_));
+}
+
+MemoryMetricsLogger::~MemoryMetricsLogger() {
+  g_instance = nullptr;
+  state_->stop_logging = true;
+}
+
+// static
+MemoryMetricsLogger* MemoryMetricsLogger::GetInstanceForTesting() {
+  return g_instance;
+}
+
+void MemoryMetricsLogger::ScheduleRecordForTesting(
+    RecordCallback done_callback) {
+  state_->task_runner->PostTask(
+      FROM_HERE, base::BindOnce(&MemoryMetricsLogger::RecordMemoryMetrics,
+                                state_, std::move(done_callback)));
+}
+
+// static
+void MemoryMetricsLogger::RecordMemoryMetricsAfterDelay(
+    scoped_refptr<State> state) {
+  if (state->stop_logging)
+    return;
+
+  state->task_runner->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&MemoryMetricsLogger::RecordMemoryMetrics, state,
+                     RecordCallback()),
+      memory_instrumentation::GetDelayForNextMemoryLog());
+}
+
+// static
+void MemoryMetricsLogger::RecordMemoryMetrics(scoped_refptr<State> state,
+                                              RecordCallback done_callback) {
+  memory_instrumentation::MemoryInstrumentation::GetInstance()
+      ->RequestGlobalDump({}, base::BindOnce(&RecordMemoryMetricsImpl,
+                                             std::move(done_callback)));
+  RecordMemoryMetricsAfterDelay(state);
+}
+
+}  // namespace android_webview
diff --git a/android_webview/browser/memory_metrics_logger.h b/android_webview/browser/memory_metrics_logger.h
new file mode 100644
index 0000000..33cf80a
--- /dev/null
+++ b/android_webview/browser/memory_metrics_logger.h
@@ -0,0 +1,59 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_MEMORY_METRICS_LOGGER_H_
+#define ANDROID_WEBVIEW_BROWSER_MEMORY_METRICS_LOGGER_H_
+
+#include <jni.h>
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+
+namespace android_webview {
+
+// MemoryMetricsLogger is responsible for logging the memory related heartbeat
+// metrics. MemoryMetricsLogger logs metrics at certain intervals for as long
+// as it exists.
+//
+// MemoryMetricsLogger does the logging on a background task runner and stops
+// logging once MemoryMetricsLogger is destroyed.
+class MemoryMetricsLogger {
+ public:
+  using RecordCallback = base::OnceCallback<void(bool)>;
+  MemoryMetricsLogger();
+  ~MemoryMetricsLogger();
+
+ private:
+  struct State;
+
+  friend jboolean JNI_MemoryMetricsLoggerTest_ForceRecordHistograms(
+      JNIEnv* env);
+
+  // Returns the single instance, if one was created.
+  static MemoryMetricsLogger* GetInstanceForTesting();
+
+  // Schedules recording metrics. Runs |done_callback| when done with the
+  // result of recording metrics. |done_callback| is run on a background
+  // TaskRunner.
+  void ScheduleRecordForTesting(RecordCallback done_callback);
+
+  // Called on the task runner to record metrics after a delay.
+  static void RecordMemoryMetricsAfterDelay(scoped_refptr<State> state);
+
+  // Requests the memory related metrics and calls
+  // RecordMemoryMetricsAfterDelay() to schedule another logging call. Runs
+  // |done_callback| when done.
+  static void RecordMemoryMetrics(scoped_refptr<State> state,
+                                  RecordCallback done_callback);
+
+  scoped_refptr<State> state_;
+
+  DISALLOW_COPY_AND_ASSIGN(MemoryMetricsLogger);
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_MEMORY_METRICS_LOGGER_H_
diff --git a/android_webview/browser/network_service/android_stream_reader_url_loader.cc b/android_webview/browser/network_service/android_stream_reader_url_loader.cc
index bb4595b2..56fdfe6 100644
--- a/android_webview/browser/network_service/android_stream_reader_url_loader.cc
+++ b/android_webview/browser/network_service/android_stream_reader_url_loader.cc
@@ -116,7 +116,6 @@
     const std::vector<std::string>& removed_headers,
     const net::HttpRequestHeaders& modified_headers,
     const base::Optional<GURL>& new_url) {}
-void AndroidStreamReaderURLLoader::ProceedWithResponse() {}
 void AndroidStreamReaderURLLoader::SetPriority(net::RequestPriority priority,
                                                int intra_priority_value) {}
 void AndroidStreamReaderURLLoader::PauseReadingBodyFromNet() {}
diff --git a/android_webview/browser/network_service/android_stream_reader_url_loader.h b/android_webview/browser/network_service/android_stream_reader_url_loader.h
index 285a921b..7796315 100644
--- a/android_webview/browser/network_service/android_stream_reader_url_loader.h
+++ b/android_webview/browser/network_service/android_stream_reader_url_loader.h
@@ -70,7 +70,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
index 1208e87..ce4de09d 100644
--- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
+++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
@@ -75,7 +75,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
@@ -588,11 +587,6 @@
   Restart();
 }
 
-void InterceptedRequest::ProceedWithResponse() {
-  if (target_loader_)
-    target_loader_->ProceedWithResponse();
-}
-
 void InterceptedRequest::SetPriority(net::RequestPriority priority,
                                      int32_t intra_priority_value) {
   if (target_loader_)
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java
new file mode 100644
index 0000000..c7ade0c
--- /dev/null
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java
@@ -0,0 +1,77 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview.test;
+
+import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.MULTI_PROCESS;
+import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.SINGLE_PROCESS;
+
+import android.support.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.base.test.util.Feature;
+
+/**
+ * Tests for memory_metrics_logger.cc.
+ */
+@JNINamespace("android_webview")
+@RunWith(AwJUnit4ClassRunner.class)
+public class MemoryMetricsLoggerTest {
+    @Rule
+    public AwActivityTestRule mActivityTestRule = new AwActivityTestRule();
+
+    @Before
+    public void setUp() throws Exception {
+        TestAwContentsClient contentsClient = new TestAwContentsClient();
+        AwTestContainerView testContainerView =
+                mActivityTestRule.createAwTestContainerViewOnMainSync(contentsClient);
+
+        mActivityTestRule.loadUrlSync(testContainerView.getAwContents(),
+                contentsClient.getOnPageFinishedHelper(), "about:blank");
+        Assert.assertTrue(nativeForceRecordHistograms());
+    }
+
+    @After
+    public void tearDown() throws Exception {}
+
+    @Test
+    @Feature({"AndroidWebView"})
+    @OnlyRunIn(MULTI_PROCESS)
+    @SmallTest
+    public void testMultiProcessHistograms() throws Throwable {
+        Assert.assertNotEquals(0,
+                RecordHistogram.getHistogramTotalCountForTesting(
+                        "Memory.Browser.PrivateMemoryFootprint"));
+        Assert.assertNotEquals(0,
+                RecordHistogram.getHistogramTotalCountForTesting(
+                        "Memory.Renderer.PrivateMemoryFootprint"));
+    }
+
+    @Test
+    @Feature({"AndroidWebView"})
+    @OnlyRunIn(SINGLE_PROCESS)
+    @SmallTest
+    public void testSingleProcessHistograms() throws Throwable {
+        Assert.assertNotEquals(0,
+                RecordHistogram.getHistogramTotalCountForTesting(
+                        "Memory.Browser.PrivateMemoryFootprint"));
+        Assert.assertEquals(0,
+                RecordHistogram.getHistogramTotalCountForTesting(
+                        "Memory.Renderer.PrivateMemoryFootprint"));
+    }
+
+    /**
+     * Calls to MemoryMetricsLogger to force recording histograms, returning true on success.
+     * A value of false means recording failed (most likely because process metrics not available.
+     */
+    public static native boolean nativeForceRecordHistograms();
+}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/memory_metrics_logger_test.cc b/android_webview/javatests/src/org/chromium/android_webview/test/memory_metrics_logger_test.cc
new file mode 100644
index 0000000..2ccd315
--- /dev/null
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/memory_metrics_logger_test.cc
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/test/webview_instrumentation_test_native_jni/MemoryMetricsLoggerTest_jni.h"
+
+#include "android_webview/browser/memory_metrics_logger.h"
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/test/test_timeouts.h"
+
+namespace android_webview {
+
+// static
+jboolean JNI_MemoryMetricsLoggerTest_ForceRecordHistograms(JNIEnv* env) {
+  auto* memory_metrics_logger = MemoryMetricsLogger::GetInstanceForTesting();
+  if (!memory_metrics_logger)
+    return false;
+
+  TestTimeouts::Initialize();
+  base::test::ScopedTaskEnvironment scoped_task_environment(
+      base::test::ScopedTaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY);
+  base::RunLoop run_loop;
+  bool result = false;
+  memory_metrics_logger->ScheduleRecordForTesting(
+      base::BindLambdaForTesting([&](bool success) {
+        result = success;
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+  return result;
+}
+
+}  // namespace android_webview
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index 9eadcdd..ec08ecbd 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -9,7 +9,7 @@
 #include "android_webview/browser/aw_content_browser_client.h"
 #include "android_webview/browser/aw_media_url_interceptor.h"
 #include "android_webview/browser/gfx/browser_view_renderer.h"
-#include "android_webview/browser/gfx/deferred_gpu_command_service.h"
+#include "android_webview/browser/gfx/gpu_service_web_view.h"
 #include "android_webview/browser/scoped_add_feature_flags.h"
 #include "android_webview/browser/tracing/aw_trace_event_args_whitelist.h"
 #include "android_webview/common/aw_descriptors.h"
@@ -316,16 +316,16 @@
 
 namespace {
 gpu::SyncPointManager* GetSyncPointManager() {
-  DCHECK(DeferredGpuCommandService::GetInstance());
-  return DeferredGpuCommandService::GetInstance()->sync_point_manager();
+  DCHECK(GpuServiceWebView::GetInstance());
+  return GpuServiceWebView::GetInstance()->sync_point_manager();
 }
 gpu::SharedImageManager* GetSharedImageManager() {
-  DCHECK(DeferredGpuCommandService::GetInstance());
+  DCHECK(GpuServiceWebView::GetInstance());
   const bool enable_shared_image =
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kWebViewEnableSharedImage);
   return enable_shared_image
-             ? DeferredGpuCommandService::GetInstance()->shared_image_manager()
+             ? GpuServiceWebView::GetInstance()->shared_image_manager()
              : nullptr;
 }
 }  // namespace
diff --git a/android_webview/lib/webview_tests.cc b/android_webview/lib/webview_tests.cc
index 6f5ff39..a424702 100644
--- a/android_webview/lib/webview_tests.cc
+++ b/android_webview/lib/webview_tests.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 "android_webview/browser/gfx/deferred_gpu_command_service.h"
+#include "android_webview/browser/gfx/gpu_service_web_view.h"
 #include "base/command_line.h"
 #include "base/test/test_suite.h"
 #include "content/public/common/content_switches.h"
@@ -13,6 +13,6 @@
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kSingleProcess);
   gl::GLSurfaceTestSupport::InitializeNoExtensionsOneOff();
-  android_webview::DeferredGpuCommandService::GetInstance();
+  android_webview::GpuServiceWebView::GetInstance();
   return base::TestSuite(argc, argv).Run();
 }
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index f2f31b73..ad1f461 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -138,6 +138,7 @@
   ]
   ldflags = [ "-Wl,-shared,-Bsymbolic" ]
   deps = [
+    ":webview_instrumentation_test_native_jni_impl",
     "//android_webview:common",
     "//base",
     "//components/heap_profiling:test_support",
@@ -250,6 +251,7 @@
     "../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/MemoryMetricsLoggerTest.java",
     "../javatests/src/org/chromium/android_webview/test/NavigationHistoryTest.java",
     "../javatests/src/org/chromium/android_webview/test/OnDiskFileTest.java",
     "../javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java",
@@ -320,6 +322,25 @@
   ]
 }
 
+generate_jni("webview_instrumentation_test_native_jni") {
+  sources = [
+    "../javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java",
+  ]
+}
+
+source_set("webview_instrumentation_test_native_jni_impl") {
+  sources = [
+    "../javatests/src/org/chromium/android_webview/test/memory_metrics_logger_test.cc",
+  ]
+
+  deps = [
+    ":webview_instrumentation_test_native_jni",
+    "//android_webview:common",
+    "//base",
+    "//base/test:test_support",
+  ]
+}
+
 test("android_webview_unittests") {
   deps = [
     ":android_webview_unittests_assets",
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index d6f4e35..7bba7cb 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1541,8 +1541,11 @@
     "//chromeos/constants",
     "//chromeos/dbus/biod",
     "//chromeos/dbus/power",
+    "//chromeos/dbus/shill",
+    "//chromeos/network",
+    "//chromeos/services/network_config",
     "//chromeos/services/network_config/public/cpp:manifest",
-    "//chromeos/services/network_config/public/cpp:test_support",
+    "//chromeos/services/network_config/public/mojom",
     "//chromeos/system",
     "//components/discardable_memory/public/mojom",
     "//components/services/font:lib",
diff --git a/ash/shell.cc b/ash/shell.cc
index ffeb9c6..9650ac53 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -595,6 +595,9 @@
   for (auto& observer : shell_observers_)
     observer.OnShellDestroying();
 
+  if (features::IsVirtualDesksEnabled())
+    desks_controller_->Shutdown();
+
   // Wayland depends upon some ash specific objects. Destroy it early on.
   wayland_server_controller_.reset();
 
diff --git a/ash/shell/content/client/DEPS b/ash/shell/content/client/DEPS
index 3eaa3d08..fe45514 100644
--- a/ash/shell/content/client/DEPS
+++ b/ash/shell/content/client/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+ash/components/shortcut_viewer",
   "+chromeos/dbus/biod",
+  "+chromeos/services/network_config",
   "+components/discardable_memory/public/interfaces",
   "+content/public",
   "+content/shell",
diff --git a/ash/shell/content/client/shell_browser_main_parts.cc b/ash/shell/content/client/shell_browser_main_parts.cc
index e9fadae5..fbcc7ec 100644
--- a/ash/shell/content/client/shell_browser_main_parts.cc
+++ b/ash/shell/content/client/shell_browser_main_parts.cc
@@ -27,7 +27,10 @@
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "chromeos/dbus/biod/biod_client.h"
-#include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
+#include "chromeos/dbus/shill/shill_clients.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/services/network_config/cros_network_config.h"
+#include "chromeos/services/network_config/public/mojom/constants.mojom.h"
 #include "components/exo/file_helper.h"
 #include "content/public/browser/context_factory.h"
 #include "content/public/browser/system_connector.h"
@@ -65,6 +68,12 @@
   main_parts = nullptr;
 }
 
+void ShellBrowserMainParts::PostEarlyInitialization() {
+  content::BrowserMainParts::PostEarlyInitialization();
+  chromeos::shill_clients::InitializeFakes();
+  chromeos::NetworkHandler::Initialize();
+}
+
 void ShellBrowserMainParts::PreMainMessageLoopStart() {}
 
 void ShellBrowserMainParts::PostMainMessageLoopStart() {
@@ -79,10 +88,10 @@
 void ShellBrowserMainParts::PreMainMessageLoopRun() {
   browser_context_.reset(new content::ShellBrowserContext(false));
 
+  // CrosNetworkConfig is required for the system tray UI.
+  InitializeCrosNetworkConfig();
+
   ash_test_helper_ = std::make_unique<AshTestHelper>();
-  network_config_helper_ =
-      std::make_unique<chromeos::network_config::CrosNetworkConfigTestHelper>(
-          content::GetSystemConnector());
 
   AshTestHelper::InitParams init_params;
   // TODO(oshima): Separate the class for ash_shell to reduce the test binary
@@ -139,25 +148,6 @@
   }
 }
 
-void ShellBrowserMainParts::PostMainMessageLoopRun() {
-  window_watcher_.reset();
-  example_app_list_client_.reset();
-  example_session_controller_client_.reset();
-
-  ash_test_helper_->TearDown();
-  ash_test_helper_.reset();
-
-  views_delegate_.reset();
-
-  network_config_helper_.reset();
-
-  // The keyboard may have created a WebContents. The WebContents is destroyed
-  // with the UI, and it needs the BrowserContext to be alive during its
-  // destruction. So destroy all of the UI elements before destroying the
-  // browser context.
-  browser_context_.reset();
-}
-
 bool ShellBrowserMainParts::MainMessageLoopRun(int* result_code) {
   if (parameters_.ui_task) {
     parameters_.ui_task->Run();
@@ -171,5 +161,53 @@
   return true;
 }
 
+void ShellBrowserMainParts::PostMainMessageLoopRun() {
+  window_watcher_.reset();
+  example_app_list_client_.reset();
+  example_session_controller_client_.reset();
+
+  ash_test_helper_->TearDown();
+  ash_test_helper_.reset();
+
+  views_delegate_.reset();
+
+  cros_network_config_.reset();
+
+  // The keyboard may have created a WebContents. The WebContents is destroyed
+  // with the UI, and it needs the BrowserContext to be alive during its
+  // destruction. So destroy all of the UI elements before destroying the
+  // browser context.
+  browser_context_.reset();
+}
+
+void ShellBrowserMainParts::PostDestroyThreads() {
+  chromeos::NetworkHandler::Shutdown();
+  chromeos::shill_clients::Shutdown();
+  content::BrowserMainParts::PostDestroyThreads();
+}
+
+void ShellBrowserMainParts::InitializeCrosNetworkConfig() {
+  chromeos::NetworkHandler* network_handler = chromeos::NetworkHandler::Get();
+  cros_network_config_ =
+      std::make_unique<chromeos::network_config::CrosNetworkConfig>(
+          network_handler->network_state_handler(),
+          network_handler->network_device_handler(),
+          network_handler->managed_network_configuration_handler());
+  // Use a test override for the mojo binding.
+  content::GetSystemConnector()->OverrideBinderForTesting(
+      service_manager::ServiceFilter::ByName(
+          chromeos::network_config::mojom::kServiceName),
+      chromeos::network_config::mojom::CrosNetworkConfig::Name_,
+      base::BindRepeating(&ShellBrowserMainParts::AddNetworkConfigBinding,
+                          base::Unretained(this)));
+}
+
+void ShellBrowserMainParts::AddNetworkConfigBinding(
+    mojo::ScopedMessagePipeHandle handle) {
+  cros_network_config_->BindRequest(
+      chromeos::network_config::mojom::CrosNetworkConfigRequest(
+          std::move(handle)));
+}
+
 }  // namespace shell
 }  // namespace ash
diff --git a/ash/shell/content/client/shell_browser_main_parts.h b/ash/shell/content/client/shell_browser_main_parts.h
index f10ee51..17fb84d 100644
--- a/ash/shell/content/client/shell_browser_main_parts.h
+++ b/ash/shell/content/client/shell_browser_main_parts.h
@@ -10,10 +10,11 @@
 #include "base/macros.h"
 #include "content/public/browser/browser_main_parts.h"
 #include "content/public/common/main_function_params.h"
+#include "mojo/public/cpp/system/message_pipe.h"
 
 namespace chromeos {
 namespace network_config {
-class CrosNetworkConfigTestHelper;
+class CrosNetworkConfig;
 }  // namespace network_config
 }  // namespace chromeos
 
@@ -43,16 +44,21 @@
   ~ShellBrowserMainParts() override;
 
   // Overridden from content::BrowserMainParts:
+  void PostEarlyInitialization() override;
   void PreMainMessageLoopStart() override;
   void PostMainMessageLoopStart() override;
   void ToolkitInitialized() override;
   void PreMainMessageLoopRun() override;
   bool MainMessageLoopRun(int* result_code) override;
   void PostMainMessageLoopRun() override;
+  void PostDestroyThreads() override;
 
   content::BrowserContext* browser_context() { return browser_context_.get(); }
 
  private:
+  void InitializeCrosNetworkConfig();
+  void AddNetworkConfigBinding(mojo::ScopedMessagePipeHandle handle);
+
   std::unique_ptr<content::BrowserContext> browser_context_;
   std::unique_ptr<views::ViewsDelegate> views_delegate_;
   std::unique_ptr<WindowWatcher> window_watcher_;
@@ -60,8 +66,8 @@
       example_session_controller_client_;
   std::unique_ptr<ExampleAppListClient> example_app_list_client_;
   std::unique_ptr<ash::AshTestHelper> ash_test_helper_;
-  std::unique_ptr<chromeos::network_config::CrosNetworkConfigTestHelper>
-      network_config_helper_;
+  std::unique_ptr<chromeos::network_config::CrosNetworkConfig>
+      cros_network_config_;
   std::unique_ptr<ShellNewWindowDelegate> new_window_delegate_;
   content::MainFunctionParams parameters_;
 
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index 12fa5ba8..5501f34 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -105,6 +105,10 @@
   return Shell::Get()->desks_controller();
 }
 
+void DesksController::Shutdown() {
+  desk_switch_animators_.clear();
+}
+
 void DesksController::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
 }
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h
index 9ad12f4..ef8c288 100644
--- a/ash/wm/desks/desks_controller.h
+++ b/ash/wm/desks/desks_controller.h
@@ -64,6 +64,9 @@
 
   const Desk* active_desk() const { return active_desk_; }
 
+  // Destroys any pending animations in preparation for shutdown.
+  void Shutdown();
+
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 87b28b1..13ef9c5 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -613,6 +613,8 @@
     "profiler/metadata_recorder.cc",
     "profiler/metadata_recorder.h",
     "profiler/native_unwinder.h",
+    "profiler/native_unwinder_android.cc",
+    "profiler/native_unwinder_android.h",
     "profiler/native_unwinder_mac.cc",
     "profiler/native_unwinder_mac.h",
     "profiler/native_unwinder_win.cc",
@@ -624,6 +626,7 @@
     "profiler/sample_metadata.h",
     "profiler/stack_sampler.cc",
     "profiler/stack_sampler.h",
+    "profiler/stack_sampler_android.cc",
     "profiler/stack_sampler_impl.cc",
     "profiler/stack_sampler_impl.h",
     "profiler/stack_sampler_mac.cc",
@@ -1329,7 +1332,10 @@
 
   # Android.
   if (is_android) {
-    sources -= [ "debug/stack_trace_posix.cc" ]
+    sources -= [
+      "debug/stack_trace_posix.cc",
+      "profiler/stack_sampler_posix.cc",
+    ]
     sources += [
       "android/android_hardware_buffer_compat.cc",
       "android/android_hardware_buffer_compat.h",
diff --git a/base/command_line.cc b/base/command_line.cc
index 281b3ded..4782f8a 100644
--- a/base/command_line.cc
+++ b/base/command_line.cc
@@ -397,16 +397,16 @@
   auto argv_switches_end = argv_.begin() + begin_args_;
   DCHECK(argv_switches_begin <= argv_switches_end);
   DCHECK(argv_switches_end <= argv_.end());
-  auto arg_iter = std::find_if(argv_switches_begin, argv_switches_end,
+  auto expell = std::remove_if(argv_switches_begin, argv_switches_end,
                                [&switch_key_native](const StringType& arg) {
                                  return IsSwitchWithKey(arg, switch_key_native);
                                });
-  if (arg_iter == argv_switches_end) {
+  if (expell == argv_switches_end) {
     NOTREACHED();
     return;
   }
-  argv_.erase(arg_iter);
-  --begin_args_;
+  begin_args_ -= argv_switches_end - expell;
+  argv_.erase(expell, argv_switches_end);
 }
 
 void CommandLine::CopySwitchesFrom(const CommandLine& source,
diff --git a/base/command_line_unittest.cc b/base/command_line_unittest.cc
index d4194fc..28d1901 100644
--- a/base/command_line_unittest.cc
+++ b/base/command_line_unittest.cc
@@ -495,6 +495,28 @@
                                               FILE_PATH_LITERAL("--switch1")));
 }
 
+TEST(CommandLineTest, RemoveSwitchDropsMultipleSameSwitches) {
+  const std::string switch1 = "switch1";
+  const std::string value2 = "value2";
+
+  CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
+
+  cl.AppendSwitch(switch1);
+  cl.AppendSwitchASCII(switch1, value2);
+
+  EXPECT_TRUE(cl.HasSwitch(switch1));
+  EXPECT_EQ(value2, cl.GetSwitchValueASCII(switch1));
+  EXPECT_THAT(cl.argv(),
+              testing::ElementsAre(FILE_PATH_LITERAL("Program"),
+                                   FILE_PATH_LITERAL("--switch1"),
+                                   FILE_PATH_LITERAL("--switch1=value2")));
+
+  cl.RemoveSwitch(switch1);
+
+  EXPECT_FALSE(cl.HasSwitch(switch1));
+  EXPECT_THAT(cl.argv(), testing::ElementsAre(FILE_PATH_LITERAL("Program")));
+}
+
 TEST(CommandLineTest, AppendAndRemoveSwitchWithDefaultPrefix) {
   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
 
diff --git a/base/profiler/native_unwinder_android.cc b/base/profiler/native_unwinder_android.cc
new file mode 100644
index 0000000..9f707c5
--- /dev/null
+++ b/base/profiler/native_unwinder_android.cc
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/profiler/native_unwinder_android.h"
+
+#include "base/profiler/native_unwinder.h"
+#include "base/profiler/profile_builder.h"
+#include "base/sampling_heap_profiler/module_cache.h"
+
+namespace base {
+
+bool NativeUnwinderAndroid::CanUnwindFrom(const Frame* current_frame) const {
+  return false;
+}
+
+UnwindResult NativeUnwinderAndroid::TryUnwind(RegisterContext* thread_context,
+                                              uintptr_t stack_top,
+                                              ModuleCache* module_cache,
+                                              std::vector<Frame>* stack) const {
+  return UnwindResult::ABORTED;
+}
+
+std::unique_ptr<Unwinder> CreateNativeUnwinder(ModuleCache* module_cache) {
+  return std::make_unique<NativeUnwinderAndroid>();
+}
+
+}  // namespace base
diff --git a/base/profiler/native_unwinder_android.h b/base/profiler/native_unwinder_android.h
new file mode 100644
index 0000000..08fa362
--- /dev/null
+++ b/base/profiler/native_unwinder_android.h
@@ -0,0 +1,33 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_PROFILER_NATIVE_UNWINDER_ANDROID_H_
+#define BASE_PROFILER_NATIVE_UNWINDER_ANDROID_H_
+
+#include "base/profiler/unwinder.h"
+
+namespace base {
+
+// Native unwinder implementation for Android, using libunwindstack.
+//
+// TODO(charliea): Implement this class.
+// See: https://crbug.com/989102
+class NativeUnwinderAndroid : public Unwinder {
+ public:
+  NativeUnwinderAndroid() = default;
+
+  NativeUnwinderAndroid(const NativeUnwinderAndroid&) = delete;
+  NativeUnwinderAndroid& operator=(const NativeUnwinderAndroid&) = delete;
+
+  // Unwinder
+  bool CanUnwindFrom(const Frame* current_frame) const override;
+  UnwindResult TryUnwind(RegisterContext* thread_context,
+                         uintptr_t stack_top,
+                         ModuleCache* module_cache,
+                         std::vector<Frame>* stack) const override;
+};
+
+}  // namespace base
+
+#endif  // BASE_PROFILER_NATIVE_UNWINDER_ANDROID_H_
diff --git a/base/profiler/stack_sampler_android.cc b/base/profiler/stack_sampler_android.cc
new file mode 100644
index 0000000..e3190e3
--- /dev/null
+++ b/base/profiler/stack_sampler_android.cc
@@ -0,0 +1,40 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/profiler/stack_sampler.h"
+
+#include <pthread.h>
+
+#include "base/profiler/native_unwinder_android.h"
+#include "base/profiler/stack_sampler_impl.h"
+#include "base/profiler/thread_delegate_android.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+std::unique_ptr<StackSampler> StackSampler::Create(
+    PlatformThreadId thread_id,
+    ModuleCache* module_cache,
+    StackSamplerTestDelegate* test_delegate) {
+  return std::make_unique<StackSamplerImpl>(
+      std::make_unique<ThreadDelegateAndroid>(),
+      std::make_unique<NativeUnwinderAndroid>(), module_cache, test_delegate);
+}
+
+size_t StackSampler::GetStackBufferSize() {
+  size_t stack_size = PlatformThread::GetDefaultThreadStackSize();
+
+  pthread_attr_t attr;
+  if (stack_size == 0 && pthread_attr_init(&attr) == 0) {
+    if (pthread_attr_getstacksize(&attr, &stack_size) != 0)
+      stack_size = 0;
+    pthread_attr_destroy(&attr);
+  }
+
+  // 1MB is default thread limit set by Android at art/runtime/thread_pool.h.
+  constexpr size_t kDefaultStackLimit = 1 << 20;
+  return stack_size > 0 ? stack_size : kDefaultStackLimit;
+}
+
+}  // namespace base
diff --git a/base/profiler/stack_sampler_posix.cc b/base/profiler/stack_sampler_posix.cc
index 0115cfd0..6062123 100644
--- a/base/profiler/stack_sampler_posix.cc
+++ b/base/profiler/stack_sampler_posix.cc
@@ -28,14 +28,8 @@
     pthread_attr_destroy(&attr);
   }
 
-// If we can't get stack limit from pthreads then use default value.
-#if defined(OS_ANDROID)
-  // 1MB is default thread limit set by Android at art/runtime/thread_pool.h.
-  constexpr size_t kDefaultStackLimit = 1 << 20;
-#else
   // Maximum limits under NPTL implementation.
   constexpr size_t kDefaultStackLimit = 4 * (1 << 20);
-#endif
   return stack_size > 0 ? stack_size : kDefaultStackLimit;
 }
 
diff --git a/base/profiler/thread_delegate_android.h b/base/profiler/thread_delegate_android.h
index f5b3162..59ff674 100644
--- a/base/profiler/thread_delegate_android.h
+++ b/base/profiler/thread_delegate_android.h
@@ -14,6 +14,7 @@
 // Android.
 //
 // TODO(charliea): Implement this class.
+// See: https://crbug.com/988574
 class BASE_EXPORT ThreadDelegateAndroid : public ThreadDelegate {
  public:
   class ScopedSuspendThread : public ThreadDelegate::ScopedSuspendThread {
diff --git a/base/sequence_checker.h b/base/sequence_checker.h
index e2ce10f..8477dde 100644
--- a/base/sequence_checker.h
+++ b/base/sequence_checker.h
@@ -74,6 +74,13 @@
 class SequenceCheckerDoNothing {
  public:
   SequenceCheckerDoNothing() = default;
+
+  // Moving between matching sequences is allowed to help classes with
+  // SequenceCheckers that want a default move-construct/assign.
+  SequenceCheckerDoNothing(SequenceCheckerDoNothing&& other) = default;
+  SequenceCheckerDoNothing& operator=(SequenceCheckerDoNothing&& other) =
+      default;
+
   bool CalledOnValidSequence() const WARN_UNUSED_RESULT { return true; }
   void DetachFromSequence() {}
 
diff --git a/base/sequence_checker_impl.cc b/base/sequence_checker_impl.cc
index bbca3238..ea5d21b 100644
--- a/base/sequence_checker_impl.cc
+++ b/base/sequence_checker_impl.cc
@@ -44,6 +44,33 @@
 SequenceCheckerImpl::SequenceCheckerImpl() : core_(std::make_unique<Core>()) {}
 SequenceCheckerImpl::~SequenceCheckerImpl() = default;
 
+SequenceCheckerImpl::SequenceCheckerImpl(SequenceCheckerImpl&& other) {
+  // Verify that |other| is called on its associated sequence and bind it now if
+  // it is currently detached (even if this isn't a DCHECK build).
+  const bool other_called_on_valid_sequence = other.CalledOnValidSequence();
+  DCHECK(other_called_on_valid_sequence);
+
+  core_ = std::move(other.core_);
+}
+
+SequenceCheckerImpl& SequenceCheckerImpl::operator=(
+    SequenceCheckerImpl&& other) {
+  // If |this| is not in a detached state it needs to be bound to the current
+  // sequence.
+  DCHECK(CalledOnValidSequence());
+
+  // Verify that |other| is called on its associated sequence and bind it now if
+  // it is currently detached (even if this isn't a DCHECK build).
+  const bool other_called_on_valid_sequence = other.CalledOnValidSequence();
+  DCHECK(other_called_on_valid_sequence);
+
+  // Intentionally not using either |lock_| in this method to let TSAN catch
+  // racy assign.
+  TS_UNCHECKED_READ(core_) = std::move(TS_UNCHECKED_READ(other.core_));
+
+  return *this;
+}
+
 bool SequenceCheckerImpl::CalledOnValidSequence() const {
   AutoLock auto_lock(lock_);
   if (!core_)
diff --git a/base/sequence_checker_impl.h b/base/sequence_checker_impl.h
index 729ad73..3599fb8 100644
--- a/base/sequence_checker_impl.h
+++ b/base/sequence_checker_impl.h
@@ -26,6 +26,15 @@
   SequenceCheckerImpl();
   ~SequenceCheckerImpl();
 
+  // Allow move construct/assign. This must be called on |other|'s associated
+  // sequence and assignment can only be made into a SequenceCheckerImpl which
+  // is detached or already associated with the current sequence. This isn't
+  // thread-safe (|this| and |other| shouldn't be in use while this move is
+  // performed). If the assignment was legal, the resulting SequenceCheckerImpl
+  // will be bound to the current sequence and |other| will be detached.
+  SequenceCheckerImpl(SequenceCheckerImpl&& other);
+  SequenceCheckerImpl& operator=(SequenceCheckerImpl&& other);
+
   // Returns true if called in sequence with previous calls to this method and
   // the constructor.
   bool CalledOnValidSequence() const WARN_UNUSED_RESULT;
diff --git a/base/sequence_checker_unittest.cc b/base/sequence_checker_unittest.cc
index 7ea52f8c..09e272d 100644
--- a/base/sequence_checker_unittest.cc
+++ b/base/sequence_checker_unittest.cc
@@ -155,6 +155,76 @@
   EXPECT_FALSE(sequence_checker.CalledOnValidSequence());
 }
 
+TEST(SequenceCheckerTest, Move) {
+  SequenceCheckerImpl initial;
+  EXPECT_TRUE(initial.CalledOnValidSequence());
+
+  SequenceCheckerImpl move_constructed(std::move(initial));
+  EXPECT_TRUE(move_constructed.CalledOnValidSequence());
+
+  SequenceCheckerImpl move_assigned;
+  move_assigned = std::move(move_constructed);
+
+  // The two SequenceCheckerImpls moved from should be able to rebind to another
+  // sequence.
+  RunCallbackThread thread1(
+      BindOnce(&ExpectCalledOnValidSequence, Unretained(&initial)));
+  RunCallbackThread thread2(
+      BindOnce(&ExpectCalledOnValidSequence, Unretained(&move_constructed)));
+
+  // But the latest one shouldn't be able to run on another sequence.
+  RunCallbackThread thread(
+      BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&move_assigned)));
+
+  EXPECT_TRUE(move_assigned.CalledOnValidSequence());
+}
+
+TEST(SequenceCheckerTest, MoveAssignIntoDetached) {
+  SequenceCheckerImpl initial;
+
+  SequenceCheckerImpl move_assigned;
+  move_assigned.DetachFromSequence();
+  move_assigned = std::move(initial);
+
+  // |initial| is detached after move.
+  RunCallbackThread thread1(
+      BindOnce(&ExpectCalledOnValidSequence, Unretained(&initial)));
+
+  // |move_assigned| should be associated with the main thread.
+  RunCallbackThread thread2(
+      BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&move_assigned)));
+
+  EXPECT_TRUE(move_assigned.CalledOnValidSequence());
+}
+
+TEST(SequenceCheckerTest, MoveFromDetachedRebinds) {
+  SequenceCheckerImpl initial;
+  initial.DetachFromSequence();
+
+  SequenceCheckerImpl moved_into(std::move(initial));
+
+  // |initial| is still detached after move.
+  RunCallbackThread thread1(
+      BindOnce(&ExpectCalledOnValidSequence, Unretained(&initial)));
+
+  // |moved_into| is bound to the current sequence as part of the move.
+  RunCallbackThread thread2(
+      BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&moved_into)));
+  EXPECT_TRUE(moved_into.CalledOnValidSequence());
+}
+
+TEST(SequenceCheckerTest, MoveOffSequenceBanned) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+
+  SequenceCheckerImpl other_sequence;
+  other_sequence.DetachFromSequence();
+  RunCallbackThread thread(
+      BindOnce(&ExpectCalledOnValidSequence, Unretained(&other_sequence)));
+
+  EXPECT_DCHECK_DEATH(
+      SequenceCheckerImpl main_sequence(std::move(other_sequence)));
+}
+
 TEST(SequenceCheckerMacroTest, Macros) {
   auto scope = std::make_unique<ScopedSetSequenceTokenForCurrentThread>(
       SequenceToken::Create());
diff --git a/base/threading/thread_checker.h b/base/threading/thread_checker.h
index d1f5bb2..05c5703 100644
--- a/base/threading/thread_checker.h
+++ b/base/threading/thread_checker.h
@@ -79,6 +79,12 @@
 class ThreadCheckerDoNothing {
  public:
   ThreadCheckerDoNothing() = default;
+
+  // Moving between matching threads is allowed to help classes with
+  // ThreadCheckers that want a default move-construct/assign.
+  ThreadCheckerDoNothing(ThreadCheckerDoNothing&& other) = default;
+  ThreadCheckerDoNothing& operator=(ThreadCheckerDoNothing&& other) = default;
+
   bool CalledOnValidThread() const WARN_UNUSED_RESULT { return true; }
   void DetachFromThread() {}
 
diff --git a/base/threading/thread_checker_impl.cc b/base/threading/thread_checker_impl.cc
index 5569391d..18d5ea3 100644
--- a/base/threading/thread_checker_impl.cc
+++ b/base/threading/thread_checker_impl.cc
@@ -4,6 +4,7 @@
 
 #include "base/threading/thread_checker_impl.h"
 
+#include "base/logging.h"
 #include "base/threading/thread_local.h"
 #include "base/threading/thread_task_runner_handle.h"
 
@@ -11,11 +12,48 @@
 
 ThreadCheckerImpl::ThreadCheckerImpl() {
   AutoLock auto_lock(lock_);
-  EnsureAssigned();
+  EnsureAssignedLockRequired();
 }
 
 ThreadCheckerImpl::~ThreadCheckerImpl() = default;
 
+ThreadCheckerImpl::ThreadCheckerImpl(ThreadCheckerImpl&& other) {
+  // Verify that |other| is called on its associated thread and bind it now if
+  // it is currently detached (even if this isn't a DCHECK build).
+  const bool other_called_on_valid_thread = other.CalledOnValidThread();
+  DCHECK(other_called_on_valid_thread);
+
+  // Intentionally not using |other.lock_| to let TSAN catch racy construct from
+  // |other|.
+  thread_id_ = other.thread_id_;
+  task_token_ = other.task_token_;
+  sequence_token_ = other.sequence_token_;
+
+  other.thread_id_ = PlatformThreadRef();
+  other.task_token_ = TaskToken();
+  other.sequence_token_ = SequenceToken();
+}
+
+ThreadCheckerImpl& ThreadCheckerImpl::operator=(ThreadCheckerImpl&& other) {
+  DCHECK(CalledOnValidThread());
+
+  // Verify that |other| is called on its associated thread and bind it now if
+  // it is currently detached (even if this isn't a DCHECK build).
+  const bool other_called_on_valid_thread = other.CalledOnValidThread();
+  DCHECK(other_called_on_valid_thread);
+
+  // Intentionally not using either |lock_| to let TSAN catch racy assign.
+  TS_UNCHECKED_READ(thread_id_) = TS_UNCHECKED_READ(other.thread_id_);
+  TS_UNCHECKED_READ(task_token_) = TS_UNCHECKED_READ(other.task_token_);
+  TS_UNCHECKED_READ(sequence_token_) = TS_UNCHECKED_READ(other.sequence_token_);
+
+  TS_UNCHECKED_READ(other.thread_id_) = PlatformThreadRef();
+  TS_UNCHECKED_READ(other.task_token_) = TaskToken();
+  TS_UNCHECKED_READ(other.sequence_token_) = SequenceToken();
+
+  return *this;
+}
+
 bool ThreadCheckerImpl::CalledOnValidThread() const {
   const bool has_thread_been_destroyed = ThreadLocalStorage::HasBeenDestroyed();
 
@@ -24,7 +62,7 @@
   // the state of thread-local storage is not guaranteed to be in a consistent
   // state. Further, task-runner only installs the tokens when running a task.
   if (!has_thread_been_destroyed) {
-    EnsureAssigned();
+    EnsureAssignedLockRequired();
 
     // Always return true when called from the task from which this
     // ThreadCheckerImpl was assigned to a thread.
@@ -57,8 +95,7 @@
   sequence_token_ = SequenceToken();
 }
 
-void ThreadCheckerImpl::EnsureAssigned() const {
-  lock_.AssertAcquired();
+void ThreadCheckerImpl::EnsureAssignedLockRequired() const {
   if (!thread_id_.is_null())
     return;
 
diff --git a/base/threading/thread_checker_impl.h b/base/threading/thread_checker_impl.h
index 83378f06..e911cec 100644
--- a/base/threading/thread_checker_impl.h
+++ b/base/threading/thread_checker_impl.h
@@ -9,6 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/sequence_token.h"
 #include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
 #include "base/threading/platform_thread.h"
 
 namespace base {
@@ -24,6 +25,15 @@
   ThreadCheckerImpl();
   ~ThreadCheckerImpl();
 
+  // Allow move construct/assign. This must be called on |other|'s associated
+  // thread and assignment can only be made into a ThreadCheckerImpl which is
+  // detached or already associated with the current thread. This isn't
+  // thread-safe (|this| and |other| shouldn't be in use while this move is
+  // performed). If the assignment was legal, the resulting ThreadCheckerImpl
+  // will be bound to the current thread and |other| will be detached.
+  ThreadCheckerImpl(ThreadCheckerImpl&& other);
+  ThreadCheckerImpl& operator=(ThreadCheckerImpl&& other);
+
   bool CalledOnValidThread() const WARN_UNUSED_RESULT;
 
   // Changes the thread that is checked for in CalledOnValidThread.  This may
@@ -32,7 +42,7 @@
   void DetachFromThread();
 
  private:
-  void EnsureAssigned() const;
+  void EnsureAssignedLockRequired() const EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
   // Members are mutable so that CalledOnValidThread() can set them.
 
@@ -40,7 +50,7 @@
   mutable base::Lock lock_;
 
   // Thread on which CalledOnValidThread() may return true.
-  mutable PlatformThreadRef thread_id_;
+  mutable PlatformThreadRef thread_id_ GUARDED_BY(lock_);
 
   // TaskToken for which CalledOnValidThread() always returns true. This allows
   // CalledOnValidThread() to return true when called multiple times from the
@@ -48,13 +58,13 @@
   // (allowing usage of ThreadChecker objects on the stack in the scope of one-
   // off tasks). Note: CalledOnValidThread() may return true even if the current
   // TaskToken is not equal to this.
-  mutable TaskToken task_token_;
+  mutable TaskToken task_token_ GUARDED_BY(lock_);
 
   // SequenceToken for which CalledOnValidThread() may return true. Used to
   // ensure that CalledOnValidThread() doesn't return true for ThreadPool
   // tasks that happen to run on the same thread but weren't posted to the same
   // SingleThreadTaskRunner.
-  mutable SequenceToken sequence_token_;
+  mutable SequenceToken sequence_token_ GUARDED_BY(lock_);
 };
 
 }  // namespace base
diff --git a/base/threading/thread_checker_unittest.cc b/base/threading/thread_checker_unittest.cc
index 1b71742..e3ffeb2 100644
--- a/base/threading/thread_checker_unittest.cc
+++ b/base/threading/thread_checker_unittest.cc
@@ -229,6 +229,76 @@
   }));
 }
 
+TEST(ThreadCheckerTest, Move) {
+  ThreadCheckerImpl initial;
+  EXPECT_TRUE(initial.CalledOnValidThread());
+
+  ThreadCheckerImpl move_constructed(std::move(initial));
+  EXPECT_TRUE(move_constructed.CalledOnValidThread());
+
+  ThreadCheckerImpl move_assigned;
+  move_assigned = std::move(move_constructed);
+  EXPECT_TRUE(move_assigned.CalledOnValidThread());
+
+  // The two ThreadCheckerImpls moved from should be able to rebind to another
+  // thread.
+  RunCallbackOnNewThreadSynchronously(
+      BindOnce(&ExpectCalledOnValidThread, Unretained(&initial)));
+  RunCallbackOnNewThreadSynchronously(
+      BindOnce(&ExpectCalledOnValidThread, Unretained(&move_constructed)));
+
+  // But the latest one shouldn't be able to run on another thread.
+  RunCallbackOnNewThreadSynchronously(
+      BindOnce(&ExpectNotCalledOnValidThread, Unretained(&move_assigned)));
+
+  EXPECT_TRUE(move_assigned.CalledOnValidThread());
+}
+
+TEST(ThreadCheckerTest, MoveAssignIntoDetached) {
+  ThreadCheckerImpl initial;
+
+  ThreadCheckerImpl move_assigned;
+  move_assigned.DetachFromThread();
+  move_assigned = std::move(initial);
+
+  // |initial| is detached after move.
+  RunCallbackOnNewThreadSynchronously(
+      BindOnce(&ExpectCalledOnValidThread, Unretained(&initial)));
+
+  // |move_assigned| should be associated with the main thread.
+  RunCallbackOnNewThreadSynchronously(
+      BindOnce(&ExpectNotCalledOnValidThread, Unretained(&move_assigned)));
+
+  EXPECT_TRUE(move_assigned.CalledOnValidThread());
+}
+
+TEST(ThreadCheckerTest, MoveFromDetachedRebinds) {
+  ThreadCheckerImpl initial;
+  initial.DetachFromThread();
+
+  ThreadCheckerImpl moved_into(std::move(initial));
+
+  // |initial| is still detached after move.
+  RunCallbackOnNewThreadSynchronously(
+      BindOnce(&ExpectCalledOnValidThread, Unretained(&initial)));
+
+  // |moved_into| is bound to the current thread as part of the move.
+  RunCallbackOnNewThreadSynchronously(
+      BindOnce(&ExpectNotCalledOnValidThread, Unretained(&moved_into)));
+  EXPECT_TRUE(moved_into.CalledOnValidThread());
+}
+
+TEST(ThreadCheckerTest, MoveOffThreadBanned) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+
+  ThreadCheckerImpl other_thread;
+  other_thread.DetachFromThread();
+  RunCallbackOnNewThreadSynchronously(
+      BindOnce(&ExpectCalledOnValidThread, Unretained(&other_thread)));
+
+  EXPECT_DCHECK_DEATH(ThreadCheckerImpl main_thread(std::move(other_thread)));
+}
+
 namespace {
 
 // This fixture is a helper for unit testing the thread checker macros as it is
@@ -265,6 +335,8 @@
 }  // namespace
 
 TEST_F(ThreadCheckerMacroTest, Macros) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+
   THREAD_CHECKER(my_thread_checker);
 
   RunCallbackOnNewThreadSynchronously(BindOnce(
diff --git a/build/fuchsia/fidlgen_js/gen.py b/build/fuchsia/fidlgen_js/gen.py
index b4f4063..1425a8ed 100755
--- a/build/fuchsia/fidlgen_js/gen.py
+++ b/build/fuchsia/fidlgen_js/gen.py
@@ -592,14 +592,16 @@
   if (this.channel === $ZX_HANDLE_INVALID) {
     throw "channel closed";
   }
-  var $encoder = new $fidl_Encoder(_k%(name)s_%(method_name)s_Ordinal);
+  var $encoder = new $fidl_Encoder(
+      _k%(name)s_%(method_name)s_Ordinal, %(has_response)d);
   $encoder.alloc(%(size)s - $fidl_kMessageHeaderSize);
 ''' % {
                 'name': name,
                 'proxy_name': proxy_name,
                 'method_name': method_name,
                 'param_names': ', '.join(param_names),
-                'size': method.maybe_request_size
+                'size': method.maybe_request_size,
+                'has_response': method.has_response
             })
 
         for param, ttname in zip(method.maybe_request, type_tables):
diff --git a/build/fuchsia/fidlgen_js/runtime/fidl.mjs b/build/fuchsia/fidlgen_js/runtime/fidl.mjs
index 722098b..9a3cfa2 100644
--- a/build/fuchsia/fidlgen_js/runtime/fidl.mjs
+++ b/build/fuchsia/fidlgen_js/runtime/fidl.mjs
@@ -31,20 +31,20 @@
  * @constructor
  * @param {number} ordinal
  */
-function $fidl_Encoder(ordinal) {
+function $fidl_Encoder(ordinal, has_response) {
   var buf = new ArrayBuffer($fidl_kInitialBufferSize);
   this.data = new DataView(buf);
   this.extent = 0;
   this.handles = [];
-  this._encodeMessageHeader(ordinal);
+  this._encodeMessageHeader(ordinal, has_response);
 }
 
 /**
  * @param {number} ordinal
  */
-$fidl_Encoder.prototype._encodeMessageHeader = function(ordinal) {
+$fidl_Encoder.prototype._encodeMessageHeader = function(ordinal, has_response) {
   this.alloc($fidl_kMessageHeaderSize);
-  var txid = $fidl__nextTxid++ & $fidl__kUserspaceTxidMask;
+  var txid = has_response ? ($fidl__nextTxid++ & $fidl__kUserspaceTxidMask) : 0;
   this.data.setUint32($fidl_kMessageTxidOffset, txid, $fidl__kLE);
   this.data.setUint32($fidl_kMessageOrdinalOffset, ordinal, $fidl__kLE);
 };
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 2132dac..0c100ed4 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8906975111514018656
\ No newline at end of file
+8906501286599338608
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index c8e0ea6..c8f0a09 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8906947743085818368
\ No newline at end of file
+8906527071452361600
\ No newline at end of file
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index a1c5a10..ab1b4a5 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -1638,7 +1638,6 @@
     "//chrome/browser/resources:net_internals_resources",
     "//chrome/browser/resources:quota_internals_resources",
     "//chrome/browser/resources:webapks_ui_resources",
-    "//chrome/browser/resources/bluetooth_internals:resources",
     "//components/autofill/core/browser:autofill_address_rewriter_resources",
   ]
 
@@ -1648,6 +1647,7 @@
       "//chrome/browser/resources:downloads_resources",
       "//chrome/browser/resources:local_ntp_resources",
       "//chrome/browser/resources:settings_resources",
+      "//chrome/browser/resources/bluetooth_internals:resources",
     ]
   }
 
@@ -1940,6 +1940,8 @@
         ":chrome_symbols",
         ":swiftshader_egl_symbols",
         ":swiftshader_gles_symbols",
+        ":angle_egl_symbols",
+        ":angle_gles_symbols",
       ]
     }
     extract_symbols("chrome_symbols") {
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 3ffa062..9645811 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1349,11 +1349,17 @@
       output_dir = "$target_gen_dir/${_variant}_paks"
       deps = []
 
+      additional_extra_paks = []
       if (_is_monochrome) {
-        additional_extra_paks =
+        additional_extra_paks +=
             [ "$root_gen_dir/android_webview/aw_resources.pak" ]
         deps += [ "//android_webview:generate_aw_resources" ]
       }
+      if (!dfmify_dev_ui) {
+        additional_extra_paks +=
+            [ "$root_gen_dir/chrome/bluetooth_internals_resources.pak" ]
+        deps += [ "//chrome/browser/resources/bluetooth_internals:resources" ]
+      }
 
       if (enable_resource_whitelist_generation) {
         repack_whitelist = _resource_whitelist_file
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index ec794b9..7c94586 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -199,13 +199,13 @@
     if (!_is_monochrome && !_is_trichrome) {
       deps += [
         "//chrome/android:chrome_public_v8_assets",
-        "//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so",
+        "//components/crash/content/app:chrome_crashpad_handler_named_as_so",
         "//third_party/icu:icu_assets",
       ]
       if (!defined(loadable_modules)) {
         loadable_modules = []
       }
-      loadable_modules += [ "$root_out_dir/libcrashpad_handler.so" ]
+      loadable_modules += [ "$root_out_dir/libchrome_crashpad_handler.so" ]
     }
 
     if (_enable_multidex) {
diff --git a/chrome/android/features/dev_ui/BUILD.gn b/chrome/android/features/dev_ui/BUILD.gn
index d1bd2fdd..191f898 100644
--- a/chrome/android/features/dev_ui/BUILD.gn
+++ b/chrome/android/features/dev_ui/BUILD.gn
@@ -13,3 +13,13 @@
     "//base:base_java",
   ]
 }
+
+android_assets("pak_assets") {
+  renaming_sources =
+      [ "$root_gen_dir/chrome/bluetooth_internals_resources.pak" ]
+  renaming_destinations = [ "dev_ui_resources.pak" ]
+  deps = [
+    "//chrome/browser/resources/bluetooth_internals:resources",
+  ]
+  disable_compression = true
+}
diff --git a/chrome/android/features/dev_ui/dev_ui_module.gni b/chrome/android/features/dev_ui/dev_ui_module.gni
index d714381..a23ce68 100644
--- a/chrome/android/features/dev_ui/dev_ui_module.gni
+++ b/chrome/android/features/dev_ui/dev_ui_module.gni
@@ -8,6 +8,9 @@
 
 dev_ui_module_desc = {
   name = "dev_ui"
-  java_deps = [ "//chrome/android/features/dev_ui:java" ]
+  java_deps = [
+    "//chrome/android/features/dev_ui:java",
+    "//chrome/android/features/dev_ui:pak_assets",
+  ]
   android_manifest = "//chrome/android/features/dev_ui/java/AndroidManifest.xml"
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
index 9806667..f39899c 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -229,6 +229,11 @@
         return view -> {
             hideDialog(false);
             Tab currentTab = mTabModelSelector.getTabById(mCurrentTabId);
+            if (currentTab == null) {
+                mTabCreatorManager.getTabCreator(mTabModelSelector.isIncognitoSelected())
+                        .launchNTP();
+                return;
+            }
             List<Tab> relatedTabs = getRelatedTabs(currentTab.getId());
 
             assert relatedTabs.size() > 0;
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
index de2a07f..6b15153 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -9,6 +9,8 @@
 import static org.junit.Assert.assertThat;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isA;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -45,6 +47,7 @@
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
 import org.chromium.chrome.browser.widget.ScrimView;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -177,7 +180,7 @@
     }
 
     @Test
-    public void onClickAdd() {
+    public void onClickAdd_HasCurrentTab() {
         // Mock that the animation source Rect is not null.
         mModel.set(TabGridSheetProperties.ANIMATION_SOURCE_RECT, mRect);
         mMediator.setCurrentTabIdForTest(TAB1_ID);
@@ -187,6 +190,19 @@
 
         assertThat(mModel.get(TabGridSheetProperties.ANIMATION_SOURCE_RECT), equalTo(null));
         verify(mDialogResetHandler).resetWithListOfTabs(null);
+        verify(mTabCreator)
+                .createNewTab(
+                        isA(LoadUrlParams.class), eq(TabLaunchType.FROM_CHROME_UI), eq(mTab1));
+    }
+
+    @Test
+    public void onClickAdd_NoCurrentTab() {
+        mMediator.setCurrentTabIdForTest(Tab.INVALID_TAB_ID);
+
+        View.OnClickListener listener = mModel.get(TabGridSheetProperties.ADD_CLICK_LISTENER);
+        listener.onClick(mView);
+
+        verify(mTabCreator).launchNTP();
     }
 
     @Test
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCardIconControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCardIconControl.java
index 5270ca4..1327c2f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCardIconControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCardIconControl.java
@@ -10,6 +10,7 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.download.home.list.view.UiUtils;
+import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
 import org.chromium.ui.resources.dynamics.ViewResourceInflater;
 
@@ -48,11 +49,15 @@
         // This middle-dot character is returned by the server and marks the beginning of the
         // pronunciation.
         int dotSeparatorLocation = searchTerm.indexOf(DEFINITION_MID_DOT);
-        if (dotSeparatorLocation <= 0) return false;
+        if (dotSeparatorLocation <= 0 || dotSeparatorLocation >= searchTerm.length() - 1) {
+            return false;
+        }
 
         // Style with the pronunciation in gray in the second half.
         String word = searchTerm.substring(0, dotSeparatorLocation);
-        String pronunciation = searchTerm.substring(dotSeparatorLocation, searchTerm.length());
+        String pronunciation = searchTerm.substring(dotSeparatorLocation + 1, searchTerm.length());
+        pronunciation = LocalizationUtils.isLayoutRtl() ? pronunciation + DEFINITION_MID_DOT
+                                                        : DEFINITION_MID_DOT + pronunciation;
         contextControl.setContextDetails(word, pronunciation);
         setVectorDrawableResourceId(R.drawable.ic_book_round);
         imageControl.setCardIconResourceId(getIconResId());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegateFactory.java
index 6f13d6e..0981203 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegateFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegateFactory.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.gesturenav;
 
+import android.annotation.TargetApi;
 import android.os.Build;
 import android.view.View;
 import android.view.WindowInsets;
@@ -56,6 +57,7 @@
                 return new TabbedActionDelegate(tab);
             }
 
+            @TargetApi(Build.VERSION_CODES.O)
             @Override
             public boolean isNavigationEnabled(View view) {
                 if (!BuildInfo.isAtLeastQ() || Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
@@ -68,9 +70,10 @@
             /**
              * @return {@link android.graphics.Insets} object.
              */
+            @TargetApi(Build.VERSION_CODES.O)
             private Object getSystemGestureInsets(Object windowInsets) {
                 if (!BuildInfo.isAtLeastQ() || Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
-                    return true;
+                    return null;
                 }
                 try {
                     Method method = WindowInsets.class.getMethod("getSystemGestureInsets");
@@ -95,6 +98,7 @@
                 return 0;
             }
 
+            @TargetApi(Build.VERSION_CODES.O)
             @Override
             public void setWindowInsetsChangeObserver(View view, Runnable runnable) {
                 if (!BuildInfo.isAtLeastQ() || Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
index 7b86064..22de707 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
@@ -318,7 +318,7 @@
 
         int startupMode =
                 getBrowserStartupController().getStartupMode(delegate.startServiceManagerOnly());
-        tasks.add(UiThreadTaskTraits.BEST_EFFORT,
+        tasks.add(UiThreadTaskTraits.DEFAULT,
                 () -> { BackgroundTaskSchedulerExternalUma.reportStartupMode(startupMode); });
 
         if (isAsync) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
index e37dc0fd..300a49e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
@@ -17,7 +17,6 @@
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
@@ -564,8 +563,7 @@
                 // https://crbug.com/729737
                 try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
                     directShareIcon = pm.getActivityIcon(component);
-                    ApplicationInfo ai = pm.getApplicationInfo(component.getPackageName(), 0);
-                    directShareTitle = pm.getApplicationLabel(ai);
+                    directShareTitle = pm.getActivityInfo(component, 0).loadLabel(pm);
                 }
                 retrieved = true;
             } catch (NameNotFoundException exception) {
diff --git a/chrome/android/monochrome/scripts/monochrome_apk_checker.py b/chrome/android/monochrome/scripts/monochrome_apk_checker.py
index b74fcec..e0b8081 100755
--- a/chrome/android/monochrome/scripts/monochrome_apk_checker.py
+++ b/chrome/android/monochrome/scripts/monochrome_apk_checker.py
@@ -25,7 +25,7 @@
     r'lib/.*/libchrome\.\d{4}\.\d{2,3}\.so', # libchrome placeholders
     r'lib/.*/libchromium_android_linker\.so',
     r'lib/.*/libchromeview\.so', # placeholder library
-    r'lib/.*/libcrashpad_handler\.so',
+    r'lib/.*/libchrome_crashpad_handler\.so',
     r'lib/.*/crazy\.libchrome\.so',
     r'lib/.*/crazy\.libchrome\.align',
     r'lib/.*/gdbserver',
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index 7af9b33..1e6ebe1 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -569,7 +569,6 @@
     "//chrome/common:buildflags",
     "//chrome/common:mojo_bindings",
     "//chrome/services/file_util/public/cpp:manifest",
-    "//components/services/patch/public/cpp:manifest",
     "//components/services/quarantine",
     "//components/services/quarantine/public/cpp:manifest",
     "//components/spellcheck/common:interfaces",
diff --git a/chrome/app/DEPS b/chrome/app/DEPS
index b79c6b8..9294552 100644
--- a/chrome/app/DEPS
+++ b/chrome/app/DEPS
@@ -96,7 +96,6 @@
     "+chromeos/services/network_config",
     "+chromeos/services/secure_channel",
     "+components/mirroring/service",
-    "+components/services/patch/public",
     "+components/services/pdf_compositor",
     "+components/services/quarantine",
     "+components/services/unzip/public",
diff --git a/chrome/app/builtin_service_manifests.cc b/chrome/app/builtin_service_manifests.cc
index 65e281c..1b2ebe7 100644
--- a/chrome/app/builtin_service_manifests.cc
+++ b/chrome/app/builtin_service_manifests.cc
@@ -9,7 +9,6 @@
 #include "chrome/common/buildflags.h"
 #include "chrome/common/constants.mojom.h"
 #include "chrome/services/file_util/public/cpp/manifest.h"
-#include "components/services/patch/public/cpp/manifest.h"
 #include "components/services/quarantine/public/cpp/manifest.h"
 #include "components/spellcheck/common/spellcheck.mojom.h"
 #include "components/startup_metric_utils/common/startup_metric.mojom.h"
@@ -104,7 +103,6 @@
   static base::NoDestructor<std::vector<service_manager::Manifest>> manifests{{
       GetChromeManifest(),
       GetFileUtilManifest(),
-      patch::GetManifest(),
       prefs::GetLocalStateManifest(),
       quarantine::GetQuarantineManifest(),
 #if BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index f6feb8b..ca1f8193 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -930,7 +930,7 @@
           <message name="IDS_ZOOM_MINUS2" desc="The text label of the Make Text Smaller menu item in the merged menu">
             &#8722;
           </message>
-          <message name="IDS_COPY_URL" desc="The text label of the Copy URL menu item for the Hosted App app menu">
+          <message name="IDS_COPY_URL" desc="The text label of the Copy URL menu item for the Hosted App app menu and Chrome Custom Tab right-click menu">
             Copy &amp;URL
           </message>
           <message name="IDS_OPEN_IN_APP_WINDOW" desc="The text label of the menu item for moving the current tab to a standalone app window">
@@ -1001,7 +1001,7 @@
           <message name="IDS_ZOOM_MINUS2" desc="The text label of the Make Text Smaller menu item in the merged menu">
             &#8722;
           </message>
-          <message name="IDS_COPY_URL" desc="In Title Case: The text label of the Copy URL menu item for the Hosted App app menu">
+          <message name="IDS_COPY_URL" desc="In Title Case: The text label of the Copy URL menu item for the Hosted App app menu and Chrome Custom Tab right-click menu">
             Copy &amp;URL
           </message>
           <message name="IDS_OPEN_IN_APP_WINDOW" desc="In Title Case: The text label of the menu item for moving the current tab to a standalone app window">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 143b2f0..fe481d3b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1072,6 +1072,14 @@
     "performance_manager/graph/page_node.cc",
     "performance_manager/graph/page_node_impl.cc",
     "performance_manager/graph/page_node_impl.h",
+    "performance_manager/graph/policies/policy_features.cc",
+    "performance_manager/graph/policies/policy_features.h",
+    "performance_manager/graph/policies/working_set_trimmer_policy.cc",
+    "performance_manager/graph/policies/working_set_trimmer_policy.h",
+    "performance_manager/graph/policies/working_set_trimmer_policy_chromeos.cc",
+    "performance_manager/graph/policies/working_set_trimmer_policy_chromeos.h",
+    "performance_manager/graph/policies/working_set_trimmer_policy_win.cc",
+    "performance_manager/graph/policies/working_set_trimmer_policy_win.h",
     "performance_manager/graph/process_node.cc",
     "performance_manager/graph/process_node_impl.cc",
     "performance_manager/graph/process_node_impl.h",
@@ -1092,8 +1100,6 @@
     "performance_manager/observers/isolation_context_metrics.h",
     "performance_manager/observers/metrics_collector.cc",
     "performance_manager/observers/metrics_collector.h",
-    "performance_manager/observers/working_set_trimmer_observer_win.cc",
-    "performance_manager/observers/working_set_trimmer_observer_win.h",
     "performance_manager/performance_manager.cc",
     "performance_manager/performance_manager.h",
     "performance_manager/performance_manager_clock.cc",
@@ -2029,7 +2035,7 @@
     "//components/security_state/core",
     "//components/send_tab_to_self",
     "//components/services/heap_profiling",
-    "//components/services/patch/public/mojom",
+    "//components/services/patch/content",
     "//components/services/quarantine",
     "//components/services/quarantine/public/mojom",
     "//components/services/unzip/content",
@@ -2138,6 +2144,7 @@
     "//services/preferences/tracked",
     "//services/proxy_resolver/public/mojom",
     "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
+    "//services/resource_coordinator/public/cpp/memory_instrumentation:browser",
     "//services/service_manager/public/cpp",
     "//services/shape_detection/public/mojom",
     "//services/strings",
@@ -3714,7 +3721,6 @@
       "//chrome/browser/safe_browsing/chrome_cleaner",
       "//chrome/browser/safe_browsing/chrome_cleaner:public",
       "//chrome/browser/win/conflicts:module_info",
-      "//chrome/chrome_elf:blacklist",
       "//chrome/chrome_elf:constants",
       "//chrome/chrome_elf:dll_hash",
       "//chrome/chrome_watcher:client",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index df68d31e..86a9fc8 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -194,8 +194,8 @@
   "+components/services/app_service/public/mojom",
   "+components/services/filesystem/public/mojom",
   "+components/services/heap_profiling",
-  "+components/services/patch/public/cpp",
-  "+components/services/patch/public/mojom",
+  "+components/services/patch/content",
+  "+components/services/patch/public",
   "+components/services/pdf_compositor/public/cpp",
   "+components/services/pdf_compositor/public/mojom",
   "+components/services/quarantine",
@@ -369,6 +369,7 @@
   "+chrome/browser/performance_manager/public",
   "+chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h",
   "+chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.h",
+  "+chrome/browser/performance_manager/graph/policies/policy_features.h",
   "+chrome/browser/performance_manager/performance_manager.h",
   "+chrome/browser/performance_manager/performance_manager_tab_helper.h",
 
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index ce7bdba..817af2b1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -30,6 +30,7 @@
 #include "chrome/browser/browser_features.h"
 #include "chrome/browser/flag_descriptions.h"
 #include "chrome/browser/notifications/scheduler/public/features.h"
+#include "chrome/browser/performance_manager/graph/policies/policy_features.h"
 #include "chrome/browser/predictors/loading_predictor_config.h"
 #include "chrome/browser/prerender/prerender_field_trial.h"
 #include "chrome/browser/resource_coordinator/tab_manager_features.h"
@@ -1541,6 +1542,14 @@
     {"enable-virtual-desks", flag_descriptions::kEnableVirtualDesksName,
      flag_descriptions::kEnableVirtualDesksDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kVirtualDesks)},
+    {"trim-on-all-frames-frozen", flag_descriptions::kTrimOnFreezeName,
+     flag_descriptions::kTrimOnFreezeDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(
+         performance_manager::features::chromeos::kTrimOnFreeze)},
+    {"trim-on-memory-pressure", flag_descriptions::kTrimOnMemoryPressureName,
+     flag_descriptions::kTrimOnMemoryPressureDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(
+         performance_manager::features::chromeos::kTrimOnMemoryPressure)},
 #endif  // OS_CHROMEOS
     {
         "disable-accelerated-video-decode",
diff --git a/chrome/browser/accessibility/accessibility_extension_api.h b/chrome/browser/accessibility/accessibility_extension_api.h
index 0d21dd3..92765e4 100644
--- a/chrome/browser/accessibility/accessibility_extension_api.h
+++ b/chrome/browser/accessibility/accessibility_extension_api.h
@@ -14,7 +14,7 @@
 
 // API function that enables or disables web content accessibility support.
 class AccessibilityPrivateSetNativeAccessibilityEnabledFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetNativeAccessibilityEnabledFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION(
@@ -23,8 +23,7 @@
 };
 
 // API function that sets the location of the accessibility focus ring.
-class AccessibilityPrivateSetFocusRingsFunction
-    : public UIThreadExtensionFunction {
+class AccessibilityPrivateSetFocusRingsFunction : public ExtensionFunction {
   ~AccessibilityPrivateSetFocusRingsFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setFocusRings",
@@ -32,8 +31,7 @@
 };
 
 // API function that sets the location of the accessibility highlights.
-class AccessibilityPrivateSetHighlightsFunction
-    : public UIThreadExtensionFunction {
+class AccessibilityPrivateSetHighlightsFunction : public ExtensionFunction {
   ~AccessibilityPrivateSetHighlightsFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setHighlights",
@@ -42,7 +40,7 @@
 
 // API function that sets keyboard capture mode.
 class AccessibilityPrivateSetKeyboardListenerFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetKeyboardListenerFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setKeyboardListener",
@@ -50,8 +48,7 @@
 };
 
 // API function that darkens or undarkens the screen.
-class AccessibilityPrivateDarkenScreenFunction
-    : public UIThreadExtensionFunction {
+class AccessibilityPrivateDarkenScreenFunction : public ExtensionFunction {
   ~AccessibilityPrivateDarkenScreenFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.darkenScreen",
@@ -60,7 +57,7 @@
 
 // Opens a specified subpage in Chrome settings.
 class AccessibilityPrivateOpenSettingsSubpageFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateOpenSettingsSubpageFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.openSettingsSubpage",
@@ -70,7 +67,7 @@
 #if defined(OS_CHROMEOS)
 // API function that sets the keys to be captured by Switch Access.
 class AccessibilityPrivateSetSwitchAccessKeysFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetSwitchAccessKeysFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setSwitchAccessKeys",
@@ -79,7 +76,7 @@
 
 // API function that sets native ChromeVox ARC support.
 class AccessibilityPrivateSetNativeChromeVoxArcSupportForCurrentAppFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetNativeChromeVoxArcSupportForCurrentAppFunction()
       override {}
   ResponseAction Run() override;
@@ -90,7 +87,7 @@
 
 // API function that injects key events.
 class AccessibilityPrivateSendSyntheticKeyEventFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSendSyntheticKeyEventFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.sendSyntheticKeyEvent",
@@ -99,7 +96,7 @@
 
 // API function that enables or disables mouse events in ChromeVox.
 class AccessibilityPrivateEnableChromeVoxMouseEventsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateEnableChromeVoxMouseEventsFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.enableChromeVoxMouseEvents",
@@ -108,7 +105,7 @@
 
 // API function that injects mouse events.
 class AccessibilityPrivateSendSyntheticMouseEventFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSendSyntheticMouseEventFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.sendSyntheticMouseEvent",
@@ -117,7 +114,7 @@
 
 // API function that is called when the Select-to-Speak extension state changes.
 class AccessibilityPrivateOnSelectToSpeakStateChangedFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateOnSelectToSpeakStateChangedFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.onSelectToSpeakStateChanged",
@@ -127,7 +124,7 @@
 // API function that is called when the Autoclick extension finds scrollable
 // bounds.
 class AccessibilityPrivateOnScrollableBoundsForPointFoundFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateOnScrollableBoundsForPointFoundFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION(
@@ -137,8 +134,7 @@
 
 // API function that is called when a user toggles Dictation from another
 // acessibility feature.
-class AccessibilityPrivateToggleDictationFunction
-    : public UIThreadExtensionFunction {
+class AccessibilityPrivateToggleDictationFunction : public ExtensionFunction {
   ~AccessibilityPrivateToggleDictationFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.toggleDictation",
@@ -147,7 +143,7 @@
 
 // API function that is called to show or hide the Switch Access menu.
 class AccessibilityPrivateSetSwitchAccessMenuStateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetSwitchAccessMenuStateFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setSwitchAccessMenuState",
@@ -157,7 +153,7 @@
 // API function that requests that key events be forwarded to the Switch
 // Access extension.
 class AccessibilityPrivateForwardKeyEventsToSwitchAccessFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateForwardKeyEventsToSwitchAccessFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION(
@@ -167,7 +163,7 @@
 
 // API function that is called to get the device's battery status as a string.
 class AccessibilityPrivateGetBatteryDescriptionFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   AccessibilityPrivateGetBatteryDescriptionFunction();
   ResponseAction Run() override;
@@ -180,7 +176,7 @@
 
 // API function that opens or closes the virtual keyboard.
 class AccessibilityPrivateSetVirtualKeyboardVisibleFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetVirtualKeyboardVisibleFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setVirtualKeyboardVisible",
diff --git a/chrome/browser/android/vr/gvr_scheduler_delegate.cc b/chrome/browser/android/vr/gvr_scheduler_delegate.cc
index e18e7947..754f1c23 100644
--- a/chrome/browser/android/vr/gvr_scheduler_delegate.cc
+++ b/chrome/browser/android/vr/gvr_scheduler_delegate.cc
@@ -237,7 +237,6 @@
   }
 
   DVLOG(1) << __func__ << ": render_path=" << static_cast<int>(render_path);
-  MetricsUtilAndroid::LogXrRenderPathUsed(render_path);
 
   device::mojom::XRPresentationTransportOptionsPtr transport_options =
       device::mojom::XRPresentationTransportOptions::New();
diff --git a/chrome/browser/android/vr/metrics_util_android.cc b/chrome/browser/android/vr/metrics_util_android.cc
index 34359eb..e07b22b5 100644
--- a/chrome/browser/android/vr/metrics_util_android.cc
+++ b/chrome/browser/android/vr/metrics_util_android.cc
@@ -84,10 +84,4 @@
   }
 }
 
-// static
-void MetricsUtilAndroid::LogXrRenderPathUsed(XRRenderPath path) {
-  UMA_HISTOGRAM_ENUMERATION("XR.WebXR.RenderPath.Used", path,
-                            XRRenderPath::kCount);
-}
-
 }  // namespace vr
diff --git a/chrome/browser/android/vr/metrics_util_android.h b/chrome/browser/android/vr/metrics_util_android.h
index a7685c7..50f213a 100644
--- a/chrome/browser/android/vr/metrics_util_android.h
+++ b/chrome/browser/android/vr/metrics_util_android.h
@@ -32,8 +32,6 @@
                                            const VrCoreInfo& vr_core_info);
   static void LogVrViewerType(gvr::ViewerType viewer_type);
 
-  static void LogXrRenderPathUsed(XRRenderPath);
-
  private:
   static device::VrViewerType GetVrViewerType(gvr::ViewerType viewer_type);
 
diff --git a/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h
index c0724af..61a7bae 100644
--- a/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h
+++ b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h
@@ -52,8 +52,7 @@
   DISALLOW_COPY_AND_ASSIGN(ArcAppsPrivateAPI);
 };
 
-class ArcAppsPrivateGetLaunchableAppsFunction
-    : public UIThreadExtensionFunction {
+class ArcAppsPrivateGetLaunchableAppsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("arcAppsPrivate.getLaunchableApps",
                              ARCAPPSPRIVATE_GETLAUNCHABLEAPPS)
@@ -70,7 +69,7 @@
   DISALLOW_COPY_AND_ASSIGN(ArcAppsPrivateGetLaunchableAppsFunction);
 };
 
-class ArcAppsPrivateLaunchAppFunction : public UIThreadExtensionFunction {
+class ArcAppsPrivateLaunchAppFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("arcAppsPrivate.launchApp",
                              ARCAPPSPRIVATE_LAUNCHAPP)
diff --git a/chrome/browser/apps/platform_apps/api/browser/browser_api.h b/chrome/browser/apps/platform_apps/api/browser/browser_api.h
index 31eaf0e..daa7fa028 100644
--- a/chrome/browser/apps/platform_apps/api/browser/browser_api.h
+++ b/chrome/browser/apps/platform_apps/api/browser/browser_api.h
@@ -10,7 +10,7 @@
 namespace chrome_apps {
 namespace api {
 
-class BrowserOpenTabFunction : public UIThreadExtensionFunction {
+class BrowserOpenTabFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("browser.openTab", BROWSER_OPENTAB)
 
diff --git a/chrome/browser/apps/platform_apps/api/first_run_private/first_run_private_api.h b/chrome/browser/apps/platform_apps/api/first_run_private/first_run_private_api.h
index f9efc2c6..5b099936 100644
--- a/chrome/browser/apps/platform_apps/api/first_run_private/first_run_private_api.h
+++ b/chrome/browser/apps/platform_apps/api/first_run_private/first_run_private_api.h
@@ -12,8 +12,7 @@
 namespace chrome_apps {
 namespace api {
 
-class FirstRunPrivateGetLocalizedStringsFunction
-    : public UIThreadExtensionFunction {
+class FirstRunPrivateGetLocalizedStringsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("firstRunPrivate.getLocalizedStrings",
                              FIRSTRUNPRIVATE_GETLOCALIZEDSTRINGS)
@@ -25,7 +24,7 @@
   ResponseAction Run() override;
 };
 
-class FirstRunPrivateLaunchTutorialFunction : public UIThreadExtensionFunction {
+class FirstRunPrivateLaunchTutorialFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("firstRunPrivate.launchTutorial",
                              FIRSTRUNPRIVATE_LAUNCHTUTORIAL)
diff --git a/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.h b/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.h
index a726b00..42db857 100644
--- a/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.h
+++ b/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.h
@@ -10,8 +10,7 @@
 namespace chrome_apps {
 namespace api {
 
-class MusicManagerPrivateGetDeviceIdFunction
-    : public UIThreadExtensionFunction {
+class MusicManagerPrivateGetDeviceIdFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("musicManagerPrivate.getDeviceId",
                              MUSICMANAGERPRIVATE_GETDEVICEID)
@@ -21,7 +20,7 @@
  protected:
   ~MusicManagerPrivateGetDeviceIdFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   void DeviceIdCallback(const std::string& device_id);
diff --git a/chrome/browser/apps/platform_apps/api/sync_file_system/sync_file_system_api.h b/chrome/browser/apps/platform_apps/api/sync_file_system/sync_file_system_api.h
index 45f2b4e..1bcfe19 100644
--- a/chrome/browser/apps/platform_apps/api/sync_file_system/sync_file_system_api.h
+++ b/chrome/browser/apps/platform_apps/api/sync_file_system/sync_file_system_api.h
@@ -122,7 +122,7 @@
 };
 
 class SyncFileSystemSetConflictResolutionPolicyFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("syncFileSystem.setConflictResolutionPolicy",
                              SYNCFILESYSTEM_SETCONFLICTRESOLUTIONPOLICY)
@@ -133,7 +133,7 @@
 };
 
 class SyncFileSystemGetConflictResolutionPolicyFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("syncFileSystem.getConflictResolutionPolicy",
                              SYNCFILESYSTEM_GETCONFLICTRESOLUTIONPOLICY)
@@ -143,8 +143,7 @@
   ResponseAction Run() override;
 };
 
-class SyncFileSystemGetServiceStatusFunction
-    : public UIThreadExtensionFunction {
+class SyncFileSystemGetServiceStatusFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("syncFileSystem.getServiceStatus",
                              SYNCFILESYSTEM_GETSERVICESTATUS)
diff --git a/chrome/browser/apps/platform_apps/api/webstore_widget_private/webstore_widget_private_api.h b/chrome/browser/apps/platform_apps/api/webstore_widget_private/webstore_widget_private_api.h
index 9d1aa430..47f80853 100644
--- a/chrome/browser/apps/platform_apps/api/webstore_widget_private/webstore_widget_private_api.h
+++ b/chrome/browser/apps/platform_apps/api/webstore_widget_private/webstore_widget_private_api.h
@@ -15,7 +15,7 @@
 namespace api {
 
 class WebstoreWidgetPrivateInstallWebstoreItemFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   WebstoreWidgetPrivateInstallWebstoreItemFunction();
 
@@ -25,7 +25,7 @@
  protected:
   ~WebstoreWidgetPrivateInstallWebstoreItemFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 11eb6cf..fa58465 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -255,7 +255,6 @@
 #include "components/services/heap_profiling/heap_profiling_service.h"
 #include "components/services/heap_profiling/public/cpp/settings.h"
 #include "components/services/heap_profiling/public/mojom/constants.mojom.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
 #include "components/services/quarantine/public/mojom/quarantine.mojom.h"
 #include "components/services/quarantine/quarantine_service.h"
 #include "components/signin/public/base/signin_pref_names.h"
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
index cee74821..3bfc0f8 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -28,7 +28,7 @@
 
 namespace extensions {
 
-class AutotestPrivateLogoutFunction : public UIThreadExtensionFunction {
+class AutotestPrivateLogoutFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.logout", AUTOTESTPRIVATE_LOGOUT)
 
@@ -37,7 +37,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateRestartFunction : public UIThreadExtensionFunction {
+class AutotestPrivateRestartFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.restart", AUTOTESTPRIVATE_RESTART)
 
@@ -46,7 +46,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateShutdownFunction : public UIThreadExtensionFunction {
+class AutotestPrivateShutdownFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.shutdown",
                              AUTOTESTPRIVATE_SHUTDOWN)
@@ -56,7 +56,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateLoginStatusFunction : public UIThreadExtensionFunction {
+class AutotestPrivateLoginStatusFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.loginStatus",
                              AUTOTESTPRIVATE_LOGINSTATUS)
@@ -66,7 +66,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateLockScreenFunction : public UIThreadExtensionFunction {
+class AutotestPrivateLockScreenFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.lockScreen",
                              AUTOTESTPRIVATE_LOCKSCREEN)
@@ -76,8 +76,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateGetExtensionsInfoFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateGetExtensionsInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getExtensionsInfo",
                              AUTOTESTPRIVATE_GETEXTENSIONSINFO)
@@ -87,8 +86,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSimulateAsanMemoryBugFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSimulateAsanMemoryBugFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.simulateAsanMemoryBug",
                              AUTOTESTPRIVATE_SIMULATEASANMEMORYBUG)
@@ -98,8 +96,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetTouchpadSensitivityFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetTouchpadSensitivityFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setTouchpadSensitivity",
                              AUTOTESTPRIVATE_SETTOUCHPADSENSITIVITY)
@@ -109,7 +106,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetTapToClickFunction : public UIThreadExtensionFunction {
+class AutotestPrivateSetTapToClickFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setTapToClick",
                              AUTOTESTPRIVATE_SETTAPTOCLICK)
@@ -119,8 +116,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetThreeFingerClickFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetThreeFingerClickFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setThreeFingerClick",
                              AUTOTESTPRIVATE_SETTHREEFINGERCLICK)
@@ -130,7 +126,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetTapDraggingFunction : public UIThreadExtensionFunction {
+class AutotestPrivateSetTapDraggingFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setTapDragging",
                              AUTOTESTPRIVATE_SETTAPDRAGGING)
@@ -140,8 +136,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetNaturalScrollFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetNaturalScrollFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setNaturalScroll",
                              AUTOTESTPRIVATE_SETNATURALSCROLL)
@@ -151,8 +146,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetMouseSensitivityFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetMouseSensitivityFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setMouseSensitivity",
                              AUTOTESTPRIVATE_SETMOUSESENSITIVITY)
@@ -162,8 +156,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetPrimaryButtonRightFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetPrimaryButtonRightFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setPrimaryButtonRight",
                              AUTOTESTPRIVATE_SETPRIMARYBUTTONRIGHT)
@@ -173,8 +166,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetMouseReverseScrollFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetMouseReverseScrollFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setMouseReverseScroll",
                              AUTOTESTPRIVATE_SETMOUSEREVERSESCROLL)
@@ -185,7 +177,7 @@
 };
 
 class AutotestPrivateGetVisibleNotificationsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   AutotestPrivateGetVisibleNotificationsFunction();
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getVisibleNotifications",
@@ -196,8 +188,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateGetPlayStoreStateFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateGetPlayStoreStateFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getPlayStoreState",
                              AUTOTESTPRIVATE_GETPLAYSTORESTATE)
@@ -207,7 +198,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateGetArcStateFunction : public UIThreadExtensionFunction {
+class AutotestPrivateGetArcStateFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getArcState",
                              AUTOTESTPRIVATE_GETARCSTATE)
@@ -217,8 +208,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetPlayStoreEnabledFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetPlayStoreEnabledFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setPlayStoreEnabled",
                              AUTOTESTPRIVATE_SETPLAYSTOREENABLED)
@@ -228,7 +218,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateGetHistogramFunction : public UIThreadExtensionFunction {
+class AutotestPrivateGetHistogramFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getHistogram",
                              AUTOTESTPRIVATE_GETHISTOGRAM)
@@ -246,7 +236,7 @@
   ResponseValue GetHistogram(const std::string& name);
 };
 
-class AutotestPrivateIsAppShownFunction : public UIThreadExtensionFunction {
+class AutotestPrivateIsAppShownFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.isAppShown",
                              AUTOTESTPRIVATE_ISAPPSHOWN)
@@ -257,8 +247,7 @@
 };
 
 // Deprecated, use GetArcState instead.
-class AutotestPrivateIsArcProvisionedFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateIsArcProvisionedFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.isArcProvisioned",
                              AUTOTESTPRIVATE_ISARCPROVISIONED)
@@ -268,7 +257,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateGetArcAppFunction : public UIThreadExtensionFunction {
+class AutotestPrivateGetArcAppFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getArcApp",
                              AUTOTESTPRIVATE_GETARCAPP)
@@ -278,7 +267,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateGetArcPackageFunction : public UIThreadExtensionFunction {
+class AutotestPrivateGetArcPackageFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getArcPackage",
                              AUTOTESTPRIVATE_GETARCPACKAGE)
@@ -288,7 +277,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateLaunchArcAppFunction : public UIThreadExtensionFunction {
+class AutotestPrivateLaunchArcAppFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.launchArcApp",
                              AUTOTESTPRIVATE_LAUNCHARCAPP)
@@ -298,7 +287,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateLaunchAppFunction : public UIThreadExtensionFunction {
+class AutotestPrivateLaunchAppFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.launchApp",
                              AUTOTESTPRIVATE_LAUNCHAPP)
@@ -308,7 +297,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateCloseAppFunction : public UIThreadExtensionFunction {
+class AutotestPrivateCloseAppFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.closeApp",
                              AUTOTESTPRIVATE_CLOSEAPP)
@@ -318,8 +307,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetCrostiniEnabledFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetCrostiniEnabledFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setCrostiniEnabled",
                              AUTOTESTPRIVATE_SETCROSTINIENABLED)
@@ -329,8 +317,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateRunCrostiniInstallerFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateRunCrostiniInstallerFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.runCrostiniInstaller",
                              AUTOTESTPRIVATE_RUNCROSTINIINSTALLER)
@@ -342,8 +329,7 @@
   void CrostiniRestarted(crostini::CrostiniResult);
 };
 
-class AutotestPrivateRunCrostiniUninstallerFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateRunCrostiniUninstallerFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.runCrostiniUninstaller",
                              AUTOTESTPRIVATE_RUNCROSTINIUNINSTALLER)
@@ -355,7 +341,7 @@
   void CrostiniRemoved(crostini::CrostiniResult);
 };
 
-class AutotestPrivateExportCrostiniFunction : public UIThreadExtensionFunction {
+class AutotestPrivateExportCrostiniFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.exportCrostini",
                              AUTOTESTPRIVATE_EXPORTCROSTINI)
@@ -367,7 +353,7 @@
   void CrostiniExported(crostini::CrostiniResult);
 };
 
-class AutotestPrivateImportCrostiniFunction : public UIThreadExtensionFunction {
+class AutotestPrivateImportCrostiniFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.importCrostini",
                              AUTOTESTPRIVATE_IMPORTCROSTINI)
@@ -379,7 +365,7 @@
   void CrostiniImported(crostini::CrostiniResult);
 };
 
-class AutotestPrivateTakeScreenshotFunction : public UIThreadExtensionFunction {
+class AutotestPrivateTakeScreenshotFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.takeScreenshot",
                              AUTOTESTPRIVATE_TAKESCREENSHOT)
@@ -394,7 +380,7 @@
 };
 
 class AutotestPrivateGetPrinterListFunction
-    : public UIThreadExtensionFunction,
+    : public ExtensionFunction,
       public chromeos::CupsPrintersManager::Observer {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getPrinterList",
@@ -413,7 +399,7 @@
   base::OneShotTimer timeout_timer_;
 };
 
-class AutotestPrivateUpdatePrinterFunction : public UIThreadExtensionFunction {
+class AutotestPrivateUpdatePrinterFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.updatePrinter",
                              AUTOTESTPRIVATE_UPDATEPRINTER)
@@ -423,7 +409,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateRemovePrinterFunction : public UIThreadExtensionFunction {
+class AutotestPrivateRemovePrinterFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.removePrinter",
                              AUTOTESTPRIVATE_REMOVEPRINTER)
@@ -434,7 +420,7 @@
 };
 
 class AutotestPrivateGetAllEnterprisePoliciesFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getAllEnterprisePolicies",
                              AUTOTESTPRIVATE_GETALLENTERPRISEPOLICIES)
@@ -445,7 +431,7 @@
 };
 
 class AutotestPrivateBootstrapMachineLearningServiceFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   AutotestPrivateBootstrapMachineLearningServiceFunction();
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.bootstrapMachineLearningService",
@@ -465,7 +451,7 @@
 // Enable/disable the Google Assistant feature. This toggles the Assistant user
 // pref which will indirectly bring up or shut down the Assistant service.
 class AutotestPrivateSetAssistantEnabledFunction
-    : public UIThreadExtensionFunction,
+    : public ExtensionFunction,
       public ash::DefaultVoiceInteractionObserver {
  public:
   AutotestPrivateSetAssistantEnabledFunction();
@@ -491,7 +477,7 @@
 
 // Send text query to Assistant and return response.
 class AutotestPrivateSendAssistantTextQueryFunction
-    : public UIThreadExtensionFunction,
+    : public ExtensionFunction,
       public chromeos::assistant::mojom::AssistantInteractionSubscriber {
  public:
   AutotestPrivateSendAssistantTextQueryFunction();
@@ -540,8 +526,7 @@
 };
 
 // Set user pref value in the pref tree.
-class AutotestPrivateSetWhitelistedPrefFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetWhitelistedPrefFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setWhitelistedPref",
                              AUTOTESTPRIVATE_SETWHITELISTEDPREF)
@@ -553,8 +538,7 @@
 
 // Enable/disable a Crostini app's "scaled" property.
 // When an app is "scaled", it will use low display density.
-class AutotestPrivateSetCrostiniAppScaledFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetCrostiniAppScaledFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setCrostiniAppScaled",
                              AUTOTESTPRIVATE_SETCROSTINIAPPSCALED)
@@ -589,7 +573,7 @@
 
 // Get the primary display's scale factor.
 class AutotestPrivateGetPrimaryDisplayScaleFactorFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getPrimaryDisplayScaleFactor",
                              AUTOTESTPRIVATE_GETPRIMARYDISPLAYSCALEFACTOR)
@@ -599,8 +583,7 @@
 };
 
 // Returns if tablet mode is enabled.
-class AutotestPrivateIsTabletModeEnabledFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateIsTabletModeEnabledFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.isTabletModeEnabled",
                              AUTOTESTPRIVATE_ISTABLETMODEENABLED)
@@ -610,8 +593,7 @@
 };
 
 // Enables/Disables tablet mode.
-class AutotestPrivateSetTabletModeEnabledFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetTabletModeEnabledFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setTabletModeEnabled",
                              AUTOTESTPRIVATE_SETTABLETMODEENABLED)
@@ -623,7 +605,7 @@
 
 // Returns the shelf auto hide behavior.
 class AutotestPrivateGetShelfAutoHideBehaviorFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   AutotestPrivateGetShelfAutoHideBehaviorFunction();
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getShelfAutoHideBehavior",
@@ -636,7 +618,7 @@
 
 // Sets shelf autohide behavior.
 class AutotestPrivateSetShelfAutoHideBehaviorFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   AutotestPrivateSetShelfAutoHideBehaviorFunction();
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setShelfAutoHideBehavior",
@@ -648,8 +630,7 @@
 };
 
 // Returns the shelf alignment.
-class AutotestPrivateGetShelfAlignmentFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateGetShelfAlignmentFunction : public ExtensionFunction {
  public:
   AutotestPrivateGetShelfAlignmentFunction();
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.getShelfAlignment",
@@ -661,8 +642,7 @@
 };
 
 // Sets shelf alignment.
-class AutotestPrivateSetShelfAlignmentFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetShelfAlignmentFunction : public ExtensionFunction {
  public:
   AutotestPrivateSetShelfAlignmentFunction();
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setShelfAlignment",
@@ -674,7 +654,7 @@
 };
 
 class AutotestPrivateShowVirtualKeyboardIfEnabledFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   AutotestPrivateShowVirtualKeyboardIfEnabledFunction();
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.showVirtualKeyboardIfEnabled",
@@ -685,8 +665,7 @@
   ResponseAction Run() override;
 };
 
-class AutotestPrivateSetArcAppWindowStateFunction
-    : public UIThreadExtensionFunction {
+class AutotestPrivateSetArcAppWindowStateFunction : public ExtensionFunction {
  public:
   AutotestPrivateSetArcAppWindowStateFunction();
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.setArcAppWindowState",
diff --git a/chrome/browser/chromeos/extensions/echo_private_api.h b/chrome/browser/chromeos/extensions/echo_private_api.h
index 60302f57..0e00caa9 100644
--- a/chrome/browser/chromeos/extensions/echo_private_api.h
+++ b/chrome/browser/chromeos/extensions/echo_private_api.h
@@ -26,8 +26,7 @@
 
 }  // namespace chromeos
 
-class EchoPrivateGetRegistrationCodeFunction
-    : public UIThreadExtensionFunction {
+class EchoPrivateGetRegistrationCodeFunction : public ExtensionFunction {
  public:
   EchoPrivateGetRegistrationCodeFunction();
 
@@ -56,7 +55,7 @@
                              ECHOPRIVATE_GETOOBETIMESTAMP)
 };
 
-class EchoPrivateSetOfferInfoFunction : public UIThreadExtensionFunction {
+class EchoPrivateSetOfferInfoFunction : public ExtensionFunction {
  public:
   EchoPrivateSetOfferInfoFunction();
 
@@ -69,7 +68,7 @@
                              ECHOPRIVATE_SETOFFERINFO)
 };
 
-class EchoPrivateGetOfferInfoFunction : public UIThreadExtensionFunction {
+class EchoPrivateGetOfferInfoFunction : public ExtensionFunction {
  public:
   EchoPrivateGetOfferInfoFunction();
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h
index b892577..bbe7cc8c 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h
@@ -81,7 +81,7 @@
 // The fileBrowserHandlerInternal.selectFile extension function implementation.
 // See the file description for more info.
 class FileBrowserHandlerInternalSelectFileFunction
-    : public extensions::LoggedUIThreadExtensionFunction {
+    : public extensions::LoggedExtensionFunction {
  public:
   // Default constructor used in production code.
   // It will create its own FileSelectorFactory implementation, and set the
@@ -108,7 +108,7 @@
   // The class is ref counted, so destructor should not be public.
   ~FileBrowserHandlerInternalSelectFileFunction() override;
 
-  // UIThreadExtensionFunction implementation.
+  // ExtensionFunction implementation.
   // Runs the extension function implementation.
   ResponseAction Run() override;
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_base.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_base.cc
index 581d480..42eec842 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_base.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_base.cc
@@ -22,16 +22,16 @@
 
 }  // namespace
 
-LoggedUIThreadExtensionFunction::LoggedUIThreadExtensionFunction()
+LoggedExtensionFunction::LoggedExtensionFunction()
     : log_on_completion_(false),
       slow_threshold_(kDefaultSlowOperationThreshold),
       very_slow_threshold_(kDefaultVerySlowOperationThreshold) {
   start_time_ = base::TimeTicks::Now();
 }
 
-LoggedUIThreadExtensionFunction::~LoggedUIThreadExtensionFunction() = default;
+LoggedExtensionFunction::~LoggedExtensionFunction() = default;
 
-void LoggedUIThreadExtensionFunction::OnResponded() {
+void LoggedExtensionFunction::OnResponded() {
   base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
 
   const ChromeExtensionFunctionDetails chrome_details(this);
@@ -61,10 +61,10 @@
                 "ms)",
                 name(), request_id(), elapsed.InMilliseconds());
   }
-  UIThreadExtensionFunction::OnResponded();
+  ExtensionFunction::OnResponded();
 }
 
-void LoggedUIThreadExtensionFunction::SetWarningThresholds(
+void LoggedExtensionFunction::SetWarningThresholds(
     base::TimeDelta slow_threshold,
     base::TimeDelta very_slow_threshold) {
   slow_threshold_ = slow_threshold;
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_base.h b/chrome/browser/chromeos/extensions/file_manager/private_api_base.h
index bf5cd6ce..28423ff3 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_base.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_base.h
@@ -12,7 +12,7 @@
 
 namespace extensions {
 
-// This class adds a logging feature to UIThreadExtensionFunction. Logging is
+// This class adds a logging feature to ExtensionFunction. Logging is
 // done when sending the response to JavaScript, using drive::util::Log().
 // API functions of fileManagerPrivate should inherit this class.
 //
@@ -20,14 +20,14 @@
 // set_log_on_completion(true) to enable it, if they want. However, even if
 // the logging is turned off, a warning is emitted when a function call is
 // very slow. See the implementation of OnResponded() for details.
-class LoggedUIThreadExtensionFunction : public UIThreadExtensionFunction {
+class LoggedExtensionFunction : public ExtensionFunction {
  public:
-  LoggedUIThreadExtensionFunction();
+  LoggedExtensionFunction();
 
  protected:
-  ~LoggedUIThreadExtensionFunction() override;
+  ~LoggedExtensionFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   void OnResponded() override;
 
   void SetWarningThresholds(base::TimeDelta slow_threshold,
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.cc
index 1832a21..712b09d 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.cc
@@ -31,7 +31,7 @@
 
 // Computes the routing ID for SelectFileDialogExtension from the |function|.
 SelectFileDialogExtension::RoutingID GetFileDialogRoutingID(
-    UIThreadExtensionFunction* function) {
+    ExtensionFunction* function) {
   return SelectFileDialogExtensionUserData::GetRoutingIdForWebContents(
       function->GetSenderWebContents());
 }
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.h b/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.h
index 492bb28..6bfcf7a 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.h
@@ -21,8 +21,7 @@
 namespace extensions {
 
 // Cancel file selection Dialog.  Closes the dialog window.
-class FileManagerPrivateCancelDialogFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateCancelDialogFunction : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.cancelDialog",
                              FILEMANAGERPRIVATE_CANCELDIALOG)
@@ -34,8 +33,7 @@
   ResponseAction Run() override;
 };
 
-class FileManagerPrivateSelectFileFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateSelectFileFunction : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.selectFile",
                              FILEMANAGERPRIVATE_SELECTFILE)
@@ -55,8 +53,7 @@
 };
 
 // Select multiple files.  Closes the dialog window.
-class FileManagerPrivateSelectFilesFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateSelectFilesFunction : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.selectFiles",
                              FILEMANAGERPRIVATE_SELECTFILES)
@@ -76,7 +73,7 @@
 
 // Get a list of Android picker apps.
 class FileManagerPrivateGetAndroidPickerAppsFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getAndroidPickerApps",
                              FILEMANAGERPRIVATE_GETANDROIDPICKERAPPS)
@@ -97,7 +94,7 @@
 
 // Select an Android picker app.  Closes the dialog window.
 class FileManagerPrivateSelectAndroidPickerAppFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.selectAndroidPickerApp",
                              FILEMANAGERPRIVATE_SELECTANDROIDPICKERAPP)
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
index c65b8493..9da60d8 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -861,7 +861,7 @@
 }
 
 void OnSearchDriveFs(
-    scoped_refptr<UIThreadExtensionFunction> function,
+    scoped_refptr<ExtensionFunction> function,
     bool filter_dirs,
     base::OnceCallback<void(std::unique_ptr<base::ListValue>)> callback,
     drive::FileError error,
@@ -911,7 +911,7 @@
 }
 
 drivefs::mojom::QueryParameters::QuerySource SearchDriveFs(
-    scoped_refptr<UIThreadExtensionFunction> function,
+    scoped_refptr<ExtensionFunction> function,
     drivefs::mojom::QueryParametersPtr query,
     bool filter_dirs,
     base::OnceCallback<void(std::unique_ptr<base::ListValue>)> callback) {
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
index 7795a90..65f69753 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
@@ -39,7 +39,7 @@
 
 // Implements the chrome.fileManagerPrivate.ensureFileDownloaded method.
 class FileManagerPrivateInternalEnsureFileDownloadedFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalEnsureFileDownloadedFunction();
 
@@ -63,7 +63,7 @@
 // On error, returns a dictionary with the key "error" set to the error number
 // (base::File::Error).
 class FileManagerPrivateInternalGetEntryPropertiesFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.getEntryProperties",
                              FILEMANAGERPRIVATEINTERNAL_GETENTRYPROPERTIES)
@@ -89,7 +89,7 @@
 
 // Implements the chrome.fileManagerPrivate.pinDriveFile method.
 class FileManagerPrivateInternalPinDriveFileFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalPinDriveFileFunction();
 
@@ -114,7 +114,7 @@
 
 // Implements the chrome.fileManagerPrivate.cancelFileTransfers method.
 class FileManagerPrivateInternalCancelFileTransfersFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.cancelFileTransfers",
                              FILEMANAGERPRIVATEINTERNAL_CANCELFILETRANSFERS)
@@ -126,8 +126,7 @@
   ResponseAction Run() override;
 };
 
-class FileManagerPrivateSearchDriveFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateSearchDriveFunction : public LoggedExtensionFunction {
  public:
   typedef std::vector<drive::SearchResultInfo> SearchResultInfoList;
 
@@ -165,7 +164,7 @@
 // Similar to FileManagerPrivateSearchDriveFunction but this one is used for
 // searching drive metadata which is stored locally.
 class FileManagerPrivateSearchDriveMetadataFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   enum class SearchType {
     kText,
@@ -207,7 +206,7 @@
 
 // Implements the chrome.fileManagerPrivate.getDriveConnectionState method.
 class FileManagerPrivateGetDriveConnectionStateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getDriveConnectionState",
                              FILEMANAGERPRIVATE_GETDRIVECONNECTIONSTATE)
@@ -220,7 +219,7 @@
 
 // Implements the chrome.fileManagerPrivate.requestAccessToken method.
 class FileManagerPrivateRequestAccessTokenFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateRequestAccessTokenFunction();
 
@@ -240,7 +239,7 @@
 
 // Implements the chrome.fileManagerPrivate.requestDriveShare method.
 class FileManagerPrivateInternalRequestDriveShareFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalRequestDriveShareFunction();
 
@@ -258,7 +257,7 @@
 
 // Implements the chrome.fileManagerPrivate.getDownloadUrl method.
 class FileManagerPrivateInternalGetDownloadUrlFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalGetDownloadUrlFunction();
 
@@ -295,7 +294,7 @@
 };
 
 class FileManagerPrivateInternalGetThumbnailFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.getThumbnail",
                              FILEMANAGERPRIVATEINTERNAL_GETTHUMBNAIL)
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
index e03f7f2d..69f82140 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
@@ -51,7 +51,7 @@
 // Grant permission to request externalfile scheme. The permission is needed to
 // start drag for external file URL.
 class FileManagerPrivateEnableExternalFileSchemeFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.enableExternalFileScheme",
                              FILEMANAGERPRIVATE_ENABLEEXTERNALFILESCHEME)
@@ -65,7 +65,7 @@
 
 // Grants R/W permissions to profile-specific directories (Drive, Downloads)
 // from other profiles.
-class FileManagerPrivateGrantAccessFunction : public UIThreadExtensionFunction {
+class FileManagerPrivateGrantAccessFunction : public ExtensionFunction {
  public:
   FileManagerPrivateGrantAccessFunction();
 
@@ -86,7 +86,7 @@
 // "FileWatch",
 // the class and its sub classes are used only for watching changes in
 // directories.
-class FileWatchFunctionBase : public LoggedUIThreadExtensionFunction {
+class FileWatchFunctionBase : public LoggedExtensionFunction {
  public:
   using ResponseCallback = base::Callback<void(bool success)>;
 
@@ -167,8 +167,7 @@
 };
 
 // Implements the chrome.fileManagerPrivate.getSizeStats method.
-class FileManagerPrivateGetSizeStatsFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateGetSizeStatsFunction : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getSizeStats",
                              FILEMANAGERPRIVATE_GETSIZESTATS)
@@ -193,7 +192,7 @@
 
 // Implements the chrome.fileManagerPrivate.validatePathNameLength method.
 class FileManagerPrivateInternalValidatePathNameLengthFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION(
       "fileManagerPrivateInternal.validatePathNameLength",
@@ -211,8 +210,7 @@
 
 // Implements the chrome.fileManagerPrivate.formatVolume method.
 // Formats Volume given its mount path.
-class FileManagerPrivateFormatVolumeFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateFormatVolumeFunction : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.formatVolume",
                              FILEMANAGERPRIVATE_FORMATVOLUME)
@@ -226,8 +224,7 @@
 
 // Implements the chrome.fileManagerPrivate.renameVolume method.
 // Renames Volume given its mount path and new Volume name.
-class FileManagerPrivateRenameVolumeFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateRenameVolumeFunction : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.renameVolume",
                              FILEMANAGERPRIVATE_RENAMEVOLUME)
@@ -241,7 +238,7 @@
 
 // Implements the chrome.fileManagerPrivate.startCopy method.
 class FileManagerPrivateInternalStartCopyFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalStartCopyFunction();
 
@@ -276,8 +273,7 @@
 };
 
 // Implements the chrome.fileManagerPrivate.cancelCopy method.
-class FileManagerPrivateCancelCopyFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateCancelCopyFunction : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.cancelCopy",
                              FILEMANAGERPRIVATE_CANCELCOPY)
@@ -292,7 +288,7 @@
 // Implements the chrome.fileManagerPrivateInternal.resolveIsolatedEntries
 // method.
 class FileManagerPrivateInternalResolveIsolatedEntriesFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION(
       "fileManagerPrivateInternal.resolveIsolatedEntries",
@@ -302,7 +298,7 @@
   ~FileManagerPrivateInternalResolveIsolatedEntriesFunction() override =
       default;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -312,7 +308,7 @@
 };
 
 class FileManagerPrivateInternalComputeChecksumFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalComputeChecksumFunction();
 
@@ -334,7 +330,7 @@
 // Implements the chrome.fileManagerPrivate.searchFilesByHashes method.
 // TODO(b/883628): Write some tests maybe?
 class FileManagerPrivateSearchFilesByHashesFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateSearchFilesByHashesFunction();
 
@@ -364,8 +360,7 @@
   const ChromeExtensionFunctionDetails chrome_details_;
 };
 
-class FileManagerPrivateSearchFilesFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateSearchFilesFunction : public LoggedExtensionFunction {
  public:
   FileManagerPrivateSearchFilesFunction();
 
@@ -387,7 +382,7 @@
 
 // Implements the chrome.fileManagerPrivate.setEntryTag method.
 class FileManagerPrivateInternalSetEntryTagFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalSetEntryTagFunction();
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.setEntryTag",
@@ -407,7 +402,7 @@
 
 // Implements the chrome.fileManagerPrivate.getDirectorySize method.
 class FileManagerPrivateInternalGetDirectorySizeFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.getDirectorySize",
                              FILEMANAGERPRIVATEINTERNAL_GETDIRECTORYSIZE)
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
index 3fa8f58..2e57b06e 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -93,7 +93,7 @@
     base::TimeDelta::FromSeconds(30);
 
 // Obtains the current app window.
-AppWindow* GetCurrentAppWindow(UIThreadExtensionFunction* function) {
+AppWindow* GetCurrentAppWindow(ExtensionFunction* function) {
   content::WebContents* const contents = function->GetSenderWebContents();
   return contents
              ? AppWindowRegistry::Get(function->browser_context())
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.h b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.h
index 8ba79a4..42eb24fd5 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.h
@@ -46,7 +46,7 @@
 // Implements the chrome.fileManagerPrivate.logoutUserForReauthentication
 // method.
 class FileManagerPrivateLogoutUserForReauthenticationFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.logoutUserForReauthentication",
                              FILEMANAGERPRIVATE_LOGOUTUSERFORREAUTHENTICATION)
@@ -60,8 +60,7 @@
 
 // Implements the chrome.fileManagerPrivate.getPreferences method.
 // Gets settings for the Files app.
-class FileManagerPrivateGetPreferencesFunction
-    : public UIThreadExtensionFunction {
+class FileManagerPrivateGetPreferencesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getPreferences",
                              FILEMANAGERPRIVATE_GETPREFERENCES)
@@ -74,8 +73,7 @@
 
 // Implements the chrome.fileManagerPrivate.setPreferences method.
 // Sets settings for the Files app.
-class FileManagerPrivateSetPreferencesFunction
-    : public UIThreadExtensionFunction {
+class FileManagerPrivateSetPreferencesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.setPreferences",
                              FILEMANAGERPRIVATE_SETPREFERENCES)
@@ -90,7 +88,7 @@
 // Sets the ARC flag for the Files app and returns what was the state before
 // setting.
 class FileManagerPrivateSetArcStorageToastShownFlagFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.setArcStorageToastShownFlag",
                              FILEMANAGERPRIVATE_SETARCSTORAGETOASTSHOWNFLAG)
@@ -104,7 +102,7 @@
 // Implements the chrome.fileManagerPrivate.zipSelection method.
 // Creates a zip file for the selected files.
 class FileManagerPrivateInternalZipSelectionFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.zipSelection",
                              FILEMANAGERPRIVATEINTERNAL_ZIPSELECTION)
@@ -126,7 +124,7 @@
 // WebContents.
 // TODO(hirono): Remove this function once the zoom level change is supported
 // for all apps. crbug.com/227175.
-class FileManagerPrivateZoomFunction : public UIThreadExtensionFunction {
+class FileManagerPrivateZoomFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.zoom", FILEMANAGERPRIVATE_ZOOM)
 
@@ -138,7 +136,7 @@
 };
 
 class FileManagerPrivateRequestWebStoreAccessTokenFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.requestWebStoreAccessToken",
                              FILEMANAGERPRIVATE_REQUESTWEBSTOREACCESSTOKEN)
@@ -159,7 +157,7 @@
   const ChromeExtensionFunctionDetails chrome_details_;
 };
 
-class FileManagerPrivateGetProfilesFunction : public UIThreadExtensionFunction {
+class FileManagerPrivateGetProfilesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getProfiles",
                              FILEMANAGERPRIVATE_GETPROFILES)
@@ -172,8 +170,7 @@
 };
 
 // Implements the chrome.fileManagerPrivate.openInspector method.
-class FileManagerPrivateOpenInspectorFunction
-    : public UIThreadExtensionFunction {
+class FileManagerPrivateOpenInspectorFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.openInspector",
                              FILEMANAGERPRIVATE_OPENINSPECTOR)
@@ -185,8 +182,7 @@
 };
 
 // Implements the chrome.fileManagerPrivate.openSettingsSubpage method.
-class FileManagerPrivateOpenSettingsSubpageFunction
-    : public UIThreadExtensionFunction {
+class FileManagerPrivateOpenSettingsSubpageFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.openSettingsSubpage",
                              FILEMANAGERPRIVATE_OPENSETTINGSSUBPAGE)
@@ -199,7 +195,7 @@
 
 // Implements the chrome.fileManagerPrivate.getMimeType method.
 class FileManagerPrivateInternalGetMimeTypeFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.getMimeType",
                              FILEMANAGERPRIVATEINTERNAL_GETMIMETYPE)
@@ -216,8 +212,7 @@
 };
 
 // Implements the chrome.fileManagerPrivate.isPiexLoaderEnabled method.
-class FileManagerPrivateIsPiexLoaderEnabledFunction
-    : public UIThreadExtensionFunction {
+class FileManagerPrivateIsPiexLoaderEnabledFunction : public ExtensionFunction {
  public:
   FileManagerPrivateIsPiexLoaderEnabledFunction() = default;
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.isPiexLoaderEnabled",
@@ -231,8 +226,7 @@
 };
 
 // Implements the chrome.fileManagerPrivate.getProviders method.
-class FileManagerPrivateGetProvidersFunction
-    : public UIThreadExtensionFunction {
+class FileManagerPrivateGetProvidersFunction : public ExtensionFunction {
  public:
   FileManagerPrivateGetProvidersFunction();
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getProviders",
@@ -248,7 +242,7 @@
 
 // Implements the chrome.fileManagerPrivate.addProvidedFileSystem method.
 class FileManagerPrivateAddProvidedFileSystemFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   FileManagerPrivateAddProvidedFileSystemFunction();
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.addProvidedFileSystem",
@@ -264,7 +258,7 @@
 
 // Implements the chrome.fileManagerPrivate.configureVolume method.
 class FileManagerPrivateConfigureVolumeFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateConfigureVolumeFunction();
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.configureVolume",
@@ -282,8 +276,7 @@
 
 // Implements the chrome.fileManagerPrivate.mountCrostini method.
 // Starts and mounts crostini container.
-class FileManagerPrivateMountCrostiniFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateMountCrostiniFunction : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.mountCrostini",
                              FILEMANAGERPRIVATE_MOUNTCROSTINI)
@@ -304,7 +297,7 @@
 // Implements the chrome.fileManagerPrivate.sharePathsWithCrostini
 // method.  Shares specified paths.
 class FileManagerPrivateInternalSharePathsWithCrostiniFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION(
       "fileManagerPrivateInternal.sharePathsWithCrostini",
@@ -325,7 +318,7 @@
 // Implements the chrome.fileManagerPrivate.unsharePathWithCrostini
 // method.  Unshares specified path.
 class FileManagerPrivateInternalUnsharePathWithCrostiniFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION(
       "fileManagerPrivateInternal.unsharePathWithCrostini",
@@ -346,7 +339,7 @@
 // Implements the chrome.fileManagerPrivate.getCrostiniSharedPaths
 // method.  Returns list of file entries.
 class FileManagerPrivateInternalGetCrostiniSharedPathsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION(
       "fileManagerPrivateInternal.getCrostiniSharedPaths",
@@ -366,7 +359,7 @@
 // Implements the chrome.fileManagerPrivate.getLinuxPackageInfo method.
 // Retrieves information about a Linux package.
 class FileManagerPrivateInternalGetLinuxPackageInfoFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.getLinuxPackageInfo",
                              FILEMANAGERPRIVATEINTERNAL_GETLINUXPACKAGEINFO)
@@ -386,7 +379,7 @@
 // Implements the chrome.fileManagerPrivate.installLinuxPackage method.
 // Starts installation of a Linux package.
 class FileManagerPrivateInternalInstallLinuxPackageFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.installLinuxPackage",
                              FILEMANAGERPRIVATEINTERNAL_INSTALLLINUXPACKAGE)
@@ -404,7 +397,7 @@
 
 // Implements the chrome.fileManagerPrivate.getCustomActions method.
 class FileManagerPrivateInternalGetCustomActionsFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalGetCustomActionsFunction();
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.getCustomActions",
@@ -423,7 +416,7 @@
 
 // Implements the chrome.fileManagerPrivate.executeCustomAction method.
 class FileManagerPrivateInternalExecuteCustomActionFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalExecuteCustomActionFunction();
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.executeCustomAction",
@@ -442,7 +435,7 @@
 
 // Implements the chrome.fileManagerPrivateInternal.getRecentFiles method.
 class FileManagerPrivateInternalGetRecentFilesFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalGetRecentFilesFunction();
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.getRecentFiles",
@@ -465,7 +458,7 @@
 
 // Implements the chrome.fileManagerPrivate.detectCharacterEncoding method.
 class FileManagerPrivateDetectCharacterEncodingFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.detectCharacterEncoding",
                              FILEMANAGERPRIVATE_DETECTCHARACTERENCODING)
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h
index af49e745..348ebcd 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h
@@ -19,8 +19,7 @@
 
 // Implements chrome.fileManagerPrivate.addMount method.
 // Mounts removable devices and archive files.
-class FileManagerPrivateAddMountFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateAddMountFunction : public LoggedExtensionFunction {
  public:
   FileManagerPrivateAddMountFunction();
 
@@ -58,8 +57,7 @@
 
 // Implements chrome.fileManagerPrivate.removeMount method.
 // Unmounts selected volume. Expects volume id as an argument.
-class FileManagerPrivateRemoveMountFunction
-    : public LoggedUIThreadExtensionFunction {
+class FileManagerPrivateRemoveMountFunction : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.removeMount",
                              FILEMANAGERPRIVATE_REMOVEMOUNT)
@@ -74,7 +72,7 @@
 // Implements chrome.fileManagerPrivate.markCacheAsMounted method.
 // Marks a cached file as mounted or unmounted.
 class FileManagerPrivateMarkCacheAsMountedFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateMarkCacheAsMountedFunction();
 
@@ -107,7 +105,7 @@
 
 // Implements chrome.fileManagerPrivate.getVolumeMetadataList method.
 class FileManagerPrivateGetVolumeMetadataListFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getVolumeMetadataList",
                              FILEMANAGERPRIVATE_GETVOLUMEMETADATALIST)
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.h b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.h
index 95ebdbc..7d2d1f3 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.h
@@ -13,7 +13,7 @@
 
 // Implements the chrome.fileManagerPrivate.getStrings method.
 // Used to get strings for the file manager from JavaScript.
-class FileManagerPrivateGetStringsFunction : public UIThreadExtensionFunction {
+class FileManagerPrivateGetStringsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getStrings",
                              FILEMANAGERPRIVATE_GETSTRINGS)
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h
index 1f9e8548..1127fec 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h
@@ -29,7 +29,7 @@
 
 // Implements the chrome.fileManagerPrivateInternal.executeTask method.
 class FileManagerPrivateInternalExecuteTaskFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalExecuteTaskFunction();
 
@@ -39,7 +39,7 @@
  protected:
   ~FileManagerPrivateInternalExecuteTaskFunction() override = default;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -51,7 +51,7 @@
 
 // Implements the chrome.fileManagerPrivateInternal.getFileTasks method.
 class FileManagerPrivateInternalGetFileTasksFunction
-    : public LoggedUIThreadExtensionFunction {
+    : public LoggedExtensionFunction {
  public:
   FileManagerPrivateInternalGetFileTasksFunction();
 
@@ -61,7 +61,7 @@
  protected:
   ~FileManagerPrivateInternalGetFileTasksFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -87,7 +87,7 @@
 
 // Implements the chrome.fileManagerPrivateInternal.setDefaultTask method.
 class FileManagerPrivateInternalSetDefaultTaskFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.setDefaultTask",
                              FILEMANAGERPRIVATEINTERNAL_SETDEFAULTTASK)
diff --git a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.h b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.h
index e5aab5e..4004b188 100644
--- a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.h
+++ b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.h
@@ -10,7 +10,7 @@
 
 namespace extensions {
 
-class FileSystemProviderMountFunction : public UIThreadExtensionFunction {
+class FileSystemProviderMountFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystemProvider.mount",
                              FILESYSTEMPROVIDER_MOUNT)
@@ -20,7 +20,7 @@
   ResponseAction Run() override;
 };
 
-class FileSystemProviderUnmountFunction : public UIThreadExtensionFunction {
+class FileSystemProviderUnmountFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystemProvider.unmount",
                              FILESYSTEMPROVIDER_UNMOUNT)
@@ -30,7 +30,7 @@
   ResponseAction Run() override;
 };
 
-class FileSystemProviderGetAllFunction : public UIThreadExtensionFunction {
+class FileSystemProviderGetAllFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystemProvider.getAll",
                              FILESYSTEMPROVIDER_GETALL)
@@ -40,7 +40,7 @@
   ResponseAction Run() override;
 };
 
-class FileSystemProviderGetFunction : public UIThreadExtensionFunction {
+class FileSystemProviderGetFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystemProvider.get", FILESYSTEMPROVIDER_GET)
 
diff --git a/chrome/browser/chromeos/extensions/file_system_provider/provider_function.cc b/chrome/browser/chromeos/extensions/file_system_provider/provider_function.cc
index 868ca65..79402b41 100644
--- a/chrome/browser/chromeos/extensions/file_system_provider/provider_function.cc
+++ b/chrome/browser/chromeos/extensions/file_system_provider/provider_function.cc
@@ -148,7 +148,7 @@
 }
 
 bool FileSystemProviderInternalFunction::PreRunValidation(std::string* error) {
-  if (!UIThreadExtensionFunction::PreRunValidation(error))
+  if (!ExtensionFunction::PreRunValidation(error))
     return false;
 
   std::string file_system_id;
diff --git a/chrome/browser/chromeos/extensions/file_system_provider/provider_function.h b/chrome/browser/chromeos/extensions/file_system_provider/provider_function.h
index 14a542a..c7975d8 100644
--- a/chrome/browser/chromeos/extensions/file_system_provider/provider_function.h
+++ b/chrome/browser/chromeos/extensions/file_system_provider/provider_function.h
@@ -46,7 +46,7 @@
 
 // Base class for internal API functions handling request results, either
 // a success or a failure.
-class FileSystemProviderInternalFunction : public UIThreadExtensionFunction {
+class FileSystemProviderInternalFunction : public ExtensionFunction {
  public:
   FileSystemProviderInternalFunction();
 
diff --git a/chrome/browser/chromeos/extensions/info_private_api.h b/chrome/browser/chromeos/extensions/info_private_api.h
index 990dc861..6031439 100644
--- a/chrome/browser/chromeos/extensions/info_private_api.h
+++ b/chrome/browser/chromeos/extensions/info_private_api.h
@@ -16,14 +16,14 @@
 
 namespace extensions {
 
-class ChromeosInfoPrivateGetFunction : public UIThreadExtensionFunction {
+class ChromeosInfoPrivateGetFunction : public ExtensionFunction {
  public:
   ChromeosInfoPrivateGetFunction();
 
  protected:
   ~ChromeosInfoPrivateGetFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -33,21 +33,20 @@
   DECLARE_EXTENSION_FUNCTION("chromeosInfoPrivate.get", CHROMEOSINFOPRIVATE_GET)
 };
 
-class ChromeosInfoPrivateSetFunction : public UIThreadExtensionFunction {
+class ChromeosInfoPrivateSetFunction : public ExtensionFunction {
  public:
   ChromeosInfoPrivateSetFunction();
 
  protected:
   ~ChromeosInfoPrivateSetFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
   DECLARE_EXTENSION_FUNCTION("chromeosInfoPrivate.set", CHROMEOSINFOPRIVATE_SET)
 };
 
-
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_INFO_PRIVATE_API_H_
diff --git a/chrome/browser/chromeos/extensions/input_method_api.h b/chrome/browser/chromeos/extensions/input_method_api.h
index ac44931..4aa05a3 100644
--- a/chrome/browser/chromeos/extensions/input_method_api.h
+++ b/chrome/browser/chromeos/extensions/input_method_api.h
@@ -24,7 +24,7 @@
 
 // Implements the inputMethodPrivate.getInputMethodConfig  method.
 class InputMethodPrivateGetInputMethodConfigFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   InputMethodPrivateGetInputMethodConfigFunction() {}
 
@@ -41,7 +41,7 @@
 
 // Implements the inputMethodPrivate.getCurrentInputMethod method.
 class InputMethodPrivateGetCurrentInputMethodFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   InputMethodPrivateGetCurrentInputMethodFunction() {}
 
@@ -58,7 +58,7 @@
 
 // Implements the inputMethodPrivate.setCurrentInputMethod method.
 class InputMethodPrivateSetCurrentInputMethodFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   InputMethodPrivateSetCurrentInputMethodFunction() {}
 
@@ -74,8 +74,7 @@
 };
 
 // Implements the inputMethodPrivate.getInputMethods method.
-class InputMethodPrivateGetInputMethodsFunction
-    : public UIThreadExtensionFunction {
+class InputMethodPrivateGetInputMethodsFunction : public ExtensionFunction {
  public:
   InputMethodPrivateGetInputMethodsFunction() {}
 
@@ -92,7 +91,7 @@
 
 // Implements the inputMethodPrivate.fetchAllDictionaryWords method.
 class InputMethodPrivateFetchAllDictionaryWordsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   InputMethodPrivateFetchAllDictionaryWordsFunction() {}
 
@@ -108,8 +107,7 @@
 };
 
 // Implements the inputMethodPrivate.addWordToDictionary method.
-class InputMethodPrivateAddWordToDictionaryFunction
-    : public UIThreadExtensionFunction {
+class InputMethodPrivateAddWordToDictionaryFunction : public ExtensionFunction {
  public:
   InputMethodPrivateAddWordToDictionaryFunction() {}
 
@@ -126,7 +124,7 @@
 
 // Implements the inputMethodPrivate.getEncryptSyncEnabled method.
 class InputMethodPrivateGetEncryptSyncEnabledFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   InputMethodPrivateGetEncryptSyncEnabledFunction() {}
 
@@ -142,8 +140,7 @@
 };
 
 // Implements the inputMethodPrivate.setXkbLayout method.
-class InputMethodPrivateSetXkbLayoutFunction
-    : public UIThreadExtensionFunction {
+class InputMethodPrivateSetXkbLayoutFunction : public ExtensionFunction {
  public:
   InputMethodPrivateSetXkbLayoutFunction() {}
 
@@ -159,8 +156,7 @@
 };
 
 // Implements the inputMethodPrivate.showInputView method.
-class InputMethodPrivateShowInputViewFunction
-    : public UIThreadExtensionFunction {
+class InputMethodPrivateShowInputViewFunction : public ExtensionFunction {
  public:
   InputMethodPrivateShowInputViewFunction() {}
 
@@ -176,8 +172,7 @@
 };
 
 // Implements the inputMethodPrivate.openOptionsPage method.
-class InputMethodPrivateOpenOptionsPageFunction
-    : public UIThreadExtensionFunction {
+class InputMethodPrivateOpenOptionsPageFunction : public ExtensionFunction {
  public:
   InputMethodPrivateOpenOptionsPageFunction() {}
 
@@ -192,8 +187,7 @@
   DISALLOW_COPY_AND_ASSIGN(InputMethodPrivateOpenOptionsPageFunction);
 };
 
-class InputMethodPrivateGetSurroundingTextFunction
-    : public UIThreadExtensionFunction {
+class InputMethodPrivateGetSurroundingTextFunction : public ExtensionFunction {
  public:
   InputMethodPrivateGetSurroundingTextFunction() {}
 
@@ -208,7 +202,7 @@
   DISALLOW_COPY_AND_ASSIGN(InputMethodPrivateGetSurroundingTextFunction);
 };
 
-class InputMethodPrivateGetSettingFunction : public UIThreadExtensionFunction {
+class InputMethodPrivateGetSettingFunction : public ExtensionFunction {
  public:
   InputMethodPrivateGetSettingFunction() = default;
 
@@ -224,7 +218,7 @@
   DISALLOW_COPY_AND_ASSIGN(InputMethodPrivateGetSettingFunction);
 };
 
-class InputMethodPrivateSetSettingFunction : public UIThreadExtensionFunction {
+class InputMethodPrivateSetSettingFunction : public ExtensionFunction {
  public:
   InputMethodPrivateSetSettingFunction() = default;
 
@@ -240,8 +234,7 @@
   DISALLOW_COPY_AND_ASSIGN(InputMethodPrivateSetSettingFunction);
 };
 
-class InputMethodPrivateSetCompositionRangeFunction
-    : public UIThreadExtensionFunction {
+class InputMethodPrivateSetCompositionRangeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("inputMethodPrivate.setCompositionRange",
                              INPUTMETHODPRIVATE_SETCOMPOSITIONRANGE)
@@ -249,7 +242,7 @@
  protected:
   ~InputMethodPrivateSetCompositionRangeFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
diff --git a/chrome/browser/chromeos/extensions/launcher_search_provider.h b/chrome/browser/chromeos/extensions/launcher_search_provider.h
index 741d5aab6..40f0d09 100644
--- a/chrome/browser/chromeos/extensions/launcher_search_provider.h
+++ b/chrome/browser/chromeos/extensions/launcher_search_provider.h
@@ -11,7 +11,7 @@
 
 // Implements chrome.launcherSearchProvider.setSearchResults method.
 class LauncherSearchProviderSetSearchResultsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("launcherSearchProvider.setSearchResults",
                              LAUNCHERSEARCHPROVIDER_SETSEARCHRESULTS)
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_api.h b/chrome/browser/chromeos/extensions/login_screen/login/login_api.h
index 20ff168d..c0a65fd5 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/login_api.h
+++ b/chrome/browser/chromeos/extensions/login_screen/login/login_api.h
@@ -17,8 +17,7 @@
 
 }
 
-class LoginLaunchManagedGuestSessionFunction
-    : public UIThreadExtensionFunction {
+class LoginLaunchManagedGuestSessionFunction : public ExtensionFunction {
  public:
   LoginLaunchManagedGuestSessionFunction();
 
@@ -35,7 +34,7 @@
   DISALLOW_COPY_AND_ASSIGN(LoginLaunchManagedGuestSessionFunction);
 };
 
-class LoginExitCurrentSessionFunction : public UIThreadExtensionFunction {
+class LoginExitCurrentSessionFunction : public ExtensionFunction {
  public:
   LoginExitCurrentSessionFunction();
 
@@ -52,7 +51,7 @@
   DISALLOW_COPY_AND_ASSIGN(LoginExitCurrentSessionFunction);
 };
 
-class LoginIsRunningInLoginProfileFunction : public UIThreadExtensionFunction {
+class LoginIsRunningInLoginProfileFunction : public ExtensionFunction {
  public:
   LoginIsRunningInLoginProfileFunction();
 
@@ -69,8 +68,7 @@
   DISALLOW_COPY_AND_ASSIGN(LoginIsRunningInLoginProfileFunction);
 };
 
-class LoginFetchDataForNextLoginAttemptFunction
-    : public UIThreadExtensionFunction {
+class LoginFetchDataForNextLoginAttemptFunction : public ExtensionFunction {
  public:
   LoginFetchDataForNextLoginAttemptFunction();
 
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_screen_ui/login_screen_ui_api.h b/chrome/browser/chromeos/extensions/login_screen/login_screen_ui/login_screen_ui_api.h
index 5c9f342..8d5f2cb2 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login_screen_ui/login_screen_ui_api.h
+++ b/chrome/browser/chromeos/extensions/login_screen/login_screen_ui/login_screen_ui_api.h
@@ -9,7 +9,7 @@
 
 namespace extensions {
 
-class LoginScreenUiShowFunction : public UIThreadExtensionFunction {
+class LoginScreenUiShowFunction : public ExtensionFunction {
  public:
   LoginScreenUiShowFunction();
 
@@ -25,7 +25,7 @@
   DISALLOW_COPY_AND_ASSIGN(LoginScreenUiShowFunction);
 };
 
-class LoginScreenUiCloseFunction : public UIThreadExtensionFunction {
+class LoginScreenUiCloseFunction : public ExtensionFunction {
  public:
   LoginScreenUiCloseFunction();
 
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h
index 6df6964..a3e52426 100644
--- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h
+++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h
@@ -22,7 +22,7 @@
 namespace extensions {
 
 class QuickUnlockPrivateGetAuthTokenFunction
-    : public UIThreadExtensionFunction,
+    : public ExtensionFunction,
       public chromeos::AuthStatusConsumer {
  public:
   using AuthenticatorAllocator =
@@ -67,7 +67,7 @@
 };
 
 class QuickUnlockPrivateSetLockScreenEnabledFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   QuickUnlockPrivateSetLockScreenEnabledFunction();
   DECLARE_EXTENSION_FUNCTION("quickUnlockPrivate.setLockScreenEnabled",
@@ -85,8 +85,7 @@
   DISALLOW_COPY_AND_ASSIGN(QuickUnlockPrivateSetLockScreenEnabledFunction);
 };
 
-class QuickUnlockPrivateGetAvailableModesFunction
-    : public UIThreadExtensionFunction {
+class QuickUnlockPrivateGetAvailableModesFunction : public ExtensionFunction {
  public:
   QuickUnlockPrivateGetAvailableModesFunction();
   DECLARE_EXTENSION_FUNCTION("quickUnlockPrivate.getAvailableModes",
@@ -104,8 +103,7 @@
   DISALLOW_COPY_AND_ASSIGN(QuickUnlockPrivateGetAvailableModesFunction);
 };
 
-class QuickUnlockPrivateGetActiveModesFunction
-    : public UIThreadExtensionFunction {
+class QuickUnlockPrivateGetActiveModesFunction : public ExtensionFunction {
  public:
   QuickUnlockPrivateGetActiveModesFunction();
   DECLARE_EXTENSION_FUNCTION("quickUnlockPrivate.getActiveModes",
@@ -126,8 +124,7 @@
   DISALLOW_COPY_AND_ASSIGN(QuickUnlockPrivateGetActiveModesFunction);
 };
 
-class QuickUnlockPrivateCheckCredentialFunction
-    : public UIThreadExtensionFunction {
+class QuickUnlockPrivateCheckCredentialFunction : public ExtensionFunction {
  public:
   QuickUnlockPrivateCheckCredentialFunction();
   DECLARE_EXTENSION_FUNCTION("quickUnlockPrivate.checkCredential",
@@ -144,7 +141,7 @@
 };
 
 class QuickUnlockPrivateGetCredentialRequirementsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   QuickUnlockPrivateGetCredentialRequirementsFunction();
   DECLARE_EXTENSION_FUNCTION("quickUnlockPrivate.getCredentialRequirements",
@@ -160,7 +157,7 @@
   DISALLOW_COPY_AND_ASSIGN(QuickUnlockPrivateGetCredentialRequirementsFunction);
 };
 
-class QuickUnlockPrivateSetModesFunction : public UIThreadExtensionFunction {
+class QuickUnlockPrivateSetModesFunction : public ExtensionFunction {
  public:
   using QuickUnlockMode =
       extensions::api::quick_unlock_private::QuickUnlockMode;
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
index 9e90689..a9b6e5a 100644
--- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -471,7 +471,7 @@
  private:
   // Runs the given |func| with the given |params|.
   std::unique_ptr<base::Value> RunFunction(
-      scoped_refptr<UIThreadExtensionFunction> func,
+      scoped_refptr<ExtensionFunction> func,
       std::unique_ptr<base::ListValue> params) {
     base::RunLoop().RunUntilIdle();
     std::unique_ptr<base::Value> result =
@@ -485,7 +485,7 @@
 
   // Runs |func| with |params|. Expects and returns an error result.
   std::string RunFunctionAndReturnError(
-      scoped_refptr<UIThreadExtensionFunction> func,
+      scoped_refptr<ExtensionFunction> func,
       std::unique_ptr<base::ListValue> params) {
     base::RunLoop().RunUntilIdle();
     std::unique_ptr<ExtensionFunctionDispatcher> dispatcher(
diff --git a/chrome/browser/chromeos/extensions/users_private/users_private_api.h b/chrome/browser/chromeos/extensions/users_private/users_private_api.h
index c38bf86..eedf258 100644
--- a/chrome/browser/chromeos/extensions/users_private/users_private_api.h
+++ b/chrome/browser/chromeos/extensions/users_private/users_private_api.h
@@ -15,8 +15,7 @@
 namespace extensions {
 
 // Implements the chrome.usersPrivate.getWhitelistedUsers method.
-class UsersPrivateGetWhitelistedUsersFunction
-    : public UIThreadExtensionFunction {
+class UsersPrivateGetWhitelistedUsersFunction : public ExtensionFunction {
  public:
   UsersPrivateGetWhitelistedUsersFunction();
   DECLARE_EXTENSION_FUNCTION("usersPrivate.getWhitelistedUsers",
@@ -35,8 +34,7 @@
 };
 
 // Implements the chrome.usersPrivate.addWhitelistedUser method.
-class UsersPrivateAddWhitelistedUserFunction
-    : public UIThreadExtensionFunction {
+class UsersPrivateAddWhitelistedUserFunction : public ExtensionFunction {
  public:
   UsersPrivateAddWhitelistedUserFunction();
   DECLARE_EXTENSION_FUNCTION("usersPrivate.addWhitelistedUser",
@@ -45,7 +43,7 @@
  protected:
   ~UsersPrivateAddWhitelistedUserFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -55,8 +53,7 @@
 };
 
 // Implements the chrome.usersPrivate.removeWhitelistedUser method.
-class UsersPrivateRemoveWhitelistedUserFunction
-    : public UIThreadExtensionFunction {
+class UsersPrivateRemoveWhitelistedUserFunction : public ExtensionFunction {
  public:
   UsersPrivateRemoveWhitelistedUserFunction();
   DECLARE_EXTENSION_FUNCTION("usersPrivate.removeWhitelistedUser",
@@ -75,8 +72,7 @@
 };
 
 // Implements the chrome.usersPrivate.isWhitelistManaged method.
-class UsersPrivateIsWhitelistManagedFunction
-    : public UIThreadExtensionFunction {
+class UsersPrivateIsWhitelistManagedFunction : public ExtensionFunction {
  public:
   UsersPrivateIsWhitelistManagedFunction();
   DECLARE_EXTENSION_FUNCTION("usersPrivate.isWhitelistManaged",
@@ -93,7 +89,7 @@
 };
 
 // Implements the chrome.usersPrivate.getCurrentUser method.
-class UsersPrivateGetCurrentUserFunction : public UIThreadExtensionFunction {
+class UsersPrivateGetCurrentUserFunction : public ExtensionFunction {
  public:
   UsersPrivateGetCurrentUserFunction();
   DECLARE_EXTENSION_FUNCTION("usersPrivate.getCurrentUser",
@@ -110,7 +106,7 @@
   DISALLOW_COPY_AND_ASSIGN(UsersPrivateGetCurrentUserFunction);
 };
 
-class UsersPrivateGetLoginStatusFunction : public UIThreadExtensionFunction {
+class UsersPrivateGetLoginStatusFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("usersPrivate.getLoginStatus",
                              USERSPRIVATE_GETLOGINSTATUS)
diff --git a/chrome/browser/chromeos/extensions/wallpaper_api.h b/chrome/browser/chromeos/extensions/wallpaper_api.h
index 8a4f75b..adfd7f9 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_api.h
+++ b/chrome/browser/chromeos/extensions/wallpaper_api.h
@@ -30,7 +30,7 @@
  protected:
   ~WallpaperSetWallpaperFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
diff --git a/chrome/browser/chromeos/extensions/wallpaper_function_base.h b/chrome/browser/chromeos/extensions/wallpaper_function_base.h
index c739a9b..13b30d3 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_function_base.h
+++ b/chrome/browser/chromeos/extensions/wallpaper_function_base.h
@@ -33,7 +33,7 @@
 
 // Wallpaper manager function base. It contains a image decoder to decode
 // wallpaper data.
-class WallpaperFunctionBase : public UIThreadExtensionFunction {
+class WallpaperFunctionBase : public ExtensionFunction {
  public:
   static const int kWallpaperThumbnailWidth;
   static const int kWallpaperThumbnailHeight;
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.h b/chrome/browser/chromeos/extensions/wallpaper_private_api.h
index e8cfe3c..8696c8f0e 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api.h
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.h
@@ -26,7 +26,7 @@
 }  // namespace backdrop_wallpaper_handlers
 
 // Wallpaper manager strings.
-class WallpaperPrivateGetStringsFunction : public UIThreadExtensionFunction {
+class WallpaperPrivateGetStringsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.getStrings",
                              WALLPAPERPRIVATE_GETSTRINGS)
@@ -39,8 +39,7 @@
 };
 
 // Check if sync themes setting is enabled.
-class WallpaperPrivateGetSyncSettingFunction
-    : public UIThreadExtensionFunction {
+class WallpaperPrivateGetSyncSettingFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.getSyncSetting",
                              WALLPAPERPRIVATE_GETSYNCSETTING)
@@ -60,8 +59,7 @@
   int retry_number_ = 0;
 };
 
-class WallpaperPrivateSetWallpaperIfExistsFunction
-    : public UIThreadExtensionFunction {
+class WallpaperPrivateSetWallpaperIfExistsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.setWallpaperIfExists",
                              WALLPAPERPRIVATE_SETWALLPAPERIFEXISTS)
@@ -71,7 +69,7 @@
  protected:
   ~WallpaperPrivateSetWallpaperIfExistsFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -81,7 +79,7 @@
   DISALLOW_COPY_AND_ASSIGN(WallpaperPrivateSetWallpaperIfExistsFunction);
 };
 
-class WallpaperPrivateSetWallpaperFunction : public UIThreadExtensionFunction {
+class WallpaperPrivateSetWallpaperFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.setWallpaper",
                              WALLPAPERPRIVATE_SETWALLPAPER)
@@ -91,7 +89,7 @@
  protected:
   ~WallpaperPrivateSetWallpaperFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -101,8 +99,7 @@
   DISALLOW_COPY_AND_ASSIGN(WallpaperPrivateSetWallpaperFunction);
 };
 
-class WallpaperPrivateResetWallpaperFunction
-    : public UIThreadExtensionFunction {
+class WallpaperPrivateResetWallpaperFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.resetWallpaper",
                              WALLPAPERPRIVATE_RESETWALLPAPER)
@@ -112,7 +109,7 @@
  protected:
   ~WallpaperPrivateResetWallpaperFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 };
 
@@ -127,7 +124,7 @@
  protected:
   ~WallpaperPrivateSetCustomWallpaperFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -145,7 +142,7 @@
 };
 
 class WallpaperPrivateSetCustomWallpaperLayoutFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.setCustomWallpaperLayout",
                              WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT)
@@ -155,12 +152,12 @@
  protected:
   ~WallpaperPrivateSetCustomWallpaperLayoutFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 };
 
 class WallpaperPrivateMinimizeInactiveWindowsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.minimizeInactiveWindows",
                              WALLPAPERPRIVATE_MINIMIZEINACTIVEWINDOWS)
@@ -173,7 +170,7 @@
 };
 
 class WallpaperPrivateRestoreMinimizedWindowsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.restoreMinimizedWindows",
                              WALLPAPERPRIVATE_RESTOREMINIMIZEDWINDOWS)
@@ -185,7 +182,7 @@
   ResponseAction Run() override;
 };
 
-class WallpaperPrivateGetThumbnailFunction : public UIThreadExtensionFunction {
+class WallpaperPrivateGetThumbnailFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.getThumbnail",
                              WALLPAPERPRIVATE_GETTHUMBNAIL)
@@ -195,7 +192,7 @@
  protected:
   ~WallpaperPrivateGetThumbnailFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -214,7 +211,7 @@
   void Get(const base::FilePath& path);
 };
 
-class WallpaperPrivateSaveThumbnailFunction : public UIThreadExtensionFunction {
+class WallpaperPrivateSaveThumbnailFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.saveThumbnail",
                              WALLPAPERPRIVATE_SAVETHUMBNAIL)
@@ -224,7 +221,7 @@
  protected:
   ~WallpaperPrivateSaveThumbnailFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -239,7 +236,7 @@
 };
 
 class WallpaperPrivateGetOfflineWallpaperListFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.getOfflineWallpaperList",
                              WALLPAPERPRIVATE_GETOFFLINEWALLPAPERLIST)
@@ -248,7 +245,7 @@
  protected:
   ~WallpaperPrivateGetOfflineWallpaperListFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
  private:
@@ -260,8 +257,7 @@
 
 // The wallpaper UMA is recorded when a new wallpaper is set, either by the
 // built-in Wallpaper Picker App, or by a third party App.
-class WallpaperPrivateRecordWallpaperUMAFunction
-    : public UIThreadExtensionFunction {
+class WallpaperPrivateRecordWallpaperUMAFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.recordWallpaperUMA",
                              WALLPAPERPRIVATE_RECORDWALLPAPERUMA)
@@ -273,8 +269,7 @@
   ResponseAction Run() override;
 };
 
-class WallpaperPrivateGetCollectionsInfoFunction
-    : public UIThreadExtensionFunction {
+class WallpaperPrivateGetCollectionsInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.getCollectionsInfo",
                              WALLPAPERPRIVATE_GETCOLLECTIONSINFO)
@@ -283,7 +278,7 @@
  protected:
   ~WallpaperPrivateGetCollectionsInfoFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -299,7 +294,7 @@
   DISALLOW_COPY_AND_ASSIGN(WallpaperPrivateGetCollectionsInfoFunction);
 };
 
-class WallpaperPrivateGetImagesInfoFunction : public UIThreadExtensionFunction {
+class WallpaperPrivateGetImagesInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.getImagesInfo",
                              WALLPAPERPRIVATE_GETIMAGESINFO)
@@ -308,7 +303,7 @@
  protected:
   ~WallpaperPrivateGetImagesInfoFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -324,8 +319,7 @@
   DISALLOW_COPY_AND_ASSIGN(WallpaperPrivateGetImagesInfoFunction);
 };
 
-class WallpaperPrivateGetLocalImagePathsFunction
-    : public UIThreadExtensionFunction {
+class WallpaperPrivateGetLocalImagePathsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.getLocalImagePaths",
                              WALLPAPERPRIVATE_GETLOCALIMAGEPATHS)
@@ -334,7 +328,7 @@
  protected:
   ~WallpaperPrivateGetLocalImagePathsFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -344,8 +338,7 @@
   DISALLOW_COPY_AND_ASSIGN(WallpaperPrivateGetLocalImagePathsFunction);
 };
 
-class WallpaperPrivateGetLocalImageDataFunction
-    : public UIThreadExtensionFunction {
+class WallpaperPrivateGetLocalImageDataFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.getLocalImageData",
                              WALLPAPERPRIVATE_GETLOCALIMAGEDATA)
@@ -354,7 +347,7 @@
  protected:
   ~WallpaperPrivateGetLocalImageDataFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -366,7 +359,7 @@
 };
 
 class WallpaperPrivateConfirmPreviewWallpaperFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.confirmPreviewWallpaper",
                              WALLPAPERPRIVATE_CONFIRMPREVIEWWALLPAPER)
@@ -375,7 +368,7 @@
  protected:
   ~WallpaperPrivateConfirmPreviewWallpaperFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -383,7 +376,7 @@
 };
 
 class WallpaperPrivateCancelPreviewWallpaperFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.cancelPreviewWallpaper",
                              WALLPAPERPRIVATE_CANCELPREVIEWWALLPAPER)
@@ -392,7 +385,7 @@
  protected:
   ~WallpaperPrivateCancelPreviewWallpaperFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -409,7 +402,7 @@
  protected:
   ~WallpaperPrivateGetCurrentWallpaperThumbnailFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -420,8 +413,7 @@
       WallpaperPrivateGetCurrentWallpaperThumbnailFunction);
 };
 
-class WallpaperPrivateGetSurpriseMeImageFunction
-    : public UIThreadExtensionFunction {
+class WallpaperPrivateGetSurpriseMeImageFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("wallpaperPrivate.getSurpriseMeImage",
                              WALLPAPERPRIVATE_GETSURPRISEMEIMAGE)
@@ -430,7 +422,7 @@
  protected:
   ~WallpaperPrivateGetSurpriseMeImageFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc
index f03c16c..30b6967 100644
--- a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc
+++ b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc
@@ -211,7 +211,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override {}
-  void ProceedWithResponse() override {}
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
diff --git a/chrome/browser/chromeos/printing/cups_proxy_service_manager.cc b/chrome/browser/chromeos/printing/cups_proxy_service_manager.cc
index 1c4f879..81d6d0a 100644
--- a/chrome/browser/chromeos/printing/cups_proxy_service_manager.cc
+++ b/chrome/browser/chromeos/printing/cups_proxy_service_manager.cc
@@ -6,8 +6,10 @@
 
 #include <memory>
 
+#include "base/feature_list.h"
 #include "chrome/browser/chromeos/printing/cups_proxy_service_delegate_impl.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/services/cups_proxy/public/mojom/constants.mojom.h"
 #include "chromeos/dbus/cups_proxy/cups_proxy_client.h"
 #include "content/public/browser/browser_context.h"
@@ -16,8 +18,12 @@
 namespace chromeos {
 
 CupsProxyServiceManager::CupsProxyServiceManager() : weak_factory_(this) {
-  CupsProxyClient::Get()->WaitForServiceToBeAvailable(base::BindOnce(
-      &CupsProxyServiceManager::OnDaemonAvailable, weak_factory_.GetWeakPtr()));
+  // Don't wait for the daemon if the feature is turned off anyway.
+  if (base::FeatureList::IsEnabled(features::kCrosVmCupsProxy)) {
+    CupsProxyClient::Get()->WaitForServiceToBeAvailable(
+        base::BindOnce(&CupsProxyServiceManager::OnDaemonAvailable,
+                       weak_factory_.GetWeakPtr()));
+  }
 }
 
 CupsProxyServiceManager::~CupsProxyServiceManager() = default;
diff --git a/chrome/browser/component_updater/chrome_component_updater_configurator.cc b/chrome/browser/component_updater/chrome_component_updater_configurator.cc
index ed04175..8532e5a1b 100644
--- a/chrome/browser/component_updater/chrome_component_updater_configurator.cc
+++ b/chrome/browser/component_updater/chrome_component_updater_configurator.cc
@@ -27,6 +27,7 @@
 #include "components/component_updater/configurator_impl.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
+#include "components/services/patch/content/patch_service.h"
 #include "components/services/unzip/content/unzip_service.h"
 #include "components/update_client/activity_data_service.h"
 #include "components/update_client/net/network_chromium.h"
@@ -36,9 +37,7 @@
 #include "components/update_client/unzipper.h"
 #include "components/update_client/update_query_params.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/system_connector.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 #if defined(OS_WIN)
 #include "base/enterprise_util.h"
@@ -204,7 +203,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!patch_factory_) {
     patch_factory_ = base::MakeRefCounted<update_client::PatchChromiumFactory>(
-        content::GetSystemConnector()->Clone());
+        base::BindRepeating(&patch::LaunchFilePatcher));
   }
   return patch_factory_;
 }
diff --git a/chrome/browser/component_updater/component_patcher_operation_browsertest.cc b/chrome/browser/component_updater/component_patcher_operation_browsertest.cc
index 952c70d..5a750789 100644
--- a/chrome/browser/component_updater/component_patcher_operation_browsertest.cc
+++ b/chrome/browser/component_updater/component_patcher_operation_browsertest.cc
@@ -17,14 +17,13 @@
 #include "base/task/task_traits.h"
 #include "build/build_config.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/services/patch/content/patch_service.h"
 #include "components/services/patch/public/cpp/patch.h"
 #include "components/update_client/component_patcher_operation.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/system_connector.h"
 #include "courgette/courgette.h"
 #include "courgette/third_party/bsdiff/bsdiff.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 namespace {
 
@@ -95,27 +94,23 @@
     quit_closure_ = run_loop.QuitClosure();
     done_called_ = false;
 
-    std::unique_ptr<service_manager::Connector> connector =
-        content::GetSystemConnector()->Clone();
     base::CreateSequencedTaskRunnerWithTraits(kTaskTraits)
-        ->PostTask(
-            FROM_HERE,
-            base::BindOnce(&PatchTest::PatchAsyncSequencedTaskRunner,
-                           base::Unretained(this), std::move(connector),
-                           operation, input, patch, output, expected_result));
+        ->PostTask(FROM_HERE,
+                   base::BindOnce(&PatchTest::PatchAsyncSequencedTaskRunner,
+                                  base::Unretained(this), operation, input,
+                                  patch, output, expected_result));
     run_loop.Run();
     EXPECT_TRUE(done_called_);
   }
 
  private:
   void PatchAsyncSequencedTaskRunner(
-      std::unique_ptr<service_manager::Connector> connector,
       const std::string& operation,
       const base::FilePath& input,
       const base::FilePath& patch,
       const base::FilePath& output,
       int expected_result) {
-    patch::Patch(connector.get(), operation, input, patch, output,
+    patch::Patch(patch::LaunchFilePatcher(), operation, input, patch, output,
                  base::BindOnce(&PatchTest::PatchDone, base::Unretained(this),
                                 expected_result));
   }
diff --git a/chrome/browser/downgrade/OWNERS b/chrome/browser/downgrade/OWNERS
index fcf1b41..f2d06103 100644
--- a/chrome/browser/downgrade/OWNERS
+++ b/chrome/browser/downgrade/OWNERS
@@ -1,2 +1,3 @@
 georgesak@chromium.org
 zmin@chromium.org
+# COMPONENT: Enterprise
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 0bc1900..b91ace4 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -220,16 +220,6 @@
   return mime_type;
 }
 
-// Reason for why danger type is DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE.
-// Used by "Download.DangerousFile.Reason" UMA metric.
-// Do not change the ordering or remove items.
-enum DangerousFileReason {
-  SB_NOT_AVAILABLE = 0,
-  SB_RETURNS_UNKOWN = 1,
-  SB_RETURNS_SAFE = 2,
-  DANGEROUS_FILE_REASON_MAX
-};
-
 // On Android, Chrome wants to warn the user of file overwrites rather than
 // uniquify.
 #if defined(OS_ANDROID)
@@ -517,8 +507,6 @@
             download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
             download::DOWNLOAD_INTERRUPT_REASON_NONE);
       }
-      UMA_HISTOGRAM_ENUMERATION("Download.DangerousFile.Reason",
-                                SB_NOT_AVAILABLE, DANGEROUS_FILE_REASON_MAX);
       base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
                                internal_complete_callback);
       return false;
@@ -1155,9 +1143,6 @@
         if (DownloadItemModel(item).GetDangerLevel() !=
             DownloadFileType::NOT_DANGEROUS) {
           danger_type = download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
-          UMA_HISTOGRAM_ENUMERATION("Download.DangerousFile.Reason",
-                                    SB_RETURNS_UNKOWN,
-                                    DANGEROUS_FILE_REASON_MAX);
         }
         break;
       case safe_browsing::DownloadCheckResult::SAFE:
@@ -1167,8 +1152,6 @@
         if (DownloadItemModel(item).GetDangerLevel() ==
             DownloadFileType::DANGEROUS) {
           danger_type = download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
-          UMA_HISTOGRAM_ENUMERATION("Download.DangerousFile.Reason",
-                                    SB_RETURNS_SAFE, DANGEROUS_FILE_REASON_MAX);
         }
         break;
       case safe_browsing::DownloadCheckResult::DANGEROUS:
diff --git a/chrome/browser/enterprise_reporting/report_generator.cc b/chrome/browser/enterprise_reporting/report_generator.cc
index 0863dad..4952084 100644
--- a/chrome/browser/enterprise_reporting/report_generator.cc
+++ b/chrome/browser/enterprise_reporting/report_generator.cc
@@ -58,7 +58,7 @@
     return;
   }
 
-  requests_.push_back(
+  requests_.push(
       std::make_unique<em::ChromeDesktopReportRequest>(basic_request_));
   GetNextProfileReport(0);
 }
@@ -167,7 +167,7 @@
              maximum_report_size_) {
     // The new full Profile report is too big to be appended into the current
     // request, move it to the next request if possible.
-    requests_.push_back(
+    requests_.push(
         std::make_unique<em::ChromeDesktopReportRequest>(basic_request_));
     requests_.back()
         ->mutable_browser_report()
diff --git a/chrome/browser/enterprise_reporting/report_generator.h b/chrome/browser/enterprise_reporting/report_generator.h
index 87e5ddd..7468c90 100644
--- a/chrome/browser/enterprise_reporting/report_generator.h
+++ b/chrome/browser/enterprise_reporting/report_generator.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_GENERATOR_H_
 
 #include <memory>
+#include <queue>
 #include <string>
 #include <vector>
 
@@ -19,13 +20,13 @@
 
 class ReportGenerator {
  public:
-  using ReportCallback = base::OnceCallback<void(
-      std::vector<std::unique_ptr<em::ChromeDesktopReportRequest>>)>;
+  using Requests = std::queue<std::unique_ptr<em::ChromeDesktopReportRequest>>;
+  using ReportCallback = base::OnceCallback<void(Requests)>;
 
   ReportGenerator();
-  ~ReportGenerator();
+  virtual ~ReportGenerator();
 
-  void Generate(ReportCallback callback);
+  virtual void Generate(ReportCallback callback);
 
   void SetMaximumReportSizeForTesting(size_t size);
 
@@ -65,7 +66,7 @@
 
   ReportCallback callback_;
 
-  std::vector<std::unique_ptr<em::ChromeDesktopReportRequest>> requests_;
+  Requests requests_;
 
   // Basic information that is shared among requests.
   em::ChromeDesktopReportRequest basic_request_;
diff --git a/chrome/browser/enterprise_reporting/report_generator_unittest.cc b/chrome/browser/enterprise_reporting/report_generator_unittest.cc
index 8fbf7a2..f2bde05d 100644
--- a/chrome/browser/enterprise_reporting/report_generator_unittest.cc
+++ b/chrome/browser/enterprise_reporting/report_generator_unittest.cc
@@ -126,10 +126,11 @@
     base::RunLoop run_loop;
     std::vector<std::unique_ptr<em::ChromeDesktopReportRequest>> rets;
     generator_.Generate(base::BindLambdaForTesting(
-        [&run_loop,
-         &rets](std::vector<std::unique_ptr<em::ChromeDesktopReportRequest>>
-                    requests) {
-          rets = std::move(requests);
+        [&run_loop, &rets](ReportGenerator::Requests requests) {
+          while (!requests.empty()) {
+            rets.push_back(std::move(requests.front()));
+            requests.pop();
+          }
           run_loop.Quit();
         }));
     run_loop.Run();
diff --git a/chrome/browser/enterprise_reporting/report_scheduler.cc b/chrome/browser/enterprise_reporting/report_scheduler.cc
index ca13c06..ba91c89 100644
--- a/chrome/browser/enterprise_reporting/report_scheduler.cc
+++ b/chrome/browser/enterprise_reporting/report_scheduler.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/syslog_logging.h"
 #include "base/task/post_task.h"
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
@@ -27,6 +28,7 @@
 namespace {
 const int kDefaultUploadIntervalHours =
     24;  // Default upload interval is 24 hours.
+const int kMaximumRetry = 10;  // Retry 10 times takes about 15 to 19 hours.
 
 // Reads DM token and client id. Returns true if boths are non empty.
 bool GetDMTokenAndDeviceId(std::string* dm_token, std::string* client_id) {
@@ -52,14 +54,21 @@
 
 ReportScheduler::ReportScheduler(
     std::unique_ptr<policy::CloudPolicyClient> client,
-    std::unique_ptr<RequestTimer> request_timer)
+    std::unique_ptr<RequestTimer> request_timer,
+    std::unique_ptr<ReportGenerator> report_generator)
     : cloud_policy_client_(std::move(client)),
-      request_timer_(std::move(request_timer)) {
+      request_timer_(std::move(request_timer)),
+      report_generator_(std::move(report_generator)) {
   RegisterPerfObserver();
 }
 
 ReportScheduler::~ReportScheduler() = default;
 
+void ReportScheduler::SetReportUploaderForTesting(
+    std::unique_ptr<ReportUploader> uploader) {
+  report_uploader_ = std::move(uploader);
+}
+
 void ReportScheduler::RegisterPerfObserver() {
   pref_change_registrar_.Init(g_browser_process->local_state());
   pref_change_registrar_.Add(
@@ -103,27 +112,48 @@
 }
 
 void ReportScheduler::GenerateAndUploadReport() {
-  VLOG(1) << "Uploading enterprise report.";
-  // TODO(zmin): Generates a real request.
-  std::unique_ptr<em::ChromeDesktopReportRequest> request =
-      std::make_unique<em::ChromeDesktopReportRequest>();
-  cloud_policy_client_->UploadChromeDesktopReport(
-      std::move(request),
-      base::BindRepeating(&ReportScheduler::OnReportUploaded,
-                          base::Unretained(this)));
+  VLOG(1) << "Generating enterprise report.";
+  report_generator_->Generate(base::BindOnce(
+      &ReportScheduler::OnReportGenerated, base::Unretained(this)));
 }
 
-void ReportScheduler::OnReportUploaded(bool status) {
-  if (status) {
-    VLOG(1) << "The enterprise report has been uploaded.";
-    g_browser_process->local_state()->SetTime(kLastUploadTimestamp,
-                                              base::Time::Now());
-    if (IsReportingEnabled())
-      request_timer_->Reset();
+void ReportScheduler::OnReportGenerated(ReportGenerator::Requests requests) {
+  if (requests.empty()) {
+    SYSLOG(ERROR)
+        << "No cloud report can be generated. Likely the report is too large.";
+    // We can't generate any report, stop the reporting.
     return;
   }
-  VLOG(1) << "The enterprise report has not been uploaded.";
-  // TODO(zmin): Implement retry logic
+  VLOG(1) << "Uploading enterprise report.";
+  if (!report_uploader_) {
+    report_uploader_ = std::make_unique<ReportUploader>(
+        cloud_policy_client_.get(), kMaximumRetry);
+  }
+  report_uploader_->SetRequestAndUpload(
+      std::move(requests), base::BindOnce(&ReportScheduler::OnReportUploaded,
+                                          base::Unretained(this)));
+}
+
+void ReportScheduler::OnReportUploaded(ReportUploader::ReportStatus status) {
+  VLOG(1) << "The enterprise report upload result " << status;
+  switch (status) {
+    case ReportUploader::kSuccess:
+      // Schedule the next report for success. Reset uploader to reset failure
+      // count.
+      report_uploader_.reset();
+      FALLTHROUGH;
+    case ReportUploader::kTransientError:
+      // Stop retrying and schedule the next report to avoid stale report.
+      // Failure count is not reset so retry delay remains.
+      g_browser_process->local_state()->SetTime(kLastUploadTimestamp,
+                                                base::Time::Now());
+      if (IsReportingEnabled())
+        request_timer_->Reset();
+      break;
+    case ReportUploader::kPersistentError:
+      // No future upload until Chrome relaunch or perf change event.
+      break;
+  }
 }
 
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/report_scheduler.h b/chrome/browser/enterprise_reporting/report_scheduler.h
index 98a8a666..c48133f 100644
--- a/chrome/browser/enterprise_reporting/report_scheduler.h
+++ b/chrome/browser/enterprise_reporting/report_scheduler.h
@@ -6,9 +6,12 @@
 #define CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_SCHEDULER_H_
 
 #include <memory>
+#include <queue>
 #include <string>
 
 #include "base/macros.h"
+#include "chrome/browser/enterprise_reporting/report_generator.h"
+#include "chrome/browser/enterprise_reporting/report_uploader.h"
 #include "components/prefs/pref_change_registrar.h"
 
 namespace policy {
@@ -24,10 +27,13 @@
 class ReportScheduler {
  public:
   ReportScheduler(std::unique_ptr<policy::CloudPolicyClient> client,
-                  std::unique_ptr<RequestTimer> request_timer);
+                  std::unique_ptr<RequestTimer> request_timer,
+                  std::unique_ptr<ReportGenerator> report_generator);
 
   ~ReportScheduler();
 
+  void SetReportUploaderForTesting(std::unique_ptr<ReportUploader> uploader);
+
  private:
   // Observes CloudReportingEnabled policy.
   void RegisterPerfObserver();
@@ -42,8 +48,11 @@
   // Generates a report and uploads it.
   void GenerateAndUploadReport();
 
+  // Callback once report is generated.
+  void OnReportGenerated(ReportGenerator::Requests requests);
+
   // Callback once report upload request is finished.
-  void OnReportUploaded(bool status);
+  void OnReportUploaded(ReportUploader::ReportStatus status);
 
   // Policy value watcher
   PrefChangeRegistrar pref_change_registrar_;
@@ -52,6 +61,10 @@
 
   std::unique_ptr<RequestTimer> request_timer_;
 
+  std::unique_ptr<ReportUploader> report_uploader_;
+
+  std::unique_ptr<ReportGenerator> report_generator_;
+
   DISALLOW_COPY_AND_ASSIGN(ReportScheduler);
 };
 
diff --git a/chrome/browser/enterprise_reporting/report_scheduler_unittest.cc b/chrome/browser/enterprise_reporting/report_scheduler_unittest.cc
index 1be2c60..1f01d088 100644
--- a/chrome/browser/enterprise_reporting/report_scheduler_unittest.cc
+++ b/chrome/browser/enterprise_reporting/report_scheduler_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/test/gmock_callback_support.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "chrome/browser/enterprise_reporting/prefs.h"
@@ -19,6 +20,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::base::test::RunOnceCallback;
 using ::testing::_;
 using ::testing::Invoke;
 using ::testing::WithArgs;
@@ -69,6 +71,35 @@
   DISALLOW_COPY_AND_ASSIGN(FakeRequestTimer);
 };
 
+ACTION_P(ScheduleGeneratorCallback, request_number) {
+  ReportGenerator::Requests requests;
+  for (int i = 0; i < request_number; i++)
+    requests.push(std::make_unique<em::ChromeDesktopReportRequest>());
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(arg0), std::move(requests)));
+}
+
+class MockReportGenerator : public ReportGenerator {
+ public:
+  void Generate(ReportCallback callback) override { OnGenerate(callback); }
+  MOCK_METHOD1(OnGenerate, void(ReportCallback& callback));
+};
+
+class MockReportUploader : public ReportUploader {
+ public:
+  MockReportUploader() : ReportUploader(nullptr, 0) {}
+  ~MockReportUploader() override = default;
+  void SetRequestAndUpload(Requests requests,
+                           ReportCallback callback) override {
+    OnSetRequestAndUpload(requests, callback);
+  }
+  MOCK_METHOD2(OnSetRequestAndUpload,
+               void(Requests& requests, ReportCallback& callback));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockReportUploader);
+};
+
 class ReportSchedulerTest : public ::testing::Test {
  public:
   ReportSchedulerTest()
@@ -84,6 +115,10 @@
     client_ = client_ptr_.get();
     timer_ptr_ = std::make_unique<FakeRequestTimer>();
     timer_ = timer_ptr_.get();
+    generator_ptr_ = std::make_unique<MockReportGenerator>();
+    generator_ = generator_ptr_.get();
+    uploader_ptr_ = std::make_unique<MockReportUploader>();
+    uploader_ = uploader_ptr_.get();
     Init(true, kDMToken, kClientId);
   }
 
@@ -97,7 +132,9 @@
 
   void CreateScheduler() {
     scheduler_ = std::make_unique<ReportScheduler>(std::move(client_ptr_),
-                                                   std::move(timer_ptr_));
+                                                   std::move(timer_ptr_),
+                                                   std::move(generator_ptr_));
+    scheduler_->SetReportUploaderForTesting(std::move(uploader_ptr_));
   }
 
   void SetLastUploadInHour(int gap) {
@@ -125,19 +162,30 @@
     }
   }
 
+  ReportGenerator::Requests CreateRequests(int number) {
+    ReportGenerator::Requests requests;
+    for (int i = 0; i < number; i++)
+      requests.push(std::make_unique<em::ChromeDesktopReportRequest>());
+    return requests;
+  }
+
   base::test::ScopedFeatureList scoped_feature_list_;
   base::test::ScopedTaskEnvironment scoped_task_environment_;
   ScopedTestingLocalState local_state_;
 
   std::unique_ptr<ReportScheduler> scheduler_;
-  FakeRequestTimer* timer_;
   policy::MockCloudPolicyClient* client_;
+  FakeRequestTimer* timer_;
+  MockReportGenerator* generator_;
+  MockReportUploader* uploader_;
   policy::FakeBrowserDMTokenStorage storage_;
   base::Time previous_set_last_upload_timestamp_;
 
  private:
   std::unique_ptr<policy::MockCloudPolicyClient> client_ptr_;
   std::unique_ptr<FakeRequestTimer> timer_ptr_;
+  std::unique_ptr<MockReportGenerator> generator_ptr_;
+  std::unique_ptr<MockReportUploader> uploader_ptr_;
   DISALLOW_COPY_AND_ASSIGN(ReportSchedulerTest);
 };
 
@@ -161,8 +209,10 @@
 
 TEST_F(ReportSchedulerTest, UploadReportSucceeded) {
   EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _));
-  EXPECT_CALL(*client_, UploadChromeDesktopReportProxy(_, _))
-      .WillOnce(WithArgs<1>(policy::ScheduleStatusCallback(true)));
+  EXPECT_CALL(*generator_, OnGenerate(_))
+      .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1)));
+  EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _))
+      .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
 
   CreateScheduler();
   EXPECT_TRUE(timer_->is_running());
@@ -180,12 +230,43 @@
   ExpectLastUploadTimestampUpdated(true);
 
   ::testing::Mock::VerifyAndClearExpectations(client_);
+  ::testing::Mock::VerifyAndClearExpectations(generator_);
 }
 
-TEST_F(ReportSchedulerTest, UploadFailed) {
+TEST_F(ReportSchedulerTest, UploadReportTransientError) {
   EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _));
-  EXPECT_CALL(*client_, UploadChromeDesktopReportProxy(_, _))
-      .WillOnce(WithArgs<1>(policy::ScheduleStatusCallback(false)));
+  EXPECT_CALL(*generator_, OnGenerate(_))
+      .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1)));
+  EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _))
+      .WillOnce(RunOnceCallback<1>(ReportUploader::kTransientError));
+
+  CreateScheduler();
+  EXPECT_TRUE(timer_->is_running());
+
+  timer_->Fire();
+
+  // timer is paused until the report is finished.
+  EXPECT_FALSE(timer_->is_running());
+
+  // Run pending task.
+  scoped_task_environment_.FastForwardBy(base::TimeDelta());
+
+  // Next report is scheduled.
+  EXPECT_TRUE(timer_->is_running());
+  ExpectLastUploadTimestampUpdated(true);
+
+  ::testing::Mock::VerifyAndClearExpectations(client_);
+  ::testing::Mock::VerifyAndClearExpectations(generator_);
+}
+
+TEST_F(ReportSchedulerTest, UploadReportPersistentError) {
+  EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _))
+      .WillOnce(WithArgs<0>(
+          Invoke(client_, &policy::MockCloudPolicyClient::SetDMToken)));
+  EXPECT_CALL(*generator_, OnGenerate(_))
+      .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1)));
+  EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _))
+      .WillOnce(RunOnceCallback<1>(ReportUploader::kPersistentError));
 
   CreateScheduler();
   EXPECT_TRUE(timer_->is_running());
@@ -202,7 +283,45 @@
   EXPECT_FALSE(timer_->is_running());
   ExpectLastUploadTimestampUpdated(false);
 
+  // Turn off and on reporting to resume.
+  ToggleCloudReport(false);
+  ToggleCloudReport(true);
+  EXPECT_TRUE(timer_->is_running());
+
   ::testing::Mock::VerifyAndClearExpectations(client_);
+  ::testing::Mock::VerifyAndClearExpectations(generator_);
+}
+
+TEST_F(ReportSchedulerTest, NoReportGenerate) {
+  EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _))
+      .WillOnce(WithArgs<0>(
+          Invoke(client_, &policy::MockCloudPolicyClient::SetDMToken)));
+  EXPECT_CALL(*generator_, OnGenerate(_))
+      .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(0)));
+  EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)).Times(0);
+
+  CreateScheduler();
+  EXPECT_TRUE(timer_->is_running());
+
+  timer_->Fire();
+
+  // timer is paused until the report is finished.
+  EXPECT_FALSE(timer_->is_running());
+
+  // Run pending task.
+  scoped_task_environment_.FastForwardBy(base::TimeDelta());
+
+  // Next report is not scheduled.
+  EXPECT_FALSE(timer_->is_running());
+  ExpectLastUploadTimestampUpdated(false);
+
+  // Turn off and on reporting to resume.
+  ToggleCloudReport(false);
+  ToggleCloudReport(true);
+  EXPECT_TRUE(timer_->is_running());
+
+  ::testing::Mock::VerifyAndClearExpectations(client_);
+  ::testing::Mock::VerifyAndClearExpectations(generator_);
 }
 
 TEST_F(ReportSchedulerTest, TimerDelayWithLastUploadTimestamp) {
@@ -220,6 +339,7 @@
             timer_->repeat_delay());
 
   ::testing::Mock::VerifyAndClearExpectations(client_);
+  ::testing::Mock::VerifyAndClearExpectations(generator_);
 }
 
 TEST_F(ReportSchedulerTest, TimerDelayWithoutLastUploadTimestamp) {
@@ -249,12 +369,15 @@
   ExpectLastUploadTimestampUpdated(false);
 
   ::testing::Mock::VerifyAndClearExpectations(client_);
+  ::testing::Mock::VerifyAndClearExpectations(generator_);
 }
 
 TEST_F(ReportSchedulerTest, ReportingIsDisabledWhileNewReportIsPosted) {
   EXPECT_CALL(*client_, SetupRegistration(kDMToken, kClientId, _));
-  EXPECT_CALL(*client_, UploadChromeDesktopReportProxy(_, _))
-      .WillOnce(WithArgs<1>(policy::ScheduleStatusCallback(true)));
+  EXPECT_CALL(*generator_, OnGenerate(_))
+      .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1)));
+  EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _))
+      .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess));
 
   CreateScheduler();
   EXPECT_TRUE(timer_->is_running());
@@ -271,6 +394,7 @@
   EXPECT_FALSE(timer_->is_running());
 
   ::testing::Mock::VerifyAndClearExpectations(client_);
+  ::testing::Mock::VerifyAndClearExpectations(generator_);
 }
 
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/report_uploader.cc b/chrome/browser/enterprise_reporting/report_uploader.cc
index 72c6ef3..614087a3 100644
--- a/chrome/browser/enterprise_reporting/report_uploader.cc
+++ b/chrome/browser/enterprise_reporting/report_uploader.cc
@@ -34,9 +34,8 @@
       maximum_number_of_retries_(maximum_number_of_retries) {}
 ReportUploader::~ReportUploader() = default;
 
-void ReportUploader::SetRequestAndUpload(
-    std::queue<std::unique_ptr<em::ChromeDesktopReportRequest>> requests,
-    ReportCallback callback) {
+void ReportUploader::SetRequestAndUpload(Requests requests,
+                                         ReportCallback callback) {
   requests_ = std::move(requests);
   callback_ = std::move(callback);
   Upload();
diff --git a/chrome/browser/enterprise_reporting/report_uploader.h b/chrome/browser/enterprise_reporting/report_uploader.h
index 3ec75e8..e4337b56 100644
--- a/chrome/browser/enterprise_reporting/report_uploader.h
+++ b/chrome/browser/enterprise_reporting/report_uploader.h
@@ -48,18 +48,17 @@
                        // invalid dm token.
   };
 
+  using Requests = std::queue<std::unique_ptr<em::ChromeDesktopReportRequest>>;
   // A callback to notify the upload result.
   using ReportCallback = base::OnceCallback<void(ReportStatus status)>;
 
   ReportUploader(policy::CloudPolicyClient* client,
                  int maximum_number_of_retries);
-  ~ReportUploader();
+  virtual ~ReportUploader();
 
   // Sets a list of requests and upload it. Request will be uploaded one after
   // another.
-  void SetRequestAndUpload(
-      std::queue<std::unique_ptr<em::ChromeDesktopReportRequest>> requests,
-      ReportCallback callback);
+  virtual void SetRequestAndUpload(Requests requests, ReportCallback callback);
 
  private:
   // Uploads the first request in the queue.
@@ -81,7 +80,7 @@
 
   policy::CloudPolicyClient* client_;
   ReportCallback callback_;
-  std::queue<std::unique_ptr<em::ChromeDesktopReportRequest>> requests_;
+  Requests requests_;
 
   net::BackoffEntry backoff_entry_;
   base::OneShotTimer backoff_request_timer_;
diff --git a/chrome/browser/enterprise_reporting/report_uploader_unittest.cc b/chrome/browser/enterprise_reporting/report_uploader_unittest.cc
index 76f63c2..b3998a0 100644
--- a/chrome/browser/enterprise_reporting/report_uploader_unittest.cc
+++ b/chrome/browser/enterprise_reporting/report_uploader_unittest.cc
@@ -35,7 +35,7 @@
       int number_of_request,
       ReportUploader::ReportStatus expected_status) {
     DCHECK_LE(number_of_request, 2) << "Please update kOsUserNames above.";
-    std::queue<std::unique_ptr<em::ChromeDesktopReportRequest>> requests;
+    ReportUploader::Requests requests;
     for (int i = 0; i < number_of_request; i++) {
       auto request = std::make_unique<em::ChromeDesktopReportRequest>();
       request->set_os_user_name(kOsUserNames[i]);
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index c678c5d..3b6e53c 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -832,6 +832,7 @@
     "//components/safe_browsing/common:safe_browsing_prefs",
     "//components/safe_browsing/db:database_manager",
     "//components/search_engines",
+    "//components/services/patch/content",
     "//components/services/unzip/content",
     "//components/services/unzip/public/cpp",
     "//components/sessions",
diff --git a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h
index d900d64..afee1976 100644
--- a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h
+++ b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h
@@ -82,8 +82,7 @@
 };
 
 // The implementation of activityLogPrivate.deleteActivities
-class ActivityLogPrivateDeleteActivitiesFunction
-    : public UIThreadExtensionFunction {
+class ActivityLogPrivateDeleteActivitiesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("activityLogPrivate.deleteActivities",
                              ACTIVITYLOGPRIVATE_DELETEACTIVITIES)
@@ -97,7 +96,7 @@
 
 // The implementation of activityLogPrivate.deleteActivitiesByExtension
 class ActivityLogPrivateDeleteActivitiesByExtensionFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("activityLogPrivate.deleteActivitiesByExtension",
                              ACTIVITYLOGPRIVATE_DELETEACTIVITIESBYEXTENSION)
@@ -110,8 +109,7 @@
 };
 
 // The implementation of activityLogPrivate.deleteDatabase
-class ActivityLogPrivateDeleteDatabaseFunction
-    : public UIThreadExtensionFunction {
+class ActivityLogPrivateDeleteDatabaseFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("activityLogPrivate.deleteDatabase",
                              ACTIVITYLOGPRIVATE_DELETEDATABASE)
@@ -124,7 +122,7 @@
 };
 
 // The implementation of activityLogPrivate.deleteUrls
-class ActivityLogPrivateDeleteUrlsFunction : public UIThreadExtensionFunction {
+class ActivityLogPrivateDeleteUrlsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("activityLogPrivate.deleteUrls",
                              ACTIVITYLOGPRIVATE_DELETEURLS)
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.h b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
index 20a4924..5b42cd4 100644
--- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
+++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
@@ -13,7 +13,7 @@
 
 namespace extensions {
 
-class AutofillPrivateSaveAddressFunction : public UIThreadExtensionFunction {
+class AutofillPrivateSaveAddressFunction : public ExtensionFunction {
  public:
   AutofillPrivateSaveAddressFunction();
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.saveAddress",
@@ -31,7 +31,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillPrivateSaveAddressFunction);
 };
 
-class AutofillPrivateGetCountryListFunction : public UIThreadExtensionFunction {
+class AutofillPrivateGetCountryListFunction : public ExtensionFunction {
  public:
   AutofillPrivateGetCountryListFunction();
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.getCountryList",
@@ -49,8 +49,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetCountryListFunction);
 };
 
-class AutofillPrivateGetAddressComponentsFunction :
-    public UIThreadExtensionFunction {
+class AutofillPrivateGetAddressComponentsFunction : public ExtensionFunction {
  public:
   AutofillPrivateGetAddressComponentsFunction() {}
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.getAddressComponents",
@@ -66,7 +65,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetAddressComponentsFunction);
 };
 
-class AutofillPrivateGetAddressListFunction : public UIThreadExtensionFunction {
+class AutofillPrivateGetAddressListFunction : public ExtensionFunction {
  public:
   AutofillPrivateGetAddressListFunction();
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.getAddressList",
@@ -84,7 +83,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetAddressListFunction);
 };
 
-class AutofillPrivateSaveCreditCardFunction : public UIThreadExtensionFunction {
+class AutofillPrivateSaveCreditCardFunction : public ExtensionFunction {
  public:
   AutofillPrivateSaveCreditCardFunction();
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.saveCreditCard",
@@ -102,7 +101,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillPrivateSaveCreditCardFunction);
 };
 
-class AutofillPrivateRemoveEntryFunction : public UIThreadExtensionFunction {
+class AutofillPrivateRemoveEntryFunction : public ExtensionFunction {
  public:
   AutofillPrivateRemoveEntryFunction();
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.removeEntry",
@@ -120,8 +119,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillPrivateRemoveEntryFunction);
 };
 
-class AutofillPrivateValidatePhoneNumbersFunction :
-    public UIThreadExtensionFunction {
+class AutofillPrivateValidatePhoneNumbersFunction : public ExtensionFunction {
  public:
   AutofillPrivateValidatePhoneNumbersFunction() {}
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.validatePhoneNumbers",
@@ -137,7 +135,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillPrivateValidatePhoneNumbersFunction);
 };
 
-class AutofillPrivateMaskCreditCardFunction : public UIThreadExtensionFunction {
+class AutofillPrivateMaskCreditCardFunction : public ExtensionFunction {
  public:
   AutofillPrivateMaskCreditCardFunction();
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.maskCreditCard",
@@ -155,8 +153,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillPrivateMaskCreditCardFunction);
 };
 
-class AutofillPrivateGetCreditCardListFunction
-    : public UIThreadExtensionFunction {
+class AutofillPrivateGetCreditCardListFunction : public ExtensionFunction {
  public:
   AutofillPrivateGetCreditCardListFunction();
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.getCreditCardList",
@@ -174,8 +171,7 @@
   DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetCreditCardListFunction);
 };
 
-class AutofillPrivateMigrateCreditCardsFunction
-    : public UIThreadExtensionFunction {
+class AutofillPrivateMigrateCreditCardsFunction : public ExtensionFunction {
  public:
   AutofillPrivateMigrateCreditCardsFunction();
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.migrateCreditCards",
@@ -194,7 +190,7 @@
 };
 
 class AutofillPrivateLogServerCardLinkClickedFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   AutofillPrivateLogServerCardLinkClickedFunction();
   DECLARE_EXTENSION_FUNCTION("autofillPrivate.logServerCardLinkClicked",
diff --git a/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc b/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc
index ea3db0a..f233313 100644
--- a/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc
+++ b/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc
@@ -66,7 +66,7 @@
 }
 
 content::WebContents* ChromeAutomationInternalApiDelegate::GetActiveWebContents(
-    UIThreadExtensionFunction* function) {
+    ExtensionFunction* function) {
   return ChromeExtensionFunctionDetails(function)
       .GetCurrentBrowser()
       ->tab_strip_model()
diff --git a/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h b/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h
index 474b575d..f2bdc73 100644
--- a/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h
+++ b/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h
@@ -26,7 +26,7 @@
                   std::string* error_msg) override;
   int GetTabId(content::WebContents* contents) override;
   content::WebContents* GetActiveWebContents(
-      UIThreadExtensionFunction* function) override;
+      ExtensionFunction* function) override;
   void EnableDesktop() override;
   ui::AXTreeID GetAXTreeID() override;
   void SetEventBundleSink(ui::AXEventBundleSink* sink) override;
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.h b/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.h
index d6a88e0..2684e50 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.h
+++ b/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.h
@@ -107,7 +107,7 @@
 };
 
 class BrailleDisplayPrivateUpdateBluetoothBrailleDisplayAddressFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~BrailleDisplayPrivateUpdateBluetoothBrailleDisplayAddressFunction()
       override {}
   ResponseAction Run() override;
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_api.h b/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
index d5a9a0c..2a588cf 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
@@ -61,7 +61,7 @@
 
 }  // namespace extension_browsing_data_api_constants
 
-class BrowsingDataSettingsFunction : public UIThreadExtensionFunction {
+class BrowsingDataSettingsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("browsingData.settings", BROWSINGDATA_SETTINGS)
 
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h
index 67b8ee0..b61e947 100644
--- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h
+++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h
@@ -28,9 +28,9 @@
 }
 
 class CertificateProviderInternalReportCertificatesFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  private:
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ~CertificateProviderInternalReportCertificatesFunction() override;
   ResponseAction Run() override;
 
@@ -43,9 +43,9 @@
 };
 
 class CertificateProviderInternalReportSignatureFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  private:
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ~CertificateProviderInternalReportSignatureFunction() override;
   ResponseAction Run() override;
 
@@ -53,9 +53,9 @@
                              CERTIFICATEPROVIDERINTERNAL_REPORTSIGNATURE)
 };
 
-class CertificateProviderRequestPinFunction : public UIThreadExtensionFunction {
+class CertificateProviderRequestPinFunction : public ExtensionFunction {
  private:
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ~CertificateProviderRequestPinFunction() override;
   ResponseAction Run() override;
   bool ShouldSkipQuotaLimiting() const override;
@@ -68,10 +68,9 @@
                              CERTIFICATEPROVIDER_REQUESTPIN)
 };
 
-class CertificateProviderStopPinRequestFunction
-    : public UIThreadExtensionFunction {
+class CertificateProviderStopPinRequestFunction : public ExtensionFunction {
  private:
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ~CertificateProviderStopPinRequestFunction() override;
   ResponseAction Run() override;
 
diff --git a/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h b/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h
index eb7494ec..35900ac 100644
--- a/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h
+++ b/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h
@@ -48,8 +48,7 @@
   virtual std::vector<std::string> GetPrinters() = 0;
 };
 
-class CloudPrintPrivateSetupConnectorFunction
-    : public UIThreadExtensionFunction {
+class CloudPrintPrivateSetupConnectorFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("cloudPrintPrivate.setupConnector",
                              CLOUDPRINTPRIVATE_SETUPCONNECTOR)
@@ -63,7 +62,7 @@
   ResponseAction Run() override;
 };
 
-class CloudPrintPrivateGetHostNameFunction : public UIThreadExtensionFunction {
+class CloudPrintPrivateGetHostNameFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("cloudPrintPrivate.getHostName",
                              CLOUDPRINTPRIVATE_GETHOSTNAME)
@@ -77,7 +76,7 @@
   ResponseAction Run() override;
 };
 
-class CloudPrintPrivateGetPrintersFunction : public UIThreadExtensionFunction {
+class CloudPrintPrivateGetPrintersFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("cloudPrintPrivate.getPrinters",
                              CLOUDPRINTPRIVATE_GETPRINTERS)
@@ -94,7 +93,7 @@
   ResponseAction Run() override;
 };
 
-class CloudPrintPrivateGetClientIdFunction : public UIThreadExtensionFunction {
+class CloudPrintPrivateGetClientIdFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("cloudPrintPrivate.getClientId",
                              CLOUDPRINTPRIVATE_GETCLIENTID)
diff --git a/chrome/browser/extensions/api/command_line_private/command_line_private_api.h b/chrome/browser/extensions/api/command_line_private/command_line_private_api.h
index 4ab0dd1..56841a47 100644
--- a/chrome/browser/extensions/api/command_line_private/command_line_private_api.h
+++ b/chrome/browser/extensions/api/command_line_private/command_line_private_api.h
@@ -9,7 +9,7 @@
 
 namespace extensions {
 
-class CommandLinePrivateHasSwitchFunction : public UIThreadExtensionFunction {
+class CommandLinePrivateHasSwitchFunction : public ExtensionFunction {
   DECLARE_EXTENSION_FUNCTION("commandLinePrivate.hasSwitch",
                              COMMANDLINEPRIVATE_HASSWITCH)
  protected:
diff --git a/chrome/browser/extensions/api/commands/commands.h b/chrome/browser/extensions/api/commands/commands.h
index 16b940f..433bdd1 100644
--- a/chrome/browser/extensions/api/commands/commands.h
+++ b/chrome/browser/extensions/api/commands/commands.h
@@ -7,7 +7,7 @@
 
 #include "extensions/browser/extension_function.h"
 
-class GetAllCommandsFunction : public UIThreadExtensionFunction {
+class GetAllCommandsFunction : public ExtensionFunction {
   ~GetAllCommandsFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("commands.getAll", COMMANDS_GETALL)
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_api.h b/chrome/browser/extensions/api/content_settings/content_settings_api.h
index fa0fb0c..be5d320 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_api.h
+++ b/chrome/browser/extensions/api/content_settings/content_settings_api.h
@@ -14,8 +14,7 @@
 
 namespace extensions {
 
-class ContentSettingsContentSettingClearFunction
-    : public UIThreadExtensionFunction {
+class ContentSettingsContentSettingClearFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("contentSettings.clear", CONTENTSETTINGS_CLEAR)
 
@@ -26,8 +25,7 @@
   ResponseAction Run() override;
 };
 
-class ContentSettingsContentSettingGetFunction
-    : public UIThreadExtensionFunction {
+class ContentSettingsContentSettingGetFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("contentSettings.get", CONTENTSETTINGS_GET)
 
@@ -38,8 +36,7 @@
   ResponseAction Run() override;
 };
 
-class ContentSettingsContentSettingSetFunction
-    : public UIThreadExtensionFunction {
+class ContentSettingsContentSettingSetFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("contentSettings.set", CONTENTSETTINGS_SET)
 
diff --git a/chrome/browser/extensions/api/context_menus/context_menus_api.h b/chrome/browser/extensions/api/context_menus/context_menus_api.h
index 78e00b7..4dc9f201 100644
--- a/chrome/browser/extensions/api/context_menus/context_menus_api.h
+++ b/chrome/browser/extensions/api/context_menus/context_menus_api.h
@@ -9,7 +9,7 @@
 
 namespace extensions {
 
-class ContextMenusCreateFunction : public UIThreadExtensionFunction {
+class ContextMenusCreateFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("contextMenus.create", CONTEXTMENUS_CREATE)
 
@@ -20,7 +20,7 @@
   ResponseAction Run() override;
 };
 
-class ContextMenusUpdateFunction : public UIThreadExtensionFunction {
+class ContextMenusUpdateFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("contextMenus.update", CONTEXTMENUS_UPDATE)
 
@@ -31,7 +31,7 @@
   ResponseAction Run() override;
 };
 
-class ContextMenusRemoveFunction : public UIThreadExtensionFunction {
+class ContextMenusRemoveFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("contextMenus.remove", CONTEXTMENUS_REMOVE)
 
@@ -42,7 +42,7 @@
   ResponseAction Run() override;
 };
 
-class ContextMenusRemoveAllFunction : public UIThreadExtensionFunction {
+class ContextMenusRemoveAllFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("contextMenus.removeAll", CONTEXTMENUS_REMOVEALL)
 
diff --git a/chrome/browser/extensions/api/cookies/cookies_api.h b/chrome/browser/extensions/api/cookies/cookies_api.h
index fbd37d6..1ac9de5 100644
--- a/chrome/browser/extensions/api/cookies/cookies_api.h
+++ b/chrome/browser/extensions/api/cookies/cookies_api.h
@@ -91,7 +91,7 @@
 };
 
 // Implements the cookies.get() extension function.
-class CookiesGetFunction : public UIThreadExtensionFunction {
+class CookiesGetFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("cookies.get", COOKIES_GET)
 
@@ -113,7 +113,7 @@
 };
 
 // Implements the cookies.getAll() extension function.
-class CookiesGetAllFunction : public UIThreadExtensionFunction {
+class CookiesGetAllFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("cookies.getAll", COOKIES_GETALL)
 
@@ -135,7 +135,7 @@
 };
 
 // Implements the cookies.set() extension function.
-class CookiesSetFunction : public UIThreadExtensionFunction {
+class CookiesSetFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("cookies.set", COOKIES_SET)
 
@@ -159,7 +159,7 @@
 };
 
 // Implements the cookies.remove() extension function.
-class CookiesRemoveFunction : public UIThreadExtensionFunction {
+class CookiesRemoveFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("cookies.remove", COOKIES_REMOVE)
 
@@ -180,7 +180,7 @@
 };
 
 // Implements the cookies.getAllCookieStores() extension function.
-class CookiesGetAllCookieStoresFunction : public UIThreadExtensionFunction {
+class CookiesGetAllCookieStoresFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("cookies.getAllCookieStores",
                              COOKIES_GETALLCOOKIESTORES)
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h
index 7c92493..9ac938c8 100644
--- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h
+++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h
@@ -27,18 +27,18 @@
     user_prefs::PrefRegistrySyncable* registry);
 
 class CryptotokenPrivateCanOriginAssertAppIdFunction
-    : public UIThreadExtensionFunction {
-  public:
-    CryptotokenPrivateCanOriginAssertAppIdFunction();
-    DECLARE_EXTENSION_FUNCTION("cryptotokenPrivate.canOriginAssertAppId",
-                               CRYPTOTOKENPRIVATE_CANORIGINASSERTAPPID)
-  protected:
-    ~CryptotokenPrivateCanOriginAssertAppIdFunction() override {}
-    ResponseAction Run() override;
+    : public ExtensionFunction {
+ public:
+  CryptotokenPrivateCanOriginAssertAppIdFunction();
+  DECLARE_EXTENSION_FUNCTION("cryptotokenPrivate.canOriginAssertAppId",
+                             CRYPTOTOKENPRIVATE_CANORIGINASSERTAPPID)
+ protected:
+  ~CryptotokenPrivateCanOriginAssertAppIdFunction() override {}
+  ResponseAction Run() override;
 };
 
 class CryptotokenPrivateIsAppIdHashInEnterpriseContextFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   CryptotokenPrivateIsAppIdHashInEnterpriseContextFunction();
   DECLARE_EXTENSION_FUNCTION(
@@ -51,7 +51,7 @@
 };
 
 class CryptotokenPrivateCanAppIdGetAttestationFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   CryptotokenPrivateCanAppIdGetAttestationFunction();
   DECLARE_EXTENSION_FUNCTION("cryptotokenPrivate.canAppIdGetAttestation",
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
index 0500f7e..4ed224a 100644
--- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
@@ -31,7 +31,7 @@
 
 using namespace api::cryptotoken_private;
 
-bool GetSingleBooleanResult(UIThreadExtensionFunction* function, bool* result) {
+bool GetSingleBooleanResult(ExtensionFunction* function, bool* result) {
   const base::ListValue* result_list = function->GetResultList();
   if (!result_list) {
     ADD_FAILURE() << "Function has no result list.";
diff --git a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.h b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.h
index 66697ef..93a75ad 100644
--- a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.h
+++ b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.h
@@ -23,7 +23,7 @@
 class Extension;
 
 class DashboardPrivateShowPermissionPromptForDelegatedInstallFunction
-    : public UIThreadExtensionFunction,
+    : public ExtensionFunction,
       public WebstoreInstallHelper::Delegate {
  public:
   DECLARE_EXTENSION_FUNCTION(
diff --git a/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.h b/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.h
index 8af53d7..0730691 100644
--- a/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.h
+++ b/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.h
@@ -15,8 +15,7 @@
 
 namespace extensions {
 
-class DataReductionProxyClearDataSavingsFunction
-    : public UIThreadExtensionFunction {
+class DataReductionProxyClearDataSavingsFunction : public ExtensionFunction {
  private:
   ~DataReductionProxyClearDataSavingsFunction() override {}
 
@@ -26,8 +25,7 @@
   ResponseAction Run() override;
 };
 
-class DataReductionProxyGetDataUsageFunction
-    : public UIThreadExtensionFunction {
+class DataReductionProxyGetDataUsageFunction : public ExtensionFunction {
  private:
   ~DataReductionProxyGetDataUsageFunction() override {}
 
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
index 595a331..798348f 100644
--- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
+++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
@@ -67,7 +67,7 @@
 };
 
 class DesktopCaptureCancelChooseDesktopMediaFunctionBase
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DesktopCaptureCancelChooseDesktopMediaFunctionBase();
 
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h
index 4113d20..639cf9e 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -294,7 +294,7 @@
 
 namespace api {
 
-class DeveloperPrivateAPIFunction : public UIThreadExtensionFunction {
+class DeveloperPrivateAPIFunction : public ExtensionFunction {
  protected:
   ~DeveloperPrivateAPIFunction() override;
 
@@ -488,7 +488,7 @@
   DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateShowPermissionsDialogFunction);
 };
 
-class DeveloperPrivateChooseEntryFunction : public UIThreadExtensionFunction,
+class DeveloperPrivateChooseEntryFunction : public ExtensionFunction,
                                             public EntryPickerClient {
  protected:
   ~DeveloperPrivateChooseEntryFunction() override;
@@ -498,7 +498,6 @@
                   int file_type_index);
 };
 
-
 class DeveloperPrivateLoadUnpackedFunction
     : public DeveloperPrivateChooseEntryFunction {
  public:
@@ -611,8 +610,7 @@
   std::string key_path_str_;
 };
 
-class DeveloperPrivateIsProfileManagedFunction
-    : public UIThreadExtensionFunction {
+class DeveloperPrivateIsProfileManagedFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("developerPrivate.isProfileManaged",
                              DEVELOPERPRIVATE_ISPROFILEMANAGED)
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index d4de3f8..91bb48ea2 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -126,7 +126,7 @@
 
   // A wrapper around extension_function_test_utils::RunFunction that runs with
   // the associated browser, no flags, and can take stack-allocated arguments.
-  bool RunFunction(const scoped_refptr<UIThreadExtensionFunction>& function,
+  bool RunFunction(const scoped_refptr<ExtensionFunction>& function,
                    const base::ListValue& args);
 
   // Loads an unpacked extension that is backed by a real directory, allowing
@@ -184,7 +184,7 @@
 };
 
 bool DeveloperPrivateApiUnitTest::RunFunction(
-    const scoped_refptr<UIThreadExtensionFunction>& function,
+    const scoped_refptr<ExtensionFunction>& function,
     const base::ListValue& args) {
   return extension_function_test_utils::RunFunction(
       function.get(), args.CreateDeepCopy(), browser(), api_test_utils::NONE);
@@ -234,7 +234,7 @@
     const base::Callback<bool()>& has_pref,
     const std::string& key,
     const std::string& extension_id) {
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateUpdateExtensionConfigurationFunction());
 
   EXPECT_FALSE(has_pref.Run()) << key;
@@ -279,7 +279,7 @@
     const base::ListValue& args,
     api::developer_private::PackStatus expected_status,
     int expected_flags) {
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivatePackDirectoryFunction());
   if (!RunFunction(function, args))
     return testing::AssertionFailure() << "Could not run function.";
@@ -308,7 +308,7 @@
 
 void DeveloperPrivateApiUnitTest::UpdateProfileConfigurationDevMode(
     bool dev_mode) {
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateUpdateProfileConfigurationFunction());
   std::unique_ptr<base::ListValue> args =
       ListBuilder()
@@ -319,7 +319,7 @@
 
 void DeveloperPrivateApiUnitTest::GetProfileConfiguration(
     std::unique_ptr<api::developer_private::ProfileInfo>* profile_info) {
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateGetProfileConfigurationFunction());
   base::ListValue args;
   EXPECT_TRUE(RunFunction(function, args)) << function->GetError();
@@ -337,7 +337,7 @@
     base::StringPiece new_access) {
   SCOPED_TRACE(new_access);
   ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
-  scoped_refptr<UIThreadExtensionFunction> function = base::MakeRefCounted<
+  scoped_refptr<ExtensionFunction> function = base::MakeRefCounted<
       api::DeveloperPrivateUpdateExtensionConfigurationFunction>();
   std::string args =
       base::StringPrintf(R"([{"extensionId": "%s", "hostAccess": "%s"}])",
@@ -405,7 +405,7 @@
 TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateReload) {
   const Extension* extension = LoadUnpackedExtension();
   std::string extension_id = extension->id();
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateReloadFunction());
   base::ListValue reload_args;
   reload_args.AppendString(extension_id);
@@ -486,7 +486,7 @@
   base::ListValue choose_args;
   choose_args.AppendString("FOLDER");
   choose_args.AppendString("LOAD");
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateChoosePathFunction());
   function->SetRenderFrameHost(web_contents->GetMainFrame());
   EXPECT_TRUE(RunFunction(function, choose_args)) << function->GetError();
@@ -527,7 +527,7 @@
 
   // Try loading a good extension (it should succeed, and the extension should
   // be added).
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateLoadUnpackedFunction());
   function->SetRenderFrameHost(web_contents->GetMainFrame());
   ExtensionIdSet current_ids = registry()->enabled_extensions().GetIDs();
@@ -577,7 +577,7 @@
     base::FilePath path = dir.UnpackedPath();
     api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path);
 
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new api::DeveloperPrivateLoadUnpackedFunction());
     function->SetRenderFrameHost(web_contents->GetMainFrame());
     std::unique_ptr<base::Value> result =
@@ -604,7 +604,7 @@
     base::FilePath path = dir.UnpackedPath();
     api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path);
 
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new api::DeveloperPrivateLoadUnpackedFunction());
     function->SetRenderFrameHost(web_contents->GetMainFrame());
     std::unique_ptr<base::Value> result =
@@ -636,7 +636,7 @@
     base::FilePath path = dir.UnpackedPath();
     api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path);
 
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new api::DeveloperPrivateLoadUnpackedFunction());
     function->SetRenderFrameHost(web_contents->GetMainFrame());
     std::unique_ptr<base::Value> result =
@@ -669,7 +669,7 @@
   {
     // Trying to load the extension should result in a load error with the
     // retry id populated.
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new api::DeveloperPrivateLoadUnpackedFunction());
     function->SetRenderFrameHost(web_contents->GetMainFrame());
     std::unique_ptr<base::Value> result =
@@ -689,7 +689,7 @@
     // same retry id.  This is somewhat an implementation detail, but is
     // important to ensure we don't allocate crazy numbers of ids if the user
     // just retries continuously.
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new api::DeveloperPrivateLoadUnpackedFunction());
     function->SetRenderFrameHost(web_contents->GetMainFrame());
     std::unique_ptr<base::Value> result =
@@ -718,7 +718,7 @@
     base::FilePath second_path = second_dir.UnpackedPath();
     api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&second_path);
 
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new api::DeveloperPrivateLoadUnpackedFunction());
     function->SetRenderFrameHost(web_contents->GetMainFrame());
     std::unique_ptr<base::Value> result =
@@ -749,7 +749,7 @@
 
   {
     // Try reloading the extension by supplying the retry id. It should succeed.
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new api::DeveloperPrivateLoadUnpackedFunction());
     function->SetRenderFrameHost(web_contents->GetMainFrame());
     TestExtensionRegistryObserver observer(registry());
@@ -766,7 +766,7 @@
 
   {
     // Try supplying an invalid retry id. It should fail with an error.
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new api::DeveloperPrivateLoadUnpackedFunction());
     function->SetRenderFrameHost(web_contents->GetMainFrame());
     std::string error = api_test_utils::RunFunctionAndReturnError(
@@ -995,7 +995,7 @@
   properties.message = kErrorMessage;
   properties.manifest_key.reset(new std::string("name"));
 
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateRequestFileSourceFunction());
   base::ListValue file_source_args;
   file_source_args.Append(properties.ToValue());
@@ -1021,7 +1021,7 @@
   // ExtensionInfoGenerator's unittest), but rather just to make sure we can
   // serialize/deserialize the result - which implicity tests that everything
   // has a sane value.
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateGetExtensionsInfoFunction());
   EXPECT_TRUE(RunFunction(function, base::ListValue())) << function->GetError();
   const base::ListValue* results = function->GetResultList();
@@ -1080,7 +1080,7 @@
                       .Set("type", type_string)
                       .Build())
           .Build();
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       new api::DeveloperPrivateDeleteExtensionErrorsFunction();
   EXPECT_TRUE(RunFunction(function, *args)) << function->GetError();
   // Two errors should remain.
@@ -1123,7 +1123,7 @@
   // Attempt to repair the good extension, expect failure.
   std::unique_ptr<base::ListValue> args =
       ListBuilder().Append(extension->id()).Build();
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       new api::DeveloperPrivateRepairExtensionFunction();
   EXPECT_FALSE(RunFunction(function, *args));
   EXPECT_EQ("Cannot repair a healthy extension.", function->GetError());
@@ -1154,7 +1154,7 @@
   // Attempt to repair the good extension, expect failure.
   std::unique_ptr<base::ListValue> args =
       ListBuilder().Append(extension_id).Build();
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       new api::DeveloperPrivateRepairExtensionFunction();
   EXPECT_FALSE(RunFunction(function, *args));
   EXPECT_EQ("Cannot repair a healthy extension.", function->GetError());
@@ -1219,7 +1219,7 @@
 
   PrefService* prefs = profile()->GetPrefs();
   prefs->SetBoolean(prefs::kExtensionsUIDeveloperMode, false);
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       base::MakeRefCounted<api::DeveloperPrivateLoadUnpackedFunction>();
   function->SetRenderFrameHost(web_contents->GetMainFrame());
   std::string error = extension_function_test_utils::RunFunctionAndReturnError(
@@ -1252,7 +1252,7 @@
 
   EXPECT_FALSE(info->can_load_unpacked);
 
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       base::MakeRefCounted<api::DeveloperPrivateLoadUnpackedFunction>();
   function->SetRenderFrameHost(web_contents->GetMainFrame());
   std::string error = extension_function_test_utils::RunFunctionAndReturnError(
@@ -1295,7 +1295,7 @@
   std::unique_ptr<content::WebContents> web_contents(
       content::WebContentsTester::CreateTestWebContents(profile(), nullptr));
 
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       base::MakeRefCounted<api::DeveloperPrivateInstallDroppedFileFunction>();
   function->SetRenderFrameHost(web_contents->GetMainFrame());
 
@@ -1321,7 +1321,7 @@
   DeveloperPrivateAPI::Get(profile())->SetDraggedPath(web_contents.get(),
                                                       crx_path);
 
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       base::MakeRefCounted<api::DeveloperPrivateInstallDroppedFileFunction>();
   function->SetRenderFrameHost(web_contents->GetMainFrame());
 
@@ -1344,7 +1344,7 @@
   DeveloperPrivateAPI::Get(profile())->SetDraggedPath(web_contents.get(),
                                                       script_path);
 
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       base::MakeRefCounted<api::DeveloperPrivateInstallDroppedFileFunction>();
   function->SetRenderFrameHost(web_contents->GetMainFrame());
 
@@ -1368,7 +1368,7 @@
                                                    bool should_succeed,
                                                    const char* expected_error) {
     SCOPED_TRACE(host);
-    scoped_refptr<UIThreadExtensionFunction> function =
+    scoped_refptr<ExtensionFunction> function =
         base::MakeRefCounted<api::DeveloperPrivateAddHostPermissionFunction>();
 
     std::string args = base::StringPrintf(R"(["%s", "%s"])",
@@ -1425,7 +1425,7 @@
                                         bool should_succeed,
                                         const char* expected_error) {
     SCOPED_TRACE(host);
-    scoped_refptr<UIThreadExtensionFunction> function = base::MakeRefCounted<
+    scoped_refptr<ExtensionFunction> function = base::MakeRefCounted<
         api::DeveloperPrivateRemoveHostPermissionFunction>();
     std::string args = base::StringPrintf(R"(["%s", "%s"])",
                                           extension->id().c_str(), host.data());
@@ -1579,7 +1579,7 @@
             *extension_prefs->GetRuntimeGrantedPermissions(extension->id()));
 
   {
-    scoped_refptr<UIThreadExtensionFunction> function =
+    scoped_refptr<ExtensionFunction> function =
         base::MakeRefCounted<api::DeveloperPrivateAddHostPermissionFunction>();
     std::string args = base::StringPrintf(
         R"(["%s", "%s"])", extension->id().c_str(), "*://chromium.org/*");
@@ -1610,7 +1610,7 @@
             *extension_prefs->GetRuntimeGrantedPermissions(extension->id()));
 
   {
-    scoped_refptr<UIThreadExtensionFunction> function = base::MakeRefCounted<
+    scoped_refptr<ExtensionFunction> function = base::MakeRefCounted<
         api::DeveloperPrivateRemoveHostPermissionFunction>();
     std::string args = base::StringPrintf(
         R"(["%s", "%s"])", extension->id().c_str(), "*://chromium.org/*");
@@ -1730,7 +1730,7 @@
   DeveloperPrivateAPI::Get(profile())->SetDraggedPath(web_contents.get(),
                                                       zip_path);
 
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       base::MakeRefCounted<api::DeveloperPrivateInstallDroppedFileFunction>();
   function->SetRenderFrameHost(web_contents->GetMainFrame());
 
@@ -1765,7 +1765,7 @@
 
   ASSERT_TRUE(profile()->IsSupervised());
 
-  scoped_refptr<UIThreadExtensionFunction> function =
+  scoped_refptr<ExtensionFunction> function =
       base::MakeRefCounted<api::DeveloperPrivateLoadUnpackedFunction>();
   function->SetRenderFrameHost(web_contents->GetMainFrame());
   std::string error = extension_function_test_utils::RunFunctionAndReturnError(
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc b/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
index 570844d..f4cb2836 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
@@ -43,7 +43,7 @@
   const Extension* app = LoadAndLaunchApp(dir);
 
   // Get the info about the app, including the inspectable views.
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateGetExtensionInfoFunction());
   std::unique_ptr<base::Value> result(
       extension_function_test_utils::RunFunctionAndReturnSingleResult(
@@ -97,7 +97,7 @@
   WaitForExtensionNotIdle(extension->id());
 
   // Get the info about the extension, including the inspectable views.
-  scoped_refptr<UIThreadExtensionFunction> function(
+  scoped_refptr<ExtensionFunction> function(
       new api::DeveloperPrivateGetExtensionInfoFunction());
   std::unique_ptr<base::Value> result(
       extension_function_test_utils::RunFunctionAndReturnSingleResult(
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.h b/chrome/browser/extensions/api/downloads/downloads_api.h
index 7a44733..81d3cc6 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.h
+++ b/chrome/browser/extensions/api/downloads/downloads_api.h
@@ -107,7 +107,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsDownloadFunction);
 };
 
-class DownloadsSearchFunction : public UIThreadExtensionFunction {
+class DownloadsSearchFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.search", DOWNLOADS_SEARCH)
   DownloadsSearchFunction();
@@ -120,7 +120,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsSearchFunction);
 };
 
-class DownloadsPauseFunction : public UIThreadExtensionFunction {
+class DownloadsPauseFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.pause", DOWNLOADS_PAUSE)
   DownloadsPauseFunction();
@@ -133,7 +133,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsPauseFunction);
 };
 
-class DownloadsResumeFunction : public UIThreadExtensionFunction {
+class DownloadsResumeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.resume", DOWNLOADS_RESUME)
   DownloadsResumeFunction();
@@ -146,7 +146,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsResumeFunction);
 };
 
-class DownloadsCancelFunction : public UIThreadExtensionFunction {
+class DownloadsCancelFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.cancel", DOWNLOADS_CANCEL)
   DownloadsCancelFunction();
@@ -159,7 +159,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsCancelFunction);
 };
 
-class DownloadsEraseFunction : public UIThreadExtensionFunction {
+class DownloadsEraseFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.erase", DOWNLOADS_ERASE)
   DownloadsEraseFunction();
@@ -211,7 +211,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsAcceptDangerFunction);
 };
 
-class DownloadsShowFunction : public UIThreadExtensionFunction {
+class DownloadsShowFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.show", DOWNLOADS_SHOW)
   DownloadsShowFunction();
@@ -224,7 +224,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsShowFunction);
 };
 
-class DownloadsShowDefaultFolderFunction : public UIThreadExtensionFunction {
+class DownloadsShowDefaultFolderFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION(
       "downloads.showDefaultFolder", DOWNLOADS_SHOWDEFAULTFOLDER)
@@ -238,7 +238,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsShowDefaultFolderFunction);
 };
 
-class DownloadsOpenFunction : public UIThreadExtensionFunction {
+class DownloadsOpenFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.open", DOWNLOADS_OPEN)
   DownloadsOpenFunction();
@@ -261,7 +261,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsOpenFunction);
 };
 
-class DownloadsSetShelfEnabledFunction : public UIThreadExtensionFunction {
+class DownloadsSetShelfEnabledFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.setShelfEnabled",
                              DOWNLOADS_SETSHELFENABLED)
@@ -275,7 +275,7 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadsSetShelfEnabledFunction);
 };
 
-class DownloadsDragFunction : public UIThreadExtensionFunction {
+class DownloadsDragFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.drag", DOWNLOADS_DRAG)
   DownloadsDragFunction();
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index fec35ae..2575f45 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -599,9 +599,8 @@
         GetCurrentManager(), download_count);
   }
 
-  bool RunFunction(UIThreadExtensionFunction* function,
-                   const std::string& args) {
-    scoped_refptr<UIThreadExtensionFunction> delete_function(function);
+  bool RunFunction(ExtensionFunction* function, const std::string& args) {
+    scoped_refptr<ExtensionFunction> delete_function(function);
     SetUpExtensionFunction(function);
     bool result = extension_function_test_utils::RunFunction(
         function, args, current_browser(), GetFlags());
@@ -622,7 +621,7 @@
   // on-record profile to match real-life behavior.
 
   base::Value* RunFunctionAndReturnResult(
-      scoped_refptr<UIThreadExtensionFunction> function,
+      scoped_refptr<ExtensionFunction> function,
       const std::string& args) {
     SetUpExtensionFunction(function.get());
     return extension_function_test_utils::RunFunctionAndReturnSingleResult(
@@ -630,17 +629,16 @@
   }
 
   std::string RunFunctionAndReturnError(
-      scoped_refptr<UIThreadExtensionFunction> function,
+      scoped_refptr<ExtensionFunction> function,
       const std::string& args) {
     SetUpExtensionFunction(function.get());
     return extension_function_test_utils::RunFunctionAndReturnError(
         function.get(), args, current_browser(), GetFlags());
   }
 
-  bool RunFunctionAndReturnString(
-      scoped_refptr<UIThreadExtensionFunction> function,
-      const std::string& args,
-      std::string* result_string) {
+  bool RunFunctionAndReturnString(scoped_refptr<ExtensionFunction> function,
+                                  const std::string& args,
+                                  std::string* result_string) {
     SetUpExtensionFunction(function.get());
     std::unique_ptr<base::Value> result(
         RunFunctionAndReturnResult(function, args));
@@ -661,7 +659,7 @@
   const Extension* extension() { return extension_; }
 
  private:
-  void SetUpExtensionFunction(UIThreadExtensionFunction* function) {
+  void SetUpExtensionFunction(ExtensionFunction* function) {
     if (extension_) {
       const GURL url = current_browser_ == incognito_browser_ &&
                                !IncognitoInfo::IsSplitMode(extension_)
@@ -1044,7 +1042,7 @@
   EXPECT_EQ(id, element);
 }
 
-scoped_refptr<UIThreadExtensionFunction> MockedGetFileIconFunction(
+scoped_refptr<ExtensionFunction> MockedGetFileIconFunction(
     const base::FilePath& expected_path,
     IconLoader::IconSize icon_size,
     const std::string& response) {
diff --git a/chrome/browser/extensions/api/downloads_internal/downloads_internal_api.h b/chrome/browser/extensions/api/downloads_internal/downloads_internal_api.h
index 639906d..490c94e 100644
--- a/chrome/browser/extensions/api/downloads_internal/downloads_internal_api.h
+++ b/chrome/browser/extensions/api/downloads_internal/downloads_internal_api.h
@@ -10,8 +10,7 @@
 
 namespace extensions {
 
-class DownloadsInternalDetermineFilenameFunction
-    : public UIThreadExtensionFunction {
+class DownloadsInternalDetermineFilenameFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloadsInternal.determineFilename",
                              DOWNLOADSINTERNAL_DETERMINEFILENAME)
diff --git a/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h b/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h
index 0f87921..5c6a57c 100644
--- a/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h
+++ b/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h
@@ -10,7 +10,7 @@
 namespace extensions {
 
 class EnterpriseDeviceAttributesGetDirectoryDeviceIdFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   EnterpriseDeviceAttributesGetDirectoryDeviceIdFunction();
 
@@ -25,7 +25,7 @@
 };
 
 class EnterpriseDeviceAttributesGetDeviceSerialNumberFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   EnterpriseDeviceAttributesGetDeviceSerialNumberFunction();
 
@@ -41,7 +41,7 @@
 };
 
 class EnterpriseDeviceAttributesGetDeviceAssetIdFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   EnterpriseDeviceAttributesGetDeviceAssetIdFunction();
 
@@ -56,7 +56,7 @@
 };
 
 class EnterpriseDeviceAttributesGetDeviceAnnotatedLocationFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   EnterpriseDeviceAttributesGetDeviceAnnotatedLocationFunction();
 
diff --git a/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h b/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h
index 1600ac5..0d69118 100644
--- a/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h
+++ b/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h
@@ -12,7 +12,7 @@
 namespace extensions {
 
 class EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction();
 
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
index 1d0643aa..cc48d23d 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
@@ -281,11 +281,11 @@
       this);
   // base::Unretained is safe on impl_ since its life-cycle matches |this| and
   // |callback| holds a reference to |this|.
-  base::Closure task = base::Bind(
-      &EPKPChallengeMachineKey::Run, base::Unretained(impl_),
-      scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
-      callback, StringFromVector(params->challenge),
-      params->register_key ? *params->register_key : false);
+  base::Closure task =
+      base::Bind(&EPKPChallengeMachineKey::Run, base::Unretained(impl_),
+                 scoped_refptr<ExtensionFunction>(this), callback,
+                 StringFromVector(params->challenge),
+                 params->register_key ? *params->register_key : false);
   base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, task);
   return RespondLater();
 }
@@ -322,10 +322,10 @@
       &EnterprisePlatformKeysChallengeUserKeyFunction::OnChallengedKey, this);
   // base::Unretained is safe on impl_ since its life-cycle matches |this| and
   // |callback| holds a reference to |this|.
-  base::Closure task = base::Bind(
-      &EPKPChallengeUserKey::Run, base::Unretained(impl_),
-      scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
-      callback, StringFromVector(params->challenge), params->register_key);
+  base::Closure task =
+      base::Bind(&EPKPChallengeUserKey::Run, base::Unretained(impl_),
+                 scoped_refptr<ExtensionFunction>(this), callback,
+                 StringFromVector(params->challenge), params->register_key);
   base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, task);
   return RespondLater();
 }
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
index 6900eb2..9ec384a2 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
@@ -21,7 +21,7 @@
 namespace extensions {
 
 class EnterprisePlatformKeysInternalGenerateKeyFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  private:
   ~EnterprisePlatformKeysInternalGenerateKeyFunction() override;
   ResponseAction Run() override;
@@ -35,8 +35,7 @@
                              ENTERPRISE_PLATFORMKEYSINTERNAL_GENERATEKEY)
 };
 
-class EnterprisePlatformKeysGetCertificatesFunction
-    : public UIThreadExtensionFunction {
+class EnterprisePlatformKeysGetCertificatesFunction : public ExtensionFunction {
  private:
   ~EnterprisePlatformKeysGetCertificatesFunction() override;
   ResponseAction Run() override;
@@ -51,7 +50,7 @@
 };
 
 class EnterprisePlatformKeysImportCertificateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  private:
   ~EnterprisePlatformKeysImportCertificateFunction() override;
   ResponseAction Run() override;
@@ -65,7 +64,7 @@
 };
 
 class EnterprisePlatformKeysRemoveCertificateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  private:
   ~EnterprisePlatformKeysRemoveCertificateFunction() override;
   ResponseAction Run() override;
@@ -79,7 +78,7 @@
 };
 
 class EnterprisePlatformKeysInternalGetTokensFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  private:
   ~EnterprisePlatformKeysInternalGetTokensFunction() override;
   ResponseAction Run() override;
@@ -94,7 +93,7 @@
 };
 
 class EnterprisePlatformKeysChallengeMachineKeyFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   EnterprisePlatformKeysChallengeMachineKeyFunction();
   explicit EnterprisePlatformKeysChallengeMachineKeyFunction(
@@ -117,7 +116,7 @@
 };
 
 class EnterprisePlatformKeysChallengeUserKeyFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   EnterprisePlatformKeysChallengeUserKeyFunction();
   explicit EnterprisePlatformKeysChallengeUserKeyFunction(
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
index 5fa0fffc2..ba3cd7e1 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -181,7 +181,7 @@
 
   // Like extension_function_test_utils::RunFunctionAndReturnError but with an
   // explicit ListValue.
-  std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
+  std::string RunFunctionAndReturnError(ExtensionFunction* function,
                                         std::unique_ptr<base::ListValue> args,
                                         Browser* browser) {
     utils::RunFunction(function, std::move(args), browser,
@@ -193,7 +193,7 @@
   // Like extension_function_test_utils::RunFunctionAndReturnSingleResult but
   // with an explicit ListValue.
   base::Value* RunFunctionAndReturnSingleResult(
-      UIThreadExtensionFunction* function,
+      ExtensionFunction* function,
       std::unique_ptr<base::ListValue> args,
       Browser* browser) {
     scoped_refptr<ExtensionFunction> function_owner(function);
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
index 92e1bc05..514a9e0 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
@@ -337,11 +337,10 @@
 EPKPChallengeMachineKey::~EPKPChallengeMachineKey() {
 }
 
-void EPKPChallengeMachineKey::Run(
-    scoped_refptr<UIThreadExtensionFunction> caller,
-    const ChallengeKeyCallback& callback,
-    const std::string& challenge,
-    bool register_key) {
+void EPKPChallengeMachineKey::Run(scoped_refptr<ExtensionFunction> caller,
+                                  const ChallengeKeyCallback& callback,
+                                  const std::string& challenge,
+                                  bool register_key) {
   callback_ = callback;
   profile_ = ChromeExtensionFunctionDetails(caller.get()).GetProfile();
   extension_ = scoped_refptr<const Extension>(caller->extension());
@@ -372,7 +371,7 @@
 }
 
 void EPKPChallengeMachineKey::DecodeAndRun(
-    scoped_refptr<UIThreadExtensionFunction> caller,
+    scoped_refptr<ExtensionFunction> caller,
     const ChallengeKeyCallback& callback,
     const std::string& encoded_challenge,
     bool register_key) {
@@ -489,7 +488,7 @@
   registry->RegisterListPref(prefs::kAttestationExtensionWhitelist);
 }
 
-void EPKPChallengeUserKey::Run(scoped_refptr<UIThreadExtensionFunction> caller,
+void EPKPChallengeUserKey::Run(scoped_refptr<ExtensionFunction> caller,
                                const ChallengeKeyCallback& callback,
                                const std::string& challenge,
                                bool register_key) {
@@ -535,11 +534,10 @@
   }
 }
 
-void EPKPChallengeUserKey::DecodeAndRun(
-    scoped_refptr<UIThreadExtensionFunction> caller,
-    const ChallengeKeyCallback& callback,
-    const std::string& encoded_challenge,
-    bool register_key) {
+void EPKPChallengeUserKey::DecodeAndRun(scoped_refptr<ExtensionFunction> caller,
+                                        const ChallengeKeyCallback& callback,
+                                        const std::string& encoded_challenge,
+                                        bool register_key) {
   std::string challenge;
   if (!base::Base64Decode(encoded_challenge, &challenge)) {
     callback.Run(false, kChallengeBadBase64Error);
@@ -645,10 +643,10 @@
                  this);
   // base::Unretained is safe on impl_ since its life-cycle matches |this| and
   // |callback| holds a reference to |this|.
-  base::Closure task = base::Bind(
-      &EPKPChallengeMachineKey::DecodeAndRun, base::Unretained(impl_),
-      scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
-      callback, params->challenge, false);
+  base::Closure task = base::Bind(&EPKPChallengeMachineKey::DecodeAndRun,
+                                  base::Unretained(impl_),
+                                  scoped_refptr<ExtensionFunction>(this),
+                                  callback, params->challenge, false);
   base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, task);
   return RespondLater();
 }
@@ -688,10 +686,10 @@
       this);
   // base::Unretained is safe on impl_ since its life-cycle matches |this| and
   // |callback| holds a reference to |this|.
-  base::Closure task = base::Bind(
-      &EPKPChallengeUserKey::DecodeAndRun, base::Unretained(impl_),
-      scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
-      callback, params->challenge, params->register_key);
+  base::Closure task =
+      base::Bind(&EPKPChallengeUserKey::DecodeAndRun, base::Unretained(impl_),
+                 scoped_refptr<ExtensionFunction>(this), callback,
+                 params->challenge, params->register_key);
   base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, task);
   return RespondLater();
 }
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
index 66cb475..460ed7b 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
+++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
@@ -176,13 +176,13 @@
 
   // Asynchronously run the flow to challenge a machine key in the |caller|
   // context.
-  void Run(scoped_refptr<UIThreadExtensionFunction> caller,
+  void Run(scoped_refptr<ExtensionFunction> caller,
            const ChallengeKeyCallback& callback,
            const std::string& encoded_challenge,
            bool register_key);
 
   // Like |Run| but expects a Base64 |encoded_challenge|.
-  void DecodeAndRun(scoped_refptr<UIThreadExtensionFunction> caller,
+  void DecodeAndRun(scoped_refptr<ExtensionFunction> caller,
                     const ChallengeKeyCallback& callback,
                     const std::string& encoded_challenge,
                     bool register_key);
@@ -223,13 +223,13 @@
 
   // Asynchronously run the flow to challenge a user key in the |caller|
   // context.
-  void Run(scoped_refptr<UIThreadExtensionFunction> caller,
+  void Run(scoped_refptr<ExtensionFunction> caller,
            const ChallengeKeyCallback& callback,
            const std::string& challenge,
            bool register_key);
 
   // Like |Run| but expects a Base64 |encoded_challenge|.
-  void DecodeAndRun(scoped_refptr<UIThreadExtensionFunction> caller,
+  void DecodeAndRun(scoped_refptr<ExtensionFunction> caller,
                     const ChallengeKeyCallback& callback,
                     const std::string& encoded_challenge,
                     bool register_key);
@@ -255,7 +255,7 @@
 };
 
 class EnterprisePlatformKeysPrivateChallengeMachineKeyFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   EnterprisePlatformKeysPrivateChallengeMachineKeyFunction();
   explicit EnterprisePlatformKeysPrivateChallengeMachineKeyFunction(
@@ -279,7 +279,7 @@
 };
 
 class EnterprisePlatformKeysPrivateChallengeUserKeyFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   EnterprisePlatformKeysPrivateChallengeUserKeyFunction();
   explicit EnterprisePlatformKeysPrivateChallengeUserKeyFunction(
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h
index c6ebd8fa..ec772107 100644
--- a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h
+++ b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h
@@ -27,7 +27,7 @@
 }  // namespace enterprise_reporting
 
 class EnterpriseReportingPrivateUploadChromeDesktopReportFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION(
       "enterprise.reportingPrivate.uploadChromeDesktopReport",
@@ -65,8 +65,7 @@
       EnterpriseReportingPrivateUploadChromeDesktopReportFunction);
 };
 
-class EnterpriseReportingPrivateGetDeviceIdFunction
-    : public UIThreadExtensionFunction {
+class EnterpriseReportingPrivateGetDeviceIdFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("enterprise.reportingPrivate.getDeviceId",
                              ENTERPRISEREPORTINGPRIVATE_GETDEVICEID)
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
index bca47a1..344b323 100644
--- a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
+++ b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
@@ -34,7 +34,7 @@
  public:
   EnterpriseReportingPrivateUploadChromeDesktopReportTest() {}
 
-  UIThreadExtensionFunction* CreateChromeDesktopReportingFunction(
+  ExtensionFunction* CreateChromeDesktopReportingFunction(
       const std::string& dm_token) {
     EnterpriseReportingPrivateUploadChromeDesktopReportFunction* function =
         EnterpriseReportingPrivateUploadChromeDesktopReportFunction::
@@ -85,7 +85,7 @@
 }
 
 TEST_F(EnterpriseReportingPrivateUploadChromeDesktopReportTest, UploadFailed) {
-  UIThreadExtensionFunction* function =
+  ExtensionFunction* function =
       CreateChromeDesktopReportingFunction(kFakeDMToken);
   EXPECT_CALL(*client_, SetupRegistration(kFakeDMToken, kFakeClientId, _))
       .Times(1);
@@ -99,7 +99,7 @@
 
 TEST_F(EnterpriseReportingPrivateUploadChromeDesktopReportTest,
        UploadSucceeded) {
-  UIThreadExtensionFunction* function =
+  ExtensionFunction* function =
       CreateChromeDesktopReportingFunction(kFakeDMToken);
   EXPECT_CALL(*client_, SetupRegistration(kFakeDMToken, kFakeClientId, _))
       .Times(1);
diff --git a/chrome/browser/extensions/api/extension_action/extension_action_api.h b/chrome/browser/extensions/api/extension_action/extension_action_api.h
index a5910ca..6ae7ffb 100644
--- a/chrome/browser/extensions/api/extension_action/extension_action_api.h
+++ b/chrome/browser/extensions/api/extension_action/extension_action_api.h
@@ -126,7 +126,7 @@
 // tabIds while browserAction's are optional, they have different internal
 // browser notification requirements, and not all functions are defined for all
 // APIs).
-class ExtensionActionFunction : public UIThreadExtensionFunction {
+class ExtensionActionFunction : public ExtensionFunction {
  public:
   static bool ParseCSSColorString(const std::string& color_string,
                                   SkColor* result);
@@ -442,7 +442,7 @@
   ~BrowserActionDisableFunction() override {}
 };
 
-class BrowserActionOpenPopupFunction : public UIThreadExtensionFunction,
+class BrowserActionOpenPopupFunction : public ExtensionFunction,
                                        public content::NotificationObserver {
  public:
   DECLARE_EXTENSION_FUNCTION("browserAction.openPopup",
diff --git a/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc b/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc
index b440c80..c5c066e 100644
--- a/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc
+++ b/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc
@@ -106,7 +106,7 @@
 // Callback called when consent is granted or denied.
 void OnConsentReceived(
     content::BrowserContext* browser_context,
-    scoped_refptr<UIThreadExtensionFunction> requester,
+    scoped_refptr<ExtensionFunction> requester,
     const FileSystemDelegate::FileSystemCallback& success_callback,
     const FileSystemDelegate::ErrorCallback& error_callback,
     const std::string& extension_id,
@@ -252,7 +252,7 @@
 }
 
 bool ChromeFileSystemDelegate::ShowSelectFileDialog(
-    scoped_refptr<UIThreadExtensionFunction> extension_function,
+    scoped_refptr<ExtensionFunction> extension_function,
     ui::SelectFileDialog::Type type,
     const base::FilePath& default_path,
     const ui::SelectFileDialog::FileTypeInfo* file_types,
@@ -282,7 +282,7 @@
     return false;
   }
 
-  // The file picker will hold a reference to the UIThreadExtensionFunction
+  // The file picker will hold a reference to the ExtensionFunction
   // instance, preventing its destruction (and subsequent sending of the
   // function response) until the user has selected a file or cancelled the
   // picker. At that point, the picker will delete itself, which will also free
@@ -330,7 +330,7 @@
 
 void ChromeFileSystemDelegate::RequestFileSystem(
     content::BrowserContext* browser_context,
-    scoped_refptr<UIThreadExtensionFunction> requester,
+    scoped_refptr<ExtensionFunction> requester,
     const Extension& extension,
     std::string volume_id,
     bool writable,
diff --git a/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h b/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h
index 9dd8784b..a127639 100644
--- a/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h
+++ b/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h
@@ -32,7 +32,7 @@
   // FileSystemDelegate:
   base::FilePath GetDefaultDirectory() override;
   bool ShowSelectFileDialog(
-      scoped_refptr<UIThreadExtensionFunction> extension_function,
+      scoped_refptr<ExtensionFunction> extension_function,
       ui::SelectFileDialog::Type type,
       const base::FilePath& default_path,
       const ui::SelectFileDialog::FileTypeInfo* file_types,
@@ -50,7 +50,7 @@
       content::RenderFrameHost* render_frame_host,
       const Extension& extension) override;
   void RequestFileSystem(content::BrowserContext* browser_context,
-                         scoped_refptr<UIThreadExtensionFunction> requester,
+                         scoped_refptr<ExtensionFunction> requester,
                          const Extension& extension,
                          std::string volume_id,
                          bool writable,
diff --git a/chrome/browser/extensions/api/font_settings/font_settings_api.h b/chrome/browser/extensions/api/font_settings/font_settings_api.h
index 880218a..6b206d4 100644
--- a/chrome/browser/extensions/api/font_settings/font_settings_api.h
+++ b/chrome/browser/extensions/api/font_settings/font_settings_api.h
@@ -101,7 +101,7 @@
 };
 
 // fontSettings.clearFont API function.
-class FontSettingsClearFontFunction : public UIThreadExtensionFunction {
+class FontSettingsClearFontFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fontSettings.clearFont", FONTSETTINGS_CLEARFONT)
 
@@ -115,7 +115,7 @@
 };
 
 // fontSettings.getFont API function.
-class FontSettingsGetFontFunction : public UIThreadExtensionFunction {
+class FontSettingsGetFontFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fontSettings.getFont", FONTSETTINGS_GETFONT)
 
@@ -127,7 +127,7 @@
 };
 
 // fontSettings.setFont API function.
-class FontSettingsSetFontFunction : public UIThreadExtensionFunction {
+class FontSettingsSetFontFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fontSettings.setFont", FONTSETTINGS_SETFONT)
 
@@ -156,7 +156,7 @@
 };
 
 // Base class for extension API functions that clear a browser font pref.
-class ClearFontPrefExtensionFunction : public UIThreadExtensionFunction {
+class ClearFontPrefExtensionFunction : public ExtensionFunction {
  protected:
   ~ClearFontPrefExtensionFunction() override {}
 
@@ -169,7 +169,7 @@
 };
 
 // Base class for extension API functions that get a browser font pref.
-class GetFontPrefExtensionFunction : public UIThreadExtensionFunction {
+class GetFontPrefExtensionFunction : public ExtensionFunction {
  protected:
   ~GetFontPrefExtensionFunction() override {}
 
@@ -186,7 +186,7 @@
 };
 
 // Base class for extension API functions that set a browser font pref.
-class SetFontPrefExtensionFunction : public UIThreadExtensionFunction {
+class SetFontPrefExtensionFunction : public ExtensionFunction {
  protected:
   ~SetFontPrefExtensionFunction() override {}
 
diff --git a/chrome/browser/extensions/api/gcm/gcm_api.h b/chrome/browser/extensions/api/gcm/gcm_api.h
index 40bbd1b..8e538f66 100644
--- a/chrome/browser/extensions/api/gcm/gcm_api.h
+++ b/chrome/browser/extensions/api/gcm/gcm_api.h
@@ -17,7 +17,7 @@
 
 namespace extensions {
 
-class GcmApiFunction : public UIThreadExtensionFunction {
+class GcmApiFunction : public ExtensionFunction {
  public:
   GcmApiFunction() {}
 
@@ -42,7 +42,7 @@
  protected:
   ~GcmRegisterFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() final;
 
  private:
@@ -59,7 +59,7 @@
  protected:
   ~GcmUnregisterFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() final;
 
  private:
@@ -75,7 +75,7 @@
  protected:
   ~GcmSendFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() final;
 
  private:
diff --git a/chrome/browser/extensions/api/history/history_api.h b/chrome/browser/extensions/api/history/history_api.h
index 9a0433db..5349fca 100644
--- a/chrome/browser/extensions/api/history/history_api.h
+++ b/chrome/browser/extensions/api/history/history_api.h
@@ -93,7 +93,7 @@
 void BrowserContextKeyedAPIFactory<HistoryAPI>::DeclareFactoryDependencies();
 
 // Base class for history function APIs.
-class HistoryFunction : public UIThreadExtensionFunction {
+class HistoryFunction : public ExtensionFunction {
  protected:
   ~HistoryFunction() override {}
 
diff --git a/chrome/browser/extensions/api/i18n/i18n_api.h b/chrome/browser/extensions/api/i18n/i18n_api.h
index 5576a363..88ed709 100644
--- a/chrome/browser/extensions/api/i18n/i18n_api.h
+++ b/chrome/browser/extensions/api/i18n/i18n_api.h
@@ -9,7 +9,7 @@
 
 namespace extensions {
 
-class I18nGetAcceptLanguagesFunction : public UIThreadExtensionFunction {
+class I18nGetAcceptLanguagesFunction : public ExtensionFunction {
   ~I18nGetAcceptLanguagesFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("i18n.getAcceptLanguages", I18N_GETACCEPTLANGUAGES)
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 99e6d39..ef79b4e6 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -89,7 +89,7 @@
 // after the call happens.
 class AsyncFunctionRunner {
  public:
-  void RunFunctionAsync(UIThreadExtensionFunction* function,
+  void RunFunctionAsync(ExtensionFunction* function,
                         const std::string& args,
                         content::BrowserContext* browser_context) {
     response_delegate_.reset(new api_test_utils::SendResponseHelper(function));
@@ -109,14 +109,14 @@
     function->RunWithValidation()->Execute();
   }
 
-  std::string WaitForError(UIThreadExtensionFunction* function) {
+  std::string WaitForError(ExtensionFunction* function) {
     RunMessageLoopUntilResponse();
     CHECK(function->response_type());
     EXPECT_EQ(ExtensionFunction::FAILED, *function->response_type());
     return function->GetError();
   }
 
-  base::Value* WaitForSingleResult(UIThreadExtensionFunction* function) {
+  base::Value* WaitForSingleResult(ExtensionFunction* function) {
     RunMessageLoopUntilResponse();
     EXPECT_TRUE(function->GetError().empty())
         << "Unexpected error: " << function->GetError();
@@ -140,18 +140,17 @@
 class AsyncExtensionBrowserTest : public ExtensionBrowserTest {
  protected:
   // Provide wrappers of AsynchronousFunctionRunner for convenience.
-  void RunFunctionAsync(UIThreadExtensionFunction* function,
-                        const std::string& args) {
+  void RunFunctionAsync(ExtensionFunction* function, const std::string& args) {
     async_function_runner_ = std::make_unique<AsyncFunctionRunner>();
     async_function_runner_->RunFunctionAsync(function, args,
                                              browser()->profile());
   }
 
-  std::string WaitForError(UIThreadExtensionFunction* function) {
+  std::string WaitForError(ExtensionFunction* function) {
     return async_function_runner_->WaitForError(function);
   }
 
-  base::Value* WaitForSingleResult(UIThreadExtensionFunction* function) {
+  base::Value* WaitForSingleResult(ExtensionFunction* function) {
     return async_function_runner_->WaitForSingleResult(function);
   }
 
diff --git a/chrome/browser/extensions/api/identity/identity_get_accounts_function.h b/chrome/browser/extensions/api/identity/identity_get_accounts_function.h
index a123670..1b8c765 100644
--- a/chrome/browser/extensions/api/identity/identity_get_accounts_function.h
+++ b/chrome/browser/extensions/api/identity/identity_get_accounts_function.h
@@ -10,7 +10,7 @@
 
 namespace extensions {
 
-class IdentityGetAccountsFunction : public UIThreadExtensionFunction {
+class IdentityGetAccountsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("identity.getAccounts", IDENTITY_GETACCOUNTS)
 
@@ -19,7 +19,7 @@
  private:
   ~IdentityGetAccountsFunction() override;
 
-  // UIThreadExtensionFunction implementation.
+  // ExtensionFunction implementation.
   ExtensionFunction::ResponseAction Run() override;
 };
 
diff --git a/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h b/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h
index f68ecc9..84edc0d 100644
--- a/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h
+++ b/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h
@@ -10,7 +10,7 @@
 
 namespace extensions {
 
-class IdentityGetProfileUserInfoFunction : public UIThreadExtensionFunction {
+class IdentityGetProfileUserInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("identity.getProfileUserInfo",
                              IDENTITY_GETPROFILEUSERINFO)
@@ -20,7 +20,7 @@
  private:
   ~IdentityGetProfileUserInfoFunction() override;
 
-  // UIThreadExtensionFunction implementation.
+  // ExtensionFunction implementation.
   ExtensionFunction::ResponseAction Run() override;
 };
 
diff --git a/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h b/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h
index 710c2eef..e99b464 100644
--- a/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h
+++ b/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h
@@ -10,7 +10,7 @@
 
 namespace extensions {
 
-class IdentityRemoveCachedAuthTokenFunction : public UIThreadExtensionFunction {
+class IdentityRemoveCachedAuthTokenFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("identity.removeCachedAuthToken",
                              EXPERIMENTAL_IDENTITY_REMOVECACHEDAUTHTOKEN)
diff --git a/chrome/browser/extensions/api/idltest/idltest_api.h b/chrome/browser/extensions/api/idltest/idltest_api.h
index 48b5e9d..5219e3e 100644
--- a/chrome/browser/extensions/api/idltest/idltest_api.h
+++ b/chrome/browser/extensions/api/idltest/idltest_api.h
@@ -7,7 +7,7 @@
 
 #include "extensions/browser/extension_function.h"
 
-class IdltestSendArrayBufferFunction : public UIThreadExtensionFunction {
+class IdltestSendArrayBufferFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("idltest.sendArrayBuffer", IDLTEST_SENDARRAYBUFFER)
 
@@ -16,7 +16,7 @@
   ResponseAction Run() override;
 };
 
-class IdltestSendArrayBufferViewFunction : public UIThreadExtensionFunction {
+class IdltestSendArrayBufferViewFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("idltest.sendArrayBufferView",
                              IDLTEST_SENDARRAYBUFFERVIEW)
@@ -26,7 +26,7 @@
   ResponseAction Run() override;
 };
 
-class IdltestGetArrayBufferFunction : public UIThreadExtensionFunction {
+class IdltestGetArrayBufferFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("idltest.getArrayBuffer", IDLTEST_GETARRAYBUFFER)
 
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.h b/chrome/browser/extensions/api/input_ime/input_ime_api.h
index 78e9fce74..c3fc3b3 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.h
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.h
@@ -128,7 +128,7 @@
   DISALLOW_COPY_AND_ASSIGN(InputImeEventRouterFactory);
 };
 
-class InputImeKeyEventHandledFunction : public UIThreadExtensionFunction {
+class InputImeKeyEventHandledFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.keyEventHandled",
                              INPUT_IME_KEYEVENTHANDLED)
@@ -136,11 +136,11 @@
  protected:
   ~InputImeKeyEventHandledFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
-class InputImeSetCompositionFunction : public UIThreadExtensionFunction {
+class InputImeSetCompositionFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.setComposition",
                              INPUT_IME_SETCOMPOSITION)
@@ -148,29 +148,29 @@
  protected:
   ~InputImeSetCompositionFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
-class InputImeCommitTextFunction : public UIThreadExtensionFunction {
+class InputImeCommitTextFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.commitText", INPUT_IME_COMMITTEXT)
 
  protected:
   ~InputImeCommitTextFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
-class InputImeSendKeyEventsFunction : public UIThreadExtensionFunction {
+class InputImeSendKeyEventsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.sendKeyEvents", INPUT_IME_SENDKEYEVENTS)
 
  protected:
   ~InputImeSendKeyEventsFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
index 20a1830..c07e7259 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
@@ -21,7 +21,7 @@
 
 namespace extensions {
 
-class InputImeClearCompositionFunction : public UIThreadExtensionFunction {
+class InputImeClearCompositionFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.clearComposition",
                              INPUT_IME_CLEARCOMPOSITION)
@@ -33,8 +33,7 @@
   ResponseAction Run() override;
 };
 
-class InputImeSetCandidateWindowPropertiesFunction
-    : public UIThreadExtensionFunction {
+class InputImeSetCandidateWindowPropertiesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.setCandidateWindowProperties",
                              INPUT_IME_SETCANDIDATEWINDOWPROPERTIES)
@@ -46,7 +45,7 @@
   ResponseAction Run() override;
 };
 
-class InputImeSetCandidatesFunction : public UIThreadExtensionFunction {
+class InputImeSetCandidatesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.setCandidates", INPUT_IME_SETCANDIDATES)
 
@@ -57,7 +56,7 @@
   ResponseAction Run() override;
 };
 
-class InputImeSetCursorPositionFunction : public UIThreadExtensionFunction {
+class InputImeSetCursorPositionFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.setCursorPosition",
                              INPUT_IME_SETCURSORPOSITION)
@@ -69,7 +68,7 @@
   ResponseAction Run() override;
 };
 
-class InputImeSetMenuItemsFunction : public UIThreadExtensionFunction {
+class InputImeSetMenuItemsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.setMenuItems", INPUT_IME_SETMENUITEMS)
 
@@ -80,7 +79,7 @@
   ResponseAction Run() override;
 };
 
-class InputImeUpdateMenuItemsFunction : public UIThreadExtensionFunction {
+class InputImeUpdateMenuItemsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.updateMenuItems",
                              INPUT_IME_UPDATEMENUITEMS)
@@ -92,7 +91,7 @@
   ResponseAction Run() override;
 };
 
-class InputImeDeleteSurroundingTextFunction : public UIThreadExtensionFunction {
+class InputImeDeleteSurroundingTextFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.deleteSurroundingText",
                              INPUT_IME_DELETESURROUNDINGTEXT)
@@ -103,7 +102,7 @@
   ResponseAction Run() override;
 };
 
-class InputImeHideInputViewFunction : public UIThreadExtensionFunction {
+class InputImeHideInputViewFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.hideInputView",
                              INPUT_IME_HIDEINPUTVIEW)
@@ -111,19 +110,19 @@
  protected:
   ~InputImeHideInputViewFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
 class InputMethodPrivateNotifyImeMenuItemActivatedFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   InputMethodPrivateNotifyImeMenuItemActivatedFunction() {}
 
  protected:
   ~InputMethodPrivateNotifyImeMenuItemActivatedFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -134,7 +133,7 @@
 };
 
 class InputMethodPrivateGetCompositionBoundsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("inputMethodPrivate.getCompositionBounds",
                              INPUTMETHODPRIVATE_GETCOMPOSITIONBOUNDS)
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h b/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h
index 84f39eb..68e06c5 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h
@@ -55,7 +55,7 @@
   DISALLOW_COPY_AND_ASSIGN(InputImeEventRouter);
 };
 
-class InputImeCreateWindowFunction : public UIThreadExtensionFunction {
+class InputImeCreateWindowFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.createWindow", INPUT_IME_CREATEWINDOW)
 
@@ -66,7 +66,7 @@
   ExtensionFunction::ResponseAction Run() override;
 };
 
-class InputImeShowWindowFunction : public UIThreadExtensionFunction {
+class InputImeShowWindowFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.showWindow", INPUT_IME_SHOWWINDOW)
 
@@ -77,7 +77,7 @@
   ExtensionFunction::ResponseAction Run() override;
 };
 
-class InputImeHideWindowFunction : public UIThreadExtensionFunction {
+class InputImeHideWindowFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.hideWindow", INPUT_IME_HIDEWINDOW)
 
@@ -88,7 +88,7 @@
   ExtensionFunction::ResponseAction Run() override;
 };
 
-class InputImeActivateFunction : public UIThreadExtensionFunction {
+class InputImeActivateFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.activate", INPUT_IME_ACTIVATE)
 
@@ -99,7 +99,7 @@
  protected:
   ~InputImeActivateFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -109,14 +109,14 @@
   void OnPermissionBubbleFinished(ImeWarningBubblePermissionStatus status);
 };
 
-class InputImeDeactivateFunction : public UIThreadExtensionFunction {
+class InputImeDeactivateFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("input.ime.deactivate", INPUT_IME_DEACTIVATE)
 
  protected:
   ~InputImeDeactivateFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
diff --git a/chrome/browser/extensions/api/instance_id/instance_id_api.h b/chrome/browser/extensions/api/instance_id/instance_id_api.h
index ffd49612..33a0bb0 100644
--- a/chrome/browser/extensions/api/instance_id/instance_id_api.h
+++ b/chrome/browser/extensions/api/instance_id/instance_id_api.h
@@ -11,7 +11,7 @@
 
 namespace extensions {
 
-class InstanceIDApiFunction : public UIThreadExtensionFunction {
+class InstanceIDApiFunction : public ExtensionFunction {
  public:
   InstanceIDApiFunction();
 
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h
index 951f544..2e745eb 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h
@@ -14,7 +14,7 @@
 
 // Implements the languageSettingsPrivate.getLanguageList method.
 class LanguageSettingsPrivateGetLanguageListFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateGetLanguageListFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.getLanguageList",
@@ -33,8 +33,7 @@
 };
 
 // Implements the languageSettingsPrivate.enableLanguage method.
-class LanguageSettingsPrivateEnableLanguageFunction
-    : public UIThreadExtensionFunction {
+class LanguageSettingsPrivateEnableLanguageFunction : public ExtensionFunction {
  public:
   LanguageSettingsPrivateEnableLanguageFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.enableLanguage",
@@ -54,7 +53,7 @@
 
 // Implements the languageSettingsPrivate.disableLanguage method.
 class LanguageSettingsPrivateDisableLanguageFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateDisableLanguageFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.disableLanguage",
@@ -75,7 +74,7 @@
 // Implements the languageSettingsPrivate.setEnableTranslationForLanguage
 // method.
 class LanguageSettingsPrivateSetEnableTranslationForLanguageFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateSetEnableTranslationForLanguageFunction();
   DECLARE_EXTENSION_FUNCTION(
@@ -95,8 +94,7 @@
 };
 
 // Implements the languageSettingsPrivate.moveLanguage method.
-class LanguageSettingsPrivateMoveLanguageFunction
-    : public UIThreadExtensionFunction {
+class LanguageSettingsPrivateMoveLanguageFunction : public ExtensionFunction {
  public:
   LanguageSettingsPrivateMoveLanguageFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.moveLanguage",
@@ -116,7 +114,7 @@
 // Implements the languageSettingsPrivate.getSpellcheckDictionaryStatuses
 // method.
 class LanguageSettingsPrivateGetSpellcheckDictionaryStatusesFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateGetSpellcheckDictionaryStatusesFunction();
   DECLARE_EXTENSION_FUNCTION(
@@ -136,7 +134,7 @@
 
 // Implements the languageSettingsPrivate.getSpellcheckWords method.
 class LanguageSettingsPrivateGetSpellcheckWordsFunction
-    : public UIThreadExtensionFunction,
+    : public ExtensionFunction,
       public SpellcheckCustomDictionary::Observer {
  public:
   LanguageSettingsPrivateGetSpellcheckWordsFunction();
@@ -163,7 +161,7 @@
 
 // Implements the languageSettingsPrivate.addSpellcheckWord method.
 class LanguageSettingsPrivateAddSpellcheckWordFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateAddSpellcheckWordFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.addSpellcheckWord",
@@ -181,7 +179,7 @@
 
 // Implements the languageSettingsPrivate.removeSpellcheckWord method.
 class LanguageSettingsPrivateRemoveSpellcheckWordFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateRemoveSpellcheckWordFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.removeSpellcheckWord",
@@ -199,7 +197,7 @@
 
 // Implements the languageSettingsPrivate.getTranslateTargetLanguage method.
 class LanguageSettingsPrivateGetTranslateTargetLanguageFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateGetTranslateTargetLanguageFunction();
   DECLARE_EXTENSION_FUNCTION(
@@ -221,7 +219,7 @@
 
 // Implements the languageSettingsPrivate.getInputMethodLists method.
 class LanguageSettingsPrivateGetInputMethodListsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateGetInputMethodListsFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.getInputMethodLists",
@@ -238,8 +236,7 @@
 };
 
 // Implements the languageSettingsPrivate.addInputMethod method.
-class LanguageSettingsPrivateAddInputMethodFunction
-    : public UIThreadExtensionFunction {
+class LanguageSettingsPrivateAddInputMethodFunction : public ExtensionFunction {
  public:
   LanguageSettingsPrivateAddInputMethodFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.addInputMethod",
@@ -259,7 +256,7 @@
 
 // Implements the languageSettingsPrivate.removeInputMethod method.
 class LanguageSettingsPrivateRemoveInputMethodFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateRemoveInputMethodFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.removeInputMethod",
@@ -279,7 +276,7 @@
 
 // Implements the languageSettingsPrivate.retryDownloadDictionary method.
 class LanguageSettingsPrivateRetryDownloadDictionaryFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   LanguageSettingsPrivateRetryDownloadDictionaryFunction();
   DECLARE_EXTENSION_FUNCTION("languageSettingsPrivate.retryDownloadDictionary",
diff --git a/chrome/browser/extensions/api/management/management_api_unittest.cc b/chrome/browser/extensions/api/management/management_api_unittest.cc
index 9b7ea704..aa72733 100644
--- a/chrome/browser/extensions/api/management/management_api_unittest.cc
+++ b/chrome/browser/extensions/api/management/management_api_unittest.cc
@@ -62,7 +62,7 @@
 
   // A wrapper around extension_function_test_utils::RunFunction that runs with
   // the associated browser, no flags, and can take stack-allocated arguments.
-  bool RunFunction(const scoped_refptr<UIThreadExtensionFunction>& function,
+  bool RunFunction(const scoped_refptr<ExtensionFunction>& function,
                    const base::ListValue& args);
 
   Browser* browser() { return browser_.get(); }
@@ -80,7 +80,7 @@
 };
 
 bool ManagementApiUnitTest::RunFunction(
-    const scoped_refptr<UIThreadExtensionFunction>& function,
+    const scoped_refptr<ExtensionFunction>& function,
     const base::ListValue& args) {
   return extension_function_test_utils::RunFunction(
       function.get(), base::WrapUnique(args.DeepCopy()), browser(),
@@ -271,7 +271,7 @@
         ScopedTestDialogAutoConfirm::ACCEPT);
 
     // Uninstall requires a user gesture, so this should fail.
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new ManagementUninstallFunction());
     EXPECT_FALSE(RunFunction(function, uninstall_args));
     EXPECT_EQ(std::string(constants::kGestureNeededForUninstallError),
@@ -295,7 +295,7 @@
     ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
 
     service()->AddExtension(extension.get());
-    scoped_refptr<UIThreadExtensionFunction> function =
+    scoped_refptr<ExtensionFunction> function =
         new ManagementUninstallFunction();
     EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
     EXPECT_FALSE(RunFunction(function, uninstall_args));
@@ -347,7 +347,7 @@
         ScopedTestDialogAutoConfirm::CANCEL);
     ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
 
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new ManagementUninstallFunction());
     function->set_extension(triggering_extension);
     EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
@@ -360,7 +360,7 @@
   }
 
   {
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new ManagementUninstallFunction());
     function->set_extension(triggering_extension);
 
@@ -397,7 +397,7 @@
   base::ListValue uninstall_args;
   uninstall_args.AppendString(extension->id());
   {
-    scoped_refptr<UIThreadExtensionFunction> function(
+    scoped_refptr<ExtensionFunction> function(
         new ManagementUninstallFunction());
     function->set_extension(triggering_extension);
 
@@ -435,8 +435,7 @@
 
   ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::ACCEPT);
   ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
-  scoped_refptr<UIThreadExtensionFunction> function(
-      new ManagementUninstallFunction());
+  scoped_refptr<ExtensionFunction> function(new ManagementUninstallFunction());
   base::ListValue uninstall_args;
   uninstall_args.AppendString(id);
   EXPECT_TRUE(RunFunction(function, uninstall_args)) << function->GetError();
@@ -452,7 +451,7 @@
   service()->BlacklistExtensionForTest(id);
   EXPECT_NE(nullptr, registry()->GetInstalledExtension(id));
 
-  scoped_refptr<UIThreadExtensionFunction> function;
+  scoped_refptr<ExtensionFunction> function;
 
   // Test enabling it.
   {
@@ -486,7 +485,7 @@
 
   const std::string args =
       base::StringPrintf("[\"%s\"]", extension->id().c_str());
-  scoped_refptr<UIThreadExtensionFunction> function;
+  scoped_refptr<ExtensionFunction> function;
 
   // Initially the extension should show as enabled.
   EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
diff --git a/chrome/browser/extensions/api/mdns/mdns_api.h b/chrome/browser/extensions/api/mdns/mdns_api.h
index 19464a2e..dbfe3b4 100644
--- a/chrome/browser/extensions/api/mdns/mdns_api.h
+++ b/chrome/browser/extensions/api/mdns/mdns_api.h
@@ -118,7 +118,7 @@
   DISALLOW_COPY_AND_ASSIGN(MDnsAPI);
 };
 
-class MdnsForceDiscoveryFunction : public UIThreadExtensionFunction {
+class MdnsForceDiscoveryFunction : public ExtensionFunction {
  public:
   MdnsForceDiscoveryFunction();
 
@@ -126,7 +126,7 @@
   ~MdnsForceDiscoveryFunction() override;
 
  private:
-  // UIThreadExtensionFunction override.
+  // ExtensionFunction override.
   ResponseAction Run() override;
 
   DECLARE_EXTENSION_FUNCTION("mdns.forceDiscovery", MDNS_FORCEDISCOVERY)
diff --git a/chrome/browser/extensions/api/module/module.h b/chrome/browser/extensions/api/module/module.h
index de81de0d..cbdde20 100644
--- a/chrome/browser/extensions/api/module/module.h
+++ b/chrome/browser/extensions/api/module/module.h
@@ -16,7 +16,7 @@
                              const std::string& extension_id);
 }  // namespace extension
 
-class ExtensionSetUpdateUrlDataFunction : public UIThreadExtensionFunction {
+class ExtensionSetUpdateUrlDataFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("extension.setUpdateUrlData",
                              EXTENSION_SETUPDATEURLDATA)
@@ -28,8 +28,7 @@
   ResponseAction Run() override;
 };
 
-class ExtensionIsAllowedIncognitoAccessFunction
-    : public UIThreadExtensionFunction {
+class ExtensionIsAllowedIncognitoAccessFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("extension.isAllowedIncognitoAccess",
                              EXTENSION_ISALLOWEDINCOGNITOACCESS)
@@ -41,8 +40,7 @@
   ResponseAction Run() override;
 };
 
-class ExtensionIsAllowedFileSchemeAccessFunction
-    : public UIThreadExtensionFunction {
+class ExtensionIsAllowedFileSchemeAccessFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("extension.isAllowedFileSchemeAccess",
                              EXTENSION_ISALLOWEDFILESCHEMEACCESS)
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
index 4f12d14..daf23fba 100644
--- a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
@@ -18,7 +18,7 @@
 namespace extensions {
 
 class NetworkingCastPrivateVerifyDestinationFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   NetworkingCastPrivateVerifyDestinationFunction() {}
   DECLARE_EXTENSION_FUNCTION("networking.castPrivate.verifyDestination",
@@ -38,7 +38,7 @@
 };
 
 class NetworkingCastPrivateVerifyAndEncryptDataFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   NetworkingCastPrivateVerifyAndEncryptDataFunction() {}
   DECLARE_EXTENSION_FUNCTION("networking.castPrivate.verifyAndEncryptData",
@@ -58,7 +58,7 @@
 };
 
 class NetworkingCastPrivateSetWifiTDLSEnabledStateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   NetworkingCastPrivateSetWifiTDLSEnabledStateFunction() {}
   DECLARE_EXTENSION_FUNCTION("networking.castPrivate.setWifiTDLSEnabledState",
@@ -82,7 +82,7 @@
 };
 
 class NetworkingCastPrivateGetWifiTDLSStatusFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   NetworkingCastPrivateGetWifiTDLSStatusFunction() {}
   DECLARE_EXTENSION_FUNCTION("networking.castPrivate.getWifiTDLSStatus",
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api.h b/chrome/browser/extensions/api/omnibox/omnibox_api.h
index 27c7981..435ea64 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_api.h
+++ b/chrome/browser/extensions/api/omnibox/omnibox_api.h
@@ -74,7 +74,7 @@
   DISALLOW_COPY_AND_ASSIGN(ExtensionOmniboxEventRouter);
 };
 
-class OmniboxSendSuggestionsFunction : public UIThreadExtensionFunction {
+class OmniboxSendSuggestionsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("omnibox.sendSuggestions", OMNIBOX_SENDSUGGESTIONS)
 
@@ -147,7 +147,7 @@
 template <>
 void BrowserContextKeyedAPIFactory<OmniboxAPI>::DeclareFactoryDependencies();
 
-class OmniboxSetDefaultSuggestionFunction : public UIThreadExtensionFunction {
+class OmniboxSetDefaultSuggestionFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("omnibox.setDefaultSuggestion",
                              OMNIBOX_SETDEFAULTSUGGESTION)
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_api.h b/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
index 5b94478..b9521497 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
@@ -17,7 +17,7 @@
 namespace extensions {
 
 class PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction() {}
   DECLARE_EXTENSION_FUNCTION(
@@ -35,8 +35,7 @@
       PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction);
 };
 
-class PasswordsPrivateChangeSavedPasswordFunction
-    : public UIThreadExtensionFunction {
+class PasswordsPrivateChangeSavedPasswordFunction : public ExtensionFunction {
  public:
   PasswordsPrivateChangeSavedPasswordFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.changeSavedPassword",
@@ -52,8 +51,7 @@
   DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateChangeSavedPasswordFunction);
 };
 
-class PasswordsPrivateRemoveSavedPasswordFunction :
-    public UIThreadExtensionFunction {
+class PasswordsPrivateRemoveSavedPasswordFunction : public ExtensionFunction {
  public:
   PasswordsPrivateRemoveSavedPasswordFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.removeSavedPassword",
@@ -69,8 +67,8 @@
   DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateRemoveSavedPasswordFunction);
 };
 
-class PasswordsPrivateRemovePasswordExceptionFunction :
-    public UIThreadExtensionFunction {
+class PasswordsPrivateRemovePasswordExceptionFunction
+    : public ExtensionFunction {
  public:
   PasswordsPrivateRemovePasswordExceptionFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.removePasswordException",
@@ -87,7 +85,7 @@
 };
 
 class PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction() {}
   DECLARE_EXTENSION_FUNCTION(
@@ -105,8 +103,8 @@
       PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction);
 };
 
-class PasswordsPrivateRequestPlaintextPasswordFunction :
-    public UIThreadExtensionFunction {
+class PasswordsPrivateRequestPlaintextPasswordFunction
+    : public ExtensionFunction {
  public:
   PasswordsPrivateRequestPlaintextPasswordFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.requestPlaintextPassword",
@@ -124,8 +122,7 @@
   DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateRequestPlaintextPasswordFunction);
 };
 
-class PasswordsPrivateGetSavedPasswordListFunction
-    : public UIThreadExtensionFunction {
+class PasswordsPrivateGetSavedPasswordListFunction : public ExtensionFunction {
  public:
   PasswordsPrivateGetSavedPasswordListFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.getSavedPasswordList",
@@ -145,7 +142,7 @@
 };
 
 class PasswordsPrivateGetPasswordExceptionListFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   PasswordsPrivateGetPasswordExceptionListFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.getPasswordExceptionList",
@@ -164,8 +161,7 @@
   DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateGetPasswordExceptionListFunction);
 };
 
-class PasswordsPrivateImportPasswordsFunction
-    : public UIThreadExtensionFunction {
+class PasswordsPrivateImportPasswordsFunction : public ExtensionFunction {
  public:
   PasswordsPrivateImportPasswordsFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.importPasswords",
@@ -181,8 +177,7 @@
   DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateImportPasswordsFunction);
 };
 
-class PasswordsPrivateExportPasswordsFunction
-    : public UIThreadExtensionFunction {
+class PasswordsPrivateExportPasswordsFunction : public ExtensionFunction {
  public:
   PasswordsPrivateExportPasswordsFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.exportPasswords",
@@ -200,8 +195,7 @@
   DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateExportPasswordsFunction);
 };
 
-class PasswordsPrivateCancelExportPasswordsFunction
-    : public UIThreadExtensionFunction {
+class PasswordsPrivateCancelExportPasswordsFunction : public ExtensionFunction {
  public:
   PasswordsPrivateCancelExportPasswordsFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.cancelExportPasswords",
@@ -218,7 +212,7 @@
 };
 
 class PasswordsPrivateRequestExportProgressStatusFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   PasswordsPrivateRequestExportProgressStatusFunction() {}
   DECLARE_EXTENSION_FUNCTION("passwordsPrivate.requestExportProgressStatus",
diff --git a/chrome/browser/extensions/api/permissions/permissions_api.h b/chrome/browser/extensions/api/permissions/permissions_api.h
index 87c04d9..e25d14c 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api.h
+++ b/chrome/browser/extensions/api/permissions/permissions_api.h
@@ -16,7 +16,7 @@
 namespace extensions {
 
 // chrome.permissions.contains
-class PermissionsContainsFunction : public UIThreadExtensionFunction {
+class PermissionsContainsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("permissions.contains", PERMISSIONS_CONTAINS)
 
@@ -28,7 +28,7 @@
 };
 
 // chrome.permissions.getAll
-class PermissionsGetAllFunction : public UIThreadExtensionFunction {
+class PermissionsGetAllFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("permissions.getAll", PERMISSIONS_GETALL)
 
@@ -40,7 +40,7 @@
 };
 
 // chrome.permissions.remove
-class PermissionsRemoveFunction : public UIThreadExtensionFunction {
+class PermissionsRemoveFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("permissions.remove", PERMISSIONS_REMOVE)
 
@@ -52,7 +52,7 @@
 };
 
 // chrome.permissions.request
-class PermissionsRequestFunction : public UIThreadExtensionFunction {
+class PermissionsRequestFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("permissions.request", PERMISSIONS_REQUEST)
 
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_api.h b/chrome/browser/extensions/api/platform_keys/platform_keys_api.h
index b632e4e..4d1ece03 100644
--- a/chrome/browser/extensions/api/platform_keys/platform_keys_api.h
+++ b/chrome/browser/extensions/api/platform_keys/platform_keys_api.h
@@ -33,7 +33,7 @@
 }  // namespace platform_keys
 
 class PlatformKeysInternalSelectClientCertificatesFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  private:
   ~PlatformKeysInternalSelectClientCertificatesFunction() override;
   ResponseAction Run() override;
@@ -47,8 +47,7 @@
                              PLATFORMKEYSINTERNAL_SELECTCLIENTCERTIFICATES)
 };
 
-class PlatformKeysInternalGetPublicKeyFunction
-    : public UIThreadExtensionFunction {
+class PlatformKeysInternalGetPublicKeyFunction : public ExtensionFunction {
  private:
   ~PlatformKeysInternalGetPublicKeyFunction() override;
   ResponseAction Run() override;
@@ -57,7 +56,7 @@
                              PLATFORMKEYSINTERNAL_GETPUBLICKEY)
 };
 
-class PlatformKeysInternalSignFunction : public UIThreadExtensionFunction {
+class PlatformKeysInternalSignFunction : public ExtensionFunction {
  private:
   ~PlatformKeysInternalSignFunction() override;
   ResponseAction Run() override;
@@ -71,7 +70,7 @@
 };
 
 class PlatformKeysVerifyTLSServerCertificateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  private:
   ~PlatformKeysVerifyTLSServerCertificateFunction() override;
   ResponseAction Run() override;
diff --git a/chrome/browser/extensions/api/preference/preference_api.h b/chrome/browser/extensions/api/preference/preference_api.h
index 80d27cc..086434a 100644
--- a/chrome/browser/extensions/api/preference/preference_api.h
+++ b/chrome/browser/extensions/api/preference/preference_api.h
@@ -175,7 +175,7 @@
 
 // A base class to provide functionality common to the other *PreferenceFunction
 // classes.
-class PreferenceFunction : public UIThreadExtensionFunction {
+class PreferenceFunction : public ExtensionFunction {
  protected:
   enum PermissionType { PERMISSION_TYPE_READ, PERMISSION_TYPE_WRITE };
 
diff --git a/chrome/browser/extensions/api/processes/processes_api.h b/chrome/browser/extensions/api/processes/processes_api.h
index f1ef0d68..f72d0525 100644
--- a/chrome/browser/extensions/api/processes/processes_api.h
+++ b/chrome/browser/extensions/api/processes/processes_api.h
@@ -110,9 +110,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 // This extension function returns the Process object for the renderer process
 // currently in use by the specified Tab.
-class ProcessesGetProcessIdForTabFunction : public UIThreadExtensionFunction {
+class ProcessesGetProcessIdForTabFunction : public ExtensionFunction {
  public:
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ExtensionFunction::ResponseAction Run() override;
 
   DECLARE_EXTENSION_FUNCTION("processes.getProcessIdForTab",
@@ -128,9 +128,9 @@
 // Using unique IDs instead of OS process IDs allows two advantages:
 // * guaranteed uniqueness, since OS process IDs can be reused.
 // * guards against killing non-Chrome processes.
-class ProcessesTerminateFunction : public UIThreadExtensionFunction {
+class ProcessesTerminateFunction : public ExtensionFunction {
  public:
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ExtensionFunction::ResponseAction Run() override;
 
   DECLARE_EXTENSION_FUNCTION("processes.terminate", PROCESSES_TERMINATE)
@@ -157,13 +157,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Extension function which returns a set of Process objects, containing the
 // details corresponding to the process IDs supplied as input.
-class ProcessesGetProcessInfoFunction :
-    public UIThreadExtensionFunction,
-    public task_manager::TaskManagerObserver {
+class ProcessesGetProcessInfoFunction
+    : public ExtensionFunction,
+      public task_manager::TaskManagerObserver {
  public:
   ProcessesGetProcessInfoFunction();
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ExtensionFunction::ResponseAction Run() override;
 
   // task_manager::TaskManagerObserver:
diff --git a/chrome/browser/extensions/api/resources_private/resources_private_api.h b/chrome/browser/extensions/api/resources_private/resources_private_api.h
index ce37f9dc..4440d65 100644
--- a/chrome/browser/extensions/api/resources_private/resources_private_api.h
+++ b/chrome/browser/extensions/api/resources_private/resources_private_api.h
@@ -10,7 +10,7 @@
 
 namespace extensions {
 
-class ResourcesPrivateGetStringsFunction : public UIThreadExtensionFunction {
+class ResourcesPrivateGetStringsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("resourcesPrivate.getStrings",
                              RESOURCESPRIVATE_GETSTRINGS)
diff --git a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api.h b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api.h
index d28ce05..13980a7 100644
--- a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api.h
+++ b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api.h
@@ -9,8 +9,7 @@
 
 namespace extensions {
 
-class SafeBrowsingPrivateGetReferrerChainFunction
-    : public UIThreadExtensionFunction {
+class SafeBrowsingPrivateGetReferrerChainFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("safeBrowsingPrivate.getReferrerChain",
                              SAFEBROWSINGPRIVATE_GETREFERRERCHAIN)
diff --git a/chrome/browser/extensions/api/sessions/sessions_api.h b/chrome/browser/extensions/api/sessions/sessions_api.h
index d859f64..6d177c1 100644
--- a/chrome/browser/extensions/api/sessions/sessions_api.h
+++ b/chrome/browser/extensions/api/sessions/sessions_api.h
@@ -27,7 +27,7 @@
 
 class SessionId;
 
-class SessionsGetRecentlyClosedFunction : public UIThreadExtensionFunction {
+class SessionsGetRecentlyClosedFunction : public ExtensionFunction {
  protected:
   ~SessionsGetRecentlyClosedFunction() override {}
   ResponseAction Run() override;
@@ -43,7 +43,7 @@
       const sessions::TabRestoreService::Entry& entry);
 };
 
-class SessionsGetDevicesFunction : public UIThreadExtensionFunction {
+class SessionsGetDevicesFunction : public ExtensionFunction {
  protected:
   ~SessionsGetDevicesFunction() override {}
   ResponseAction Run() override;
@@ -64,7 +64,7 @@
       const sync_sessions::SyncedSession* session);
 };
 
-class SessionsRestoreFunction : public UIThreadExtensionFunction {
+class SessionsRestoreFunction : public ExtensionFunction {
  protected:
   ~SessionsRestoreFunction() override {}
   ResponseAction Run() override;
diff --git a/chrome/browser/extensions/api/settings_private/settings_private_api.h b/chrome/browser/extensions/api/settings_private/settings_private_api.h
index f9a377d..ec333f2 100644
--- a/chrome/browser/extensions/api/settings_private/settings_private_api.h
+++ b/chrome/browser/extensions/api/settings_private/settings_private_api.h
@@ -13,7 +13,7 @@
 namespace extensions {
 
 // Implements the chrome.settingsPrivate.setPref method.
-class SettingsPrivateSetPrefFunction : public UIThreadExtensionFunction {
+class SettingsPrivateSetPrefFunction : public ExtensionFunction {
  public:
   SettingsPrivateSetPrefFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.setPref", SETTINGSPRIVATE_SETPREF)
@@ -21,14 +21,14 @@
  protected:
   ~SettingsPrivateSetPrefFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateSetPrefFunction);
 };
 
 // Implements the chrome.settingsPrivate.getAllPrefs method.
-class SettingsPrivateGetAllPrefsFunction : public UIThreadExtensionFunction {
+class SettingsPrivateGetAllPrefsFunction : public ExtensionFunction {
  public:
   SettingsPrivateGetAllPrefsFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.getAllPrefs",
@@ -37,14 +37,14 @@
  protected:
   ~SettingsPrivateGetAllPrefsFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateGetAllPrefsFunction);
 };
 
 // Implements the chrome.settingsPrivate.getPref method.
-class SettingsPrivateGetPrefFunction : public UIThreadExtensionFunction {
+class SettingsPrivateGetPrefFunction : public ExtensionFunction {
  public:
   SettingsPrivateGetPrefFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.getPref", SETTINGSPRIVATE_GETPREF)
@@ -52,15 +52,14 @@
  protected:
   ~SettingsPrivateGetPrefFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateGetPrefFunction);
 };
 
 // Implements the chrome.settingsPrivate.getDefaultZoom method.
-class SettingsPrivateGetDefaultZoomFunction
-    : public UIThreadExtensionFunction {
+class SettingsPrivateGetDefaultZoomFunction : public ExtensionFunction {
  public:
   SettingsPrivateGetDefaultZoomFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.getDefaultZoom",
@@ -69,15 +68,14 @@
  protected:
   ~SettingsPrivateGetDefaultZoomFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateGetDefaultZoomFunction);
 };
 
 // Implements the chrome.settingsPrivate.setDefaultZoom method.
-class SettingsPrivateSetDefaultZoomFunction
-    : public UIThreadExtensionFunction {
+class SettingsPrivateSetDefaultZoomFunction : public ExtensionFunction {
  public:
   SettingsPrivateSetDefaultZoomFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.setDefaultZoom",
@@ -86,7 +84,7 @@
  protected:
   ~SettingsPrivateSetDefaultZoomFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateSetDefaultZoomFunction);
diff --git a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h
index b24066b..c46442ec 100644
--- a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h
+++ b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h
@@ -37,7 +37,7 @@
     syncer::DeviceInfoTracker* device_tracker,
     ExtensionPrefs* extension_prefs);
 
-class SignedInDevicesGetFunction : public UIThreadExtensionFunction {
+class SignedInDevicesGetFunction : public ExtensionFunction {
  protected:
   ~SignedInDevicesGetFunction() override {}
 
diff --git a/chrome/browser/extensions/api/system_indicator/system_indicator_api.h b/chrome/browser/extensions/api/system_indicator/system_indicator_api.h
index b0bd25e..5b3ca7b 100644
--- a/chrome/browser/extensions/api/system_indicator/system_indicator_api.h
+++ b/chrome/browser/extensions/api/system_indicator/system_indicator_api.h
@@ -9,7 +9,7 @@
 
 namespace extensions {
 
-class SystemIndicatorSetIconFunction : public UIThreadExtensionFunction {
+class SystemIndicatorSetIconFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("systemIndicator.setIcon", SYSTEMINDICATOR_SETICON)
 
@@ -19,7 +19,7 @@
   ~SystemIndicatorSetIconFunction() override {}
 };
 
-class SystemIndicatorEnableFunction : public UIThreadExtensionFunction {
+class SystemIndicatorEnableFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("systemIndicator.enable", SYSTEMINDICATOR_ENABLE)
 
@@ -29,7 +29,7 @@
   ~SystemIndicatorEnableFunction() override {}
 };
 
-class SystemIndicatorDisableFunction : public UIThreadExtensionFunction {
+class SystemIndicatorDisableFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("systemIndicator.disable", SYSTEMINDICATOR_DISABLE)
 
diff --git a/chrome/browser/extensions/api/system_private/system_private_api.h b/chrome/browser/extensions/api/system_private/system_private_api.h
index 5d6fb2bc..9c912f0 100644
--- a/chrome/browser/extensions/api/system_private/system_private_api.h
+++ b/chrome/browser/extensions/api/system_private/system_private_api.h
@@ -13,7 +13,7 @@
 namespace extensions {
 
 class SystemPrivateGetIncognitoModeAvailabilityFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("systemPrivate.getIncognitoModeAvailability",
                              SYSTEMPRIVATE_GETINCOGNITOMODEAVAILABILITY)
@@ -26,7 +26,7 @@
 };
 
 // API function which returns the status of system update.
-class SystemPrivateGetUpdateStatusFunction : public UIThreadExtensionFunction {
+class SystemPrivateGetUpdateStatusFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("systemPrivate.getUpdateStatus",
                              SYSTEMPRIVATE_GETUPDATESTATUS)
@@ -39,7 +39,7 @@
 };
 
 // API function which returns the Google API key.
-class SystemPrivateGetApiKeyFunction : public UIThreadExtensionFunction {
+class SystemPrivateGetApiKeyFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("systemPrivate.getApiKey", SYSTEMPRIVATE_GETAPIKEY)
 
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_api.h b/chrome/browser/extensions/api/tab_capture/tab_capture_api.h
index 2f3979b..15c0827e 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_api.h
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_api.h
@@ -22,7 +22,7 @@
 // Extension ids for the chromecast.
 extern const char* const kChromecastExtensionIds[6];
 
-class TabCaptureCaptureFunction : public UIThreadExtensionFunction {
+class TabCaptureCaptureFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("tabCapture.capture", TABCAPTURE_CAPTURE)
 
@@ -33,7 +33,7 @@
   ResponseAction Run() final;
 };
 
-class TabCaptureGetCapturedTabsFunction : public UIThreadExtensionFunction {
+class TabCaptureGetCapturedTabsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("tabCapture.getCapturedTabs",
                              TABCAPTURE_GETCAPTUREDTABS)
@@ -45,7 +45,7 @@
   ResponseAction Run() final;
 };
 
-class TabCaptureCaptureOffscreenTabFunction : public UIThreadExtensionFunction {
+class TabCaptureCaptureOffscreenTabFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("tabCapture.captureOffscreenTab",
                              TABCAPTURE_CAPTUREOFFSCREENTAB)
@@ -62,7 +62,7 @@
   ResponseAction Run() final;
 };
 
-class TabCaptureGetMediaStreamIdFunction : public UIThreadExtensionFunction {
+class TabCaptureGetMediaStreamIdFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("tabCapture.getMediaStreamId",
                              TABCAPTURE_GETMEDIASTREAMID)
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index 03306fa..1e8ca806 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -148,7 +148,7 @@
   return true;
 }
 
-bool GetBrowserFromWindowID(UIThreadExtensionFunction* function,
+bool GetBrowserFromWindowID(ExtensionFunction* function,
                             int window_id,
                             Browser** browser,
                             std::string* error) {
@@ -182,10 +182,9 @@
 // Gets the WebContents for |tab_id| if it is specified. Otherwise get the
 // WebContents for the active tab in the |function|'s current window.
 // Returns nullptr and fills |error| if failed.
-content::WebContents* GetTabsAPIDefaultWebContents(
-    UIThreadExtensionFunction* function,
-    int tab_id,
-    std::string* error) {
+content::WebContents* GetTabsAPIDefaultWebContents(ExtensionFunction* function,
+                                                   int tab_id,
+                                                   std::string* error) {
   content::WebContents* web_contents = nullptr;
   if (tab_id != -1) {
     // We assume this call leaves web_contents unchanged if it is unsuccessful.
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.h b/chrome/browser/extensions/api/tabs/tabs_api.h
index 37c2da5..ed3aa53 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.h
+++ b/chrome/browser/extensions/api/tabs/tabs_api.h
@@ -44,27 +44,27 @@
                             api::tabs::ZoomSettings* zoom_settings);
 
 // Windows
-class WindowsGetFunction : public UIThreadExtensionFunction {
+class WindowsGetFunction : public ExtensionFunction {
   ~WindowsGetFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.get", WINDOWS_GET)
 };
-class WindowsGetCurrentFunction : public UIThreadExtensionFunction {
+class WindowsGetCurrentFunction : public ExtensionFunction {
   ~WindowsGetCurrentFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.getCurrent", WINDOWS_GETCURRENT)
 };
-class WindowsGetLastFocusedFunction : public UIThreadExtensionFunction {
+class WindowsGetLastFocusedFunction : public ExtensionFunction {
   ~WindowsGetLastFocusedFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.getLastFocused", WINDOWS_GETLASTFOCUSED)
 };
-class WindowsGetAllFunction : public UIThreadExtensionFunction {
+class WindowsGetAllFunction : public ExtensionFunction {
   ~WindowsGetAllFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.getAll", WINDOWS_GETALL)
 };
-class WindowsCreateFunction : public UIThreadExtensionFunction {
+class WindowsCreateFunction : public ExtensionFunction {
   ~WindowsCreateFunction() override {}
   ResponseAction Run() override;
   // Returns whether the window should be created in incognito mode.
@@ -80,54 +80,54 @@
       std::string* error);
   DECLARE_EXTENSION_FUNCTION("windows.create", WINDOWS_CREATE)
 };
-class WindowsUpdateFunction : public UIThreadExtensionFunction {
+class WindowsUpdateFunction : public ExtensionFunction {
   ~WindowsUpdateFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.update", WINDOWS_UPDATE)
 };
-class WindowsRemoveFunction : public UIThreadExtensionFunction {
+class WindowsRemoveFunction : public ExtensionFunction {
   ~WindowsRemoveFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.remove", WINDOWS_REMOVE)
 };
 
 // Tabs
-class TabsGetFunction : public UIThreadExtensionFunction {
+class TabsGetFunction : public ExtensionFunction {
   ~TabsGetFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.get", TABS_GET)
 };
-class TabsGetCurrentFunction : public UIThreadExtensionFunction {
+class TabsGetCurrentFunction : public ExtensionFunction {
   ~TabsGetCurrentFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.getCurrent", TABS_GETCURRENT)
 };
-class TabsGetSelectedFunction : public UIThreadExtensionFunction {
+class TabsGetSelectedFunction : public ExtensionFunction {
   ~TabsGetSelectedFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.getSelected", TABS_GETSELECTED)
 };
-class TabsGetAllInWindowFunction : public UIThreadExtensionFunction {
+class TabsGetAllInWindowFunction : public ExtensionFunction {
   ~TabsGetAllInWindowFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.getAllInWindow", TABS_GETALLINWINDOW)
 };
-class TabsQueryFunction : public UIThreadExtensionFunction {
+class TabsQueryFunction : public ExtensionFunction {
   ~TabsQueryFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.query", TABS_QUERY)
 };
-class TabsCreateFunction : public UIThreadExtensionFunction {
+class TabsCreateFunction : public ExtensionFunction {
   ~TabsCreateFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.create", TABS_CREATE)
 };
-class TabsDuplicateFunction : public UIThreadExtensionFunction {
+class TabsDuplicateFunction : public ExtensionFunction {
   ~TabsDuplicateFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.duplicate", TABS_DUPLICATE)
 };
-class TabsHighlightFunction : public UIThreadExtensionFunction {
+class TabsHighlightFunction : public ExtensionFunction {
   ~TabsHighlightFunction() override {}
   ResponseAction Run() override;
   bool HighlightTab(TabStripModel* tabstrip,
@@ -137,7 +137,7 @@
                     std::string* error);
   DECLARE_EXTENSION_FUNCTION("tabs.highlight", TABS_HIGHLIGHT)
 };
-class TabsUpdateFunction : public UIThreadExtensionFunction {
+class TabsUpdateFunction : public ExtensionFunction {
  public:
   TabsUpdateFunction();
 
@@ -158,7 +158,7 @@
 
   DECLARE_EXTENSION_FUNCTION("tabs.update", TABS_UPDATE)
 };
-class TabsMoveFunction : public UIThreadExtensionFunction {
+class TabsMoveFunction : public ExtensionFunction {
   ~TabsMoveFunction() override {}
   ResponseAction Run() override;
   bool MoveTab(int tab_id,
@@ -169,19 +169,19 @@
                std::string* error);
   DECLARE_EXTENSION_FUNCTION("tabs.move", TABS_MOVE)
 };
-class TabsReloadFunction : public UIThreadExtensionFunction {
+class TabsReloadFunction : public ExtensionFunction {
   ~TabsReloadFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.reload", TABS_RELOAD)
 };
-class TabsRemoveFunction : public UIThreadExtensionFunction {
+class TabsRemoveFunction : public ExtensionFunction {
   ~TabsRemoveFunction() override {}
   ResponseAction Run() override;
   bool RemoveTab(int tab_id, std::string* error);
   DECLARE_EXTENSION_FUNCTION("tabs.remove", TABS_REMOVE)
 };
 class TabsDetectLanguageFunction
-    : public UIThreadExtensionFunction,
+    : public ExtensionFunction,
       public content::WebContentsObserver,
       public translate::ContentTranslateDriver::Observer {
  private:
@@ -209,7 +209,7 @@
 
 class TabsCaptureVisibleTabFunction
     : public extensions::WebContentsCaptureClient,
-      public UIThreadExtensionFunction {
+      public ExtensionFunction {
  public:
   TabsCaptureVisibleTabFunction();
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
@@ -280,7 +280,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.insertCSS", TABS_INSERTCSS)
 };
 
-class TabsSetZoomFunction : public UIThreadExtensionFunction {
+class TabsSetZoomFunction : public ExtensionFunction {
  private:
   ~TabsSetZoomFunction() override {}
 
@@ -289,7 +289,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.setZoom", TABS_SETZOOM)
 };
 
-class TabsGetZoomFunction : public UIThreadExtensionFunction {
+class TabsGetZoomFunction : public ExtensionFunction {
  private:
   ~TabsGetZoomFunction() override {}
 
@@ -298,7 +298,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.getZoom", TABS_GETZOOM)
 };
 
-class TabsSetZoomSettingsFunction : public UIThreadExtensionFunction {
+class TabsSetZoomSettingsFunction : public ExtensionFunction {
  private:
   ~TabsSetZoomSettingsFunction() override {}
 
@@ -307,7 +307,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.setZoomSettings", TABS_SETZOOMSETTINGS)
 };
 
-class TabsGetZoomSettingsFunction : public UIThreadExtensionFunction {
+class TabsGetZoomSettingsFunction : public ExtensionFunction {
  private:
   ~TabsGetZoomSettingsFunction() override {}
 
@@ -316,7 +316,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.getZoomSettings", TABS_GETZOOMSETTINGS)
 };
 
-class TabsDiscardFunction : public UIThreadExtensionFunction {
+class TabsDiscardFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("tabs.discard", TABS_DISCARD)
 
@@ -331,7 +331,7 @@
   DISALLOW_COPY_AND_ASSIGN(TabsDiscardFunction);
 };
 
-class TabsGoForwardFunction : public UIThreadExtensionFunction {
+class TabsGoForwardFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("tabs.goForward", TABS_GOFORWARD)
 
@@ -346,7 +346,7 @@
   DISALLOW_COPY_AND_ASSIGN(TabsGoForwardFunction);
 };
 
-class TabsGoBackFunction : public UIThreadExtensionFunction {
+class TabsGoBackFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("tabs.goBack", TABS_GOBACK)
 
diff --git a/chrome/browser/extensions/api/tabs/tabs_test.cc b/chrome/browser/extensions/api/tabs/tabs_test.cc
index b6f0fe9f28..f5fb1424 100644
--- a/chrome/browser/extensions/api/tabs/tabs_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -795,7 +795,7 @@
 
   int GetTabId(const base::DictionaryValue* value) const;
 
-  base::Value* RunFunction(UIThreadExtensionFunction* function,
+  base::Value* RunFunction(ExtensionFunction* function,
                            const std::string& params);
 
   const Extension* extension() { return extension_.get(); }
@@ -880,7 +880,7 @@
 }
 
 base::Value* ExtensionWindowLastFocusedTest::RunFunction(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& params) {
   function->set_extension(extension_.get());
   return utils::RunFunctionAndReturnSingleResult(function, params, browser());
diff --git a/chrome/browser/extensions/api/tabs/windows_util.cc b/chrome/browser/extensions/api/tabs/windows_util.cc
index 684183d..ae70d40 100644
--- a/chrome/browser/extensions/api/tabs/windows_util.cc
+++ b/chrome/browser/extensions/api/tabs/windows_util.cc
@@ -23,7 +23,7 @@
 
 namespace windows_util {
 
-bool GetBrowserFromWindowID(UIThreadExtensionFunction* function,
+bool GetBrowserFromWindowID(ExtensionFunction* function,
                             int window_id,
                             extensions::WindowController::TypeFilter filter,
                             Browser** browser,
@@ -68,7 +68,7 @@
   return true;
 }
 
-bool CanOperateOnWindow(const UIThreadExtensionFunction* function,
+bool CanOperateOnWindow(const ExtensionFunction* function,
                         const extensions::WindowController* controller,
                         extensions::WindowController::TypeFilter filter) {
   if (filter && !controller->MatchesFilter(filter))
diff --git a/chrome/browser/extensions/api/tabs/windows_util.h b/chrome/browser/extensions/api/tabs/windows_util.h
index f080d06..551e1bbbb 100644
--- a/chrome/browser/extensions/api/tabs/windows_util.h
+++ b/chrome/browser/extensions/api/tabs/windows_util.h
@@ -9,7 +9,7 @@
 
 #include "chrome/browser/extensions/window_controller_list.h"
 
-class UIThreadExtensionFunction;
+class ExtensionFunction;
 
 namespace extensions {
 class WindowController;
@@ -19,7 +19,7 @@
 
 // Populates |browser| for given |window_id|. If the window is not found,
 // returns false and sets |error|.
-bool GetBrowserFromWindowID(UIThreadExtensionFunction* function,
+bool GetBrowserFromWindowID(ExtensionFunction* function,
                             int window_id,
                             extensions::WindowController::TypeFilter filter,
                             Browser** browser,
@@ -31,7 +31,7 @@
 // kind of window (including app and devtools), otherwise it will
 // return true only for normal browser windows as well as windows
 // created by the extension.
-bool CanOperateOnWindow(const UIThreadExtensionFunction* function,
+bool CanOperateOnWindow(const ExtensionFunction* function,
                         const extensions::WindowController* controller,
                         extensions::WindowController::TypeFilter filter);
 
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.h b/chrome/browser/extensions/api/terminal/terminal_private_api.h
index 601c34e..caf14dc1 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_api.h
+++ b/chrome/browser/extensions/api/terminal/terminal_private_api.h
@@ -13,8 +13,7 @@
 namespace extensions {
 
 // Opens new terminal process. Returns the new terminal id.
-class TerminalPrivateOpenTerminalProcessFunction
-    : public UIThreadExtensionFunction {
+class TerminalPrivateOpenTerminalProcessFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("terminalPrivate.openTerminalProcess",
                              TERMINALPRIVATE_OPENTERMINALPROCESS)
@@ -43,7 +42,7 @@
 
 // Send input to the terminal process specified by the terminal ID, which is set
 // as an argument.
-class TerminalPrivateSendInputFunction : public UIThreadExtensionFunction {
+class TerminalPrivateSendInputFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("terminalPrivate.sendInput",
                              TERMINALPRIVATE_SENDINPUT)
@@ -60,8 +59,7 @@
 };
 
 // Closes terminal process.
-class TerminalPrivateCloseTerminalProcessFunction
-    : public UIThreadExtensionFunction {
+class TerminalPrivateCloseTerminalProcessFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("terminalPrivate.closeTerminalProcess",
                              TERMINALPRIVATE_CLOSETERMINALPROCESS)
@@ -77,8 +75,7 @@
 };
 
 // Called by extension when terminal size changes.
-class TerminalPrivateOnTerminalResizeFunction
-    : public UIThreadExtensionFunction {
+class TerminalPrivateOnTerminalResizeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("terminalPrivate.onTerminalResize",
                              TERMINALPRIVATE_ONTERMINALRESIZE)
@@ -95,7 +92,7 @@
   void RespondOnUIThread(bool success);
 };
 
-class TerminalPrivateAckOutputFunction : public UIThreadExtensionFunction {
+class TerminalPrivateAckOutputFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("terminalPrivate.ackOutput",
                              TERMINALPRIVATE_ACKOUTPUT)
diff --git a/chrome/browser/extensions/api/top_sites/top_sites_api.h b/chrome/browser/extensions/api/top_sites/top_sites_api.h
index 1b86893..0bcfa27 100644
--- a/chrome/browser/extensions/api/top_sites/top_sites_api.h
+++ b/chrome/browser/extensions/api/top_sites/top_sites_api.h
@@ -10,7 +10,7 @@
 
 namespace extensions {
 
-class TopSitesGetFunction : public UIThreadExtensionFunction {
+class TopSitesGetFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("topSites.get", TOPSITES_GET)
 
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api.h b/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
index d76a63e..99186382 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
@@ -179,14 +179,14 @@
 };
 
 // API function that returns the state of a given frame.
-class WebNavigationGetFrameFunction : public UIThreadExtensionFunction {
+class WebNavigationGetFrameFunction : public ExtensionFunction {
   ~WebNavigationGetFrameFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("webNavigation.getFrame", WEBNAVIGATION_GETFRAME)
 };
 
 // API function that returns the states of all frames in a given tab.
-class WebNavigationGetAllFramesFunction : public UIThreadExtensionFunction {
+class WebNavigationGetAllFramesFunction : public ExtensionFunction {
   ~WebNavigationGetAllFramesFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("webNavigation.getAllFrames",
diff --git a/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.h b/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.h
index 9ca71ed..b9f6354 100644
--- a/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.h
+++ b/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.h
@@ -17,7 +17,7 @@
 namespace extensions {
 
 class ChromeWebViewInternalContextMenusCreateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("chromeWebViewInternal.contextMenusCreate",
                              WEBVIEWINTERNAL_CONTEXTMENUSCREATE)
@@ -26,7 +26,7 @@
  protected:
   ~ChromeWebViewInternalContextMenusCreateFunction() override {}
 
-  // UIThreadExtensionFunction implementation.
+  // ExtensionFunction implementation.
   ResponseAction Run() override;
 
  private:
@@ -34,7 +34,7 @@
 };
 
 class ChromeWebViewInternalContextMenusUpdateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("chromeWebViewInternal.contextMenusUpdate",
                              WEBVIEWINTERNAL_CONTEXTMENUSUPDATE)
@@ -43,7 +43,7 @@
  protected:
   ~ChromeWebViewInternalContextMenusUpdateFunction() override {}
 
-  // UIThreadExtensionFunction implementation.
+  // ExtensionFunction implementation.
   ResponseAction Run() override;
 
  private:
@@ -51,7 +51,7 @@
 };
 
 class ChromeWebViewInternalContextMenusRemoveFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("chromeWebViewInternal.contextMenusRemove",
                              WEBVIEWINTERNAL_CONTEXTMENUSREMOVE)
@@ -60,7 +60,7 @@
  protected:
   ~ChromeWebViewInternalContextMenusRemoveFunction() override {}
 
-  // UIThreadExtensionFunction implementation.
+  // ExtensionFunction implementation.
   ResponseAction Run() override;
 
  private:
@@ -68,7 +68,7 @@
 };
 
 class ChromeWebViewInternalContextMenusRemoveAllFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("chromeWebViewInternal.contextMenusRemoveAll",
                              WEBVIEWINTERNAL_CONTEXTMENUSREMOVEALL)
@@ -77,7 +77,7 @@
  protected:
   ~ChromeWebViewInternalContextMenusRemoveAllFunction() override {}
 
-  // UIThreadExtensionFunction implementation.
+  // ExtensionFunction implementation.
   ResponseAction Run() override;
 
  private:
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
index c79032d..8a6d956d 100644
--- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
@@ -287,7 +287,7 @@
 
   // Post a task since this is an asynchronous extension function.
   // TODO(devlin): This is unneccessary; this should just be a
-  // UIThreadExtensionFunction. Fix this.
+  // ExtensionFunction. Fix this.
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
       base::BindOnce(
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
index 0e74942..72f6544 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
@@ -42,7 +42,7 @@
 };
 
 class WebstorePrivateBeginInstallWithManifest3Function
-    : public UIThreadExtensionFunction,
+    : public ExtensionFunction,
       public WebstoreInstallHelper::Delegate {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.beginInstallWithManifest3",
@@ -97,7 +97,7 @@
 };
 
 class WebstorePrivateCompleteInstallFunction
-    : public UIThreadExtensionFunction,
+    : public ExtensionFunction,
       public WebstoreInstaller::Delegate {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.completeInstall",
@@ -126,8 +126,7 @@
   std::unique_ptr<ScopedActiveInstall> scoped_active_install_;
 };
 
-class WebstorePrivateEnableAppLauncherFunction
-    : public UIThreadExtensionFunction {
+class WebstorePrivateEnableAppLauncherFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.enableAppLauncher",
                              WEBSTOREPRIVATE_ENABLEAPPLAUNCHER)
@@ -143,8 +142,7 @@
   ChromeExtensionFunctionDetails chrome_details_;
 };
 
-class WebstorePrivateGetBrowserLoginFunction
-    : public UIThreadExtensionFunction {
+class WebstorePrivateGetBrowserLoginFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.getBrowserLogin",
                              WEBSTOREPRIVATE_GETBROWSERLOGIN)
@@ -160,8 +158,7 @@
   ChromeExtensionFunctionDetails chrome_details_;
 };
 
-class WebstorePrivateGetStoreLoginFunction
-    : public UIThreadExtensionFunction {
+class WebstorePrivateGetStoreLoginFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.getStoreLogin",
                              WEBSTOREPRIVATE_GETSTORELOGIN)
@@ -177,8 +174,7 @@
   ChromeExtensionFunctionDetails chrome_details_;
 };
 
-class WebstorePrivateSetStoreLoginFunction
-    : public UIThreadExtensionFunction {
+class WebstorePrivateSetStoreLoginFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.setStoreLogin",
                              WEBSTOREPRIVATE_SETSTORELOGIN)
@@ -194,8 +190,7 @@
   ChromeExtensionFunctionDetails chrome_details_;
 };
 
-class WebstorePrivateGetWebGLStatusFunction
-    : public UIThreadExtensionFunction {
+class WebstorePrivateGetWebGLStatusFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.getWebGLStatus",
                              WEBSTOREPRIVATE_GETWEBGLSTATUS)
@@ -213,8 +208,7 @@
   scoped_refptr<content::GpuFeatureChecker> feature_checker_;
 };
 
-class WebstorePrivateGetIsLauncherEnabledFunction
-    : public UIThreadExtensionFunction {
+class WebstorePrivateGetIsLauncherEnabledFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.getIsLauncherEnabled",
                              WEBSTOREPRIVATE_GETISLAUNCHERENABLED)
@@ -230,8 +224,7 @@
   void OnIsLauncherCheckCompleted(bool is_enabled);
 };
 
-class WebstorePrivateIsInIncognitoModeFunction
-    : public UIThreadExtensionFunction {
+class WebstorePrivateIsInIncognitoModeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.isInIncognitoMode",
                              WEBSTOREPRIVATE_ISININCOGNITOMODEFUNCTION)
@@ -247,8 +240,7 @@
   ChromeExtensionFunctionDetails chrome_details_;
 };
 
-class WebstorePrivateLaunchEphemeralAppFunction
-    : public UIThreadExtensionFunction {
+class WebstorePrivateLaunchEphemeralAppFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.launchEphemeralApp",
                              WEBSTOREPRIVATE_LAUNCHEPHEMERALAPP)
@@ -272,7 +264,7 @@
 };
 
 class WebstorePrivateGetEphemeralAppsEnabledFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.getEphemeralAppsEnabled",
                              WEBSTOREPRIVATE_GETEPHEMERALAPPSENABLED)
@@ -287,7 +279,7 @@
 };
 
 class WebstorePrivateIsPendingCustodianApprovalFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.isPendingCustodianApproval",
                              WEBSTOREPRIVATE_ISPENDINGCUSTODIANAPPROVAL)
@@ -305,8 +297,7 @@
   ChromeExtensionFunctionDetails chrome_details_;
 };
 
-class WebstorePrivateGetReferrerChainFunction
-    : public UIThreadExtensionFunction {
+class WebstorePrivateGetReferrerChainFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webstorePrivate.getReferrerChain",
                              WEBSTOREPRIVATE_GETREFERRERCHAIN)
diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
index cff9ee5..218ccbb 100644
--- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
+++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
@@ -755,7 +755,7 @@
 
   host->AddFilter(new ChromeExtensionMessageFilter(id, profile));
   host->AddFilter(new ExtensionMessageFilter(id, profile));
-  host->AddFilter(new IOThreadExtensionMessageFilter(id, profile));
+  host->AddFilter(new IOThreadExtensionMessageFilter());
   host->AddFilter(new ExtensionsGuestViewMessageFilter(id, profile));
   if (extensions::ExtensionsClient::Get()
           ->ExtensionAPIEnabledInExtensionServiceWorkers()) {
diff --git a/chrome/browser/extensions/chrome_extension_function.cc b/chrome/browser/extensions/chrome_extension_function.cc
index 587f441..db287d0 100644
--- a/chrome/browser/extensions/chrome_extension_function.cc
+++ b/chrome/browser/extensions/chrome_extension_function.cc
@@ -30,7 +30,7 @@
 }
 
 const std::string& ChromeAsyncExtensionFunction::GetError() const {
-  return error_.empty() ? UIThreadExtensionFunction::GetError() : error_;
+  return error_.empty() ? ExtensionFunction::GetError() : error_;
 }
 
 void ChromeAsyncExtensionFunction::SendResponse(bool success) {
diff --git a/chrome/browser/extensions/chrome_extension_function.h b/chrome/browser/extensions/chrome_extension_function.h
index a21d33e..dba9bb2 100644
--- a/chrome/browser/extensions/chrome_extension_function.h
+++ b/chrome/browser/extensions/chrome_extension_function.h
@@ -14,10 +14,10 @@
 // A chrome specific analog to AsyncExtensionFunction. This has access to a
 // chrome Profile.
 //
-// DEPRECATED: Inherit directly from UIThreadExtensionFunction.
+// DEPRECATED: Inherit directly from ExtensionFunction.
 // Then if you need access to Chrome details, you can construct a
 // ChromeExtensionFunctionDetails object within your function implementation.
-class ChromeAsyncExtensionFunction : public UIThreadExtensionFunction {
+class ChromeAsyncExtensionFunction : public ExtensionFunction {
  public:
   ChromeAsyncExtensionFunction();
 
@@ -56,7 +56,7 @@
 
  private:
   // If you're hitting a compile error here due to "final" - great! You're doing
-  // the right thing, you just need to extend UIThreadExtensionFunction instead
+  // the right thing, you just need to extend ExtensionFunction instead
   // of ChromeAsyncExtensionFunction.
   ResponseAction Run() final;
 
diff --git a/chrome/browser/extensions/chrome_extension_function_details.cc b/chrome/browser/extensions/chrome_extension_function_details.cc
index d925583..4adaa2ec 100644
--- a/chrome/browser/extensions/chrome_extension_function_details.cc
+++ b/chrome/browser/extensions/chrome_extension_function_details.cc
@@ -21,9 +21,8 @@
 #include "extensions/browser/extension_function_dispatcher.h"
 
 ChromeExtensionFunctionDetails::ChromeExtensionFunctionDetails(
-    UIThreadExtensionFunction* function)
-    : function_(function) {
-}
+    ExtensionFunction* function)
+    : function_(function) {}
 
 ChromeExtensionFunctionDetails::~ChromeExtensionFunctionDetails() {
 }
diff --git a/chrome/browser/extensions/chrome_extension_function_details.h b/chrome/browser/extensions/chrome_extension_function_details.h
index be55786..79f6863 100644
--- a/chrome/browser/extensions/chrome_extension_function_details.h
+++ b/chrome/browser/extensions/chrome_extension_function_details.h
@@ -10,16 +10,16 @@
 
 class Browser;
 class Profile;
-class UIThreadExtensionFunction;
+class ExtensionFunction;
 
-// Provides Chrome-specific details to UIThreadExtensionFunction
+// Provides Chrome-specific details to ExtensionFunction
 // implementations.
 class ChromeExtensionFunctionDetails {
  public:
   // Constructs a new ChromeExtensionFunctionDetails instance for |function|.
   // This instance does not own |function|. |function| must outlive this
   // instance.
-  explicit ChromeExtensionFunctionDetails(UIThreadExtensionFunction* function);
+  explicit ChromeExtensionFunctionDetails(ExtensionFunction* function);
   ~ChromeExtensionFunctionDetails();
 
   Profile* GetProfile() const;
@@ -55,14 +55,14 @@
   // - A browser with the same profile
   gfx::NativeWindow GetNativeWindowForUI();
 
-  // Returns a pointer to the associated UIThreadExtensionFunction
-  UIThreadExtensionFunction* function() { return function_; }
-  const UIThreadExtensionFunction* function() const { return function_; }
+  // Returns a pointer to the associated ExtensionFunction
+  ExtensionFunction* function() { return function_; }
+  const ExtensionFunction* function() const { return function_; }
 
  private:
   // The function for which these details have been created. Must outlive the
   // ChromeExtensionFunctionDetails instance.
-  UIThreadExtensionFunction* function_;
+  ExtensionFunction* function_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeExtensionFunctionDetails);
 };
diff --git a/chrome/browser/extensions/chrome_extension_function_unittest.cc b/chrome/browser/extensions/chrome_extension_function_unittest.cc
index 9d3fe1a..d5305a41 100644
--- a/chrome/browser/extensions/chrome_extension_function_unittest.cc
+++ b/chrome/browser/extensions/chrome_extension_function_unittest.cc
@@ -31,7 +31,7 @@
   *did_respond = true;
 }
 
-class ValidationFunction : public UIThreadExtensionFunction {
+class ValidationFunction : public ExtensionFunction {
  public:
   explicit ValidationFunction(bool should_succeed)
       : should_succeed_(should_succeed), did_respond_(false) {
diff --git a/chrome/browser/extensions/chrome_url_request_util.cc b/chrome/browser/extensions/chrome_url_request_util.cc
index 2ecc9e3e..4a62cd53 100644
--- a/chrome/browser/extensions/chrome_url_request_util.cc
+++ b/chrome/browser/extensions/chrome_url_request_util.cc
@@ -122,7 +122,6 @@
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
   void ResumeReadingBodyFromNet() override {}
-  void ProceedWithResponse() override {}
 
  private:
   ResourceBundleFileLoader(const std::string& content_security_policy,
diff --git a/chrome/browser/extensions/extension_api_unittest.cc b/chrome/browser/extensions/extension_api_unittest.cc
index b28dfcad..ebc9dd9 100644
--- a/chrome/browser/extensions/extension_api_unittest.cc
+++ b/chrome/browser/extensions/extension_api_unittest.cc
@@ -29,7 +29,7 @@
 }
 
 std::unique_ptr<base::Value> ExtensionApiUnittest::RunFunctionAndReturnValue(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args) {
   function->set_extension(extension());
   return std::unique_ptr<base::Value>(
@@ -38,7 +38,7 @@
 
 std::unique_ptr<base::DictionaryValue>
 ExtensionApiUnittest::RunFunctionAndReturnDictionary(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args) {
   base::Value* value = RunFunctionAndReturnValue(function, args).release();
   base::DictionaryValue* dict = NULL;
@@ -53,7 +53,7 @@
 }
 
 std::unique_ptr<base::ListValue> ExtensionApiUnittest::RunFunctionAndReturnList(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args) {
   base::Value* value = RunFunctionAndReturnValue(function, args).release();
   base::ListValue* list = NULL;
@@ -68,13 +68,14 @@
 }
 
 std::string ExtensionApiUnittest::RunFunctionAndReturnError(
-    UIThreadExtensionFunction* function, const std::string& args) {
+    ExtensionFunction* function,
+    const std::string& args) {
   function->set_extension(extension());
   return utils::RunFunctionAndReturnError(function, args, browser());
 }
 
-void ExtensionApiUnittest::RunFunction(
-    UIThreadExtensionFunction* function, const std::string& args) {
+void ExtensionApiUnittest::RunFunction(ExtensionFunction* function,
+                                       const std::string& args) {
   RunFunctionAndReturnValue(function, args);
 }
 
diff --git a/chrome/browser/extensions/extension_api_unittest.h b/chrome/browser/extensions/extension_api_unittest.h
index b4922eb..8ddb90b 100644
--- a/chrome/browser/extensions/extension_api_unittest.h
+++ b/chrome/browser/extensions/extension_api_unittest.h
@@ -17,7 +17,7 @@
 class ListValue;
 }
 
-class UIThreadExtensionFunction;
+class ExtensionFunction;
 
 namespace extensions {
 
@@ -54,29 +54,28 @@
 
   // Return the function result as a base::Value.
   std::unique_ptr<base::Value> RunFunctionAndReturnValue(
-      UIThreadExtensionFunction* function,
+      ExtensionFunction* function,
       const std::string& args);
 
   // Return the function result as a base::DictionaryValue, or NULL.
   // This will EXPECT-fail if the result is not a DictionaryValue.
   std::unique_ptr<base::DictionaryValue> RunFunctionAndReturnDictionary(
-      UIThreadExtensionFunction* function,
+      ExtensionFunction* function,
       const std::string& args);
 
   // Return the function result as a base::ListValue, or NULL.
   // This will EXPECT-fail if the result is not a ListValue.
   std::unique_ptr<base::ListValue> RunFunctionAndReturnList(
-      UIThreadExtensionFunction* function,
+      ExtensionFunction* function,
       const std::string& args);
 
   // Return an error thrown from the function, if one exists.
   // This will EXPECT-fail if any result is returned from the function.
-  std::string RunFunctionAndReturnError(
-      UIThreadExtensionFunction* function, const std::string& args);
+  std::string RunFunctionAndReturnError(ExtensionFunction* function,
+                                        const std::string& args);
 
   // Run the function and ignore any result.
-  void RunFunction(
-      UIThreadExtensionFunction* function, const std::string& args);
+  void RunFunction(ExtensionFunction* function, const std::string& args);
 
  private:
   // The Extension used when running API function calls.
diff --git a/chrome/browser/extensions/extension_function_test_utils.cc b/chrome/browser/extensions/extension_function_test_utils.cc
index edf3ff8..f6a0e27 100644
--- a/chrome/browser/extensions/extension_function_test_utils.cc
+++ b/chrome/browser/extensions/extension_function_test_utils.cc
@@ -83,14 +83,14 @@
   return false;
 }
 
-std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
+std::string RunFunctionAndReturnError(ExtensionFunction* function,
                                       const std::string& args,
                                       Browser* browser) {
   return RunFunctionAndReturnError(function, args, browser,
                                    extensions::api_test_utils::NONE);
 }
 std::string RunFunctionAndReturnError(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args,
     Browser* browser,
     extensions::api_test_utils::RunFunctionFlags flags) {
@@ -106,15 +106,14 @@
   return function->GetError();
 }
 
-base::Value* RunFunctionAndReturnSingleResult(
-    UIThreadExtensionFunction* function,
-    const std::string& args,
-    Browser* browser) {
+base::Value* RunFunctionAndReturnSingleResult(ExtensionFunction* function,
+                                              const std::string& args,
+                                              Browser* browser) {
   return RunFunctionAndReturnSingleResult(function, args, browser,
                                           extensions::api_test_utils::NONE);
 }
 base::Value* RunFunctionAndReturnSingleResult(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args,
     Browser* browser,
     extensions::api_test_utils::RunFunctionFlags flags) {
@@ -130,7 +129,7 @@
   return NULL;
 }
 
-bool RunFunction(UIThreadExtensionFunction* function,
+bool RunFunction(ExtensionFunction* function,
                  const std::string& args,
                  Browser* browser,
                  extensions::api_test_utils::RunFunctionFlags flags) {
@@ -140,7 +139,7 @@
   return RunFunction(function, std::move(parsed_args), browser, flags);
 }
 
-bool RunFunction(UIThreadExtensionFunction* function,
+bool RunFunction(ExtensionFunction* function,
                  std::unique_ptr<base::ListValue> args,
                  Browser* browser,
                  extensions::api_test_utils::RunFunctionFlags flags) {
diff --git a/chrome/browser/extensions/extension_function_test_utils.h b/chrome/browser/extensions/extension_function_test_utils.h
index 27976b63..b6b70f7b 100644
--- a/chrome/browser/extensions/extension_function_test_utils.h
+++ b/chrome/browser/extensions/extension_function_test_utils.h
@@ -12,7 +12,7 @@
 #include "extensions/common/manifest.h"
 
 class Browser;
-class UIThreadExtensionFunction;
+class ExtensionFunction;
 
 namespace base {
 class Value;
@@ -43,11 +43,11 @@
 // the current test if |function| returns a result. Takes ownership of
 // |function|.
 std::string RunFunctionAndReturnError(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args,
     Browser* browser,
     extensions::api_test_utils::RunFunctionFlags flags);
-std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
+std::string RunFunctionAndReturnError(ExtensionFunction* function,
                                       const std::string& args,
                                       Browser* browser);
 
@@ -55,14 +55,13 @@
 // current test if |function| returns an error. Takes ownership of
 // |function|. The caller takes ownership of the result.
 base::Value* RunFunctionAndReturnSingleResult(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args,
     Browser* browser,
     extensions::api_test_utils::RunFunctionFlags flags);
-base::Value* RunFunctionAndReturnSingleResult(
-    UIThreadExtensionFunction* function,
-    const std::string& args,
-    Browser* browser);
+base::Value* RunFunctionAndReturnSingleResult(ExtensionFunction* function,
+                                              const std::string& args,
+                                              Browser* browser);
 
 // Create and run |function| with |args|. Works with both synchronous and async
 // functions. Ownership of |function| remains with the caller.
@@ -74,11 +73,11 @@
 // TODO(aa): I'm concerned that this style won't scale to all the bits and bobs
 // we're going to need to frob for all the different extension functions. But
 // we can refactor when we see what is needed.
-bool RunFunction(UIThreadExtensionFunction* function,
+bool RunFunction(ExtensionFunction* function,
                  const std::string& args,
                  Browser* browser,
                  extensions::api_test_utils::RunFunctionFlags flags);
-bool RunFunction(UIThreadExtensionFunction* function,
+bool RunFunction(ExtensionFunction* function,
                  std::unique_ptr<base::ListValue> args,
                  Browser* browser,
                  extensions::api_test_utils::RunFunctionFlags flags);
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index d508ef4..18b81d0 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -129,11 +129,10 @@
 
 // Opens a new tab for a given extension. Returns nullptr and sets |error| if an
 // error occurs.
-base::DictionaryValue* ExtensionTabUtil::OpenTab(
-    UIThreadExtensionFunction* function,
-    const OpenTabParams& params,
-    bool user_gesture,
-    std::string* error) {
+base::DictionaryValue* ExtensionTabUtil::OpenTab(ExtensionFunction* function,
+                                                 const OpenTabParams& params,
+                                                 bool user_gesture,
+                                                 std::string* error) {
   ChromeExtensionFunctionDetails chrome_details(function);
   Profile* profile = chrome_details.GetProfile();
   // windowId defaults to "current" window.
diff --git a/chrome/browser/extensions/extension_tab_util.h b/chrome/browser/extensions/extension_tab_util.h
index f255bc7c..c873ae0176 100644
--- a/chrome/browser/extensions/extension_tab_util.h
+++ b/chrome/browser/extensions/extension_tab_util.h
@@ -16,7 +16,7 @@
 class ChromeExtensionFunctionDetails;
 class GURL;
 class TabStripModel;
-class UIThreadExtensionFunction;
+class ExtensionFunction;
 
 namespace base {
 class DictionaryValue;
@@ -75,7 +75,7 @@
   // Opens a new tab given an extension function |function| and creation
   // parameters |params|. Returns a Tab object if successful, or NULL and
   // optionally sets |error| if an error occurs.
-  static base::DictionaryValue* OpenTab(UIThreadExtensionFunction* function,
+  static base::DictionaryValue* OpenTab(ExtensionFunction* function,
                                         const OpenTabParams& params,
                                         bool user_gesture,
                                         std::string* error);
diff --git a/chrome/browser/extensions/updater/chrome_update_client_config.cc b/chrome/browser/extensions/updater/chrome_update_client_config.cc
index c857bb0b..4f45e9d 100644
--- a/chrome/browser/extensions/updater/chrome_update_client_config.cc
+++ b/chrome/browser/extensions/updater/chrome_update_client_config.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/update_client/chrome_update_query_params_delegate.h"
 #include "chrome/common/channel_info.h"
 #include "components/prefs/pref_service.h"
+#include "components/services/patch/content/patch_service.h"
 #include "components/services/unzip/content/unzip_service.h"
 #include "components/update_client/activity_data_service.h"
 #include "components/update_client/net/network_chromium.h"
@@ -28,9 +29,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_prefs.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 namespace extensions {
 
@@ -197,7 +196,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!patch_factory_) {
     patch_factory_ = base::MakeRefCounted<update_client::PatchChromiumFactory>(
-        content::GetSystemConnector()->Clone());
+        base::BindRepeating(&patch::LaunchFilePatcher));
   }
   return patch_factory_;
 }
diff --git a/chrome/browser/extensions/window_controller_list.cc b/chrome/browser/extensions/window_controller_list.cc
index d419073..74042cc 100644
--- a/chrome/browser/extensions/window_controller_list.cc
+++ b/chrome/browser/extensions/window_controller_list.cc
@@ -55,7 +55,7 @@
 }
 
 WindowController* WindowControllerList::FindWindowForFunctionByIdWithFilter(
-    const UIThreadExtensionFunction* function,
+    const ExtensionFunction* function,
     int id,
     WindowController::TypeFilter filter) const {
   for (auto iter = windows().begin(); iter != windows().end(); ++iter) {
@@ -69,13 +69,13 @@
 }
 
 WindowController* WindowControllerList::CurrentWindowForFunction(
-    const UIThreadExtensionFunction* function) const {
+    const ExtensionFunction* function) const {
   return CurrentWindowForFunctionWithFilter(function,
                                             WindowController::kNoWindowFilter);
 }
 
 WindowController* WindowControllerList::CurrentWindowForFunctionWithFilter(
-    const UIThreadExtensionFunction* function,
+    const ExtensionFunction* function,
     WindowController::TypeFilter filter) const {
   WindowController* result = nullptr;
   // Returns either the focused window (if any), or the last window in the list.
diff --git a/chrome/browser/extensions/window_controller_list.h b/chrome/browser/extensions/window_controller_list.h
index 5081543f..47f978c 100644
--- a/chrome/browser/extensions/window_controller_list.h
+++ b/chrome/browser/extensions/window_controller_list.h
@@ -13,7 +13,7 @@
 #include "base/observer_list.h"
 #include "chrome/browser/extensions/window_controller.h"
 
-class UIThreadExtensionFunction;
+class ExtensionFunction;
 
 namespace extensions {
 
@@ -36,19 +36,19 @@
   // Returns a window matching the context the function was invoked in
   // using |filter|.
   WindowController* FindWindowForFunctionByIdWithFilter(
-      const UIThreadExtensionFunction* function,
+      const ExtensionFunction* function,
       int id,
       WindowController::TypeFilter filter) const;
 
   // Returns the focused or last added window matching the context the function
   // was invoked in.
   WindowController* CurrentWindowForFunction(
-      const UIThreadExtensionFunction* function) const;
+      const ExtensionFunction* function) const;
 
   // Returns the focused or last added window matching the context the function
   // was invoked in using |filter|.
   WindowController* CurrentWindowForFunctionWithFilter(
-      const UIThreadExtensionFunction* function,
+      const ExtensionFunction* function,
       WindowController::TypeFilter filter) const;
 
   const ControllerList& windows() const { return windows_; }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 1523569..68a093d 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3082,6 +3082,16 @@
     "expiry_milestone": 78
   },
   {
+    "name": "trim-on-all-frames-frozen",
+    "owners": [ "bgeffon", "sonnyrao" ],
+    "expiry_milestone": 81
+  },
+  {
+    "name": "trim-on-memory-pressure",
+    "owners": [ "bgeffon", "sonnyrao" ],
+    "expiry_milestone": 81
+  },
+  {
     "name": "try-supported-channel-layouts",
     "owners": [ "dalecurtis" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 1807c80..4727217a 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3220,6 +3220,13 @@
 const char kEnableVirtualDesksDescription[] =
     "A preview of the upcoming Virtual Desks features on Chrome OS devices.";
 
+const char kTrimOnFreezeName[] = "Trim Working Set on freeze";
+const char kTrimOnFreezeDescription[] = "Trim Working Set on all frames frozen";
+
+const char kTrimOnMemoryPressureName[] = "Trim Working Set on memory pressure";
+const char kTrimOnMemoryPressureDescription[] =
+    "Trim Working Set periodically on memory pressure";
+
 const char kEnableZeroStateSuggestionsName[] = "Enable Zero State Suggetions";
 const char kEnableZeroStateSuggestionsDescription[] =
     "Enable Zero State Suggestions feature in Launcher, which will show "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index e9bd0de..649fa49 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1924,6 +1924,12 @@
 extern const char kEnableVirtualDesksName[];
 extern const char kEnableVirtualDesksDescription[];
 
+extern const char kTrimOnFreezeName[];
+extern const char kTrimOnFreezeDescription[];
+
+extern const char kTrimOnMemoryPressureName[];
+extern const char kTrimOnMemoryPressureDescription[];
+
 extern const char kEnableZeroStateSuggestionsName[];
 extern const char kEnableZeroStateSuggestionsDescription[];
 
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
index ced82c9..688743f 100644
--- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -31,6 +31,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_switches.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h"
 #include "ui/base/pointer/pointer_device.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/display/screen.h"
@@ -72,21 +73,12 @@
 
 void RecordMemoryMetrics();
 
-// Records memory metrics after a delay, with a fixed mean interval but randomly
-// distributed samples using a poisson process.
+// Records memory metrics after a delay.
 void RecordMemoryMetricsAfterDelay() {
-#if defined(OS_ANDROID)
-  base::TimeDelta mean_time = base::TimeDelta::FromMinutes(5);
-#else
-  base::TimeDelta mean_time = base::TimeDelta::FromMinutes(30);
-#endif
-
-  // Compute the actual delay before sampling using a Poisson process.
-  double uniform = base::RandDouble();
-  base::TimeDelta delay = -std::log(uniform) * mean_time;
-
-  base::PostDelayedTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                                  base::BindOnce(&RecordMemoryMetrics), delay);
+  base::PostDelayedTaskWithTraits(
+      FROM_HERE, {content::BrowserThread::UI},
+      base::BindOnce(&RecordMemoryMetrics),
+      memory_instrumentation::GetDelayForNextMemoryLog());
 }
 
 // Records memory metrics, and then triggers memory colleciton after a delay.
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc
index 9d317b3..1aecf98 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter.cc
@@ -29,6 +29,7 @@
 #include "extensions/buildflags/buildflags.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
 #include "url/gurl.h"
 
@@ -39,7 +40,11 @@
 #endif
 
 using base::trace_event::MemoryAllocatorDump;
+using memory_instrumentation::GetPrivateFootprintHistogramName;
 using memory_instrumentation::GlobalMemoryDump;
+using memory_instrumentation::HistogramProcessType;
+using memory_instrumentation::HistogramProcessTypeToString;
+using memory_instrumentation::kMemoryHistogramPrefix;
 using ukm::builders::Memory_Experimental;
 
 const base::Feature kMemoryMetricsOldTiming{"MemoryMetricsOldTiming",
@@ -282,15 +287,10 @@
      &Memory_Experimental::SetWebCache_OtherResources},
 };
 
-#define UMA_PREFIX "Memory."
 #define EXPERIMENTAL_UMA_PREFIX "Memory.Experimental."
 #define VERSION_SUFFIX_NORMAL "2."
 #define VERSION_SUFFIX_SMALL "2.Small."
 
-// Use the values from UMA_HISTOGRAM_MEMORY_LARGE_MB.
-#define MEMORY_METRICS_HISTOGRAM_MB(name, value) \
-  base::UmaHistogramCustomCounts(name, value, 1, 64000, 100)
-
 // Used to measure KB-granularity memory stats. Range is from 1KB to 500,000KB
 // (500MB).
 #define MEMORY_METRICS_HISTOGRAM_KB(name, value) \
@@ -303,7 +303,7 @@
   (builder->*(item.ukm_setter))(value);
 }
 
-void EmitProcessUma(const char* process_name,
+void EmitProcessUma(HistogramProcessType process_type,
                     const Metric& item,
                     uint64_t value) {
   std::string uma_name;
@@ -317,8 +317,9 @@
   } else {
     const char* version_suffix =
         item.is_large_metric ? VERSION_SUFFIX_NORMAL : VERSION_SUFFIX_SMALL;
-    uma_name = std::string(EXPERIMENTAL_UMA_PREFIX) + process_name +
-               version_suffix + item.uma_name;
+    uma_name = std::string(EXPERIMENTAL_UMA_PREFIX) +
+               HistogramProcessTypeToString(process_type) + version_suffix +
+               item.uma_name;
   }
 
   if (item.is_large_metric) {
@@ -329,7 +330,7 @@
 }
 
 void EmitProcessUmaAndUkm(const GlobalMemoryDump::ProcessDump& pmd,
-                          const char* process_name,
+                          HistogramProcessType process_type,
                           const base::Optional<base::TimeDelta>& uptime,
                           bool record_uma,
                           Memory_Experimental* builder) {
@@ -344,13 +345,13 @@
         break;
       case EmitTo::kSizeInUmaOnly:
         if (record_uma)
-          EmitProcessUma(process_name, item, value.value());
+          EmitProcessUma(process_type, item, value.value());
         break;
       case EmitTo::kSizeInUkmAndUma:
         // For each 'size' metric, emit size as MB.
         EmitProcessUkm(item, value.value() / 1024 / 1024, builder);
         if (record_uma)
-          EmitProcessUma(process_name, item, value.value());
+          EmitProcessUma(process_type, item, value.value());
         break;
       default:
         NOTREACHED();
@@ -373,24 +374,24 @@
   if (!record_uma)
     return;
 
+  const char* process_name = HistogramProcessTypeToString(process_type);
 #if defined(OS_MACOSX)
   // Resident set is not populated on Mac.
   DCHECK_EQ(pmd.os_dump().resident_set_kb, 0U);
 #else
   MEMORY_METRICS_HISTOGRAM_MB(
-      std::string(UMA_PREFIX) + process_name + ".ResidentSet",
+      std::string(kMemoryHistogramPrefix) + process_name + ".ResidentSet",
       pmd.os_dump().resident_set_kb / 1024);
 #endif
-  MEMORY_METRICS_HISTOGRAM_MB(
-      std::string(UMA_PREFIX) + process_name + ".PrivateMemoryFootprint",
-      pmd.os_dump().private_footprint_kb / 1024);
-  MEMORY_METRICS_HISTOGRAM_MB(
-      std::string(UMA_PREFIX) + process_name + ".SharedMemoryFootprint",
-      pmd.os_dump().shared_footprint_kb / 1024);
+  MEMORY_METRICS_HISTOGRAM_MB(GetPrivateFootprintHistogramName(process_type),
+                              pmd.os_dump().private_footprint_kb / 1024);
+  MEMORY_METRICS_HISTOGRAM_MB(std::string(kMemoryHistogramPrefix) +
+                                  process_name + ".SharedMemoryFootprint",
+                              pmd.os_dump().shared_footprint_kb / 1024);
 #if defined(OS_LINUX) || defined(OS_ANDROID)
-  MEMORY_METRICS_HISTOGRAM_MB(
-      std::string(UMA_PREFIX) + process_name + ".PrivateSwapFootprint",
-      pmd.os_dump().private_footprint_swap_kb / 1024);
+  MEMORY_METRICS_HISTOGRAM_MB(std::string(kMemoryHistogramPrefix) +
+                                  process_name + ".PrivateSwapFootprint",
+                              pmd.os_dump().private_footprint_swap_kb / 1024);
 #endif
 }
 
@@ -416,11 +417,11 @@
         pmd.GetMetric(gpu_categories[i], synthetic_metric.metric).value_or(0);
   }
 
-  // Always use "Gpu" as the process name for this even for the in process
+  // Always use kGpu as the process name for this even for the in process
   // command buffer case.
   EmitProcessUkm(synthetic_metric, total, builder);
   if (record_uma)
-    EmitProcessUma("Gpu", synthetic_metric, total);
+    EmitProcessUma(HistogramProcessType::kGpu, synthetic_metric, total);
 }
 
 void EmitBrowserMemoryMetrics(const GlobalMemoryDump::ProcessDump& pmd,
@@ -431,7 +432,8 @@
   Memory_Experimental builder(ukm_source_id);
   builder.SetProcessType(static_cast<int64_t>(
       memory_instrumentation::mojom::ProcessType::BROWSER));
-  EmitProcessUmaAndUkm(pmd, "Browser", uptime, record_uma, &builder);
+  EmitProcessUmaAndUkm(pmd, HistogramProcessType::kBrowser, uptime, record_uma,
+                       &builder);
   EmitSummedGpuMemory(pmd, &builder, record_uma);
 
   builder.Record(ukm_recorder);
@@ -451,8 +453,10 @@
       memory_instrumentation::mojom::ProcessType::RENDERER));
   builder.SetNumberOfExtensions(number_of_extensions);
 
-  const char* process = number_of_extensions == 0 ? "Renderer" : "Extension";
-  EmitProcessUmaAndUkm(pmd, process, uptime, record_uma, &builder);
+  const HistogramProcessType process_type =
+      (number_of_extensions == 0) ? HistogramProcessType::kRenderer
+                                  : HistogramProcessType::kExtension;
+  EmitProcessUmaAndUkm(pmd, process_type, uptime, record_uma, &builder);
 
   if (page_info) {
     builder.SetIsVisible(page_info->is_visible);
@@ -473,7 +477,8 @@
   Memory_Experimental builder(ukm_source_id);
   builder.SetProcessType(
       static_cast<int64_t>(memory_instrumentation::mojom::ProcessType::GPU));
-  EmitProcessUmaAndUkm(pmd, "Gpu", uptime, record_uma, &builder);
+  EmitProcessUmaAndUkm(pmd, HistogramProcessType::kGpu, uptime, record_uma,
+                       &builder);
   EmitSummedGpuMemory(pmd, &builder, record_uma);
   builder.Record(ukm_recorder);
 }
@@ -486,7 +491,8 @@
   Memory_Experimental builder(ukm_source_id);
   builder.SetProcessType(static_cast<int64_t>(
       memory_instrumentation::mojom::ProcessType::UTILITY));
-  EmitProcessUmaAndUkm(pmd, "Utility", uptime, record_uma, &builder);
+  EmitProcessUmaAndUkm(pmd, HistogramProcessType::kUtility, uptime, record_uma,
+                       &builder);
 
   builder.Record(ukm_recorder);
 }
@@ -500,7 +506,8 @@
   Memory_Experimental builder(ukm_source_id);
   builder.SetProcessType(static_cast<int64_t>(
       memory_instrumentation::mojom::ProcessType::UTILITY));
-  EmitProcessUmaAndUkm(pmd, "AudioService", uptime, record_uma, &builder);
+  EmitProcessUmaAndUkm(pmd, HistogramProcessType::kAudioService, uptime,
+                       record_uma, &builder);
 
   builder.Record(ukm_recorder);
 }
@@ -514,7 +521,8 @@
   Memory_Experimental builder(ukm_source_id);
   builder.SetProcessType(static_cast<int64_t>(
       memory_instrumentation::mojom::ProcessType::UTILITY));
-  EmitProcessUmaAndUkm(pmd, "NetworkService", uptime, record_uma, &builder);
+  EmitProcessUmaAndUkm(pmd, HistogramProcessType::kNetworkService, uptime,
+                       record_uma, &builder);
 
   builder.Record(ukm_recorder);
 }
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.cc b/chrome/browser/navigation_predictor/navigation_predictor.cc
index 8df46ee..b47759b 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor.cc
@@ -219,11 +219,7 @@
       normalize_navigation_scores_(base::GetFieldTrialParamByFeatureAsBool(
           blink::features::kNavigationPredictor,
           "normalize_scores",
-          true)),
-      send_ukm_metrics_(base::GetFieldTrialParamByFeatureAsBool(
-          blink::features::kNavigationPredictor,
-          "send_ukm_metrics",
-          false)) {
+          true)) {
   DCHECK(browser_context_);
   DETACH_FROM_SEQUENCE(sequence_checker_);
   DCHECK_LE(0, preconnect_origin_score_threshold_);
@@ -440,7 +436,7 @@
 }
 
 void NavigationPredictor::MaybeSendMetricsToUkm() const {
-  if (!send_ukm_metrics_ || !ukm_recorder_) {
+  if (!ukm_recorder_) {
     return;
   }
 
@@ -513,7 +509,7 @@
 
 void NavigationPredictor::MaybeSendClickMetricsToUkm(
     const std::string& clicked_url) const {
-  if (!send_ukm_metrics_ || !ukm_recorder_) {
+  if (!ukm_recorder_) {
     return;
   }
 
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.h b/chrome/browser/navigation_predictor/navigation_predictor.h
index a20e9cd..3d8c4f1 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor.h
+++ b/chrome/browser/navigation_predictor/navigation_predictor.h
@@ -196,14 +196,13 @@
   // MaybePreconnectNow preconnects to an origin server if it's allowed.
   void MaybePreconnectNow(Action log_action);
 
-  // Sends metrics to the UKM id at |ukm_source_id_| if |send_ukm_metrics_|
-  // is true.
+  // Sends metrics to the UKM id at |ukm_source_id_|.
   void MaybeSendMetricsToUkm() const;
 
   // After an in-page click, sends the index of the url that was clicked to the
-  // UKM id at |ukm_source_id_| if |send_ukm_metrics_| is true. The index sent
-  // corresponds to the index of that url in |top_urls_|, and is 1-indexed.
-  // If the url does not appear in top_urls_, a 0 is returned.
+  // UKM id at |ukm_source_id_|. The index sent corresponds to the index of that
+  // url in |top_urls_|, and is 1-indexed. If the url does not appear in
+  // |top_urls_|, a 0 is returned.
   void MaybeSendClickMetricsToUkm(const std::string& clicked_url) const;
 
   // Returns the minimum of the bucket that |value| belongs in, for page-wide
@@ -299,10 +298,6 @@
   // all navigation scores for a page.
   const bool normalize_navigation_scores_;
 
-  // True if |this| should send metrics about aggregate link information
-  // to the UKM at id |ukm_source_id_|.
-  const bool send_ukm_metrics_;
-
   // Timing of document loaded and last click.
   base::TimeTicks document_loaded_timing_;
   base::TimeTicks last_click_timing_;
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc b/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc
index 9f84b589..1935e28 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc
@@ -128,8 +128,7 @@
 
   void SetupFieldTrial(base::Optional<int> preconnect_origin_score_threshold,
                        base::Optional<int> prefetch_url_score_threshold,
-                       base::Optional<bool> prefetch_after_preconnect,
-                       base::Optional<bool> send_ukm_metrics) {
+                       base::Optional<bool> prefetch_after_preconnect) {
     if (field_trial_initiated_)
       return;
 
@@ -150,9 +149,6 @@
       params["prefetch_after_preconnect"] =
           prefetch_after_preconnect.value() ? "true" : "false";
     }
-    if (send_ukm_metrics.has_value()) {
-      params["send_ukm_metrics"] = send_ukm_metrics.value() ? "true" : "false";
-    }
     scoped_feature_list.InitAndEnableFeatureWithParameters(
         blink::features::kNavigationPredictor, params);
   }
@@ -504,7 +500,7 @@
     : public NavigationPredictorTest {
  public:
   NavigationPredictorSendUkmMetricsEnabledTest() {
-    SetupFieldTrial(base::nullopt, base::nullopt, base::nullopt, true);
+    SetupFieldTrial(base::nullopt, base::nullopt, base::nullopt);
   }
 
   void SetUp() override {
@@ -721,7 +717,7 @@
     : public NavigationPredictorTest {
  public:
   NavigationPredictorPrefetchAfterPreconnectEnabledTest() {
-    SetupFieldTrial(base::nullopt, base::nullopt, true, base::nullopt);
+    SetupFieldTrial(base::nullopt, base::nullopt, true);
   }
 
   void SetUp() override {
@@ -768,8 +764,7 @@
  public:
   NavigationPredictorPrefetchDisabledTest() {
     SetupFieldTrial(0 /* preconnect_origin_score_threshold */,
-                    101 /* prefetch_url_score_threshold */, base::nullopt,
-                    base::nullopt);
+                    101 /* prefetch_url_score_threshold */, base::nullopt);
   }
 
   void SetUp() override {
@@ -867,8 +862,7 @@
  public:
   NavigationPredictorPreconnectPrefetchDisabledTest() {
     SetupFieldTrial(101 /* preconnect_origin_score_threshold */,
-                    101 /* prefetch_url_score_threshold */, base::nullopt,
-                    base::nullopt);
+                    101 /* prefetch_url_score_threshold */, base::nullopt);
   }
 
   void SetUp() override {
diff --git a/chrome/browser/net/dns_probe_browsertest.cc b/chrome/browser/net/dns_probe_browsertest.cc
index d1241af..6fc5241 100644
--- a/chrome/browser/net/dns_probe_browsertest.cc
+++ b/chrome/browser/net/dns_probe_browsertest.cc
@@ -186,7 +186,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override {}
-  void ProceedWithResponse() override {}
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
diff --git a/chrome/browser/notifications/OWNERS b/chrome/browser/notifications/OWNERS
index 02152be..2ae91f0 100644
--- a/chrome/browser/notifications/OWNERS
+++ b/chrome/browser/notifications/OWNERS
@@ -6,6 +6,9 @@
 stevenjb@chromium.org
 yoshiki@chromium.org
 
+# Linux files
+per-file *_linux*=thomasanderson@chromium.org
+
 # Mac files
 per-file *_mac*=rsesek@chromium.org
 
diff --git a/chrome/browser/offline_pages/offline_page_url_loader.cc b/chrome/browser/offline_pages/offline_page_url_loader.cc
index 029bcb010..cd315e8 100644
--- a/chrome/browser/offline_pages/offline_page_url_loader.cc
+++ b/chrome/browser/offline_pages/offline_page_url_loader.cc
@@ -120,10 +120,6 @@
   NOTREACHED();
 }
 
-void OfflinePageURLLoader::ProceedWithResponse() {
-  NOTREACHED();
-}
-
 void OfflinePageURLLoader::SetPriority(net::RequestPriority priority,
                                        int32_t intra_priority_value) {
   // Ignore: this class doesn't have a concept of priority.
diff --git a/chrome/browser/offline_pages/offline_page_url_loader.h b/chrome/browser/offline_pages/offline_page_url_loader.h
index 4fd73a6..4214893 100644
--- a/chrome/browser/offline_pages/offline_page_url_loader.h
+++ b/chrome/browser/offline_pages/offline_page_url_loader.h
@@ -59,7 +59,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 224a0a3..418793ae 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -1152,6 +1152,78 @@
 }
 #endif
 
+// Test that Previous/NextOnLineId attributes are present and properly linked on
+// InlineTextBoxes within a line.
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibilityNextOnLine) {
+  content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
+
+  GURL test_pdf_url(
+      embedded_test_server()->GetURL("/pdf/accessibility/next-on-line.pdf"));
+  WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url);
+  ASSERT_TRUE(guest_contents);
+
+  WaitForAccessibilityTreeToContainNodeWithName(guest_contents, "Page 1");
+  ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents);
+
+  // The test file contains several lines delimited with '<<' and '>>' markers.
+  // We loop over the content looking for these markers, and ensure that the
+  // NextOnLine and PreviousOnLine attributes are properly linked for all
+  // InlineTextBoxes within each delimited line.
+  int current_line = 0;
+  bool currently_in_delimited_line = false;
+  int32_t previous_node_id = 0;
+  int32_t previous_node_next_id = 0;
+
+  for (const auto& node : ax_tree.nodes) {
+    if (node.role != ax::mojom::Role::kInlineTextBox)
+      continue;
+
+    std::string name =
+        node.GetStringAttribute(ax::mojom::StringAttribute::kName);
+    base::StringPiece trimmed_name =
+        base::TrimWhitespaceASCII(name, base::TRIM_ALL);
+
+    ASSERT_FALSE(trimmed_name.starts_with("<<") && trimmed_name.ends_with(">>"))
+        << "test is not useful if the runs have been pre-merged; consider "
+           "changing the input file";
+
+    if (trimmed_name.starts_with("<<")) {
+      // Started a delimited line; there should be no PreviousOnLine id.
+      ASSERT_FALSE(currently_in_delimited_line);
+      current_line++;
+      currently_in_delimited_line = true;
+      ASSERT_FALSE(
+          node.HasIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId))
+          << "line " << current_line;
+    } else if (currently_in_delimited_line) {
+      // We're in the middle of a delimited line; the previous node's
+      // NextOnLineId should point to us, and our PreviousOnLine id should point
+      // to the previous node.
+      ASSERT_EQ(node.id, previous_node_next_id) << "line " << current_line;
+      int32_t prev_id =
+          node.GetIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId);
+      ASSERT_EQ(prev_id, previous_node_id) << "line " << current_line;
+    }
+
+    if (trimmed_name.ends_with(">>")) {
+      // This is the end of a delimited line; there should be no NextOnLine id.
+      // (The previous node ids were already checked above.)
+      ASSERT_TRUE(currently_in_delimited_line);
+      currently_in_delimited_line = false;
+      ASSERT_FALSE(node.HasIntAttribute(ax::mojom::IntAttribute::kNextOnLineId))
+          << "line " << current_line;
+    }
+
+    // Keep track of the previous node & its NextOnLine id so that we can test
+    // against them when we encounter the next node.
+    previous_node_id = node.id;
+    previous_node_next_id =
+        node.GetIntAttribute(ax::mojom::IntAttribute::kNextOnLineId);
+  }
+  ASSERT_FALSE(currently_in_delimited_line);
+  ASSERT_EQ(current_line, 2);
+}
+
 // Test that if the plugin tries to load a URL that redirects then it will fail
 // to load. This is to avoid the source origin of the document changing during
 // the redirect, which can have security implications. https://crbug.com/653749.
diff --git a/chrome/browser/performance_manager/graph/policies/policy_features.cc b/chrome/browser/performance_manager/graph/policies/policy_features.cc
new file mode 100644
index 0000000..00cd050
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/policy_features.cc
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/performance_manager/graph/policies/policy_features.h"
+
+#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+
+namespace performance_manager {
+namespace features {
+
+#if defined(OS_CHROMEOS)
+namespace chromeos {
+
+const base::Feature kTrimOnMemoryPressure{"TrimOnMemoryPressure",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kTrimOnFreeze{"TrimOnFreeze",
+                                  base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::FeatureParam<int> kGraphWalkBackoffTimeSec = {
+    &kTrimOnMemoryPressure, "GraphWalkBackoffTimeSec", 120};
+
+// Specifies the minimum amount of time a parent frame node must be invisible
+// before considering the process node for working set trim.
+const base::FeatureParam<int> kNodeInvisibileTimeSec = {
+    &kTrimOnMemoryPressure, "NodeInvisibleTimeSec", 360};
+
+// Specifies the minimum amount of time a parent frame node must be invisible
+// before considering the process node for working set trim.
+const base::FeatureParam<int> kNodeTrimBackoffTimeSec = {
+    &kTrimOnMemoryPressure, "NodeTrimBackoffTimeSec", 1200};
+
+TrimOnMemoryPressureParams::TrimOnMemoryPressureParams() = default;
+TrimOnMemoryPressureParams::TrimOnMemoryPressureParams(
+    const TrimOnMemoryPressureParams& other) = default;
+
+TrimOnMemoryPressureParams TrimOnMemoryPressureParams::GetParams() {
+  TrimOnMemoryPressureParams params;
+  params.graph_walk_backoff_time =
+      base::TimeDelta::FromSeconds(kGraphWalkBackoffTimeSec.Get());
+  params.node_invisible_time =
+      base::TimeDelta::FromSeconds(kNodeInvisibileTimeSec.Get());
+  params.node_trim_backoff_time =
+      base::TimeDelta::FromSeconds(kNodeTrimBackoffTimeSec.Get());
+  return params;
+}
+
+}  // namespace chromeos
+#endif
+
+}  // namespace features
+}  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/policies/policy_features.h b/chrome/browser/performance_manager/graph/policies/policy_features.h
new file mode 100644
index 0000000..9ec9eea6
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/policy_features.h
@@ -0,0 +1,60 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+
+#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_POLICY_FEATURES_H_
+#define CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_POLICY_FEATURES_H_
+
+namespace performance_manager {
+namespace features {
+
+// TODO(bgeffon): The WorkingSetTrimmer for windows feature should also be moved
+// from resource manager to here.
+#if defined(OS_CHROMEOS)
+namespace chromeos {
+
+// The trim on Memory Pressure feature will trim a process nodes working set
+// according to the parameters below.
+extern const base::Feature kTrimOnMemoryPressure;
+
+// The trim on freeze feature will trim the working set of a process when all
+// frames are frozen.
+extern const base::Feature kTrimOnFreeze;
+
+// The graph walk backoff is the _minimum_ backoff time between graph walks
+// under moderate pressure in seconds. By default we will not walk more than
+// once every 2 minutes.
+extern const base::FeatureParam<int> kGraphWalkBackoffTimeSec;
+
+// Specifies the minimum amount of time a parent frame node must be invisible
+// before considering the process node for working set trim.
+extern const base::FeatureParam<int> kNodeInvisibileTimeSec;
+
+// Specifies the minimum amount of time a parent frame node must be invisible
+// before considering the process node for working set trim.
+extern const base::FeatureParam<int> kNodeTrimBackoffTimeSec;
+
+struct TrimOnMemoryPressureParams {
+  TrimOnMemoryPressureParams();
+  TrimOnMemoryPressureParams(const TrimOnMemoryPressureParams& other);
+
+  // GetParams will return this struct with the populated parameters below.
+  static TrimOnMemoryPressureParams GetParams();
+
+  base::TimeDelta graph_walk_backoff_time;
+  base::TimeDelta node_invisible_time;
+  base::TimeDelta node_trim_backoff_time;
+};
+
+}  // namespace chromeos
+#endif
+
+}  // namespace features
+}  // namespace performance_manager
+
+#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_POLICY_FEATURES_H_
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.cc b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.cc
new file mode 100644
index 0000000..1f46588
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.cc
@@ -0,0 +1,112 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h"
+
+#include "build/build_config.h"
+
+#include "chrome/browser/performance_manager/mechanisms/working_set_trimmer.h"
+#include "chrome/browser/performance_manager/public/graph/graph.h"
+#include "chrome/browser/performance_manager/public/graph/node_attached_data.h"
+#include "chrome/browser/performance_manager/public/graph/process_node.h"
+#if defined(OS_WIN)
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_win.h"
+#elif defined(OS_CHROMEOS)
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.h"
+#endif
+
+namespace performance_manager {
+namespace policies {
+
+namespace {
+
+class WorkingSetTrimData
+    : public ExternalNodeAttachedDataImpl<WorkingSetTrimData> {
+ public:
+  explicit WorkingSetTrimData(const ProcessNode* node) {}
+  ~WorkingSetTrimData() override = default;
+
+  base::TimeTicks last_trim_;
+};
+
+}  // namespace
+
+WorkingSetTrimmerPolicy::WorkingSetTrimmerPolicy() = default;
+WorkingSetTrimmerPolicy::~WorkingSetTrimmerPolicy() = default;
+
+void WorkingSetTrimmerPolicy::OnPassedToGraph(Graph* graph) {
+  RegisterObservers(graph);
+}
+
+void WorkingSetTrimmerPolicy::OnTakenFromGraph(Graph* graph) {
+  UnregisterObservers(graph);
+}
+
+void WorkingSetTrimmerPolicy::OnAllFramesInProcessFrozen(
+    const ProcessNode* process_node) {
+  TrimWorkingSet(process_node);
+}
+
+void WorkingSetTrimmerPolicy::RegisterObservers(Graph* graph) {
+  graph->AddProcessNodeObserver(this);
+}
+
+void WorkingSetTrimmerPolicy::UnregisterObservers(Graph* graph) {
+  graph->RemoveProcessNodeObserver(this);
+}
+
+base::TimeTicks WorkingSetTrimmerPolicy::GetLastTrimTime(
+    const ProcessNode* process_node) {
+  auto* data = WorkingSetTrimData::GetOrCreate(process_node);
+  return data->last_trim_;
+}
+
+void WorkingSetTrimmerPolicy::SetLastTrimTimeNow(
+    const ProcessNode* process_node) {
+  SetLastTrimTime(process_node, base::TimeTicks::Now());
+}
+
+void WorkingSetTrimmerPolicy::SetLastTrimTime(const ProcessNode* process_node,
+                                              base::TimeTicks time) {
+  auto* data = WorkingSetTrimData::GetOrCreate(process_node);
+  data->last_trim_ = time;
+}
+
+bool WorkingSetTrimmerPolicy::TrimWorkingSet(const ProcessNode* process_node) {
+  auto* trimmer = mechanism::WorkingSetTrimmer::GetInstance();
+  DCHECK(trimmer);
+  if (process_node->GetProcess().IsValid()) {
+    SetLastTrimTimeNow(process_node);
+    return trimmer->TrimWorkingSet(process_node);
+  }
+
+  return false;
+}
+
+// static
+bool WorkingSetTrimmerPolicy::PlatformSupportsWorkingSetTrim() {
+#if defined(OS_WIN)
+  return WorkingSetTrimmerPolicyWin::PlatformSupportsWorkingSetTrim();
+#elif defined(OS_CHROMEOS)
+  return WorkingSetTrimmerPolicyChromeOS::PlatformSupportsWorkingSetTrim();
+#else
+  return false;
+#endif
+}
+
+// static
+std::unique_ptr<WorkingSetTrimmerPolicy>
+WorkingSetTrimmerPolicy::CreatePolicyForPlatform() {
+#if defined(OS_WIN)
+  return std::make_unique<WorkingSetTrimmerPolicyWin>();
+#elif defined(OS_CHROMEOS)
+  return std::make_unique<WorkingSetTrimmerPolicyChromeOS>();
+#else
+  NOTIMPLEMENTED() << "Platform does not support WorkingSetTrim.";
+  return nullptr;
+#endif
+}
+
+}  // namespace policies
+}  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h
new file mode 100644
index 0000000..ba9cfc961
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h
@@ -0,0 +1,85 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_WORKING_SET_TRIMMER_POLICY_H_
+#define CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_WORKING_SET_TRIMMER_POLICY_H_
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "chrome/browser/performance_manager/public/graph/graph.h"
+#include "chrome/browser/performance_manager/public/graph/node_attached_data.h"
+#include "chrome/browser/performance_manager/public/graph/process_node.h"
+
+namespace performance_manager {
+namespace policies {
+
+// Empties the working set of processes in which all frames are frozen.
+//
+// Objective #1: Track working set growth rate.
+//   Swap thrashing occurs when a lot of pages are accessed in a short period of
+//   time. Swap thrashing can be reduced by reducing the number of pages
+//   accessed by processes in which all frames are frozen. To track efforts
+//   towards this goal, we empty the working set of processes when all their
+//   frames become frozen and record the size of their working set after x
+//   minutes.
+//   TODO(fdoray): Record the working set size x minutes after emptying it.
+//   https://crbug.com/885293
+//
+// Objective #2: Improve performance.
+//   We hypothesize that emptying the working set of a process causes its pages
+//   to be compressed and/or written to disk preemptively, which makes more
+//   memory available quickly for foreground processes and improves global
+//   browser performance.
+class WorkingSetTrimmerPolicy : public GraphOwned,
+                                public ProcessNode::ObserverDefaultImpl {
+ public:
+  WorkingSetTrimmerPolicy();
+  ~WorkingSetTrimmerPolicy() override;
+
+  // CreatePolicyForPlatform will create a working set trimmer policy for a
+  // specific platform which should be owned by the graph, you should always
+  // check PlatformSupportsWorkingSetTrim() before creating a policy to do so as
+  // it would result in unnecessary book-keeping.
+  static std::unique_ptr<WorkingSetTrimmerPolicy> CreatePolicyForPlatform();
+
+  // Returns true if running on a platform that supports working set trimming.
+  static bool PlatformSupportsWorkingSetTrim();
+
+  // GraphOwned implementation:
+  void OnPassedToGraph(Graph* graph) override;
+  void OnTakenFromGraph(Graph* graph) override;
+
+  // ProcessNodeObserver implementation:
+  void OnAllFramesInProcessFrozen(const ProcessNode* process_node) override;
+
+ protected:
+  // (Un)registers the various node observer flavors of this object with the
+  // graph. These are invoked by OnPassedToGraph and OnTakenFromGraph, but
+  // hoisted to their own functions for testing.
+  void RegisterObservers(Graph* graph);
+  void UnregisterObservers(Graph* graph);
+
+  // Returns the time in which this process was last trimmed.
+  base::TimeTicks GetLastTrimTime(const ProcessNode* process_node);
+
+  // Sets the last trim time to TimeTicks::Now().
+  void SetLastTrimTimeNow(const ProcessNode* process_node);
+
+  // TrimWorkingSet will trim a ProcessNode's working set, it will return true
+  // on success. This is virtual for testing.
+  virtual bool TrimWorkingSet(const ProcessNode* process_node);
+
+ private:
+  friend class WorkingSetTrimmerPolicyTest;
+
+  // A helper method which sets the last trim time to the specified time.
+  void SetLastTrimTime(const ProcessNode* process_node, base::TimeTicks time);
+
+  DISALLOW_COPY_AND_ASSIGN(WorkingSetTrimmerPolicy);
+};
+
+}  // namespace policies
+}  // namespace performance_manager
+
+#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_WORKING_SET_TRIMMER_POLICY_H_
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.cc b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.cc
new file mode 100644
index 0000000..9d20a71
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.cc
@@ -0,0 +1,109 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.h"
+
+#include "base/bind.h"
+#include "chrome/browser/performance_manager/graph/policies/policy_features.h"
+#include "chrome/browser/performance_manager/mechanisms/working_set_trimmer.h"
+#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/public/graph/frame_node.h"
+#include "chrome/browser/performance_manager/public/graph/graph.h"
+#include "chrome/browser/performance_manager/public/graph/page_node.h"
+#include "url/gurl.h"
+
+namespace performance_manager {
+namespace policies {
+
+WorkingSetTrimmerPolicyChromeOS::WorkingSetTrimmerPolicyChromeOS() {
+  trim_on_memory_pressure_enabled_ =
+      base::FeatureList::IsEnabled(features::chromeos::kTrimOnMemoryPressure);
+  trim_on_freeze_enabled_ =
+      base::FeatureList::IsEnabled(features::chromeos::kTrimOnFreeze);
+
+  if (trim_on_memory_pressure_enabled_) {
+    trim_on_memory_pressure_params_ =
+        features::chromeos::TrimOnMemoryPressureParams::GetParams();
+  }
+}
+
+WorkingSetTrimmerPolicyChromeOS::~WorkingSetTrimmerPolicyChromeOS() = default;
+
+// On MemoryPressure we will try to trim the working set of some renders if they
+// have been backgrounded for some period of time and have not been trimmed for
+// at least the backoff period.
+void WorkingSetTrimmerPolicyChromeOS::OnMemoryPressure(
+    base::MemoryPressureListener::MemoryPressureLevel level) {
+  if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE)
+    return;
+
+  // Try not to walk the graph too frequently because we can receive moderate
+  // memory pressure notifications every 10s.
+  if (base::TimeTicks::Now() - last_graph_walk_ <
+      trim_on_memory_pressure_params_.graph_walk_backoff_time) {
+    return;
+  }
+
+  TrimNodesOnGraph();
+}
+
+void WorkingSetTrimmerPolicyChromeOS::TrimNodesOnGraph() {
+  const base::TimeTicks now_ticks = base::TimeTicks::Now();
+  for (const PageNode* node : graph_->GetAllPageNodes()) {
+    if (!node->IsVisible() &&
+        node->GetTimeSinceLastVisibilityChange() >
+            trim_on_memory_pressure_params_.node_invisible_time) {
+      // Get the process node and if it has not been
+      // trimmed within the backoff period, we will do that
+      // now.
+      const ProcessNode* process_node =
+          node->GetMainFrameNode()->GetProcessNode();
+      if (process_node->GetProcess().IsValid()) {
+        base::TimeTicks last_trim = GetLastTrimTime(process_node);
+        if (now_ticks - last_trim >
+            trim_on_memory_pressure_params_.node_trim_backoff_time) {
+          TrimWorkingSet(process_node);
+        }
+      }
+    }
+  }
+  last_graph_walk_ = now_ticks;
+}
+
+void WorkingSetTrimmerPolicyChromeOS::OnTakenFromGraph(Graph* graph) {
+  memory_pressure_listener_.reset();
+  graph_ = nullptr;
+  WorkingSetTrimmerPolicy::OnTakenFromGraph(graph);
+}
+
+void WorkingSetTrimmerPolicyChromeOS::OnAllFramesInProcessFrozen(
+    const ProcessNode* process_node) {
+  if (trim_on_freeze_enabled_) {
+    WorkingSetTrimmerPolicy::OnAllFramesInProcessFrozen(process_node);
+  }
+}
+
+void WorkingSetTrimmerPolicyChromeOS::OnPassedToGraph(Graph* graph) {
+  if (trim_on_memory_pressure_enabled_) {
+    // We wait to register the memory pressure listener so we're on the
+    // right sequence.
+    trim_on_memory_pressure_params_ =
+        features::chromeos::TrimOnMemoryPressureParams::GetParams();
+    memory_pressure_listener_.emplace(
+        base::BindRepeating(&WorkingSetTrimmerPolicyChromeOS::OnMemoryPressure,
+                            base::Unretained(this)));
+  }
+
+  graph_ = graph;
+  WorkingSetTrimmerPolicy::OnPassedToGraph(graph);
+}
+
+// static
+bool WorkingSetTrimmerPolicyChromeOS::PlatformSupportsWorkingSetTrim() {
+  return mechanism::WorkingSetTrimmer::GetInstance()
+      ->PlatformSupportsWorkingSetTrim();
+}
+
+}  // namespace policies
+}  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.h b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.h
new file mode 100644
index 0000000..84df00ae
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.h
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_WORKING_SET_TRIMMER_POLICY_CHROMEOS_H_
+#define CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_WORKING_SET_TRIMMER_POLICY_CHROMEOS_H_
+
+#include "base/memory/memory_pressure_listener.h"
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "chrome/browser/performance_manager/graph/policies/policy_features.h"
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h"
+
+namespace performance_manager {
+namespace policies {
+
+class WorkingSetTrimmerPolicyChromeOSTest;
+
+// ChromeOS specific WorkingSetTrimmerPolicy which uses the default policy on
+// all frames frozen, additionally it will add working set trim under memory
+// pressure.
+class WorkingSetTrimmerPolicyChromeOS : public WorkingSetTrimmerPolicy {
+ public:
+  ~WorkingSetTrimmerPolicyChromeOS() override;
+  WorkingSetTrimmerPolicyChromeOS();
+
+  // Returns true if this platform supports working set trim, in the case of
+  // Windows this will check that the appropriate flags are set for working set
+  // trim.
+  static bool PlatformSupportsWorkingSetTrim();
+
+  // GraphOwned implementation:
+  void OnTakenFromGraph(Graph* graph) override;
+  void OnPassedToGraph(Graph* graph) override;
+
+  // ProcessNodeObserver implementation:
+  void OnAllFramesInProcessFrozen(const ProcessNode* process_node) override;
+
+ protected:
+  friend class WorkingSetTrimmerPolicyChromeOSTest;
+
+  void OnMemoryPressure(
+      base::MemoryPressureListener::MemoryPressureLevel level);
+
+  void TrimNodesOnGraph();
+
+  bool trim_on_freeze_enabled_ = false;
+  bool trim_on_memory_pressure_enabled_ = false;
+
+  features::chromeos::TrimOnMemoryPressureParams
+      trim_on_memory_pressure_params_;
+
+  // Keeps track of the last time we walked the graph looking for processes
+  // to trim.
+  base::TimeTicks last_graph_walk_;
+
+  base::Optional<base::MemoryPressureListener> memory_pressure_listener_;
+
+ private:
+  Graph* graph_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(WorkingSetTrimmerPolicyChromeOS);
+};
+
+}  // namespace policies
+}  // namespace performance_manager
+
+#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_WORKING_SET_TRIMMER_POLICY_CHROMEOS_H_
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos_unittest.cc b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos_unittest.cc
new file mode 100644
index 0000000..158d96cb
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos_unittest.cc
@@ -0,0 +1,218 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.h"
+
+#include "base/memory/memory_pressure_listener.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "chrome/browser/performance_manager/graph/graph_impl_operations.h"
+#include "chrome/browser/performance_manager/graph/graph_test_harness.h"
+#include "chrome/browser/performance_manager/graph/mock_graphs.h"
+#include "chrome/browser/performance_manager/graph/page_node_impl.h"
+#include "chrome/browser/performance_manager/graph/process_node_impl.h"
+#include "chrome/browser/performance_manager/performance_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace performance_manager {
+namespace policies {
+
+class MockWorkingSetTrimmerPolicyChromeOS
+    : public WorkingSetTrimmerPolicyChromeOS {
+ public:
+  MockWorkingSetTrimmerPolicyChromeOS() {
+    trim_on_memory_pressure_enabled_ = true;
+    trim_on_freeze_enabled_ = true;
+
+    // Setup parameters for trimming on memory pressure.
+    trim_on_memory_pressure_params_.graph_walk_backoff_time =
+        base::TimeDelta::FromSeconds(30);
+
+    trim_on_memory_pressure_params_.node_invisible_time =
+        base::TimeDelta::FromSeconds(30);
+
+    trim_on_memory_pressure_params_.node_trim_backoff_time =
+        base::TimeDelta::FromSeconds(30);
+  }
+
+  ~MockWorkingSetTrimmerPolicyChromeOS() override {}
+
+  base::MemoryPressureListener& listener() {
+    return memory_pressure_listener_.value();
+  }
+
+  base::TimeTicks get_last_graph_walk() { return last_graph_walk_; }
+
+  MOCK_METHOD1(TrimWorkingSet, bool(const ProcessNode*));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockWorkingSetTrimmerPolicyChromeOS);
+};
+
+class WorkingSetTrimmerPolicyChromeOSTest : public GraphTestHarness {
+ public:
+  WorkingSetTrimmerPolicyChromeOSTest()
+      : GraphTestHarness(
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME_AND_NOW) {}
+  ~WorkingSetTrimmerPolicyChromeOSTest() override {}
+
+  void SetUp() override {
+    GraphTestHarness::SetUp();
+
+    // Add our mock policy to the graph.
+    std::unique_ptr<MockWorkingSetTrimmerPolicyChromeOS> mock_policy(
+        new MockWorkingSetTrimmerPolicyChromeOS);
+    policy_ = mock_policy.get();
+    graph()->PassToGraph(std::move(mock_policy));
+  }
+
+  void TearDown() override {
+    policy_ = nullptr;
+    GraphTestHarness::TearDown();
+  }
+
+  MockWorkingSetTrimmerPolicyChromeOS* policy() { return policy_; }
+
+  base::TimeTicks NowTicks() { return task_env().NowTicks(); }
+
+  base::TimeTicks FastForwardBy(base::TimeDelta delta) {
+    task_env().FastForwardBy(delta);
+    return NowTicks();
+  }
+
+ private:
+  MockWorkingSetTrimmerPolicyChromeOS* policy_ = nullptr;  // Not owned.
+
+  DISALLOW_COPY_AND_ASSIGN(WorkingSetTrimmerPolicyChromeOSTest);
+};
+
+// Validate that we don't walk again before the backoff period has expired.
+TEST_F(WorkingSetTrimmerPolicyChromeOSTest, GraphWalkBackoffPeriod) {
+  // Since we've never walked the graph we should do so now.
+  const base::TimeTicks initial_walk_time = policy()->get_last_graph_walk();
+  ASSERT_EQ(initial_walk_time, base::TimeTicks());
+
+  policy()->listener().SimulatePressureNotification(
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
+
+  FastForwardBy(base::TimeDelta::FromSeconds(1));
+
+  // Since we have never walked we expect that we walked it now, we confirm by
+  // checking the last walk time against the known clock.
+  const base::TimeTicks last_walk_time = policy()->get_last_graph_walk();
+  EXPECT_LT(initial_walk_time, last_walk_time);
+
+  policy()->listener().SimulatePressureNotification(
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
+
+  FastForwardBy(base::TimeDelta::FromSeconds(1));
+
+  // We will not have caused a walk as the clock has not advanced beyond the
+  // backoff period.
+  EXPECT_EQ(last_walk_time, policy()->get_last_graph_walk());
+}
+
+// Validate that we will walk the graph again after the backoff period is
+// expired.
+TEST_F(WorkingSetTrimmerPolicyChromeOSTest, GraphWalkAfterBackoffPeriod) {
+  // Since we've never walked the graph we should do so now.
+  const base::TimeTicks initial_walk_time = policy()->get_last_graph_walk();
+  ASSERT_EQ(initial_walk_time, base::TimeTicks());
+
+  policy()->listener().SimulatePressureNotification(
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
+
+  FastForwardBy(base::TimeDelta::FromSeconds(1));
+
+  // Since we have never walked we expect that we walked it now, we confirm by
+  // checking the last walk time against the known clock.
+  const base::TimeTicks last_walk_time = policy()->get_last_graph_walk();
+  EXPECT_LT(initial_walk_time, last_walk_time);
+
+  FastForwardBy(base::TimeDelta::FromDays(1));
+
+  policy()->listener().SimulatePressureNotification(
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
+
+  // Finally advance the clock beyond the backoff period and it should allow it
+  // to walk again.
+  FastForwardBy(base::TimeDelta::FromSeconds(1));
+
+  const base::TimeTicks final_walk_time = policy()->get_last_graph_walk();
+  EXPECT_GT(final_walk_time, last_walk_time);
+}
+
+// This test will validate that we will NOT try to trim a node if it has not
+// been invisible for long enough.
+TEST_F(WorkingSetTrimmerPolicyChromeOSTest, DontTrimIfNotInvisibleLongEnough) {
+  // Create a simple graph
+  auto process_node = CreateNode<ProcessNodeImpl>();
+  auto page_node = CreateNode<PageNodeImpl>();
+  auto parent_frame =
+      CreateNode<FrameNodeImpl>(process_node.get(), page_node.get());
+
+  // Since we've never walked the graph we should do so now.
+  const base::TimeTicks clock_time = NowTicks();
+  const base::TimeTicks initial_walk_time = policy()->get_last_graph_walk();
+
+  // Set the PageNode to invisible but the state change time to now, since it
+  // will not have been invisible long enough it will NOT trigger a call to
+  // TrimWorkingSet.
+  page_node->SetIsVisible(true);   // Reset visibility and set invisible Now.
+  page_node->SetIsVisible(false);  // Uses the testing clock.
+  EXPECT_CALL(*policy(), TrimWorkingSet(testing::_)).Times(0);
+
+  // Triger memory pressure and we should observe the walk.
+  policy()->listener().SimulatePressureNotification(
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
+
+  FastForwardBy(base::TimeDelta::FromSeconds(1));
+
+  const base::TimeTicks current_walk_time = policy()->get_last_graph_walk();
+  EXPECT_EQ(clock_time, current_walk_time);
+  EXPECT_NE(current_walk_time, initial_walk_time);
+}
+
+// This test will validate that we WILL trim the working set if it has been
+// invisible long enough.
+TEST_F(WorkingSetTrimmerPolicyChromeOSTest, TrimIfInvisibleLongEnough) {
+  // Create a simple graph
+  auto process_node = CreateNode<ProcessNodeImpl>();
+  auto page_node = CreateNode<PageNodeImpl>();
+  auto parent_frame =
+      CreateNode<FrameNodeImpl>(process_node.get(), page_node.get());
+
+  ASSERT_EQ(1u, graph()->GetAllPageNodes().size());
+
+  // Create a Process so this process node doesn't bail on Process.IsValid();
+  const base::Process self = base::Process::Current();
+  auto duplicate = self.Duplicate();
+  ASSERT_TRUE(duplicate.IsValid());
+  process_node->SetProcess(std::move(duplicate), base::Time::Now());
+
+  // Set it invisible using the current clock, then we will advance the clock
+  // and it should result in a TrimWorkingSet since it's been invisible long
+  // enough.
+  page_node->SetIsVisible(true);   // Reset visibility and then set invisible.
+  page_node->SetIsVisible(false);  // Uses the testing clock.
+  const base::TimeTicks cur_time =
+      FastForwardBy(base::TimeDelta::FromDays(365));
+
+  // We will attempt to trim to corresponding ProcessNode since we've been
+  // invisible long enough.
+  EXPECT_CALL(*policy(), TrimWorkingSet(process_node.get())).Times(1);
+
+  // Triger memory pressure and we should observe the walk since we've never
+  // walked before.
+  policy()->listener().SimulatePressureNotification(
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
+
+  FastForwardBy(base::TimeDelta::FromSeconds(1));
+
+  // We should have triggered the walk and it should have trimmed.
+  EXPECT_EQ(cur_time, policy()->get_last_graph_walk());
+}
+
+}  // namespace policies
+}  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_unittest.cc b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_unittest.cc
new file mode 100644
index 0000000..dd8d183
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_unittest.cc
@@ -0,0 +1,74 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h"
+
+#include "chrome/browser/performance_manager/graph/graph_test_harness.h"
+#include "chrome/browser/performance_manager/graph/process_node_impl.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace performance_manager {
+namespace policies {
+
+class MockWorkingSetTrimmerPolicy : public WorkingSetTrimmerPolicy {
+ public:
+  MockWorkingSetTrimmerPolicy() {}
+  ~MockWorkingSetTrimmerPolicy() override {}
+
+  MOCK_METHOD1(TrimWorkingSet, bool(const ProcessNode*));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockWorkingSetTrimmerPolicy);
+};
+
+class WorkingSetTrimmerPolicyTest : public GraphTestHarness {
+ public:
+  WorkingSetTrimmerPolicyTest() {}
+  ~WorkingSetTrimmerPolicyTest() override {}
+
+  void SetUp() override { policy_.reset(new WorkingSetTrimmerPolicy); }
+
+  void SetLastTrimTime(const ProcessNode* node, base::TimeTicks time) {
+    policy_->SetLastTrimTime(node, time);
+  }
+
+  base::TimeTicks GetLastTrimTime(const ProcessNode* node) {
+    return policy_->GetLastTrimTime(node);
+  }
+
+ protected:
+  std::unique_ptr<WorkingSetTrimmerPolicy> policy_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WorkingSetTrimmerPolicyTest);
+};
+
+// Validate that we can set and get the last trim time on a ProcessNode.
+TEST_F(WorkingSetTrimmerPolicyTest, SetTrimTimeOnNode) {
+  auto process_node = CreateNode<ProcessNodeImpl>();
+  ASSERT_NE(process_node.get(), nullptr);
+
+  auto now_ticks = base::TimeTicks::Now();
+  SetLastTrimTime(process_node.get(), now_ticks);
+  ASSERT_EQ(GetLastTrimTime(process_node.get()), now_ticks);
+}
+
+// Validate that when all frames in a ProcessNode are frozen we attempt to trim
+// the working set.
+TEST_F(WorkingSetTrimmerPolicyTest, TrimOnFrozen) {
+  std::unique_ptr<MockWorkingSetTrimmerPolicy> mock_policy(
+      new MockWorkingSetTrimmerPolicy);
+  auto process_node = CreateNode<ProcessNodeImpl>();
+  ASSERT_NE(process_node.get(), nullptr);
+
+  EXPECT_CALL(*mock_policy, TrimWorkingSet(process_node.get())).Times(1);
+  graph()->PassToGraph(std::move(mock_policy));
+
+  process_node->OnAllFramesInProcessFrozenForTesting();
+}
+
+}  // namespace policies
+}  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_win.cc b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_win.cc
new file mode 100644
index 0000000..220d678
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_win.cc
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_win.h"
+
+#include "base/feature_list.h"
+#include "chrome/browser/performance_manager/mechanisms/working_set_trimmer.h"
+#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
+
+namespace performance_manager {
+namespace policies {
+
+WorkingSetTrimmerPolicyWin::WorkingSetTrimmerPolicyWin() = default;
+WorkingSetTrimmerPolicyWin::~WorkingSetTrimmerPolicyWin() = default;
+
+// static
+bool WorkingSetTrimmerPolicyWin::PlatformSupportsWorkingSetTrim() {
+  bool enabled = base::FeatureList::IsEnabled(features::kEmptyWorkingSet);
+  bool supported = mechanism::WorkingSetTrimmer::GetInstance()
+                       ->PlatformSupportsWorkingSetTrim();
+
+  return enabled && supported;
+}
+
+}  // namespace policies
+}  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_win.h b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_win.h
new file mode 100644
index 0000000..13b1c83
--- /dev/null
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_win.h
@@ -0,0 +1,33 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_WORKING_SET_TRIMMER_POLICY_WIN_H_
+#define CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_WORKING_SET_TRIMMER_POLICY_WIN_H_
+
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h"
+
+namespace performance_manager {
+namespace policies {
+
+// The Windows WorkingSetTrimmerPolicy uses the defaults except it defines it's
+// own PlatformSupportsWorkingSetTrim() because we want to flag guard this
+// feature.
+class WorkingSetTrimmerPolicyWin : public WorkingSetTrimmerPolicy {
+ public:
+  ~WorkingSetTrimmerPolicyWin() override;
+  WorkingSetTrimmerPolicyWin();
+
+  // Returns true if this platform supports working set trim, in the case of
+  // Windows this will check that the appropriate flags are set for working set
+  // trim.
+  static bool PlatformSupportsWorkingSetTrim();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WorkingSetTrimmerPolicyWin);
+};
+
+}  // namespace policies
+}  // namespace performance_manager
+
+#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_POLICIES_WORKING_SET_TRIMMER_POLICY_WIN_H_
diff --git a/chrome/browser/performance_manager/observers/working_set_trimmer_observer_win_unittest.cc b/chrome/browser/performance_manager/mechanisms/working_set_trimmer_win_unittest.cc
similarity index 93%
rename from chrome/browser/performance_manager/observers/working_set_trimmer_observer_win_unittest.cc
rename to chrome/browser/performance_manager/mechanisms/working_set_trimmer_win_unittest.cc
index 3d6113b..4deb867 100644
--- a/chrome/browser/performance_manager/observers/working_set_trimmer_observer_win_unittest.cc
+++ b/chrome/browser/performance_manager/mechanisms/working_set_trimmer_win_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 "chrome/browser/performance_manager/observers/working_set_trimmer_observer_win.h"
+#include "chrome/browser/performance_manager/mechanisms/working_set_trimmer_win.h"
 
 #include <windows.h>  // Must be in front of other Windows header files.
 
@@ -110,7 +110,6 @@
   base::Process child_process_;
   TestNodeWrapper<ProcessNodeImpl> process_node_ =
       CreateNode<ProcessNodeImpl>();
-  WorkingSetTrimmer working_set_trimmer_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(WorkingSetTrimmerTest);
@@ -126,7 +125,12 @@
   // When all frames in the process node are frozen, the working set of
   // |child_process_| should be emptied.
   size_t working_set_before = GetWorkingSetSizeMb(child_process_.Handle());
-  working_set_trimmer_.OnAllFramesInProcessFrozen(process_node_.get());
+
+  ASSERT_TRUE(mechanism::WorkingSetTrimmer::GetInstance()
+                  ->PlatformSupportsWorkingSetTrim());
+  mechanism::WorkingSetTrimmer::GetInstance()->TrimWorkingSet(
+      process_node_.get());
+
   // Make sure the working set has shrunk by at least the 10mb allocation.
   EXPECT_GE(working_set_before - 10U,
             GetWorkingSetSizeMb(child_process_.Handle()));
diff --git a/chrome/browser/performance_manager/observers/working_set_trimmer_observer_win.cc b/chrome/browser/performance_manager/observers/working_set_trimmer_observer_win.cc
deleted file mode 100644
index 253eb0ef..0000000
--- a/chrome/browser/performance_manager/observers/working_set_trimmer_observer_win.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/performance_manager/observers/working_set_trimmer_observer_win.h"
-
-#include "base/logging.h"
-#include "base/process/process.h"
-#include "base/time/time.h"
-#include "chrome/browser/performance_manager/graph/node_base.h"
-#include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/mechanisms/working_set_trimmer.h"
-
-namespace performance_manager {
-
-WorkingSetTrimmer::WorkingSetTrimmer() = default;
-WorkingSetTrimmer::~WorkingSetTrimmer() = default;
-
-void WorkingSetTrimmer::OnPassedToGraph(Graph* graph) {
-  RegisterObservers(graph);
-}
-
-void WorkingSetTrimmer::OnTakenFromGraph(Graph* graph) {
-  UnregisterObservers(graph);
-}
-
-void WorkingSetTrimmer::OnAllFramesInProcessFrozen(
-    const ProcessNode* process_node) {
-  auto* trimmer = mechanism::WorkingSetTrimmer::GetInstance();
-
-  if (process_node->GetProcess().IsValid() &&
-      trimmer->PlatformSupportsWorkingSetTrim())
-    trimmer->TrimWorkingSet(process_node);
-}
-
-void WorkingSetTrimmer::RegisterObservers(Graph* graph) {
-  graph->AddProcessNodeObserver(this);
-}
-
-void WorkingSetTrimmer::UnregisterObservers(Graph* graph) {
-  graph->RemoveProcessNodeObserver(this);
-}
-
-}  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/observers/working_set_trimmer_observer_win.h b/chrome/browser/performance_manager/observers/working_set_trimmer_observer_win.h
deleted file mode 100644
index f333c68..0000000
--- a/chrome/browser/performance_manager/observers/working_set_trimmer_observer_win.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_WORKING_SET_TRIMMER_OBSERVER_WIN_H_
-#define CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_WORKING_SET_TRIMMER_OBSERVER_WIN_H_
-
-#include "base/macros.h"
-#include "chrome/browser/performance_manager/public/graph/graph.h"
-#include "chrome/browser/performance_manager/public/graph/process_node.h"
-
-namespace performance_manager {
-
-// Empties the working set of processes in which all frames are frozen.
-//
-// Objective #1: Track working set growth rate.
-//   Swap trashing occurs when a lot of pages are accessed in a short period of
-//   time. Swap trashing can be reduced by reducing the number of pages accessed
-//   by processes in which all frames are frozen. To track efforts towards this
-//   goal, we empty the working set of processes when all their frames become
-//   frozen and record the size of their working set after x minutes.
-//   TODO(fdoray): Record the working set size x minutes after emptying it.
-//   https://crbug.com/885293
-//
-// Objective #2: Improve performance.
-//   We hypothesize that emptying the working set of a process causes its pages
-//   to be compressed and/or written to disk preemptively, which makes more
-//   memory available quickly for foreground processes and improves global
-//   browser performance.
-class WorkingSetTrimmer : public GraphOwned,
-                          public ProcessNode::ObserverDefaultImpl {
- public:
-  WorkingSetTrimmer();
-  ~WorkingSetTrimmer() override;
-
-  // GraphOwned implementation:
-  void OnPassedToGraph(Graph* graph) override;
-  void OnTakenFromGraph(Graph* graph) override;
-
-  // ProcessNodeObserver:
-  void OnAllFramesInProcessFrozen(const ProcessNode* process_node) override;
-
- protected:
-  // (Un)registers the various node observer flavors of this object with the
-  // graph. These are invoked by OnPassedToGraph and OnTakenFromGraph, but
-  // hoisted to their own functions for testing.
-  void RegisterObservers(Graph* graph);
-  void UnregisterObservers(Graph* graph);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WorkingSetTrimmer);
-};
-
-}  // namespace performance_manager
-
-#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_WORKING_SET_TRIMMER_OBSERVER_WIN_H_
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc
index 373b3974..8ba37ee 100644
--- a/chrome/browser/performance_manager/performance_manager.cc
+++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -20,11 +20,11 @@
 #include "chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h"
 #include "chrome/browser/performance_manager/graph/frame_node_impl.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
 #include "chrome/browser/performance_manager/graph/system_node_impl.h"
 #include "chrome/browser/performance_manager/observers/isolation_context_metrics.h"
 #include "chrome/browser/performance_manager/observers/metrics_collector.h"
-#include "chrome/browser/performance_manager/observers/working_set_trimmer_observer_win.h"
 #include "content/public/browser/system_connector.h"
 #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
 
@@ -322,10 +322,10 @@
   graph_.PassToGraph(std::make_unique<IsolationContextMetrics>());
   graph_.PassToGraph(std::make_unique<MetricsCollector>());
 
-#if defined(OS_WIN)
-  if (base::FeatureList::IsEnabled(features::kEmptyWorkingSet))
-    graph_.PassToGraph(std::make_unique<WorkingSetTrimmer>());
-#endif
+  if (policies::WorkingSetTrimmerPolicy::PlatformSupportsWorkingSetTrim()) {
+    graph_.PassToGraph(
+        policies::WorkingSetTrimmerPolicy::CreatePolicyForPlatform());
+  }
 
   interface_registry_.AddInterface(base::BindRepeating(
       &PerformanceManager::BindWebUIGraphDump, base::Unretained(this)));
diff --git a/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc b/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
index b6fc3e9..a48e85fce 100644
--- a/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
+++ b/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
@@ -197,12 +197,6 @@
   NOTREACHED();
 }
 
-void PreviewsLitePageRedirectURLLoader::ProceedWithResponse() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  // This class never provides a response past the headers.
-  NOTREACHED();
-}
-
 void PreviewsLitePageRedirectURLLoader::SetPriority(
     net::RequestPriority priority,
     int32_t intra_priority_value) {
diff --git a/chrome/browser/previews/previews_lite_page_redirect_url_loader.h b/chrome/browser/previews/previews_lite_page_redirect_url_loader.h
index 0b63ac9..1c69b4ba 100644
--- a/chrome/browser/previews/previews_lite_page_redirect_url_loader.h
+++ b/chrome/browser/previews/previews_lite_page_redirect_url_loader.h
@@ -53,7 +53,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/chrome/browser/previews/previews_lite_page_serving_url_loader.cc b/chrome/browser/previews/previews_lite_page_serving_url_loader.cc
index f3b3013..36fd50c 100644
--- a/chrome/browser/previews/previews_lite_page_serving_url_loader.cc
+++ b/chrome/browser/previews/previews_lite_page_serving_url_loader.cc
@@ -413,12 +413,6 @@
   NOTREACHED();
 }
 
-void PreviewsLitePageServingURLLoader::ProceedWithResponse() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  // Pass through.
-  network_url_loader_->ProceedWithResponse();
-}
-
 void PreviewsLitePageServingURLLoader::SetPriority(
     net::RequestPriority priority,
     int32_t intra_priority_value) {
diff --git a/chrome/browser/previews/previews_lite_page_serving_url_loader.h b/chrome/browser/previews/previews_lite_page_serving_url_loader.h
index 4e22826..95a6152 100644
--- a/chrome/browser/previews/previews_lite_page_serving_url_loader.h
+++ b/chrome/browser/previews/previews_lite_page_serving_url_loader.h
@@ -67,7 +67,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index 12c14fd..728bb5b 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -374,18 +374,6 @@
       ->GetDownloadManagerDelegate();
 }
 
-net::URLRequestContextGetter* OffTheRecordProfileImpl::CreateRequestContext(
-    content::ProtocolHandlerMap* protocol_handlers,
-    content::URLRequestInterceptorScopedVector request_interceptors) {
-  return nullptr;
-}
-
-net::URLRequestContextGetter*
-    OffTheRecordProfileImpl::CreateMediaRequestContext() {
-  // In OTR mode, media request context is the same as the original one.
-  return GetRequestContext();
-}
-
 std::unique_ptr<service_manager::Service>
 OffTheRecordProfileImpl::HandleServiceRequest(
     const std::string& service_name,
@@ -420,10 +408,6 @@
 }
 #endif  // defined(OS_CHROMEOS)
 
-net::URLRequestContextGetter* OffTheRecordProfileImpl::GetRequestContext() {
-  return GetDefaultStoragePartition(this)->GetURLRequestContext();
-}
-
 scoped_refptr<network::SharedURLLoaderFactory>
 OffTheRecordProfileImpl::GetURLLoaderFactory() {
   return GetDefaultStoragePartition(this)
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h
index 8e5e63fc..eb89c27 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.h
+++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -67,12 +67,7 @@
 #else
   policy::UserCloudPolicyManager* GetUserCloudPolicyManager() override;
 #endif  // defined(OS_CHROMEOS)
-  net::URLRequestContextGetter* GetRequestContext() override;
   scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
-  net::URLRequestContextGetter* CreateRequestContext(
-      content::ProtocolHandlerMap* protocol_handlers,
-      content::URLRequestInterceptorScopedVector request_interceptors) override;
-  net::URLRequestContextGetter* CreateMediaRequestContext() override;
   std::unique_ptr<service_manager::Service> HandleServiceRequest(
       const std::string& service_name,
       service_manager::mojom::ServiceRequest request) override;
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index e47a894..8d5839a 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -219,9 +219,6 @@
   // (i.e. HasOffTheRecordProfile is false).
   virtual PrefService* GetReadOnlyOffTheRecordPrefs();
 
-  // Returns the main request context.
-  virtual net::URLRequestContextGetter* GetRequestContext() = 0;
-
   // Returns the main URLLoaderFactory.
   virtual scoped_refptr<network::SharedURLLoaderFactory>
   GetURLLoaderFactory() = 0;
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index da0cfff..dd69852 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -1149,10 +1149,6 @@
   return io_data_.GetResourceContext();
 }
 
-net::URLRequestContextGetter* ProfileImpl::GetRequestContext() {
-  return GetDefaultStoragePartition(this)->GetURLRequestContext();
-}
-
 scoped_refptr<network::SharedURLLoaderFactory>
 ProfileImpl::GetURLLoaderFactory() {
   return GetDefaultStoragePartition(this)
@@ -1217,16 +1213,6 @@
   return ContentIndexProviderFactory::GetForProfile(this);
 }
 
-net::URLRequestContextGetter* ProfileImpl::CreateRequestContext(
-    content::ProtocolHandlerMap* protocol_handlers,
-    content::URLRequestInterceptorScopedVector request_interceptors) {
-  return nullptr;
-}
-
-net::URLRequestContextGetter* ProfileImpl::CreateMediaRequestContext() {
-  return nullptr;
-}
-
 void ProfileImpl::SetCorsOriginAccessListForOrigin(
     const url::Origin& source_origin,
     std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index e33619d..a47b648de 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -87,10 +87,6 @@
       override;
   content::BackgroundFetchDelegate* GetBackgroundFetchDelegate() override;
   content::BackgroundSyncController* GetBackgroundSyncController() override;
-  net::URLRequestContextGetter* CreateRequestContext(
-      content::ProtocolHandlerMap* protocol_handlers,
-      content::URLRequestInterceptorScopedVector request_interceptors) override;
-  net::URLRequestContextGetter* CreateMediaRequestContext() override;
   void SetCorsOriginAccessListForOrigin(
       const url::Origin& source_origin,
       std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
@@ -147,7 +143,6 @@
   policy::ProfilePolicyConnector* GetProfilePolicyConnector() override;
   const policy::ProfilePolicyConnector* GetProfilePolicyConnector()
       const override;
-  net::URLRequestContextGetter* GetRequestContext() override;
   scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
   bool IsSameProfile(Profile* profile) override;
   base::Time GetStartTime() const override;
diff --git a/chrome/browser/resources/chromeos/switch_access/BUILD.gn b/chrome/browser/resources/chromeos/switch_access/BUILD.gn
index 33cef10..42083e7a 100644
--- a/chrome/browser/resources/chromeos/switch_access/BUILD.gn
+++ b/chrome/browser/resources/chromeos/switch_access/BUILD.gn
@@ -37,6 +37,8 @@
     "background.js",
     "commands.js",
     "icons/back.svg",
+    "icons/copy.svg",
+    "icons/cut.svg",
     "icons/decrement.svg",
     "icons/dictation.svg",
     "icons/increment.svg",
@@ -50,6 +52,7 @@
     "icons/moveForwardOneWordOfText.svg",
     "icons/moveUpOneLineOfText.svg",
     "icons/options.svg",
+    "icons/paste.svg",
     "icons/scrollDownOrForward.svg",
     "icons/scrollLeft.svg",
     "icons/scrollRight.svg",
diff --git a/chrome/browser/resources/chromeos/switch_access/icons/copy.svg b/chrome/browser/resources/chromeos/switch_access/icons/copy.svg
new file mode 100644
index 0000000..591966a3
--- /dev/null
+++ b/chrome/browser/resources/chromeos/switch_access/icons/copy.svg
@@ -0,0 +1,4 @@
+<!-- Copyright 2019 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<svg height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><path d="m13 16h-8v-8h-2v8c0 1.1.9 2 2 2h8zm5-4v-8c0-1.1-.9-2-2-2h-7c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h7c1.1 0 2-.9 2-2zm-2 0h-7v-8h7z" fill="#E8EAED" fill-rule="evenodd"/></svg>
diff --git a/chrome/browser/resources/chromeos/switch_access/icons/cut.svg b/chrome/browser/resources/chromeos/switch_access/icons/cut.svg
new file mode 100644
index 0000000..49ad306
--- /dev/null
+++ b/chrome/browser/resources/chromeos/switch_access/icons/cut.svg
@@ -0,0 +1,4 @@
+<!-- Copyright 2019 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<svg height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><path d="m7.70950283 6.28949254 9.79049717 9.71050746v1.5h-1.5l-6.01810633-6.0676801-2.27426466 2.2742646c.18741883.3916353.29237099.830269.29237099 1.2934155 0 1.6568542-1.34314575 3-3 3s-3-1.3431458-3-3 1.34314575-3 3-3c.46314653 0 .90178018.1049522 1.29341545.292371l2.28006551-2.2800655-2.28398842-2.30280267c-.39064059.18624442-.8278918.29049717-1.28949254.29049717-1.65685425 0-3-1.34314575-3-3s1.34314575-3 3-3 3 1.34314575 3 3c0 .46160074-.10425275.89885195-.29049717 1.28949254zm-2.70950283-.28949254c.55228475 0 1-.44771525 1-1s-.44771525-1-1-1-1 .44771525-1 1 .44771525 1 1 1zm0 10c.55228475 0 1-.4477153 1-1s-.44771525-1-1-1-1 .4477153-1 1 .44771525 1 1 1zm11-13.5h2v1l-5.4494019 5.37683105-1.4087524-1.4232788zm-6 8c.2761424 0 .5-.2238576.5-.5 0-.27614237-.2238576-.5-.5-.5-.27614237 0-.5.22385763-.5.5 0 .2761424.22385763.5.5.5z" fill="#E8EAED" fill-rule="evenodd"/></svg>
diff --git a/chrome/browser/resources/chromeos/switch_access/icons/paste.svg b/chrome/browser/resources/chromeos/switch_access/icons/paste.svg
new file mode 100644
index 0000000..b1705b5d
--- /dev/null
+++ b/chrome/browser/resources/chromeos/switch_access/icons/paste.svg
@@ -0,0 +1,4 @@
+<!-- Copyright 2019 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<svg height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><path d="m16 3h-3.18c-.42-1.16-1.52-2-2.82-2s-2.4.84-2.82 2h-3.18c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-11c0-1.1-.9-2-2-2zm-6 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm6 13h-12v-11h3v2h6v-2h3z" fill="#E8EAED" fill-rule="evenodd"/></svg>
diff --git a/chrome/browser/resources/chromeos/switch_access/menu_manager.js b/chrome/browser/resources/chromeos/switch_access/menu_manager.js
index 86e803f..bcd4c3b 100644
--- a/chrome/browser/resources/chromeos/switch_access/menu_manager.js
+++ b/chrome/browser/resources/chromeos/switch_access/menu_manager.js
@@ -326,6 +326,9 @@
         if (this.navigationManager_.selectionStarted()) {
           actions.push(SAConstants.MenuAction.SELECT_END);
         }
+        actions.push(SAConstants.MenuAction.CUT);
+        actions.push(SAConstants.MenuAction.COPY);
+        actions.push(SAConstants.MenuAction.PASTE);
       }
     } else if (actions.length > 0) {
       actions.push(SAConstants.MenuAction.SELECT);
@@ -415,12 +418,12 @@
         exitAfterAction = false;
         break;
       case SAConstants.MenuAction.SELECT_START:
-        this.navigationManager_.setSelectStart();
+        this.navigationManager_.saveSelectStart();
         this.reloadMenu_(this.navigationManager_.currentNode());
         exitAfterAction = false;
         break;
       case SAConstants.MenuAction.SELECT_END:
-        this.navigationManager_.setSelectEnd();
+        this.navigationManager_.saveSelectEnd();
         exitAfterAction = false;
         break;
       default:
diff --git a/chrome/browser/resources/chromeos/switch_access/menu_panel.html b/chrome/browser/resources/chromeos/switch_access/menu_panel.html
index f5221e2..0e80e26 100644
--- a/chrome/browser/resources/chromeos/switch_access/menu_panel.html
+++ b/chrome/browser/resources/chromeos/switch_access/menu_panel.html
@@ -93,6 +93,18 @@
       <img src="icons/textSelectionEnd.svg">
       <p class="i18n" msgid="selection_end"></p>
     </button>
+    <button class="action" id="cut">
+      <img src="icons/cut.svg">
+      <p class="i18n" msgid="cut"></p>
+    </button>
+    <button class="action" id="copy">
+      <img src="icons/copy.svg">
+      <p class="i18n" msgid="copy"></p>
+    </button>
+    <button class="action" id="paste">
+      <img src="icons/paste.svg">
+      <p class="i18n" msgid="paste"></p>
+    </button>
     <button class="action" id="dictation">
       <img src="icons/dictation.svg">
       <p class="i18n" msgid="dictation"></p>
diff --git a/chrome/browser/resources/chromeos/switch_access/navigation_manager.js b/chrome/browser/resources/chromeos/switch_access/navigation_manager.js
index 401a885..3b0dade 100644
--- a/chrome/browser/resources/chromeos/switch_access/navigation_manager.js
+++ b/chrome/browser/resources/chromeos/switch_access/navigation_manager.js
@@ -316,16 +316,16 @@
    * node.
    * @public
    */
-  setSelectStart() {
-    this.textNavigationManager_.setSelectStart();
+  saveSelectStart() {
+    this.textNavigationManager_.saveSelectStart();
   }
 
   /**
    * Sets the selectionEnd variable based on the selection of the current node.
    * @public
    */
-  setSelectEnd() {
-    this.textNavigationManager_.setSelectEnd();
+  saveSelectEnd() {
+    this.textNavigationManager_.saveSelectEnd();
   }
 
   /**
diff --git a/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings.grd b/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings.grd
index 637e823..81460004 100644
--- a/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings.grd
+++ b/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings.grd
@@ -192,6 +192,15 @@
       <message desc="The Switch Access action to set the end of a text selection area." name="IDS_SWITCH_ACCESS_SELECTION_END">
         Selection end
       </message>
+      <message desc="The Switch Access action to cut text." name="IDS_SWITCH_ACCESS_CUT">
+        Cut
+      </message>
+      <message desc="The Switch Access action to copy text." name="IDS_SWITCH_ACCESS_COPY">
+        Copy
+      </message>
+      <message desc="The Switch Access action to paste text." name="IDS_SWITCH_ACCESS_PASTE">
+        Paste
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings_grd/IDS_SWITCH_ACCESS_COPY.png.sha1 b/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings_grd/IDS_SWITCH_ACCESS_COPY.png.sha1
new file mode 100644
index 0000000..24a5ee0
--- /dev/null
+++ b/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings_grd/IDS_SWITCH_ACCESS_COPY.png.sha1
@@ -0,0 +1 @@
+d0bfb94111d9cb0774c6caccc1c776de2ed8ae5e
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings_grd/IDS_SWITCH_ACCESS_CUT.sha1 b/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings_grd/IDS_SWITCH_ACCESS_CUT.sha1
new file mode 100644
index 0000000..24a5ee0
--- /dev/null
+++ b/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings_grd/IDS_SWITCH_ACCESS_CUT.sha1
@@ -0,0 +1 @@
+d0bfb94111d9cb0774c6caccc1c776de2ed8ae5e
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings_grd/IDS_SWITCH_ACCESS_PASTE.sha1 b/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings_grd/IDS_SWITCH_ACCESS_PASTE.sha1
new file mode 100644
index 0000000..24a5ee0
--- /dev/null
+++ b/chrome/browser/resources/chromeos/switch_access/strings/switch_access_strings_grd/IDS_SWITCH_ACCESS_PASTE.sha1
@@ -0,0 +1 @@
+d0bfb94111d9cb0774c6caccc1c776de2ed8ae5e
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/switch_access/switch_access_constants.js b/chrome/browser/resources/chromeos/switch_access/switch_access_constants.js
index b694a4b..476f8ca 100644
--- a/chrome/browser/resources/chromeos/switch_access/switch_access_constants.js
+++ b/chrome/browser/resources/chromeos/switch_access/switch_access_constants.js
@@ -130,6 +130,10 @@
  * @const
  */
 SAConstants.MenuAction = {
+  // Copy text.
+  COPY: 'copy',
+  // Cut text.
+  CUT: 'cut',
   // Decrement the value of an input field.
   DECREMENT: chrome.automation.ActionType.DECREMENT,
   // Activate dictation for voice input to an editable text region.
@@ -156,6 +160,8 @@
   MOVE_UP_ONE_LINE_OF_TEXT: 'moveUpOneLineOfText',
   // Open and jump to the Switch Access settings in a new Chrome tab.
   OPTIONS: 'options',
+  // Paste text.
+  PASTE: 'paste',
   // Scroll the current element (or its ancestor) logically backwards.
   // Primarily used by ARC++ apps.
   SCROLL_BACKWARD: chrome.automation.ActionType.SCROLL_BACKWARD,
@@ -204,4 +210,4 @@
   UP_ARROW: 38,
   RIGHT_ARROW: 39,
   DOWN_ARROW: 40
-};
\ No newline at end of file
+};
diff --git a/chrome/browser/resources/chromeos/switch_access/text_navigation_manager.js b/chrome/browser/resources/chromeos/switch_access/text_navigation_manager.js
index 1cc91e1..d0771c0 100644
--- a/chrome/browser/resources/chromeos/switch_access/text_navigation_manager.js
+++ b/chrome/browser/resources/chromeos/switch_access/text_navigation_manager.js
@@ -136,24 +136,17 @@
    */
 
   /**
-   * Get the currently selected node.
-   * @private
-   * @return {!chrome.automation.AutomationNode}
-   */
-  node_() {
-    return this.navigationManager_.currentNode();
-  }
-
-  /**
    * Sets the selection using the selectionStart and selectionEnd
    * as the offset input for setDocumentSelection and the parameter
    * textNode as the object input for setDocumentSelection.
    * @private
    */
-  setSelection_() {
+  saveSelection_() {
     if (this.selectionStartIndex_ == NO_SELECT_INDEX ||
         this.selectionEndIndex_ == NO_SELECT_INDEX) {
-      console.log('Selection bounds are not set properly.');
+      console.log(
+          'Selection bounds are not set properly:', this.selectionStartIndex_,
+          this.selectionEndIndex_);
     } else {
       chrome.automation.setDocumentSelection({
         anchorObject: this.selectionStartObject_,
@@ -165,17 +158,47 @@
   }
 
   /**
+   * Returns the selection end index.
+   * @return {number}
+   * @public
+   */
+  getSelEndIndex() {
+    return this.selectionEndIndex_;
+  }
+
+  /**
    * Returns the selection start index.
+   * @return {number}
+   * @public
+   */
+  getSelStartIndex() {
+    return this.selectionStartIndex_;
+  }
+
+  /**
+   * Sets the selection start index.
+   * @param {number} startIndex
+   * @param {!chrome.automation.AutomationNode} textNode
+   * @public
+   */
+  setSelStartIndexAndNode(startIndex, textNode) {
+    this.selectionStartIndex_ = startIndex;
+    this.selectionStartObject_ = textNode;
+  }
+
+  /**
+   * Returns if the selection start index is set.
    * @return {boolean}
    * @public
    */
   isSelStartIndexSet() {
     return this.selectionStartIndex_ !== NO_SELECT_INDEX;
   }
+
   /**
    * Returns either the selection start index or the selection end index of the
    * node based on the getStart param.
-   * @param {!chrome.accessibilityPrivate.SyntheticKeyboardModifiers} node
+   * @param {!chrome.automation.AutomationNode} node
    * @param {boolean} getStart
    * @return {number} selection start if getStart is true otherwise selection
    * end
@@ -199,20 +222,25 @@
    * node.
    * @public
    */
-  setSelectStart() {
-    this.selectionStartObject_ = this.node_();
-    this.selectionStartIndex_ =
-        this.getSelectionIndexFromNode_(this.selectionStartObject_, true);
+  saveSelectStart() {
+    chrome.automation.getFocus((focusedNode) => {
+      this.selectionStartObject_ = focusedNode;
+      this.selectionStartIndex_ = this.getSelectionIndexFromNode_(
+          this.selectionStartObject_, true /*We are getting the start index.*/);
+    });
   }
 
   /**
    * Sets the selectionEnd variable based on the selection of the current node.
    * @public
    */
-  setSelectEnd() {
-    this.selectionEndObject_ = this.node_();
-    this.selectionEndIndex_ =
-        this.getSelectionIndexFromNode_(this.selectionEndObject_, false);
-    this.setSelection_();
+  saveSelectEnd() {
+    chrome.automation.getFocus((focusedNode) => {
+      this.selectionEndObject_ = focusedNode;
+      this.selectionEndIndex_ = this.getSelectionIndexFromNode_(
+          this.selectionEndObject_,
+          false /*We are not getting the start index.*/);
+      this.saveSelection_();
+    });
   }
 }
diff --git a/chrome/browser/resources/chromeos/switch_access/text_navigation_manager_test.extjs b/chrome/browser/resources/chromeos/switch_access/text_navigation_manager_test.extjs
index b039fb4..3aa924e 100644
--- a/chrome/browser/resources/chromeos/switch_access/text_navigation_manager_test.extjs
+++ b/chrome/browser/resources/chromeos/switch_access/text_navigation_manager_test.extjs
@@ -20,6 +20,8 @@
       setUp: function() {
         this.textNavigationManager =
             switchAccess.navigationManager_.textNavigationManager_;
+        this.navigationManager =
+            switchAccess.navigationManager_;
       }
     }
 
@@ -29,16 +31,7 @@
  * area, sets up the node to listen for a text navigation action, and then
  * executes the specified text navigation action. Upon detecting the
  * text navigation action, the node will verify that the action correctly
- * changed the index of the text caret. textParams should specify parameters
- * for the test as follows:
- *  -content: content of the text area.
- *  -initialIndex: index of the text caret before the navigation action.
- *  -targetIndex: index of the text caret after the navigation action.
- *  -navigationAction: function executing a text navigation action.
- *  -id: id of the text area element (optional).
- *  -cols: number of columns in the text area (optional).
- *  -wrap: the wrap attribute ("hard" or "soft") of the text area (optional).
- *
+ * changed the index of the text caret.
  * @param {!SwitchAccessE2ETest} testHelper
  * @param {{content: string,
  *          initialIndex: number,
@@ -67,8 +60,73 @@
     const inputNode = findNodeById(desktop, textId);
     assertNotEquals(inputNode, null);
 
-    setUpTextNavigationListener(
-        testHelper, inputNode, initialTextIndex, targetTextIndex);
+    setUpCursorChangeListener(
+        testHelper, inputNode, initialTextIndex, targetTextIndex, targetTextIndex);
+
+    textNavigationAction();
+  });
+}
+
+/**
+ * This function:
+ * - Generates a website with a text area
+ * - Executes setSelectStart finds the node for the text
+ * area
+ * - Sets up the node to listen for a text navigation action
+ * - executes the specified text navigation action. Upon detecting the
+ * - Verifies that the action correctly changed the index of the text caret
+ * - Sets up a second listener for a text selection action
+ * - Calls saveSelectEnd function from the event listener
+ * - Verifies that the selection was set correctly
+ * textParams should specify parameters
+ * for the test as follows:
+ *  -content: content of the text area.
+ *  -initialIndex: index of the text caret before the navigation action.
+ *  -targetStartIndex: start index of the selection after the selection action.
+ *  -targetEndIndex: end index of the selection after the navigation action.
+ *  -navigationAction: function executing a text navigation action or selection action.
+ *  -id: id of the text area element (optional).
+ *  -cols: number of columns in the text area (optional).
+ *  -wrap: the wrap attribute ("hard" or "soft") of the text area (optional).
+ *
+ * @param {!SwitchAccessE2ETest} testHelper
+ * @param {selectionTextParams} textParams,
+ */
+function runTextSelectionTest(testHelper, textParams) {
+  // Required parameters.
+  const textContent = textParams.content;
+  const initialTextIndex = textParams.initialIndex;
+  const targetTextStartIndex = textParams.targetStartIndex;
+  const targetTextEndIndex = textParams.targetEndIndex;
+  const textNavigationAction = textParams.navigationAction;
+
+  // Default parameters.
+  const selectionIsBackward = textParams.backward || false;
+  const textId = textParams.id || 'test';
+  const textCols = textParams.cols || 20;
+  const textWrap = textParams.wrap || 'soft';
+
+  const website = generateWebsiteWithTextArea(
+      textId, textContent, initialTextIndex, textCols, textWrap);
+
+  let navigationTargetIndex = targetTextEndIndex;
+  if(selectionIsBackward){
+    navigationTargetIndex = targetTextStartIndex;
+  }
+
+  testHelper.runWithLoadedTree(website, function(desktop) {
+    const inputNode = findNodeById(desktop, textId, testHelper);
+    assertNotEquals(inputNode, null);
+    checkNodeIsFocused(inputNode);
+    let callback = testHelper.newCallback(function() {
+      setUpCursorChangeListener(testHelper, inputNode, targetTextEndIndex, targetTextStartIndex, targetTextEndIndex);
+      testHelper.textNavigationManager.saveSelectEnd();
+    });
+
+    testHelper.textNavigationManager.saveSelectStart();
+
+    setUpCursorChangeListener(
+        testHelper, inputNode, initialTextIndex, navigationTargetIndex, navigationTargetIndex, callback);
 
     textNavigationAction();
   });
@@ -91,6 +149,7 @@
       const input = document.getElementById("${id}");
       input.selectionStart = ${textIndex};
       input.selectionEnd = ${textIndex};
+      input.focus();
     </script>`;
   return website;
 }
@@ -116,33 +175,54 @@
 }
 
 /**
+ * Check that the node in the JS file matches the node in the test.
+ * The nodes can be assumed to be the same if their roles match as there is only
+ * one text input node on the generated webpage.
+ * @param {!chrome.automation.AutomationNode} inputNode
+ */
+function checkNodeIsFocused(inputNode) {
+  chrome.automation.getFocus((focusedNode) => {
+      assertEquals(focusedNode.role, inputNode.role);
+    });
+}
+
+/**
  * Sets up the input node (text field) to listen for text
- * navigation actions. When the index of the text caret
+ * navigation and selection actions. When the index of the text selection
  * changes from its initial position, checks that the text
- * caret now matches the target text index. Assumes that the
- * initial and target text indices are distinct (to detect a
+ * indices now matches the target text start and end index. Assumes that the
+ * initial and target text start/end indices are distinct (to detect a
  * change from the text navigation action). Also assumes that
- * the text navigation action directly changes the text caret
+ * the text navigation and selection actions directly changes the text caret
  * to the correct index (with no intermediate movements).
  * @param {!SwitchAccessE2ETest} testHelper
  * @param {!chrome.automation.AutomationNode} inputNode
  * @param {number} initialTextIndex
- * @param {number} targetTextIndex
+ * @param {number} targetTextStartIndex
+ * @param {number} targetTextEndIndex
+ * @param {function() || undefined} callback
  */
-function setUpTextNavigationListener(
-    testHelper, inputNode, initialTextIndex, targetTextIndex) {
+function setUpCursorChangeListener( testHelper, inputNode, initialTextIndex,
+  targetTextStartIndex, targetTextEndIndex, callback) {
   // Ensures that the text index has changed before checking the new index.
   const checkActionFinished = function(tab) {
     if (inputNode.textSelStart != initialTextIndex ||
         inputNode.textSelEnd != initialTextIndex) {
       checkTextIndex();
+      if(callback) callback();
     }
   };
 
   // Test will not exit until this check is called.
   const checkTextIndex = testHelper.newCallback(function() {
-    assertEquals(inputNode.textSelStart, targetTextIndex);
-    assertEquals(inputNode.textSelEnd, targetTextIndex);
+    assertEquals(inputNode.textSelStart, targetTextStartIndex);
+    assertEquals(inputNode.textSelEnd, targetTextEndIndex);
+    // If there's a callback then this is the navigation listener for a selection
+    // test, thus remove it when fired to make way for the selection listener.
+    if (callback){
+      inputNode.removeEventListener(
+        chrome.automation.EventType.TEXT_SELECTION_CHANGED, checkActionFinished);
+    }
   });
 
   inputNode.addEventListener(
@@ -243,4 +323,107 @@
       this.textNavigationManager.moveDownOneLine()
     }
   });
-});
\ No newline at end of file
+});
+
+
+/**
+* Test the setSelectStart function by checking correct index is stored as the
+* selection start index.
+*/
+TEST_F('SwitchAccessTextNavigationManagerTest', 'DISABLED_SelectStart', function(){
+  const website = generateWebsiteWithTextArea(
+      'test', 'test123', 3, 20, 'hard');
+
+  this.runWithLoadedTree(website, function(desktop) {
+    const inputNode = findNodeById(desktop, 'test', this);
+    assertNotEquals(inputNode, null);
+    checkNodeIsFocused(inputNode);
+
+    this.textNavigationManager.saveSelectStart();
+    let startIndex = this.textNavigationManager.getSelStartIndex();
+    assertEquals(startIndex, 3)
+  });
+});
+
+/**
+* Test the setSelectEnd function by manually setting the selection start index
+* and node then calling setSelectEnd and checking for the correct selection
+* bounds
+*/
+TEST_F('SwitchAccessTextNavigationManagerTest', 'DISABLED_SelectEnd', function(){
+
+  const website = generateWebsiteWithTextArea(
+      'test', 'test 123', 6, 20, 'hard');
+
+  this.runWithLoadedTree(website, function(desktop) {
+    const inputNode = findNodeById(desktop, 'test', this);
+    assertNotEquals(inputNode, null);
+    checkNodeIsFocused(inputNode)
+
+
+    let startIndex = 3;
+    this.textNavigationManager.setSelStartIndexAndNode(startIndex, inputNode);
+    this.textNavigationManager.saveSelectEnd();
+    let endIndex = inputNode.textSelEnd;
+    assertEquals(6, endIndex);
+
+  });
+});
+
+/**
+* Test use of setSelectStart and setSelectEnd with the moveForwardOneChar function.
+*/
+TEST_F('SwitchAccessTextNavigationManagerTest', 'DISABLED_SelectCharacter', function() {
+  runTextSelectionTest(this, {
+    content: 'hello world!',
+    initialIndex: 0,
+    targetStartIndex: 0,
+    targetEndIndex: 1,
+    cols: 8,
+    wrap: 'hard',
+    navigationAction: () => {
+      this.textNavigationManager.moveForwardOneChar();
+    }
+  });
+});
+
+/**
+* Test use of setSelectStart and setSelectEnd with a backward selection using
+* the moveBackwardOneWord function.
+*/
+TEST_F('SwitchAccessTextNavigationManagerTest', 'DISABLED_SelectWordBackward', function() {
+  runTextSelectionTest(this, {
+    content: 'hello world!',
+    initialIndex: 5,
+    targetStartIndex: 0,
+    targetEndIndex: 5,
+    cols: 8,
+    wrap: 'hard',
+    navigationAction: () => {
+      this.textNavigationManager.moveBackwardOneWord();
+    },
+    backward: true
+  });
+});
+
+/**
+ * selectionTextParams should specify parameters
+ * for the test as follows:
+ *  -content: content of the text area.
+ *  -initialIndex: index of the text caret before the navigation action.
+ *  -targetIndex: index of the text caret after the navigation action.
+ *  -navigationAction: function executing a text navigation action.
+ *  -id: id of the text area element (optional).
+ *  -cols: number of columns in the text area (optional).
+ *  -wrap: the wrap attribute ("hard" or "soft") of the text area (optional).
+ *@typedef {{content: string,
+ *          initialIndex: number,
+ *          targetStartIndex: number,
+ *          targetEndIndex: number,
+ *          textAction: function(),
+ *          backward: (boolean || undefined)
+ *          id: (string || undefined),
+ *          cols: (number || undefined),
+ *          wrap: (string || undefined),}}
+ */
+let selectionTextParams;
diff --git a/chrome/browser/resources/local_ntp/customize.js b/chrome/browser/resources/local_ntp/customize.js
index 9e121e10..de3b7a76 100644
--- a/chrome/browser/resources/local_ntp/customize.js
+++ b/chrome/browser/resources/local_ntp/customize.js
@@ -54,14 +54,10 @@
   NTP_BACKGROUND_OPEN_COLLECTION: 68,
   // A image tile was selected in the richer picker.
   NTP_BACKGROUND_SELECT_IMAGE: 69,
-  // A image tile was deselected in the richer picker.
-  NTP_BACKGROUND_DESELECT_IMAGE: 70,
   // The back arrow was clicked in the richer picker.
   NTP_BACKGROUND_BACK_CLICK: 72,
   // The 'No background' tile was selected in the richer picker.
   NTP_BACKGROUND_DEFAULT_SELECTED: 73,
-  // The 'No background' tile was deselected in the richer picker.
-  NTP_BACKGROUND_DEFAULT_DESELECTED: 74,
   // The custom links option in the shortcuts submenu was clicked.
   NTP_CUSTOMIZE_SHORTCUT_CUSTOM_LINKS_CLICKED: 78,
   // The Most Visited option in the shortcuts submenu was clicked.
@@ -285,7 +281,8 @@
   // visited.
   shortcutType: null,
   shortcutsAreHidden: false,
-  colorsMenuTile: null,  // Selected tile for Colors menu.
+  colorsMenuTile: null,       // Selected tile for Colors menu.
+  backgroundsMenuTile: null,  // Selected tile for Backgrounds menu.
 };
 
 /**
@@ -790,10 +787,7 @@
             .classList.toggle(customize.CLASSES.MENU_SHOWN, true);
 
         // In the RP the upload or default tile may be selected.
-        if (configData.richerPicker) {
-          customize.richerPicker_deselectBackgroundTile(
-              customize.selectedOptions.background);
-        } else {
+        if (!configData.richerPicker) {
           customize.resetSelectionDialog();
         }
         customize.showImageSelectionDialog(
@@ -848,7 +842,7 @@
  * Return true if any option is selected. Used to enable the 'done' button.
  */
 customize.richerPicker_isOptionSelected = function() {
-  return !!customize.selectedOptions.background ||
+  return customize.isBackgroundOptionSelected() ||
       customize.isColorOptionSelected() ||
       customize.richerPicker_isShortcutOptionSelected();
 };
@@ -914,16 +908,19 @@
   // Set preview images at 720p by replacing the params in the url.
   const background = $(customize.IDS.CUSTOM_BG);
   const preview = $(customize.IDS.CUSTOM_BG_PREVIEW);
-  if (tile.id !== customize.IDS.BACKGROUNDS_DEFAULT_ICON) {
+  if (tile.id === customize.IDS.BACKGROUNDS_DEFAULT_ICON) {
+    preview.dataset.hasImage = false;
+    preview.style.backgroundImage = '';
+    preview.style.backgroundColor = document.body.style.backgroundColor;
+  } else if (tile.id === customize.IDS.BACKGROUNDS_UPLOAD_ICON) {
+    // No previews for uploaded images.
+    return;
+  } else {
     preview.dataset.hasImage = true;
 
     const re = /w\d+\-h\d+/;
     preview.style.backgroundImage =
         tile.style.backgroundImage.replace(re, 'w1280-h720');
-  } else {
-    preview.dataset.hasImage = false;
-    preview.style.backgroundImage = '';
-    preview.style.backgroundColor = document.body.style.backgroundColor;
   }
   background.style.opacity = 0;
   preview.style.opacity = 1;
@@ -960,15 +957,14 @@
     return;
   }
 
-  // Deselect any currently selected tile. If it was the clicked tile don't
-  // reselect it.
-  if (customize.selectedOptions.background) {
-    const id = customize.selectedOptions.background.id;
-    customize.richerPicker_deselectBackgroundTile(
+  if (customize.selectedOptions.background &&
+      customize.selectedOptions.background.id == tile.id) {
+    // If the clicked tile is already selected do nothing.
+    return;
+  } else if (customize.selectedOptions.background) {
+    // Deselect any currently selected tile.
+    customize.richerPicker_removeSelectedState(
         customize.selectedOptions.background);
-    if (id === tile.id) {
-      return;
-    }
   }
 
   customize.selectedOptions.background = tile;
@@ -985,22 +981,6 @@
 };
 
 /**
- * Handles background deselection. Remove selected styling from the background
- * tile, unpreview the background, and disable the done button.
- * @param {?Element} tile The background tile to deselect.
- */
-customize.richerPicker_deselectBackgroundTile = function(tile) {
-  if (!tile) {
-    return;
-  }
-  customize.selectedOptions.background = null;
-  customize.selectedOptions.backgroundData = null;
-  customize.richerPicker_removeSelectedState(tile);
-  customize.richerPicker_maybeToggleDone();
-  customize.richerPicker_unpreviewImage();
-};
-
-/**
  * Handles shortcut type selection. Apply styling to a selected shortcut option
  * and enable the done button.
  * @param {?Element} shortcutType The shortcut type option's element.
@@ -1110,10 +1090,8 @@
     }
 
     if (configData.richerPicker) {
-      if (customize.selectedOptions.backgroundData &&
-          customize.selectedOptions.backgroundData.id === tile.id) {
-        ntpApiHandle.logEvent(customize.LOG_TYPE.NTP_BACKGROUND_DESELECT_IMAGE);
-      } else {
+      if (!customize.selectedOptions.backgroundData ||
+          customize.selectedOptions.backgroundData.id !== tile.id) {
         ntpApiHandle.logEvent(customize.LOG_TYPE.NTP_BACKGROUND_SELECT_IMAGE);
       }
       customize.richerPicker_selectBackgroundTile(tile);
@@ -1203,6 +1181,8 @@
     if (selected) {
       customize.richerPicker_selectBackgroundTile(selected);
     }
+  } else {
+    customize.richerPicker_preselectBackgroundOption();
   }
 
   if (configData.richerPicker) {
@@ -1327,6 +1307,7 @@
       $(customize.IDS.BACKGROUNDS_BUTTON), $(customize.IDS.BACKGROUNDS_MENU));
 
   customize.richerPicker_preselectShortcutOptions();
+  customize.richerPicker_preselectBackgroundOption();
   customize.loadChromeBackgrounds();
   customize.loadColorsMenu();
   if (!$(customize.IDS.CUSTOMIZATION_MENU).open) {
@@ -1339,7 +1320,7 @@
  */
 customize.richerPicker_resetSelectedOptions = function() {
   // Reset background selection.
-  customize.richerPicker_deselectBackgroundTile(
+  customize.richerPicker_removeSelectedState(
       customize.selectedOptions.background);
   customize.selectedOptions.background = null;
   customize.selectedOptions.backgroundData = null;
@@ -1369,6 +1350,34 @@
 };
 
 /**
+ * Preselect the background tile that corresponds to the current page
+ * background.
+ */
+customize.richerPicker_preselectBackgroundOption = function() {
+  customize.preselectedOptions.backgroundsMenuTile = null;
+
+  const themeInfo = ntpApiHandle.themeBackgroundInfo;
+  if (!themeInfo.customBackgroundConfigured) {
+    // Default.
+    customize.preselectedOptions.backgroundsMenuTile =
+        $(customize.IDS.BACKGROUNDS_DEFAULT_ICON);
+  } else if (themeInfo.imageUrl.includes(
+                 'chrome-search://local-ntp/background.jpg')) {
+    // Local image.
+    customize.preselectedOptions.backgroundsMenuTile =
+        $(customize.IDS.BACKGROUNDS_UPLOAD_ICON);
+  } else if (!customize.selectedOptions.backgroundData) {
+    // Image tile. Only if another background hasn't already been selected.
+    customize.preselectedOptions.backgroundsMenuTile =
+        document.querySelector('[data-url="' + themeInfo.imageUrl + '"]');
+  }
+
+  customize.richerPicker_selectBackgroundTile(
+      customize.preselectedOptions.backgroundsMenuTile);
+  customize.selectedOptions.backgroundData = null;
+};
+
+/**
  * Resets the customization menu.
  */
 customize.richerPicker_resetCustomizationMenu = function() {
@@ -1456,8 +1465,6 @@
   if (configData.richerPicker) {
     ntpApiHandle.onlocalbackgroundselected = () => {
       customize.selectedOptions.backgroundData = null;
-      customize.richerPicker_deselectBackgroundTile(
-          customize.selectedOptions.background);
       customize.richerPicker_applyCustomization();
     };
   }
@@ -1875,12 +1882,8 @@
     tile.dataset.attributionLine1 = '';
     tile.dataset.attributionLine2 = '';
     tile.dataset.attributionActionUrl = '';
-    if ($(customize.IDS.BACKGROUNDS_DEFAULT)
-            .classList.contains(customize.CLASSES.SELECTED)) {
-      ntpApiHandle.logEvent(
-          customize.LOG_TYPE.NTP_BACKGROUND_DEFAULT_DESELECTED);
-      customize.richerPicker_deselectBackgroundTile(tile);
-    } else {
+    if (!$(customize.IDS.BACKGROUNDS_DEFAULT)
+             .classList.contains(customize.CLASSES.SELECTED)) {
       ntpApiHandle.logEvent(customize.LOG_TYPE.NTP_BACKGROUND_DEFAULT_SELECTED);
       customize.richerPicker_selectBackgroundTile(tile);
     }
@@ -2176,6 +2179,17 @@
 };
 
 /**
+ * Indicates whether a background tile other then the preselected one was
+ * selected on the backgrounds menu.
+ */
+customize.isBackgroundOptionSelected = function() {
+  return customize.selectedOptions.backgroundData &&
+      (!customize.preselectedOptions.backgroundsMenuTile ||
+       customize.selectedOptions.backgroundData.id !=
+           customize.preselectedOptions.backgroundsMenuTile.id);
+};
+
+/**
  * Permanently applies the color changes. Called when the done button is
  * pressed.
  */
diff --git a/chrome/browser/safe_browsing/download_protection/download_feedback_service.cc b/chrome/browser/safe_browsing/download_protection/download_feedback_service.cc
index 69679cf..c519930 100644
--- a/chrome/browser/safe_browsing/download_protection/download_feedback_service.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_feedback_service.cc
@@ -94,13 +94,9 @@
     return;
   }
 
-  UMA_HISTOGRAM_BOOLEAN("SBDownloadFeedback.UploadRequestedByServer",
-                        upload_requested);
   if (!upload_requested)
     return;
 
-  UMA_HISTOGRAM_COUNTS_1M("SBDownloadFeedback.SizeEligibleKB",
-                          download->GetReceivedBytes() / 1024);
   if (download->GetReceivedBytes() > DownloadFeedback::kMaxUploadSize)
     return;
 
@@ -138,9 +134,6 @@
     download::DownloadItem* download,
     DownloadCommands::Command download_command) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  UMA_HISTOGRAM_ENUMERATION("SBDownloadFeedback.Activations",
-                            download->GetDangerType(),
-                            download::DOWNLOAD_DANGER_TYPE_MAX);
 
   DownloadFeedbackPings* pings = DownloadFeedbackPings::FromDownload(*download);
   DCHECK(pings);
@@ -164,10 +157,7 @@
     const std::string& ping_response,
     const base::FilePath& path) {
   if (service) {
-    bool is_path_empty = path.empty();
-    UMA_HISTOGRAM_BOOLEAN("SBDownloadFeedback.EmptyFilePathFailure",
-                          is_path_empty);
-    if (is_path_empty)
+    if (path.empty())
       return;
     service->BeginFeedback(ping_request, ping_response, path);
   } else {
diff --git a/chrome/browser/services_unittest.cc b/chrome/browser/services_unittest.cc
index 441a03e..279fd5a2 100644
--- a/chrome/browser/services_unittest.cc
+++ b/chrome/browser/services_unittest.cc
@@ -7,14 +7,12 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/test/bind_test_util.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
+#include "components/services/patch/content/patch_service.h"
 #include "components/services/patch/public/mojom/file_patcher.mojom.h"
 #include "components/services/unzip/content/unzip_service.h"
 #include "components/services/unzip/public/mojom/unzipper.mojom.h"
-#include "content/public/browser/system_connector.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -25,22 +23,6 @@
       : thread_bundle_(content::TestBrowserThreadBundle::MainThreadType::IO) {}
 
   template <typename Interface>
-  bool CanAccessInterfaceFromBrowser(const std::string& service_name) {
-    mojo::InterfacePtr<Interface> interface;
-    connector()->BindInterface(service_name, mojo::MakeRequest(&interface));
-
-    // If the service is present, the interface will be connected and
-    // FlushForTesting will complete without an error on the interface.
-    // Conversely if there is a problem connecting to the interface, we will
-    // always hit the error handler before FlushForTesting returns.
-    bool encountered_error = false;
-    interface.set_connection_error_handler(
-        base::BindLambdaForTesting([&] { encountered_error = true; }));
-    interface.FlushForTesting();
-    return !encountered_error;
-  }
-
-  template <typename Interface>
   bool IsConnected(mojo::Remote<Interface>* remote) {
     bool connected = true;
     remote->set_disconnect_handler(
@@ -50,10 +32,6 @@
   }
 
  private:
-  service_manager::Connector* connector() {
-    return content::GetSystemConnector();
-  }
-
   content::TestBrowserThreadBundle thread_bundle_;
   content::InProcessUtilityThreadHelper in_process_utility_thread_helper_;
 
@@ -68,6 +46,6 @@
 }
 
 TEST_F(ServicesTest, ConnectToFilePatch) {
-  EXPECT_TRUE(CanAccessInterfaceFromBrowser<patch::mojom::FilePatcher>(
-      patch::mojom::kServiceName));
+  mojo::Remote<patch::mojom::FilePatcher> patcher(patch::LaunchFilePatcher());
+  EXPECT_TRUE(IsConnected(&patcher));
 }
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_browsertest.cc b/chrome/browser/sharing/click_to_call/click_to_call_browsertest.cc
deleted file mode 100644
index 6e105a8..0000000
--- a/chrome/browser/sharing/click_to_call/click_to_call_browsertest.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-#include <string>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/gcm/gcm_profile_service_factory.h"
-#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
-#include "chrome/browser/sharing/click_to_call/feature.h"
-#include "chrome/browser/sharing/features.h"
-#include "chrome/browser/sharing/sharing_device_info.h"
-#include "chrome/browser/sharing/sharing_device_registration_result.h"
-#include "chrome/browser/sharing/sharing_service.h"
-#include "chrome/browser/sharing/sharing_service_factory.h"
-#include "chrome/browser/sharing/sharing_sync_preference.h"
-#include "chrome/browser/sync/test/integration/sync_test.h"
-#include "chrome/browser/ui/browser.h"
-#include "components/gcm_driver/fake_gcm_profile_service.h"
-#include "components/sync/driver/sync_driver_switches.h"
-#include "url/gurl.h"
-
-namespace {
-const char kTelUrl[] = "tel:+9876543210";
-}  // namespace
-
-class ClickToCallBrowserTest : public SyncTest {
- public:
-  ClickToCallBrowserTest()
-      : SyncTest(TWO_CLIENT),
-        scoped_testing_factory_installer_(
-            base::BindRepeating(&gcm::FakeGCMProfileService::Build)) {}
-
-  ~ClickToCallBrowserTest() override {}
-
-  void SetUpOnMainThread() override {
-    SyncTest::SetUpOnMainThread();
-
-    scoped_feature_list_.InitWithFeatures(
-        {kClickToCallUI, kSharingDeviceRegistration}, {});
-
-    ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
-
-    std::unique_ptr<content::WebContents> web_contents_ptr =
-        content::WebContents::Create(
-            content::WebContents::CreateParams(GetProfile(0)));
-    web_contents = web_contents_ptr.get();
-    Browser* browser = AddBrowser(0);
-    browser->tab_strip_model()->AppendWebContents(std::move(web_contents_ptr),
-                                                  true);
-  }
-
-  content::WebContents* GetWebContents() { return web_contents; }
-
-  void SetUpDevices(int count) {
-    for (int i = 0; i < count; i++) {
-      SharingService* service =
-          SharingServiceFactory::GetForBrowserContext(GetProfile(i));
-
-      base::RunLoop run_loop;
-      service->RegisterDeviceInTesting(
-          std::string("TEST"),
-          static_cast<int>(SharingDeviceCapability::kTelephony),
-          base::BindLambdaForTesting([&](SharingDeviceRegistrationResult r) {
-            ASSERT_EQ(SharingDeviceRegistrationResult::kSuccess, r);
-            run_loop.Quit();
-          }));
-      run_loop.Run();
-    }
-  }
-
-  std::unique_ptr<TestRenderViewContextMenu> InitRightClickMenu(
-      content::WebContents* web_contents,
-      const GURL& url,
-      const base::string16& link_text) {
-    content::ContextMenuParams params;
-    params.media_type = blink::WebContextMenuData::MediaType::kMediaTypeNone;
-    params.unfiltered_link_url = url;
-    params.link_url = url;
-    params.src_url = url;
-    params.link_text = link_text;
-    params.page_url = web_contents->GetVisibleURL();
-    params.source_type = ui::MenuSourceType::MENU_SOURCE_MOUSE;
-#if defined(OS_MACOSX)
-    params.writing_direction_default = 0;
-    params.writing_direction_left_to_right = 0;
-    params.writing_direction_right_to_left = 0;
-#endif
-    auto menu = std::make_unique<TestRenderViewContextMenu>(
-        web_contents->GetMainFrame(), params);
-    menu->Init();
-    return menu;
-  }
-
-  void GetDeviceFCMToken(SharingService* sharing_service,
-                         const std::string& guid,
-                         std::string* fcm_token) const {
-    auto devices = sharing_service->GetSyncPreferences()->GetSyncedDevices();
-    auto it = devices.find(guid);
-    ASSERT_NE(devices.end(), it);
-    *fcm_token = it->second.fcm_token;
-  }
-
- private:
-  gcm::GCMProfileServiceFactory::ScopedTestingFactoryInstaller
-      scoped_testing_factory_installer_;
-  base::test::ScopedFeatureList scoped_feature_list_;
-  content::WebContents* web_contents;
-  std::vector<std::string> device_fcm_tokens_;
-  DISALLOW_COPY_AND_ASSIGN(ClickToCallBrowserTest);
-};
-
-// TODO(himanshujaju): Add UI checks. Modularize common functions.
-IN_PROC_BROWSER_TEST_F(ClickToCallBrowserTest,
-                       ContextMenu_SingleDeviceAvailable) {
-  SetUpDevices(1);
-  AwaitQuiescence();
-
-  gcm::FakeGCMProfileService* gcm_service =
-      static_cast<gcm::FakeGCMProfileService*>(
-          gcm::GCMProfileServiceFactory::GetForProfile(GetProfile(0)));
-  gcm_service->set_collect(true);
-
-  SharingService* sharing_service =
-      SharingServiceFactory::GetForBrowserContext(GetProfile(0));
-  auto devices = sharing_service->GetDeviceCandidates(
-      static_cast<int>(SharingDeviceCapability::kTelephony));
-
-  std::unique_ptr<TestRenderViewContextMenu> menu = InitRightClickMenu(
-      GetWebContents(), GURL(kTelUrl), base::ASCIIToUTF16("Google"));
-
-  // Check click to call items in context menu
-  ASSERT_TRUE(menu->IsItemPresent(
-      IDC_CONTENT_CONTEXT_SHARING_CLICK_TO_CALL_SINGLE_DEVICE));
-  EXPECT_FALSE(menu->IsItemPresent(
-      IDC_CONTENT_CONTEXT_SHARING_CLICK_TO_CALL_MULTIPLE_DEVICES));
-
-  menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SHARING_CLICK_TO_CALL_SINGLE_DEVICE,
-                       0);
-
-  // Check SharingMessage and Receiver id
-  std::string fcm_token;
-  GetDeviceFCMToken(sharing_service, devices[0].guid(), &fcm_token);
-  EXPECT_EQ(fcm_token, gcm_service->last_receiver_id());
-  chrome_browser_sharing::SharingMessage sharing_message;
-  sharing_message.ParseFromString(gcm_service->last_web_push_message().payload);
-  ASSERT_TRUE(sharing_message.has_click_to_call_message());
-  EXPECT_EQ(GURL(kTelUrl).GetContent(),
-            sharing_message.click_to_call_message().phone_number());
-}
diff --git a/chrome/browser/sharing/sharing_device_registration.cc b/chrome/browser/sharing/sharing_device_registration.cc
index 742bd145..4e7d35080 100644
--- a/chrome/browser/sharing/sharing_device_registration.cc
+++ b/chrome/browser/sharing/sharing_device_registration.cc
@@ -188,10 +188,6 @@
 }
 
 int SharingDeviceRegistration::GetDeviceCapabilities() const {
-  // Used in tests
-  if (device_capabilities_testing_value_)
-    return device_capabilities_testing_value_.value();
-
   int device_capabilities = static_cast<int>(SharingDeviceCapability::kNone);
   if (IsTelephonySupported()) {
     device_capabilities |=
@@ -210,8 +206,3 @@
 
   return false;
 }
-
-void SharingDeviceRegistration::SetDeviceCapabilityForTesting(
-    int device_capabilities) {
-  device_capabilities_testing_value_ = device_capabilities;
-}
diff --git a/chrome/browser/sharing/sharing_device_registration.h b/chrome/browser/sharing/sharing_device_registration.h
index 0b81920e..9e514bc 100644
--- a/chrome/browser/sharing/sharing_device_registration.h
+++ b/chrome/browser/sharing/sharing_device_registration.h
@@ -47,9 +47,6 @@
   // Un-registers device with sharing sync preferences.
   virtual void UnregisterDevice(RegistrationCallback callback);
 
-  // For testing
-  void SetDeviceCapabilityForTesting(int device_capabilities);
-
  private:
   FRIEND_TEST_ALL_PREFIXES(SharingDeviceRegistrationTest,
                            RegisterDeviceTest_Success);
@@ -94,7 +91,6 @@
   instance_id::InstanceIDDriver* instance_id_driver_;
   VapidKeyManager* vapid_key_manager_;
   syncer::LocalDeviceInfoProvider* local_device_info_provider_;
-  base::Optional<int> device_capabilities_testing_value_;
 
   base::WeakPtrFactory<SharingDeviceRegistration> weak_ptr_factory_{this};
 
diff --git a/chrome/browser/sharing/sharing_service.cc b/chrome/browser/sharing/sharing_service.cc
index 22abed13..4dfe5893 100644
--- a/chrome/browser/sharing/sharing_service.cc
+++ b/chrome/browser/sharing/sharing_service.cc
@@ -127,6 +127,8 @@
 
   std::unordered_set<std::string> device_names;
   std::vector<SharingDeviceInfo> device_candidates;
+  const syncer::DeviceInfo* local_device_info =
+      local_device_info_provider_->GetLocalDeviceInfo();
   for (const auto& device : all_devices) {
     // If the current device is considered expired for our purposes, stop here
     // since the next devices in the vector are at least as expired than this
@@ -134,7 +136,8 @@
     if (device->last_updated_timestamp() < min_updated_time)
       break;
 
-    if (GetDeviceName() == device->client_name()) {
+    if (local_device_info &&
+        (local_device_info->client_name() == device->client_name())) {
       continue;
     }
 
@@ -265,15 +268,6 @@
       &SharingService::OnDeviceRegistered, weak_ptr_factory_.GetWeakPtr()));
 }
 
-void SharingService::RegisterDeviceInTesting(
-    std::string device_name,
-    int capabilities,
-    SharingDeviceRegistration::RegistrationCallback callback) {
-  local_device_name_for_tests_ = std::move(device_name);
-  sharing_device_registration_->SetDeviceCapabilityForTesting(capabilities);
-  sharing_device_registration_->RegisterDevice(std::move(callback));
-}
-
 void SharingService::UnregisterDevice() {
   sharing_device_registration_->UnregisterDevice(base::BindOnce(
       &SharingService::OnDeviceUnregistered, weak_ptr_factory_.GetWeakPtr()));
@@ -364,10 +358,6 @@
          sync_service_->GetActiveDataTypes().Has(syncer::PREFERENCES);
 }
 
-SharingSyncPreference* SharingService::GetSyncPreferences() const {
-  return sync_prefs_.get();
-}
-
 bool SharingService::IsSyncDisabled() const {
   return sync_service_ &&
          (sync_service_->GetTransportState() ==
@@ -376,15 +366,3 @@
                syncer::SyncService::TransportState::ACTIVE &&
            !sync_service_->GetActiveDataTypes().Has(syncer::PREFERENCES)));
 }
-
-base::Optional<std::string> SharingService::GetDeviceName() const {
-  if (local_device_name_for_tests_)
-    return local_device_name_for_tests_;
-
-  const syncer::DeviceInfo* local_device_info =
-      local_device_info_provider_->GetLocalDeviceInfo();
-  if (local_device_info)
-    return local_device_info->client_name();
-  else
-    return base::nullopt;
-}
diff --git a/chrome/browser/sharing/sharing_service.h b/chrome/browser/sharing/sharing_service.h
index 145eb0e..fa0811b 100644
--- a/chrome/browser/sharing/sharing_service.h
+++ b/chrome/browser/sharing/sharing_service.h
@@ -98,14 +98,6 @@
   // Returns the current state of SharingService.
   virtual State GetState() const;
 
-  // For testing
-  void RegisterDeviceInTesting(
-      std::string device_name,
-      int capabilities,
-      SharingDeviceRegistration::RegistrationCallback callback);
-
-  SharingSyncPreference* GetSyncPreferences() const;
-
  private:
   // Overrides for syncer::SyncServiceObserver.
   void OnSyncShutdown(syncer::SyncService* sync) override;
@@ -115,7 +107,6 @@
   void OnAckReceived(const std::string& message_id) override;
 
   void RegisterDevice();
-
   void UnregisterDevice();
   void OnDeviceRegistered(SharingDeviceRegistrationResult result);
   void OnDeviceUnregistered(SharingDeviceRegistrationResult result);
@@ -131,10 +122,6 @@
   // in transitioning state.
   bool IsSyncDisabled() const;
 
-  // Returns |local_device_name_for_tests_| if set, otherwise returns the actual
-  // device name from |local_device_info_provider_|.
-  base::Optional<std::string> GetDeviceName() const;
-
   std::unique_ptr<SharingSyncPreference> sync_prefs_;
   std::unique_ptr<VapidKeyManager> vapid_key_manager_;
   std::unique_ptr<SharingDeviceRegistration> sharing_device_registration_;
@@ -147,7 +134,6 @@
   PingMessageHandler ping_message_handler_;
   net::BackoffEntry backoff_entry_;
   State state_;
-  base::Optional<std::string> local_device_name_for_tests_;
 
   // Map of random GUID to SendMessageCallback.
   std::map<std::string, SendMessageCallback> send_message_callbacks_;
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
index 907b8c6..c9f4f5ca 100644
--- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
+++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
@@ -108,8 +108,6 @@
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
 
-  void ProceedWithResponse() override { target_loader_->ProceedWithResponse(); }
-
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {
     target_loader_->SetPriority(priority, intra_priority_value);
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api.h b/chrome/browser/speech/extension_api/tts_engine_extension_api.h
index 9c358ea..c8c2a73 100644
--- a/chrome/browser/speech/extension_api/tts_engine_extension_api.h
+++ b/chrome/browser/speech/extension_api/tts_engine_extension_api.h
@@ -40,8 +40,7 @@
 
 // Function that allows tts engines to update its list of supported voices at
 // runtime.
-class ExtensionTtsEngineUpdateVoicesFunction
-    : public UIThreadExtensionFunction {
+class ExtensionTtsEngineUpdateVoicesFunction : public ExtensionFunction {
  private:
   ~ExtensionTtsEngineUpdateVoicesFunction() override {}
   ResponseAction Run() override;
@@ -50,8 +49,7 @@
 
 // Hidden/internal extension function used to allow TTS engine extensions
 // to send events back to the client that's calling tts.speak().
-class ExtensionTtsEngineSendTtsEventFunction
-    : public UIThreadExtensionFunction {
+class ExtensionTtsEngineSendTtsEventFunction : public ExtensionFunction {
  private:
   ~ExtensionTtsEngineSendTtsEventFunction() override {}
   ResponseAction Run() override;
diff --git a/chrome/browser/speech/extension_api/tts_extension_api.h b/chrome/browser/speech/extension_api/tts_extension_api.h
index 7caeda6..db88b08 100644
--- a/chrome/browser/speech/extension_api/tts_extension_api.h
+++ b/chrome/browser/speech/extension_api/tts_extension_api.h
@@ -27,35 +27,35 @@
   DECLARE_EXTENSION_FUNCTION("tts.speak", TTS_SPEAK)
 };
 
-class TtsStopSpeakingFunction : public UIThreadExtensionFunction {
+class TtsStopSpeakingFunction : public ExtensionFunction {
  private:
   ~TtsStopSpeakingFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tts.stop", TTS_STOP)
 };
 
-class TtsPauseFunction : public UIThreadExtensionFunction {
+class TtsPauseFunction : public ExtensionFunction {
  private:
   ~TtsPauseFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tts.pause", TTS_PAUSE)
 };
 
-class TtsResumeFunction : public UIThreadExtensionFunction {
+class TtsResumeFunction : public ExtensionFunction {
  private:
   ~TtsResumeFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tts.resume", TTS_RESUME)
 };
 
-class TtsIsSpeakingFunction : public UIThreadExtensionFunction {
+class TtsIsSpeakingFunction : public ExtensionFunction {
  private:
   ~TtsIsSpeakingFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tts.isSpeaking", TTS_ISSPEAKING)
 };
 
-class TtsGetVoicesFunction : public UIThreadExtensionFunction {
+class TtsGetVoicesFunction : public ExtensionFunction {
  private:
   ~TtsGetVoicesFunction() override {}
   ResponseAction Run() override;
diff --git a/chrome/browser/spellchecker/spelling_service_client_unittest.cc b/chrome/browser/spellchecker/spelling_service_client_unittest.cc
index c94a5e21..4631c94 100644
--- a/chrome/browser/spellchecker/spelling_service_client_unittest.cc
+++ b/chrome/browser/spellchecker/spelling_service_client_unittest.cc
@@ -157,6 +157,9 @@
   if (is_rest) {
     scoped_feature_list_.InitAndEnableFeature(
         spellcheck::kSpellingServiceRestApi);
+  } else {
+    scoped_feature_list_.InitAndDisableFeature(
+        spellcheck::kSpellingServiceRestApi);
   }
 
   PrefService* pref = profile_.GetPrefs();
diff --git a/chrome/browser/ui/views/certificate_selector.cc b/chrome/browser/ui/views/certificate_selector.cc
index 0f196d3..7940320 100644
--- a/chrome/browser/ui/views/certificate_selector.cc
+++ b/chrome/browser/ui/views/certificate_selector.cc
@@ -246,7 +246,7 @@
 }
 
 net::ClientCertIdentity* CertificateSelector::GetSelectedCert() const {
-  const int selected = table_->FirstSelectedRow();
+  const int selected = table_->GetFirstSelectedRow();
   if (selected < 0)  // Nothing is selected in |table_|.
     return nullptr;
   DCHECK_LT(static_cast<size_t>(selected), identities_.size());
@@ -254,7 +254,7 @@
 }
 
 bool CertificateSelector::Accept() {
-  const int selected = table_->FirstSelectedRow();
+  const int selected = table_->GetFirstSelectedRow();
   if (selected < 0)  // Nothing is selected in |table_|.
     return false;
 
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.cc
index e60242f..2fa68b2 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.cc
@@ -91,7 +91,7 @@
 bool DesktopMediaPickerViewsTestApi::HasSourceAtIndex(size_t index) const {
   const views::TableView* table = GetTableView();
   if (table)
-    return base::checked_cast<size_t>(table->RowCount()) > index;
+    return base::checked_cast<size_t>(table->GetRowCount()) > index;
   return bool{GetSourceAtIndex(index)};
 }
 
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list.cc
index d5301a0..fc3369a 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list.cc
@@ -162,7 +162,7 @@
   // hundreds of tabs, but don't show too few if there's only one tab because
   // the UI then looks squished.
   rows = base::ClampToRange(rows, 4, 10);
-  return gfx::Size(0, rows * child_->row_height());
+  return gfx::Size(0, rows * child_->GetRowHeight());
 }
 
 int DesktopMediaTabList::GetHeightForWidth(int width) const {
@@ -175,7 +175,7 @@
 }
 
 base::Optional<content::DesktopMediaID> DesktopMediaTabList::GetSelection() {
-  int row = child_->FirstSelectedRow();
+  int row = child_->GetFirstSelectedRow();
   if (row == -1)
     return base::nullopt;
   return controller_->GetSource(row).id;
diff --git a/chrome/browser/ui/views/device_chooser_content_view.cc b/chrome/browser/ui/views/device_chooser_content_view.cc
index 18c25098..91e47a7 100644
--- a/chrome/browser/ui/views/device_chooser_content_view.cc
+++ b/chrome/browser/ui/views/device_chooser_content_view.cc
@@ -133,7 +133,7 @@
                                                       : views::TEXT_ONLY,
       !chooser_controller_->AllowMultipleSelection() /* single_selection */);
   table_view_ = table_view.get();
-  table_view->set_select_on_remove(false);
+  table_view->SetSelectOnRemove(false);
   table_view->set_observer(table_view_observer);
 
   table_parent_ = AddChildView(
diff --git a/chrome/browser/ui/views/device_chooser_content_view_unittest.cc b/chrome/browser/ui/views/device_chooser_content_view_unittest.cc
index 4d9baf13..cce955a 100644
--- a/chrome/browser/ui/views/device_chooser_content_view_unittest.cc
+++ b/chrome/browser/ui/views/device_chooser_content_view_unittest.cc
@@ -106,7 +106,7 @@
 
   void ExpectNoDevices() {
     EXPECT_TRUE(no_options_label()->GetVisible());
-    EXPECT_EQ(0, table_view()->RowCount());
+    EXPECT_EQ(0, table_view()->GetRowCount());
     // The table should be disabled since there are no (real) options.
     EXPECT_FALSE(table_parent()->GetVisible());
     EXPECT_FALSE(table_view()->GetEnabled());
@@ -139,14 +139,14 @@
   EXPECT_CALL(table_observer(), OnSelectionChanged()).Times(0);
   AddPairedDevice();
 
-  EXPECT_EQ(1, table_view()->RowCount());
+  EXPECT_EQ(1, table_view()->GetRowCount());
   EXPECT_EQ(GetPairedDeviceTextAtRow(0), table_model()->GetText(0, 0));
   // The table should be enabled now that there's an option.
   EXPECT_TRUE(table_view()->GetEnabled());
   EXPECT_FALSE(IsDeviceSelected());
 
   AddUnpairedDevice();
-  EXPECT_EQ(2, table_view()->RowCount());
+  EXPECT_EQ(2, table_view()->GetRowCount());
   EXPECT_EQ(GetUnpairedDeviceTextAtRow(1), table_model()->GetText(1, 0));
   EXPECT_TRUE(table_view()->GetEnabled());
   EXPECT_FALSE(IsDeviceSelected());
@@ -161,7 +161,7 @@
 
   // Remove the paired device.
   controller()->RemoveDevice(0);
-  EXPECT_EQ(2, table_view()->RowCount());
+  EXPECT_EQ(2, table_view()->GetRowCount());
   EXPECT_EQ(GetUnpairedDeviceTextAtRow(0), table_model()->GetText(0, 0));
   EXPECT_EQ(GetUnpairedDeviceTextAtRow(1), table_model()->GetText(1, 0));
   EXPECT_TRUE(table_view()->GetEnabled());
@@ -185,7 +185,7 @@
       1, {"Nice Device", FakeBluetoothChooserController::CONNECTED,
           FakeBluetoothChooserController::PAIRED,
           FakeBluetoothChooserController::kSignalStrengthUnknown});
-  EXPECT_EQ(3, table_view()->RowCount());
+  EXPECT_EQ(3, table_view()->GetRowCount());
   EXPECT_EQ(GetPairedDeviceTextAtRow(1), table_model()->GetText(1, 0));
   EXPECT_FALSE(IsDeviceSelected());
 }
@@ -197,11 +197,11 @@
 
   table_view()->Select(0);
   EXPECT_TRUE(IsDeviceSelected());
-  EXPECT_EQ(0, table_view()->FirstSelectedRow());
+  EXPECT_EQ(0, table_view()->GetFirstSelectedRow());
 
   table_view()->Select(-1);
   EXPECT_FALSE(IsDeviceSelected());
-  EXPECT_EQ(-1, table_view()->FirstSelectedRow());
+  EXPECT_EQ(-1, table_view()->GetFirstSelectedRow());
 }
 
 TEST_F(DeviceChooserContentViewTest, TurnBluetoothOffAndOn) {
@@ -231,7 +231,7 @@
 TEST_F(DeviceChooserContentViewTest, ScanForDevices) {
   controller()->SetBluetoothStatus(
       FakeBluetoothChooserController::BluetoothStatus::SCANNING);
-  EXPECT_EQ(0, table_view()->RowCount());
+  EXPECT_EQ(0, table_view()->GetRowCount());
   EXPECT_FALSE(table_view()->GetEnabled());
   EXPECT_FALSE(adapter_off_help_link()->GetVisible());
   EXPECT_TRUE(throbber()->GetVisible());
@@ -239,7 +239,7 @@
   EXPECT_FALSE(re_scan_button()->GetVisible());
 
   AddUnpairedDevice();
-  EXPECT_EQ(1, table_view()->RowCount());
+  EXPECT_EQ(1, table_view()->GetRowCount());
   EXPECT_TRUE(table_view()->GetEnabled());
   EXPECT_FALSE(adapter_off_help_link()->GetVisible());
   EXPECT_TRUE(throbber()->GetVisible());
@@ -279,7 +279,7 @@
   controller()->set_table_view_always_disabled(true);
   EXPECT_FALSE(table_view()->GetEnabled());
   AddUnpairedDevice();
-  EXPECT_EQ(1, table_view()->RowCount());
+  EXPECT_EQ(1, table_view()->GetRowCount());
   // The table should still be disabled even though there's an option.
   EXPECT_FALSE(table_view()->GetEnabled());
 }
diff --git a/chrome/browser/ui/views/hats/hats_bubble_view.cc b/chrome/browser/ui/views/hats/hats_bubble_view.cc
index 07f31ca..0bd51cb 100644
--- a/chrome/browser/ui/views/hats/hats_bubble_view.cc
+++ b/chrome/browser/ui/views/hats/hats_bubble_view.cc
@@ -8,6 +8,7 @@
 #include "base/task/post_task.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/frame/app_menu_button.h"
 #include "chrome/browser/ui/views/hats/hats_web_dialog.h"
 #include "chrome/grit/chromium_strings.h"
@@ -19,8 +20,10 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/base/buildflags.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 
@@ -54,19 +57,15 @@
 
   set_close_on_deactivate(false);
   set_parent_window(parent_view);
-  set_margins(gfx::Insets());
 
-  auto* layout_manager = SetLayoutManager(std::make_unique<views::BoxLayout>(
-      views::BoxLayout::Orientation::kHorizontal, gfx::Insets(10, 20, 10, 0),
-      10));
-  layout_manager->set_cross_axis_alignment(
-      views::BoxLayout::CrossAxisAlignment::kCenter);
-  layout_manager->set_main_axis_alignment(
-      views::BoxLayout::MainAxisAlignment::kStart);
+  ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
+  set_margins(
+      provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT));
+  SetLayoutManager(std::make_unique<views::FillLayout>());
 
   auto message = std::make_unique<views::Label>(
       l10n_util::GetStringUTF16(IDS_HATS_BUBBLE_TEXT));
-  message->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
+  message->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   AddChildView(std::move(message));
 
   views::BubbleDialogDelegateView::CreateBubble(this);
@@ -80,6 +79,15 @@
   return l10n_util::GetStringUTF16(IDS_HATS_BUBBLE_TITLE);
 }
 
+gfx::ImageSkia HatsBubbleView::GetWindowIcon() {
+  return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+      IDR_PRODUCT_LOGO_32);
+}
+
+bool HatsBubbleView::ShouldShowWindowIcon() const {
+  return true;
+}
+
 base::string16 HatsBubbleView::GetDialogButtonLabel(
     ui::DialogButton button) const {
   return button == ui::DIALOG_BUTTON_OK
@@ -100,3 +108,16 @@
   BubbleDialogDelegateView::OnWidgetDestroying(widget);
   instance_ = nullptr;
 }
+
+void HatsBubbleView::Layout() {
+  auto* frame_view = GetBubbleFrameView();
+  if (frame_view && frame_view->title()) {
+    // Align bubble content to the beginning of the title text.
+    gfx::Point point(frame_view->title()->x(), 0);
+    views::View::ConvertPointToTarget(frame_view, GetWidget()->client_view(),
+                                      &point);
+    SetX(point.x());
+  }
+
+  views::BubbleDialogDelegateView::Layout();
+}
diff --git a/chrome/browser/ui/views/hats/hats_bubble_view.h b/chrome/browser/ui/views/hats/hats_bubble_view.h
index 4eac185..6baf775e 100644
--- a/chrome/browser/ui/views/hats/hats_bubble_view.h
+++ b/chrome/browser/ui/views/hats/hats_bubble_view.h
@@ -24,13 +24,22 @@
   static void Show(AppMenuButton* anchor_button, Browser* browser);
 
  protected:
-  // views::BubbleDialogDelegateView:
+  // views::WidgetDelegate:
   base::string16 GetWindowTitle() const override;
+  bool ShouldShowCloseButton() const override;
+  gfx::ImageSkia GetWindowIcon() override;
+  bool ShouldShowWindowIcon() const override;
+
+  // views::DialogDelegate:
   base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
   bool Accept() override;
-  bool ShouldShowCloseButton() const override;
+
+  // views::WidgetObserver:
   void OnWidgetDestroying(views::Widget* widget) override;
 
+  // views::View:
+  void Layout() override;
+
  private:
   HatsBubbleView(AppMenuButton* anchor_button,
                  Browser* browser,
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
index 655884a..26c345cf 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
@@ -6,7 +6,10 @@
 
 #include <memory>
 
+#include "base/metrics/user_metrics.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/extensions/hosted_app_browser_controller.h"
 #include "chrome/browser/ui/layout_constants.h"
@@ -16,6 +19,7 @@
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/hosted_app_button_container.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
+#include "chrome/grit/generated_resources.h"
 #include "components/security_interstitials/content/security_interstitial_tab_helper.h"
 #include "components/url_formatter/url_formatter.h"
 #include "components/vector_icons/vector_icons.h"
@@ -178,10 +182,11 @@
                                    LocationBarView::Delegate* delegate)
     : TabStripModelObserver(),
       delegate_(delegate),
-      tab_strip_model_observer_(this) {
-  Browser* browser = browser_view->browser();
+      tab_strip_model_observer_(this),
+      browser_(browser_view->browser()) {
+  set_context_menu_controller(this);
   base::Optional<SkColor> optional_theme_color =
-      browser->app_controller()->GetThemeColor();
+      browser_->app_controller()->GetThemeColor();
 
   // If we have a theme color, use that, otherwise fall back to the default
   // frame color.
@@ -220,7 +225,7 @@
       .SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
       .SetInteriorMargin(GetLayoutInsets(LayoutInset::TOOLBAR_INTERIOR_MARGIN));
 
-  tab_strip_model_observer_.Add(browser->tab_strip_model());
+  tab_strip_model_observer_.Add(browser_->tab_strip_model());
 }
 
 CustomTabBarView::~CustomTabBarView() {}
@@ -328,6 +333,29 @@
   SchedulePaint();
 }
 
+void CustomTabBarView::ShowContextMenuForViewImpl(
+    views::View* source,
+    const gfx::Point& point,
+    ui::MenuSourceType source_type) {
+  if (!context_menu_model_) {
+    context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
+    context_menu_model_->AddItemWithStringId(IDC_COPY_URL, IDS_COPY_URL);
+  }
+  context_menu_runner_ = std::make_unique<views::MenuRunner>(
+      context_menu_model_.get(),
+      views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU);
+  context_menu_runner_->RunMenuAt(
+      views::View::GetWidget(), nullptr, gfx::Rect(point, gfx::Size()),
+      views::MenuAnchorPosition::kTopLeft, source_type);
+}
+
+void CustomTabBarView::ExecuteCommand(int command_id, int event_flags) {
+  if (command_id == IDC_COPY_URL) {
+    base::RecordAction(base::UserMetricsAction("CopyCustomTabBarUrl"));
+    chrome::ExecuteCommand(browser_, command_id);
+  }
+}
+
 content::WebContents* CustomTabBarView::GetWebContents() {
   return delegate_->GetWebContents();
 }
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
index 19d07c5..16fe0b1 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
@@ -11,7 +11,9 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
+#include "ui/base/models/simple_menu_model.h"
 #include "ui/views/accessible_pane_view.h"
+#include "ui/views/context_menu_controller.h"
 #include "ui/views/controls/button/button.h"
 
 namespace gfx {
@@ -20,6 +22,7 @@
 
 namespace views {
 class FlexLayout;
+class MenuRunner;
 }
 
 class CustomTabBarTitleOriginView;
@@ -31,6 +34,8 @@
 // scope.
 class CustomTabBarView : public views::AccessiblePaneView,
                          public TabStripModelObserver,
+                         public ui::SimpleMenuModel::Delegate,
+                         public views::ContextMenuController,
                          public LocationIconView::Delegate,
                          public views::ButtonListener {
  public:
@@ -75,6 +80,9 @@
   base::string16 title_for_testing() const { return last_title_; }
   base::string16 location_for_testing() const { return last_location_; }
   views::Button* close_button_for_testing() const { return close_button_; }
+  ui::SimpleMenuModel* context_menu_for_testing() const {
+    return context_menu_model_.get();
+  }
   void GoBackToAppForTesting();
   bool IsShowingOriginForTesting() const;
 
@@ -87,6 +95,14 @@
   void AppInfoClosedCallback(views::Widget::ClosedReason closed_reason,
                              bool reload_prompt);
 
+  // views::SimpleMenuModel::Delegate:
+  void ExecuteCommand(int command_id, int event_flags) override;
+
+  // views::ContextMenuController:
+  void ShowContextMenuForViewImpl(View* source,
+                                  const gfx::Point& point,
+                                  ui::MenuSourceType source_type) override;
+
   SkColor title_bar_color_;
   SkColor background_color_;
 
@@ -98,6 +114,9 @@
   LocationIconView* location_icon_view_ = nullptr;
   CustomTabBarTitleOriginView* title_origin_view_ = nullptr;
   ScopedObserver<TabStripModel, CustomTabBarView> tab_strip_model_observer_;
+  std::unique_ptr<ui::SimpleMenuModel> context_menu_model_;
+  std::unique_ptr<views::MenuRunner> context_menu_runner_;
+  Browser* browser_ = nullptr;
 
   views::FlexLayout* layout_manager_;
 
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
index c5562e3..29451f4 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
@@ -3,7 +3,10 @@
 // found in the LICENSE file.
 
 #include "base/scoped_observer.h"
+#include "build/build_config.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
+#include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
@@ -23,6 +26,7 @@
 #include "content/public/test/content_mock_cert_verifier.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "net/dns/mock_host_resolver.h"
+#include "ui/base/clipboard/clipboard.h"
 
 namespace {
 
@@ -400,6 +404,44 @@
   EXPECT_EQ(other_app_url, web_contents->GetLastCommittedURL());
 }
 
+// Right-click menu on CustomTabBar should have Copy URL option.
+// TODO(crbug.com/988323): Times out on Mac.
+#if defined(OS_MACOSX)
+#define MAYBE_RightClickMenuShowsCopyUrl DISABLED_RightClickMenuShowsCopyUrl
+#else
+#define MAYBE_RightClickMenuShowsCopyUrl RightClickMenuShowsCopyUrl
+#endif
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest,
+                       MAYBE_RightClickMenuShowsCopyUrl) {
+  ASSERT_TRUE(https_server()->Start());
+
+  const GURL& app_url = https_server()->GetURL("app.com", "/ssl/google.html");
+  InstallPWA(app_url);
+
+  BrowserView* app_view = BrowserView::GetBrowserViewForBrowser(app_browser_);
+  auto* web_contents = app_view->GetActiveWebContents();
+
+  // Navigate out of scope.
+  NavigateAndWait(web_contents, GURL("http://example.test/"));
+  EXPECT_TRUE(app_controller_->ShouldShowCustomTabBar());
+
+  // Show the right-click context menu.
+  app_view->toolbar()->custom_tab_bar()->ShowContextMenu(gfx::Point(),
+                                                         ui::MENU_SOURCE_MOUSE);
+
+  content::BrowserTestClipboardScope test_clipboard_scope;
+  // Activate the first and only context menu item: IDC_COPY_URL.
+  app_view->toolbar()
+      ->custom_tab_bar()
+      ->context_menu_for_testing()
+      ->ActivatedAt(0);
+
+  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
+  base::string16 result;
+  clipboard->ReadText(ui::ClipboardType::kCopyPaste, &result);
+  EXPECT_EQ(result, base::UTF8ToUTF16("http://example.test/"));
+}
+
 // Paths above the launch url should be out of scope and should be closable from
 // the CustomTabBar.
 IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest,
diff --git a/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view.cc b/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view.cc
index df3e693..eb0603ec 100644
--- a/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view.cc
+++ b/chrome/browser/ui/views/native_file_system/native_file_system_usage_bubble_view.cc
@@ -155,7 +155,7 @@
         model, std::move(table_columns), views::ICON_AND_TEXT,
         /*single_selection=*/true);
     table_view->SetEnabled(false);
-    int row_height = table_view->row_height();
+    int row_height = table_view->GetRowHeight();
     int table_height = table_view->GetPreferredSize().height();
     table_view_parent_ = AddChildView(
         views::TableView::CreateScrollViewWithTable(std::move(table_view)));
diff --git a/chrome/browser/ui/views/task_manager_view.cc b/chrome/browser/ui/views/task_manager_view.cc
index 9ac2c30..9177d72 100644
--- a/chrome/browser/ui/views/task_manager_view.cc
+++ b/chrome/browser/ui/views/task_manager_view.cc
@@ -122,7 +122,7 @@
 }
 
 bool TaskManagerView::IsTableSorted() const {
-  return tab_table_->is_sorted();
+  return tab_table_->GetIsSorted();
 }
 
 TableSortDescriptor TaskManagerView::GetSortDescriptor() const {
@@ -328,7 +328,7 @@
   table_model_.reset(new TaskManagerTableModel(this));
   tab_table->SetModel(table_model_.get());
   tab_table->SetGrouper(this);
-  tab_table->set_sort_on_paint(true);
+  tab_table->SetSortOnPaint(true);
   tab_table->set_observer(this);
   tab_table->set_context_menu_controller(this);
   set_context_menu_controller(this);
diff --git a/chrome/browser/ui/views/task_manager_view_browsertest.cc b/chrome/browser/ui/views/task_manager_view_browsertest.cc
index a8090b6..a2550ab4 100644
--- a/chrome/browser/ui/views/task_manager_view_browsertest.cc
+++ b/chrome/browser/ui/views/task_manager_view_browsertest.cc
@@ -139,7 +139,7 @@
   views::TableView* table = GetTable();
   ASSERT_TRUE(table);
 
-  EXPECT_FALSE(table->is_sorted());
+  EXPECT_FALSE(table->GetIsSorted());
   for (size_t i = 0; i < kColumnsSize; ++i) {
     EXPECT_EQ(kColumns[i].default_visibility,
               table->IsColumnVisible(kColumns[i].id));
@@ -158,7 +158,7 @@
   ASSERT_TRUE(table);
 
   // Toggle the visibility of all columns.
-  EXPECT_FALSE(table->is_sorted());
+  EXPECT_FALSE(table->GetIsSorted());
   for (size_t i = 0; i < kColumnsSize; ++i) {
     EXPECT_EQ(kColumns[i].default_visibility,
               table->IsColumnVisible(kColumns[i].id));
@@ -181,7 +181,7 @@
   }
 
   if (is_sorted) {
-    EXPECT_TRUE(table->is_sorted());
+    EXPECT_TRUE(table->GetIsSorted());
     EXPECT_FALSE(table->sort_descriptors().front().ascending);
     EXPECT_EQ(table->sort_descriptors().front().column_id, sorted_col_id);
   }
@@ -198,7 +198,7 @@
   ASSERT_TRUE(table);
 
   if (is_sorted) {
-    EXPECT_TRUE(table->is_sorted());
+    EXPECT_TRUE(table->GetIsSorted());
     EXPECT_FALSE(table->sort_descriptors().front().ascending);
     EXPECT_EQ(table->sort_descriptors().front().column_id, sorted_col_id);
   }
@@ -223,14 +223,14 @@
   chrome::ShowTaskManager(browser());
 
   EXPECT_EQ(1UL, GetTable()->selection_model().size());
-  EXPECT_EQ(GetTable()->FirstSelectedRow(),
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(),
             FindRowForTab(browser()->tab_strip_model()->GetWebContentsAt(1)));
 
   // Activate tab 0. The selection should not change.
   browser()->tab_strip_model()->ActivateTabAt(
       0, {TabStripModel::GestureType::kOther});
   EXPECT_EQ(1UL, GetTable()->selection_model().size());
-  EXPECT_EQ(GetTable()->FirstSelectedRow(),
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(),
             FindRowForTab(browser()->tab_strip_model()->GetWebContentsAt(1)));
 
   // If the user re-triggers chrome::ShowTaskManager (e.g. via shift-esc), this
@@ -238,7 +238,7 @@
   chrome::ShowTaskManager(browser());
 
   EXPECT_EQ(1UL, GetTable()->selection_model().size());
-  EXPECT_EQ(GetTable()->FirstSelectedRow(),
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(),
             FindRowForTab(browser()->tab_strip_model()->GetWebContentsAt(0)));
 }
 
@@ -282,33 +282,33 @@
 
   // Select the middle row, and store its tab id.
   GetTable()->Select(FindRowForTab(tabs[1]));
-  EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1]));
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[1]));
   EXPECT_EQ(1UL, GetTable()->selection_model().size());
 
   // Add 3 rows above the selection. The selected tab should not change.
   for (int i = 0; i < 3; ++i) {
     ASSERT_TRUE(content::ExecuteScript(tabs[0], "window.open('title3.html');"));
-    EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1]));
+    EXPECT_EQ(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[1]));
   }
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows((rows += 3), pattern));
-  EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1]));
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[1]));
   EXPECT_EQ(1UL, GetTable()->selection_model().size());
 
   // Add 2 rows below the selection. The selected tab should not change.
   for (int i = 0; i < 2; ++i) {
     ASSERT_TRUE(content::ExecuteScript(tabs[2], "window.open('title3.html');"));
-    EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1]));
+    EXPECT_EQ(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[1]));
   }
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows((rows += 2), pattern));
-  EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1]));
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[1]));
   EXPECT_EQ(1UL, GetTable()->selection_model().size());
 
   // Add a new row in the same process as the selection. The selected tab should
   // not change.
   ASSERT_TRUE(content::ExecuteScript(tabs[1], "window.open('title3.html');"));
-  EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1]));
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[1]));
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows((rows += 1), pattern));
-  EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1]));
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[1]));
   EXPECT_EQ(1UL, GetTable()->selection_model().size());
 
   {
@@ -324,8 +324,8 @@
   // A later row should now be selected. The selection should be after the 4
   // rows sharing the tabs[0] process, and it should be at or before
   // the tabs[2] row.
-  ASSERT_LT(FindRowForTab(tabs[0]) + 3, GetTable()->FirstSelectedRow());
-  ASSERT_LE(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[2]));
+  ASSERT_LT(FindRowForTab(tabs[0]) + 3, GetTable()->GetFirstSelectedRow());
+  ASSERT_LE(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[2]));
 
   // Now select tabs[2].
   GetTable()->Select(FindRowForTab(tabs[2]));
@@ -337,12 +337,12 @@
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows((rows += 1), pattern));
 
   // tabs[2] should still be selected.
-  EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[2]));
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[2]));
 
   // Close tabs[0]. The selection should not change.
   chrome::CloseWebContents(browser(), tabs[0], false);
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows((rows -= 1), pattern));
-  EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[2]));
+  EXPECT_EQ(GetTable()->GetFirstSelectedRow(), FindRowForTab(tabs[2]));
 }
 
 // Make sure the task manager's bounds are saved across instances on Chrome OS.
diff --git a/chrome/browser/win/chrome_elf_init.cc b/chrome/browser/win/chrome_elf_init.cc
index ef3ae4c..e0302d80 100644
--- a/chrome/browser/win/chrome_elf_init.cc
+++ b/chrome/browser/win/chrome_elf_init.cc
@@ -9,13 +9,12 @@
 #include "base/bind.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "base/win/registry.h"
-#include "chrome/chrome_elf/blacklist/blacklist.h"
 #include "chrome/chrome_elf/chrome_elf_constants.h"
 #include "chrome/chrome_elf/dll_hash/dll_hash.h"
+#include "chrome/chrome_elf/third_party_dlls/public_api.h"
 #include "chrome/common/chrome_version.h"
 #include "chrome/install_static/install_util.h"
 #include "components/variations/variations_associated_data.h"
@@ -59,9 +58,9 @@
 };
 
 void RecordBlacklistSetupEvent(BlacklistSetupEventType blacklist_setup_event) {
-  UMA_HISTOGRAM_ENUMERATION("Blacklist.Setup",
-                            blacklist_setup_event,
-                            BLACKLIST_SETUP_EVENT_MAX);
+  base::UmaHistogramEnumeration("ChromeElf.Beacon.SetupStatus",
+                                blacklist_setup_event,
+                                BLACKLIST_SETUP_EVENT_MAX);
 }
 
 base::string16 GetBeaconRegistryPath() {
@@ -117,7 +116,7 @@
 
   if (blacklist_state == blacklist::BLACKLIST_ENABLED) {
     // The blacklist setup didn't crash, so we report if it was enabled or not.
-    if (blacklist::IsBlacklistInitialized()) {
+    if (IsThirdPartyInitialized()) {
       RecordBlacklistSetupEvent(BLACKLIST_SETUP_RAN_SUCCESSFULLY);
     } else {
       // The only way for the blacklist to be enabled, but not fully
@@ -131,7 +130,8 @@
     DWORD attempt_count = 0;
     blacklist_registry_key.ReadValueDW(blacklist::kBeaconAttemptCount,
                                        &attempt_count);
-    UMA_HISTOGRAM_COUNTS_100("Blacklist.RetryAttempts.Success", attempt_count);
+    base::UmaHistogramCounts100("ChromeElf.Beacon.RetryAttemptsBeforeSuccess",
+                                attempt_count);
   } else if (blacklist_state == blacklist::BLACKLIST_SETUP_FAILED) {
     // We can set the state to disabled without checking that the maximum number
     // of attempts was exceeded because blacklist.cc has already done this.
diff --git a/chrome/chrome_cleaner/OWNERS b/chrome/chrome_cleaner/OWNERS
index 243cdd33..6459769 100644
--- a/chrome/chrome_cleaner/OWNERS
+++ b/chrome/chrome_cleaner/OWNERS
@@ -1,4 +1,3 @@
-csharp@chromium.org
 joenotcharles@google.com
 proberge@chromium.org
 
diff --git a/chrome/chrome_cleaner/ipc/sandbox.cc b/chrome/chrome_cleaner/ipc/sandbox.cc
index 9afa86e4..154bd05 100644
--- a/chrome/chrome_cleaner/ipc/sandbox.cc
+++ b/chrome/chrome_cleaner/ipc/sandbox.cc
@@ -44,8 +44,11 @@
 
 // Switches to propagate to the sandbox target process.
 const char* kSwitchesToPropagate[] = {
-    kEnableCrashReportingSwitch, kExecutionModeSwitch,
-    kExtendedSafeBrowsingEnabledSwitch, switches::kTestChildProcess,
+    kEnableCrashReportingSwitch,
+    kExecutionModeSwitch,
+    kExtendedSafeBrowsingEnabledSwitch,
+    switches::kTestChildProcess,
+    kTestingSwitch,
 };
 
 std::map<SandboxType, base::Process>* g_target_processes = nullptr;  // Leaked.
diff --git a/chrome/chrome_elf/BUILD.gn b/chrome/chrome_elf/BUILD.gn
index 9c59c4b..8d2c7b1 100644
--- a/chrome/chrome_elf/BUILD.gn
+++ b/chrome/chrome_elf/BUILD.gn
@@ -119,6 +119,7 @@
   deps = [
     ":constants",
     ":nt_registry",
+    ":third_party_dlls",
     "//chrome/install_static:install_static_util",
   ]
 }
@@ -234,6 +235,10 @@
 static_library("third_party_dlls") {
   visibility = [ ":*" ]  # Only targets in this file can depend on this.
   sources = [
+    "third_party_dlls/beacon.cc",
+    "third_party_dlls/beacon.h",
+    "third_party_dlls/hardcoded_blocklist.cc",
+    "third_party_dlls/hardcoded_blocklist.h",
     "third_party_dlls/hook.cc",
     "third_party_dlls/hook.h",
     "third_party_dlls/logs.cc",
@@ -244,7 +249,7 @@
     "third_party_dlls/packed_list_file.h",
   ]
   public_deps = [
-    ":blacklist",
+    ":constants",
     ":crash",
     ":hook_util",
     ":nt_registry",
@@ -278,13 +283,13 @@
 test("chrome_elf_unittests") {
   output_name = "chrome_elf_unittests"
   sources = [
-    "blacklist/test/blacklist_test.cc",
     "chrome_elf_util_unittest.cc",
     "hook_util/test/hook_util_test.cc",
     "nt_registry/nt_registry_unittest.cc",
     "pe_image_safe/pe_image_safe_unittest.cc",
     "run_all_unittests.cc",
     "sha1/sha1_unittest.cc",
+    "third_party_dlls/beacon_unittest.cc",
     "third_party_dlls/logs_unittest.cc",
     "third_party_dlls/main_unittest.cc",
     "third_party_dlls/main_unittest_exe.h",
diff --git a/chrome/chrome_elf/DEPS b/chrome/chrome_elf/DEPS
index 8beca0c0..7e168ba 100644
--- a/chrome/chrome_elf/DEPS
+++ b/chrome/chrome_elf/DEPS
@@ -2,7 +2,6 @@
   "+chrome/app/chrome_crash_reporter_client_win.h",
   "+chrome/chrome_elf",
   "+chrome/common/chrome_switches.h",
-  "+chrome/common/chrome_version.h",
   "+chrome/install_static",
   "+components/crash/content/app/crashpad.h",
   "+components/crash/core/common/crash_keys.h",
diff --git a/chrome/chrome_elf/blacklist/blacklist.cc b/chrome/chrome_elf/blacklist/blacklist.cc
index 2d174ad9..7752992 100644
--- a/chrome/chrome_elf/blacklist/blacklist.cc
+++ b/chrome/chrome_elf/blacklist/blacklist.cc
@@ -4,174 +4,29 @@
 
 #include "chrome/chrome_elf/blacklist/blacklist.h"
 
+#include <windows.h>
+
 #include <assert.h>
 #include <string.h>
 
-#include "chrome/chrome_elf/chrome_elf_constants.h"
-#include "chrome/chrome_elf/nt_registry/nt_registry.h"
-#include "chrome/install_static/install_util.h"
+#include "chrome/chrome_elf/third_party_dlls/hardcoded_blocklist.h"
 
 namespace blacklist {
+
 namespace {
 
 // Record if the blacklist was successfully initialized so processes can easily
 // determine if the blacklist is enabled for them.
 bool g_blacklist_initialized = false;
 
-// Utility function for converting UTF-8 to UTF-16.
-bool UTF8ToUTF16(const std::string& utf8, std::wstring* utf16) {
-  assert(utf16);
-
-  if (utf8.empty()) {
-    utf16->clear();
-    return true;
-  }
-
-  int size_needed_chars = ::MultiByteToWideChar(
-      CP_UTF8, 0, utf8.c_str(), static_cast<int>(utf8.size()), nullptr, 0);
-  if (!size_needed_chars)
-    return false;
-
-  utf16->resize(size_needed_chars);
-  return ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(),
-                               static_cast<int>(utf8.size()), &(*utf16)[0],
-                               size_needed_chars);
-}
 }  // namespace
 
-// The DLLs listed here are known (or under strong suspicion) of causing crashes
-// when they are loaded in the browser. DLLs should only be added to this list
-// if there is nothing else Chrome can do to prevent those crashes.
-// For more information about how this list is generated, and how to get off
-// of it, see:
-// https://sites.google.com/a/chromium.org/dev/Home/third-party-developers
-const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount] = {
-    L"949ba8b6a9.dll",           // Coupon Time.
-    L"activedetect32.dll",       // Lenovo One Key Theater.
-                                 // See crbug.com/379218.
-    L"activedetect64.dll",       // Lenovo One Key Theater.
-    L"bitguard.dll",             // Unknown (suspected malware).
-    L"bsvc.dll",                 // Unknown (suspected adware).
-    L"chrmxtn.dll",              // Unknown (keystroke logger).
-    L"cplushook.dll",            // Unknown (suspected malware).
-    L"crdli.dll",                // Linkury Inc.
-    L"crdli64.dll",              // Linkury Inc.
-    L"datamngr.dll",             // Unknown (suspected adware).
-    L"dpinterface32.dll",        // Unknown (suspected adware).
-    L"explorerex.dll",           // Unknown (suspected adware).
-    L"hk.dll",                   // Unknown (keystroke logger).
-    L"libapi2hook.dll",          // V-Bates.
-    L"libinject.dll",            // V-Bates.
-    L"libinject2.dll",           // V-Bates.
-    L"libredir2.dll",            // V-Bates.
-    L"libsvn_tsvn32.dll",        // TortoiseSVN.
-    L"libwinhook.dll",           // V-Bates.
-    L"lmrn.dll",                 // Unknown.
-    L"minisp.dll",               // Unknown (suspected malware).
-    L"minisp32.dll",             // Unknown (suspected malware).
-    L"offerswizarddll.dll",      // Unknown (suspected adware).
-    L"safetynut.dll",            // Unknown (suspected adware).
-    L"smdmf.dll",                // Unknown (suspected adware).
-    L"spappsv32.dll",            // Unknown (suspected adware).
-    L"systemk.dll",              // Unknown (suspected adware).
-    L"vntsrv.dll",               // Virtual New Tab by APN LLC.
-    L"wajam_goblin_64.dll",      // Wajam Internet Technologies.
-    L"wajam_goblin.dll",         // Wajam Internet Technologies.
-    L"windowsapihookdll32.dll",  // Lenovo One Key Theater.
-                                 // See crbug.com/379218.
-    L"windowsapihookdll64.dll",  // Lenovo One Key Theater.
-    L"virtualcamera.ax",         // %PROGRAMFILES%\ASUS\VirtualCamera.
-                                 // See crbug.com/422522.
-    L"ycwebcamerasource.ax",     // CyberLink Youcam, crbug.com/424159
-    // Keep this null pointer here to mark the end of the list.
-    NULL,
-};
+using third_party_dlls::g_troublesome_dlls;
+using third_party_dlls::kTroublesomeDllsMaxCount;
 
 bool g_blocked_dlls[kTroublesomeDllsMaxCount] = {};
 int g_num_blocked_dlls = 0;
 
-bool LeaveSetupBeacon() {
-  HANDLE key_handle = INVALID_HANDLE_VALUE;
-
-  if (!nt::CreateRegKey(nt::HKCU,
-                        install_static::GetRegistryPath()
-                            .append(kRegistryBeaconKeyName)
-                            .c_str(),
-                        KEY_QUERY_VALUE | KEY_SET_VALUE, &key_handle))
-    return false;
-
-  DWORD blacklist_state = BLACKLIST_STATE_MAX;
-  if (!nt::QueryRegValueDWORD(key_handle, kBeaconState, &blacklist_state) ||
-      blacklist_state == BLACKLIST_DISABLED) {
-    nt::CloseRegKey(key_handle);
-    return false;
-  }
-
-  // Handle attempt count.
-  // Only return true if BL is enabled and succeeded on previous run.
-  bool success = false;
-  if (blacklist_state == BLACKLIST_ENABLED) {
-    // If the blacklist succeeded on the previous run reset the failure
-    // counter.  Then update the beacon state.
-    if (nt::SetRegValueDWORD(key_handle, kBeaconAttemptCount,
-                             static_cast<DWORD>(0))) {
-      if (nt::SetRegValueDWORD(key_handle, kBeaconState,
-                               BLACKLIST_SETUP_RUNNING))
-        success = true;
-    }
-  } else {
-    // Some part of the blacklist setup failed last time.  If this has occured
-    // blacklist::kBeaconMaxAttempts times in a row we switch the state to
-    // failed and skip setting up the blacklist.
-    DWORD attempt_count = 0;
-
-    nt::QueryRegValueDWORD(key_handle, blacklist::kBeaconAttemptCount,
-                           &attempt_count);
-    ++attempt_count;
-    nt::SetRegValueDWORD(key_handle, blacklist::kBeaconAttemptCount,
-                         attempt_count);
-
-    if (attempt_count >= blacklist::kBeaconMaxAttempts) {
-      blacklist_state = blacklist::BLACKLIST_SETUP_FAILED;
-      nt::SetRegValueDWORD(key_handle, blacklist::kBeaconState,
-                           blacklist_state);
-    }
-  }
-
-  nt::CloseRegKey(key_handle);
-  return success;
-}
-
-bool ResetBeacon() {
-  HANDLE key_handle = INVALID_HANDLE_VALUE;
-
-  if (!nt::CreateRegKey(nt::HKCU,
-                        install_static::GetRegistryPath()
-                            .append(kRegistryBeaconKeyName)
-                            .c_str(),
-                        KEY_QUERY_VALUE | KEY_SET_VALUE, &key_handle))
-    return false;
-
-  DWORD blacklist_state = BLACKLIST_STATE_MAX;
-  if (!nt::QueryRegValueDWORD(key_handle, kBeaconState, &blacklist_state)) {
-    nt::CloseRegKey(key_handle);
-    return false;
-  }
-
-  // Reaching this point with the setup running state means the setup did not
-  // crash, so we reset to enabled.  Any other state indicates that setup was
-  // skipped; in that case we leave the state alone for later recording.
-  if (blacklist_state == BLACKLIST_SETUP_RUNNING) {
-    if (!nt::SetRegValueDWORD(key_handle, kBeaconState, BLACKLIST_ENABLED)) {
-      nt::CloseRegKey(key_handle);
-      return false;
-    }
-  }
-
-  nt::CloseRegKey(key_handle);
-  return true;
-}
-
 int BlacklistSize() {
   int size = -1;
   while (blacklist::g_troublesome_dlls[++size] != NULL) {
@@ -269,30 +124,4 @@
   return -1;
 }
 
-bool DllMatch(const std::string& module_name) {
-  if (module_name.empty())
-    return false;
-
-  // Convert UTF-8 to UTF-16 for this comparison.
-  std::wstring wide_string;
-  if (!UTF8ToUTF16(module_name, &wide_string)) {
-    return false;
-  }
-
-  return DllMatch(wide_string) != -1;
-}
-
-bool Initialize(bool force) {
-  // Check to see if this is a non-browser process, abort if so.
-  if (install_static::IsNonBrowserProcess())
-    return false;
-
-  // Check to see if the blacklist beacon is still set to running (indicating a
-  // failure) or disabled, and abort if so.
-  if (!force && !LeaveSetupBeacon())
-    return false;
-
-  return true;
-}
-
 }  // namespace blacklist
diff --git a/chrome/chrome_elf/blacklist/blacklist.h b/chrome/chrome_elf/blacklist/blacklist.h
index 24d6efa9..f2f9d8d 100644
--- a/chrome/chrome_elf/blacklist/blacklist.h
+++ b/chrome/chrome_elf/blacklist/blacklist.h
@@ -11,25 +11,6 @@
 
 namespace blacklist {
 
-// Max size of the DLL blacklist.
-const size_t kTroublesomeDllsMaxCount = 64;
-
-// The DLL blacklist.
-extern const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount];
-
-// Attempts to leave a beacon in the current user's registry hive. If the
-// blacklist beacon doesn't say it is enabled or there are any other errors when
-// creating the beacon, returns false. Otherwise returns true. The intent of the
-// beacon is to act as an extra failure mode protection whereby if Chrome
-// repeatedly fails to start during blacklist setup, it will skip blacklisting
-// on the subsequent run.
-bool LeaveSetupBeacon();
-
-// Looks for the setup running beacon that LeaveSetupBeacon() creates and resets
-// it to to show the setup was successful.
-// Returns true if the beacon was successfully set to BLACKLIST_ENABLED.
-bool ResetBeacon();
-
 // Return the size of the current blacklist.
 extern "C" int BlacklistSize();
 
@@ -63,16 +44,6 @@
 // Returns the index of the blacklist found in |g_troublesome_dlls|, or -1.
 int DllMatch(const std::wstring& module_name);
 
-// New wrapper for above match function.
-// Returns true if a matching name is found in the legacy blacklist.
-// Note: |module_name| must be an ASCII encoded string.
-bool DllMatch(const std::string& module_name);
-
-// Initializes the deprecated DLL blacklist in the current process.
-// - If |force| is set to true, then initialization will take place even if a
-//   beacon is present. This is useful for tests.
-bool Initialize(bool force);
-
 }  // namespace blacklist
 
 #endif  // CHROME_CHROME_ELF_BLACKLIST_BLACKLIST_H_
diff --git a/chrome/chrome_elf/chrome_elf_arm64.def b/chrome/chrome_elf/chrome_elf_arm64.def
index 46e51af..1da85bc4 100644
--- a/chrome/chrome_elf/chrome_elf_arm64.def
+++ b/chrome/chrome_elf/chrome_elf_arm64.def
@@ -43,3 +43,6 @@
   ; From chrome/chrome_elf/third_party_dlls/hook.cc
   DisableHook
   GetApplyHookResult
+
+  ; From chrome/chrome_elf/third_party_dlls/main.cc
+  IsThirdPartyInitialized
diff --git a/chrome/chrome_elf/chrome_elf_main.cc b/chrome/chrome_elf/chrome_elf_main.cc
index c6cd0c8..4006acf 100644
--- a/chrome/chrome_elf/chrome_elf_main.cc
+++ b/chrome/chrome_elf/chrome_elf_main.cc
@@ -7,9 +7,9 @@
 #include <assert.h>
 #include <windows.h>
 
-#include "chrome/chrome_elf/blacklist/blacklist.h"
 #include "chrome/chrome_elf/chrome_elf_security.h"
 #include "chrome/chrome_elf/crash/crash_helper.h"
+#include "chrome/chrome_elf/third_party_dlls/beacon.h"
 #include "chrome/chrome_elf/third_party_dlls/main.h"
 #include "chrome/install_static/install_details.h"
 #include "chrome/install_static/install_util.h"
@@ -28,7 +28,7 @@
 }
 
 void SignalChromeElf() {
-  blacklist::ResetBeacon();
+  third_party_dlls::ResetBeacon();
 }
 
 bool GetUserDataDirectoryThunk(wchar_t* user_data_dir,
@@ -75,10 +75,9 @@
     elf_security::EarlyBrowserSecurity();
 
     __try {
-      // Initialize blacklist before initializing third_party_dlls.
-      // Note: "blacklist" is deprecated in favor of "third_party_dlls", but
-      //       beacon management temporarily remains in the blacklist project.
-      if (blacklist::Initialize(false))
+      // Initialize the blocking of third-party DLLs if the initialization of
+      // the safety beacon succeeds.
+      if (third_party_dlls::LeaveSetupBeacon())
         third_party_dlls::Init();
     } __except (elf_crash::GenerateCrashDump(GetExceptionInformation())) {
     }
diff --git a/chrome/chrome_elf/chrome_elf_test_stubs.cc b/chrome/chrome_elf/chrome_elf_test_stubs.cc
index 0229940..0dc7ef4 100644
--- a/chrome/chrome_elf/chrome_elf_test_stubs.cc
+++ b/chrome/chrome_elf/chrome_elf_test_stubs.cc
@@ -46,6 +46,10 @@
 // - Stubs should shadow third_party_dlls\public_api.h and logs_unittest.cc.
 //------------------------------------------------------------------------------
 
+bool IsThirdPartyInitialized() {
+  return false;
+}
+
 struct TestLogEntry {
   third_party_dlls::LogType log_type;
   uint32_t module_size;
diff --git a/chrome/chrome_elf/chrome_elf_x64.def b/chrome/chrome_elf/chrome_elf_x64.def
index f9f62f7..bda181c 100644
--- a/chrome/chrome_elf/chrome_elf_x64.def
+++ b/chrome/chrome_elf/chrome_elf_x64.def
@@ -43,3 +43,6 @@
   ; From chrome/chrome_elf/third_party_dlls/hook.cc
   DisableHook
   GetApplyHookResult
+
+  ; From chrome/chrome_elf/third_party_dlls/main.cc
+  IsThirdPartyInitialized
diff --git a/chrome/chrome_elf/chrome_elf_x86.def b/chrome/chrome_elf/chrome_elf_x86.def
index 6fe6b75..238b4ca 100644
--- a/chrome/chrome_elf/chrome_elf_x86.def
+++ b/chrome/chrome_elf/chrome_elf_x86.def
@@ -43,3 +43,6 @@
   ; From chrome/chrome_elf/third_party_dlls/hook.cc
   DisableHook
   GetApplyHookResult
+
+  ; From chrome/chrome_elf/third_party_dlls/main.cc
+  IsThirdPartyInitialized
diff --git a/chrome/chrome_elf/third_party_dlls/DEPS b/chrome/chrome_elf/third_party_dlls/DEPS
index 1bf966fc..e8a67bd 100644
--- a/chrome/chrome_elf/third_party_dlls/DEPS
+++ b/chrome/chrome_elf/third_party_dlls/DEPS
@@ -5,6 +5,7 @@
   "-chrome",
   "+chrome/install_static",
   "+chrome/chrome_elf/blacklist/blacklist.h",
+  "+chrome/chrome_elf/chrome_elf_constants.h",
   "+chrome/chrome_elf/crash/crash_helper.h",
   "+chrome/chrome_elf/hook_util/hook_util.h",
   "+chrome/chrome_elf/nt_registry/nt_registry.h",
diff --git a/chrome/chrome_elf/third_party_dlls/beacon.cc b/chrome/chrome_elf/third_party_dlls/beacon.cc
new file mode 100644
index 0000000..41a7bf1
--- /dev/null
+++ b/chrome/chrome_elf/third_party_dlls/beacon.cc
@@ -0,0 +1,99 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_elf/third_party_dlls/beacon.h"
+
+#include "chrome/chrome_elf/chrome_elf_constants.h"
+#include "chrome/chrome_elf/nt_registry/nt_registry.h"
+#include "chrome/install_static/install_util.h"
+
+namespace third_party_dlls {
+
+bool LeaveSetupBeacon() {
+  HANDLE key_handle = INVALID_HANDLE_VALUE;
+
+  if (!nt::CreateRegKey(nt::HKCU,
+                        install_static::GetRegistryPath()
+                            .append(blacklist::kRegistryBeaconKeyName)
+                            .c_str(),
+                        KEY_QUERY_VALUE | KEY_SET_VALUE, &key_handle)) {
+    return false;
+  }
+
+  DWORD blocking_state = blacklist::BLACKLIST_STATE_MAX;
+  if (!nt::QueryRegValueDWORD(key_handle, blacklist::kBeaconState,
+                              &blocking_state) ||
+      blocking_state == blacklist::BLACKLIST_DISABLED) {
+    nt::CloseRegKey(key_handle);
+    return false;
+  }
+
+  // Handle attempt count.
+  // Only return true if BL is enabled and succeeded on previous run.
+  bool success = false;
+  if (blocking_state == blacklist::BLACKLIST_ENABLED) {
+    // If the blocking was successfully initialized on the previous run, reset
+    // the failure counter. Then update the beacon state.
+    if (nt::SetRegValueDWORD(key_handle, blacklist::kBeaconAttemptCount,
+                             static_cast<DWORD>(0))) {
+      if (nt::SetRegValueDWORD(key_handle, blacklist::kBeaconState,
+                               blacklist::BLACKLIST_SETUP_RUNNING))
+        success = true;
+    }
+  } else {
+    // Some part of the blocking setup failed last time. If this has occurred
+    // blacklist::kBeaconMaxAttempts times in a row, we switch the state to
+    // failed and skip setting up the blocking.
+    DWORD attempt_count = 0;
+
+    nt::QueryRegValueDWORD(key_handle, blacklist::kBeaconAttemptCount,
+                           &attempt_count);
+    ++attempt_count;
+    nt::SetRegValueDWORD(key_handle, blacklist::kBeaconAttemptCount,
+                         attempt_count);
+
+    if (attempt_count >= blacklist::kBeaconMaxAttempts) {
+      blocking_state = blacklist::BLACKLIST_SETUP_FAILED;
+      nt::SetRegValueDWORD(key_handle, blacklist::kBeaconState, blocking_state);
+    }
+  }
+
+  nt::CloseRegKey(key_handle);
+  return success;
+}
+
+bool ResetBeacon() {
+  HANDLE key_handle = INVALID_HANDLE_VALUE;
+
+  if (!nt::CreateRegKey(nt::HKCU,
+                        install_static::GetRegistryPath()
+                            .append(blacklist::kRegistryBeaconKeyName)
+                            .c_str(),
+                        KEY_QUERY_VALUE | KEY_SET_VALUE, &key_handle)) {
+    return false;
+  }
+
+  DWORD blocking_state = blacklist::BLACKLIST_STATE_MAX;
+  if (!nt::QueryRegValueDWORD(key_handle, blacklist::kBeaconState,
+                              &blocking_state)) {
+    nt::CloseRegKey(key_handle);
+    return false;
+  }
+
+  // Reaching this point with the setup running state means the setup did not
+  // crash, so we reset to enabled.  Any other state indicates that setup was
+  // skipped; in that case we leave the state alone for later recording.
+  if (blocking_state == blacklist::BLACKLIST_SETUP_RUNNING) {
+    if (!nt::SetRegValueDWORD(key_handle, blacklist::kBeaconState,
+                              blacklist::BLACKLIST_ENABLED)) {
+      nt::CloseRegKey(key_handle);
+      return false;
+    }
+  }
+
+  nt::CloseRegKey(key_handle);
+  return true;
+}
+
+}  // namespace third_party_dlls
diff --git a/chrome/chrome_elf/third_party_dlls/beacon.h b/chrome/chrome_elf/third_party_dlls/beacon.h
new file mode 100644
index 0000000..cef73fc6
--- /dev/null
+++ b/chrome/chrome_elf/third_party_dlls/beacon.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_CHROME_ELF_THIRD_PARTY_DLLS_BEACON_H_
+#define CHROME_CHROME_ELF_THIRD_PARTY_DLLS_BEACON_H_
+
+namespace third_party_dlls {
+
+// Attempts to leave a beacon in the current user's registry hive. If the beacon
+// doesn't say it is enabled or there are any other errors when creating the
+// beacon, returns false. Otherwise returns true. The intent of the beacon is to
+// act as an extra failure mode protection whereby if Chrome repeatedly fails to
+// start during the initialization of third-party DLL blocking, it will skip
+// blocking on the subsequent run.
+bool LeaveSetupBeacon();
+
+// Looks for the setup running beacon that LeaveSetupBeacon() creates and resets
+// it to to show the setup was successful.
+// Returns true if the beacon was successfully set to BLACKLIST_ENABLED.
+bool ResetBeacon();
+
+}  // namespace third_party_dlls
+
+#endif  // CHROME_CHROME_ELF_THIRD_PARTY_DLLS_BEACON_H_
diff --git a/chrome/chrome_elf/blacklist/test/blacklist_test.cc b/chrome/chrome_elf/third_party_dlls/beacon_unittest.cc
similarity index 62%
rename from chrome/chrome_elf/blacklist/test/blacklist_test.cc
rename to chrome/chrome_elf/third_party_dlls/beacon_unittest.cc
index 815cfe0..637d44d 100644
--- a/chrome/chrome_elf/blacklist/test/blacklist_test.cc
+++ b/chrome/chrome_elf/third_party_dlls/beacon_unittest.cc
@@ -6,23 +6,25 @@
 
 #include <memory>
 
+#include "chrome/chrome_elf/third_party_dlls/beacon.h"
+
 #include "base/strings/string16.h"
 #include "base/test/test_reg_util_win.h"
 #include "base/win/registry.h"
-#include "chrome/chrome_elf/blacklist/blacklist.h"
 #include "chrome/chrome_elf/chrome_elf_constants.h"
 #include "chrome/chrome_elf/nt_registry/nt_registry.h"
-#include "chrome/common/chrome_version.h"
 #include "chrome/install_static/install_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace third_party_dlls {
+
 namespace {
 
-class BlacklistTest : public testing::Test {
+class BeaconTest : public testing::Test {
  protected:
-  BlacklistTest() : override_manager_() {}
+  BeaconTest() : override_manager_() {}
 
-  std::unique_ptr<base::win::RegKey> blacklist_registry_key_;
+  std::unique_ptr<base::win::RegKey> beacon_registry_key_;
   registry_util::RegistryOverrideManager override_manager_;
 
  private:
@@ -32,7 +34,7 @@
         override_manager_.OverrideRegistry(HKEY_CURRENT_USER, &temp));
     ASSERT_TRUE(nt::SetTestingOverride(nt::HKCU, temp));
 
-    blacklist_registry_key_.reset(
+    beacon_registry_key_.reset(
         new base::win::RegKey(HKEY_CURRENT_USER,
                               install_static::GetRegistryPath()
                                   .append(blacklist::kRegistryBeaconKeyName)
@@ -45,25 +47,27 @@
   }
 };
 
+}  // namespace
+
 //------------------------------------------------------------------------------
 // Beacon tests
 //------------------------------------------------------------------------------
 
-TEST_F(BlacklistTest, Beacon) {
-  // Ensure that the beacon state starts off 'running' for this version.
-  LONG result = blacklist_registry_key_->WriteValue(
+// Ensure that the beacon state starts off 'running' if a version is specified.
+TEST_F(BeaconTest, Beacon) {
+  LONG result = beacon_registry_key_->WriteValue(
       blacklist::kBeaconState, blacklist::BLACKLIST_SETUP_RUNNING);
   EXPECT_EQ(ERROR_SUCCESS, result);
 
-  result = blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion,
-                                               TEXT(CHROME_VERSION_STRING));
+  result = beacon_registry_key_->WriteValue(blacklist::kBeaconVersion,
+                                            L"beacon_version");
   EXPECT_EQ(ERROR_SUCCESS, result);
 
   // First call should find the beacon and reset it.
-  EXPECT_TRUE(blacklist::ResetBeacon());
+  EXPECT_TRUE(ResetBeacon());
 
   // First call should succeed as the beacon is enabled.
-  EXPECT_TRUE(blacklist::LeaveSetupBeacon());
+  EXPECT_TRUE(LeaveSetupBeacon());
 }
 
 void TestResetBeacon(std::unique_ptr<base::win::RegKey>& key,
@@ -72,76 +76,75 @@
   LONG result = key->WriteValue(blacklist::kBeaconState, input_state);
   EXPECT_EQ(ERROR_SUCCESS, result);
 
-  EXPECT_TRUE(blacklist::ResetBeacon());
+  EXPECT_TRUE(ResetBeacon());
   DWORD blacklist_state = blacklist::BLACKLIST_STATE_MAX;
   result = key->ReadValueDW(blacklist::kBeaconState, &blacklist_state);
   EXPECT_EQ(ERROR_SUCCESS, result);
   EXPECT_EQ(expected_output_state, blacklist_state);
 }
 
-TEST_F(BlacklistTest, ResetBeacon) {
+TEST_F(BeaconTest, ResetBeacon) {
   // Ensure that ResetBeacon resets properly on successful runs and not on
   // failed or disabled runs.
-  TestResetBeacon(blacklist_registry_key_, blacklist::BLACKLIST_SETUP_RUNNING,
+  TestResetBeacon(beacon_registry_key_, blacklist::BLACKLIST_SETUP_RUNNING,
                   blacklist::BLACKLIST_ENABLED);
 
-  TestResetBeacon(blacklist_registry_key_, blacklist::BLACKLIST_SETUP_FAILED,
+  TestResetBeacon(beacon_registry_key_, blacklist::BLACKLIST_SETUP_FAILED,
                   blacklist::BLACKLIST_SETUP_FAILED);
 
-  TestResetBeacon(blacklist_registry_key_, blacklist::BLACKLIST_DISABLED,
+  TestResetBeacon(beacon_registry_key_, blacklist::BLACKLIST_DISABLED,
                   blacklist::BLACKLIST_DISABLED);
 }
 
-TEST_F(BlacklistTest, SetupFailed) {
+TEST_F(BeaconTest, SetupFailed) {
   // Ensure that when the number of failed tries reaches the maximum allowed,
   // the blacklist state is set to failed.
-  LONG result = blacklist_registry_key_->WriteValue(
+  LONG result = beacon_registry_key_->WriteValue(
       blacklist::kBeaconState, blacklist::BLACKLIST_SETUP_RUNNING);
   EXPECT_EQ(ERROR_SUCCESS, result);
 
   // Set the attempt count so that on the next failure the blacklist is
   // disabled.
-  result = blacklist_registry_key_->WriteValue(
-      blacklist::kBeaconAttemptCount, blacklist::kBeaconMaxAttempts - 1);
+  result = beacon_registry_key_->WriteValue(blacklist::kBeaconAttemptCount,
+                                            blacklist::kBeaconMaxAttempts - 1);
   EXPECT_EQ(ERROR_SUCCESS, result);
 
-  EXPECT_FALSE(blacklist::LeaveSetupBeacon());
+  EXPECT_FALSE(LeaveSetupBeacon());
 
   DWORD attempt_count = 0;
-  blacklist_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount,
-                                       &attempt_count);
+  beacon_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount,
+                                    &attempt_count);
   EXPECT_EQ(attempt_count, blacklist::kBeaconMaxAttempts);
 
   DWORD blacklist_state = blacklist::BLACKLIST_STATE_MAX;
-  result = blacklist_registry_key_->ReadValueDW(blacklist::kBeaconState,
-                                                &blacklist_state);
+  result = beacon_registry_key_->ReadValueDW(blacklist::kBeaconState,
+                                             &blacklist_state);
   EXPECT_EQ(ERROR_SUCCESS, result);
   EXPECT_EQ(blacklist_state,
             static_cast<DWORD>(blacklist::BLACKLIST_SETUP_FAILED));
 }
 
-TEST_F(BlacklistTest, SetupSucceeded) {
+TEST_F(BeaconTest, SetupSucceeded) {
   // Starting with the enabled beacon should result in the setup running state
   // and the attempt counter reset to zero.
-  LONG result = blacklist_registry_key_->WriteValue(
-      blacklist::kBeaconState, blacklist::BLACKLIST_ENABLED);
+  LONG result = beacon_registry_key_->WriteValue(blacklist::kBeaconState,
+                                                 blacklist::BLACKLIST_ENABLED);
   EXPECT_EQ(ERROR_SUCCESS, result);
-  result = blacklist_registry_key_->WriteValue(blacklist::kBeaconAttemptCount,
-                                               blacklist::kBeaconMaxAttempts);
+  result = beacon_registry_key_->WriteValue(blacklist::kBeaconAttemptCount,
+                                            blacklist::kBeaconMaxAttempts);
   EXPECT_EQ(ERROR_SUCCESS, result);
 
-  EXPECT_TRUE(blacklist::LeaveSetupBeacon());
+  EXPECT_TRUE(LeaveSetupBeacon());
 
   DWORD blacklist_state = blacklist::BLACKLIST_STATE_MAX;
-  blacklist_registry_key_->ReadValueDW(blacklist::kBeaconState,
-                                       &blacklist_state);
+  beacon_registry_key_->ReadValueDW(blacklist::kBeaconState, &blacklist_state);
   EXPECT_EQ(blacklist_state,
             static_cast<DWORD>(blacklist::BLACKLIST_SETUP_RUNNING));
 
   DWORD attempt_count = blacklist::kBeaconMaxAttempts;
-  blacklist_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount,
-                                       &attempt_count);
+  beacon_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount,
+                                    &attempt_count);
   EXPECT_EQ(static_cast<DWORD>(0), attempt_count);
 }
 
-}  // namespace
+}  // namespace third_party_dlls
diff --git a/chrome/chrome_elf/third_party_dlls/hardcoded_blocklist.cc b/chrome/chrome_elf/third_party_dlls/hardcoded_blocklist.cc
new file mode 100644
index 0000000..3f1c435
--- /dev/null
+++ b/chrome/chrome_elf/third_party_dlls/hardcoded_blocklist.cc
@@ -0,0 +1,106 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/chrome_elf/third_party_dlls/hardcoded_blocklist.h"
+
+#include <windows.h>
+
+namespace third_party_dlls {
+
+namespace {
+
+// Utility function for converting UTF-8 to UTF-16.
+// Note: Not using base::UTF8ToUTF16() because chrome_elf can not have any
+//       dependencies on //base.
+bool UTF8ToUTF16(const std::string& utf8, std::wstring* utf16) {
+  assert(utf16);
+
+  if (utf8.empty()) {
+    utf16->clear();
+    return true;
+  }
+
+  int size_needed_chars = ::MultiByteToWideChar(
+      CP_UTF8, 0, utf8.c_str(), static_cast<int>(utf8.size()), nullptr, 0);
+  if (!size_needed_chars)
+    return false;
+
+  utf16->resize(size_needed_chars);
+  return ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(),
+                               static_cast<int>(utf8.size()), &(*utf16)[0],
+                               size_needed_chars);
+}
+
+}  // namespace
+
+// The DLLs listed here are known (or under strong suspicion) of causing crashes
+// when they are loaded in the browser. DLLs should only be added to this list
+// if there is nothing else Chrome can do to prevent those crashes.
+// For more information about how this list is generated, and how to get off
+// of it, see:
+// https://sites.google.com/a/chromium.org/dev/Home/third-party-developers
+// NOTE: Please remember to update the DllHash enum in histograms.xml when
+//       adding a new value to the blacklist.
+// TODO(pmonette): Change to const char* const when the
+//                 chrome/chrome_elf/blacklist directory gets deleted.
+const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount] = {
+    L"949ba8b6a9.dll",           // Coupon Time.
+    L"activedetect32.dll",       // Lenovo One Key Theater.
+                                 // See crbug.com/379218.
+    L"activedetect64.dll",       // Lenovo One Key Theater.
+    L"bitguard.dll",             // Unknown (suspected malware).
+    L"bsvc.dll",                 // Unknown (suspected adware).
+    L"chrmxtn.dll",              // Unknown (keystroke logger).
+    L"cplushook.dll",            // Unknown (suspected malware).
+    L"crdli.dll",                // Linkury Inc.
+    L"crdli64.dll",              // Linkury Inc.
+    L"datamngr.dll",             // Unknown (suspected adware).
+    L"dpinterface32.dll",        // Unknown (suspected adware).
+    L"explorerex.dll",           // Unknown (suspected adware).
+    L"hk.dll",                   // Unknown (keystroke logger).
+    L"libapi2hook.dll",          // V-Bates.
+    L"libinject.dll",            // V-Bates.
+    L"libinject2.dll",           // V-Bates.
+    L"libredir2.dll",            // V-Bates.
+    L"libsvn_tsvn32.dll",        // TortoiseSVN.
+    L"libwinhook.dll",           // V-Bates.
+    L"lmrn.dll",                 // Unknown.
+    L"minisp.dll",               // Unknown (suspected malware).
+    L"minisp32.dll",             // Unknown (suspected malware).
+    L"offerswizarddll.dll",      // Unknown (suspected adware).
+    L"safetynut.dll",            // Unknown (suspected adware).
+    L"smdmf.dll",                // Unknown (suspected adware).
+    L"spappsv32.dll",            // Unknown (suspected adware).
+    L"systemk.dll",              // Unknown (suspected adware).
+    L"vntsrv.dll",               // Virtual New Tab by APN LLC.
+    L"wajam_goblin_64.dll",      // Wajam Internet Technologies.
+    L"wajam_goblin.dll",         // Wajam Internet Technologies.
+    L"windowsapihookdll32.dll",  // Lenovo One Key Theater.
+                                 // See crbug.com/379218.
+    L"windowsapihookdll64.dll",  // Lenovo One Key Theater.
+    L"virtualcamera.ax",         // %PROGRAMFILES%\ASUS\VirtualCamera.
+                                 // See crbug.com/422522.
+    L"ycwebcamerasource.ax",     // CyberLink Youcam, crbug.com/424159
+    // Keep this null pointer here to mark the end of the list.
+    nullptr,
+};
+
+bool DllMatch(const std::string& module_name) {
+  if (module_name.empty())
+    return false;
+
+  // Convert UTF-8 to UTF-16 for this comparison.
+  std::wstring wide_module_name;
+  if (!UTF8ToUTF16(module_name, &wide_module_name))
+    return false;
+
+  for (int i = 0; g_troublesome_dlls[i] != nullptr; ++i) {
+    if (_wcsicmp(wide_module_name.c_str(), g_troublesome_dlls[i]) == 0)
+      return i;
+  }
+
+  return false;
+}
+
+}  // namespace third_party_dlls
diff --git a/chrome/chrome_elf/third_party_dlls/hardcoded_blocklist.h b/chrome/chrome_elf/third_party_dlls/hardcoded_blocklist.h
new file mode 100644
index 0000000..c3f989d3
--- /dev/null
+++ b/chrome/chrome_elf/third_party_dlls/hardcoded_blocklist.h
@@ -0,0 +1,24 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_CHROME_ELF_THIRD_PARTY_DLLS_HARDCODED_BLOCKLIST_H_
+#define CHROME_CHROME_ELF_THIRD_PARTY_DLLS_HARDCODED_BLOCKLIST_H_
+
+#include <string>
+
+namespace third_party_dlls {
+
+// Max size of the DLL blocklist.
+constexpr size_t kTroublesomeDllsMaxCount = 64u;
+
+// The DLL blacklist.
+extern const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount];
+
+// Returns true if a matching name is found in the hard-coded blocklist.
+// Note: |module_name| must be an ASCII encoded string.
+bool DllMatch(const std::string& module_name);
+
+}  // namespace third_party_dlls
+
+#endif  // CHROME_CHROME_ELF_THIRD_PARTY_DLLS_HARDCODED_BLOCKLIST_H_
diff --git a/chrome/chrome_elf/third_party_dlls/hook.cc b/chrome/chrome_elf/third_party_dlls/hook.cc
index 66f5f1b..1b83703a 100644
--- a/chrome/chrome_elf/third_party_dlls/hook.cc
+++ b/chrome/chrome_elf/third_party_dlls/hook.cc
@@ -10,11 +10,11 @@
 
 #include <assert.h>
 
-#include "chrome/chrome_elf/blacklist/blacklist.h"
 #include "chrome/chrome_elf/crash/crash_helper.h"
 #include "chrome/chrome_elf/hook_util/hook_util.h"
 #include "chrome/chrome_elf/pe_image_safe/pe_image_safe.h"
 #include "chrome/chrome_elf/sha1/sha1.h"
+#include "chrome/chrome_elf/third_party_dlls/hardcoded_blocklist.h"
 #include "chrome/chrome_elf/third_party_dlls/logs.h"
 #include "chrome/chrome_elf/third_party_dlls/main.h"
 #include "chrome/chrome_elf/third_party_dlls/packed_list_file.h"
@@ -326,12 +326,12 @@
              IsModuleListed(section_basename_hash, fingerprint_hash)) {
     // 2) Third-party DLL blacklist, check for image name from the section.
     block = true;
-  } else if (!image_name.empty() && blacklist::DllMatch(image_name)) {
+  } else if (!image_name.empty() && DllMatch(image_name)) {
     // 3) Hard-coded blacklist with name from PE header (deprecated).
     block = true;
   } else if (!section_basename.empty() &&
              section_basename.compare(image_name) != 0 &&
-             blacklist::DllMatch(section_basename)) {
+             DllMatch(section_basename)) {
     // 4) Hard-coded blacklist with name from the section (deprecated).
     block = true;
   }
diff --git a/chrome/chrome_elf/third_party_dlls/main.cc b/chrome/chrome_elf/third_party_dlls/main.cc
index 3d1c38d..da3e681 100644
--- a/chrome/chrome_elf/third_party_dlls/main.cc
+++ b/chrome/chrome_elf/third_party_dlls/main.cc
@@ -90,10 +90,6 @@
 // Public defines & functions
 //------------------------------------------------------------------------------
 
-bool IsThirdPartyInitialized() {
-  return g_third_party_initialized;
-}
-
 bool Init() {
   // Debug check: Init should not be called more than once.
   assert(!g_third_party_initialized);
@@ -155,3 +151,9 @@
 }
 
 }  // namespace third_party_dlls
+
+using namespace third_party_dlls;
+
+bool IsThirdPartyInitialized() {
+  return g_third_party_initialized;
+}
diff --git a/chrome/chrome_elf/third_party_dlls/main.h b/chrome/chrome_elf/third_party_dlls/main.h
index b907b89a..d51ae69 100644
--- a/chrome/chrome_elf/third_party_dlls/main.h
+++ b/chrome/chrome_elf/third_party_dlls/main.h
@@ -17,9 +17,6 @@
 
 namespace third_party_dlls {
 
-// Third-party DLL control is enabled and initialized in this process.
-bool IsThirdPartyInitialized();
-
 // Init Third-Party
 // ----------------
 // Central initialization for all third-party DLL management. Users only need to
diff --git a/chrome/chrome_elf/third_party_dlls/main_unittest_exe.cc b/chrome/chrome_elf/third_party_dlls/main_unittest_exe.cc
index 3c19ba9..4a97b07f 100644
--- a/chrome/chrome_elf/third_party_dlls/main_unittest_exe.cc
+++ b/chrome/chrome_elf/third_party_dlls/main_unittest_exe.cc
@@ -93,7 +93,7 @@
   if (!argv)
     return kBadCommandLine;
 
-  if (third_party_dlls::IsThirdPartyInitialized())
+  if (IsThirdPartyInitialized())
     return kThirdPartyAlreadyInitialized;
 
   install_static::InitializeProductDetailsForPrimaryModule();
diff --git a/chrome/chrome_elf/third_party_dlls/public_api.h b/chrome/chrome_elf/third_party_dlls/public_api.h
index c8a97641..d74ac1d 100644
--- a/chrome/chrome_elf/third_party_dlls/public_api.h
+++ b/chrome/chrome_elf/third_party_dlls/public_api.h
@@ -65,6 +65,9 @@
 
 // Exported API for calling from outside chrome_elf.dll.
 
+// Third-party DLL control is enabled and initialized in this process.
+extern "C" bool IsThirdPartyInitialized();
+
 // Drains the load attempt LogEntries into the provided buffer.
 // - Returns the number of bytes written.  See comments above for LogEntry
 //   details.
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni
index 77c398a..c47abebf 100644
--- a/chrome/chrome_paks.gni
+++ b/chrome/chrome_paks.gni
@@ -91,7 +91,6 @@
                            ])
     output = "${invoker.output_dir}/resources.pak"
     sources = [
-      "$root_gen_dir/chrome/bluetooth_internals_resources.pak",
       "$root_gen_dir/chrome/browser_resources.pak",
       "$root_gen_dir/chrome/chrome_unscaled_resources.pak",
       "$root_gen_dir/chrome/common_resources.pak",
@@ -113,7 +112,6 @@
       "//chrome/browser/resources:invalidations_resources",
       "//chrome/browser/resources:net_internals_resources",
       "//chrome/browser/resources:quota_internals_resources",
-      "//chrome/browser/resources/bluetooth_internals:resources",
       "//chrome/common:resources",
       "//components/autofill/core/browser:autofill_address_rewriter_resources",
       "//components/resources",
@@ -137,6 +135,7 @@
     } else {
       # New paks should be added here by default.
       sources += [
+        "$root_gen_dir/chrome/bluetooth_internals_resources.pak",
         "$root_gen_dir/chrome/component_extension_resources.pak",
         "$root_gen_dir/chrome/downloads_resources.pak",
         "$root_gen_dir/chrome/local_ntp_resources.pak",
@@ -149,6 +148,7 @@
         "//chrome/browser/resources:downloads_resources",
         "//chrome/browser/resources:local_ntp_resources",
         "//chrome/browser/resources:settings_resources",
+        "//chrome/browser/resources/bluetooth_internals:resources",
         "//content/browser/devtools:devtools_resources",
         "//headless:resources",
       ]
diff --git a/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.cc b/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.cc
index 5ed5489..26383bf 100644
--- a/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.cc
+++ b/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.cc
@@ -362,7 +362,7 @@
         break;
       }
       case ValueType::DATE: {
-        // Note: We never expect date-attributes to be single-valued.
+        // Note: We expect date-attributes to be single-valued.
         const uint8_t* v =
             reinterpret_cast<const uint8_t*>(ippGetDate(attr, 0));
         if (!v) {
diff --git a/chrome/services/cups_proxy/ipp_attribute_validator.cc b/chrome/services/cups_proxy/ipp_attribute_validator.cc
index bfd4555..ccddf35 100644
--- a/chrome/services/cups_proxy/ipp_attribute_validator.cc
+++ b/chrome/services/cups_proxy/ipp_attribute_validator.cc
@@ -15,649 +15,188 @@
 
 namespace {
 
-// represents a type of a single attribute
+using ValueType = cups_ipp_parser::mojom::ValueType;
+
+// Represents the type of a single attribute.
 struct AttributeDefinition {
-  bool is_a_set;
-  cups_ipp_parser::mojom::ValueType type;
+  bool multivalued;
+
+  // Internal serialization type.
+  ValueType type;
 };
 
-// definitions of all known attributes grouped by operations
-std::map<ipp_op_t, std::map<std::string, AttributeDefinition>>
-    attributesDefinitions = {
-        {IPP_OP_CUPS_GET_PPD,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_CUPS_GET_PRINTERS,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"limit", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"printer-location",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requested-attributes",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"charset-configured",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"charset-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"color-supported",
-              {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
-             {"compression-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"copies-default",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"document-format-default",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-format-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"finishings-default",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"finishings-supported",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"generated-natural-language-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"ipp-versions-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"media-default",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"media-ready", {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"media-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"natural-language-configured",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"operations-supported",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"orientation-requested-default",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"orientation-requested-supported",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"output-bin-default",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"output-bin-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"pdl-override-supported",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"print-quality-default",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"print-quality-supported",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"printer-device-id",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-info",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-location",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-make-and-model",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"sides-default",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"sides-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"uri-authentication-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"uri-security-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_CANCEL_JOB,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_CREATE_JOB,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"ipp-attribute-fidelity",
-              {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
-             {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"orientation-requested",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"print-quality",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-state-reasons",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_GET_JOB_ATTRIBUTES,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requested-attributes",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-originating-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-printer-up-time",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-state-reasons",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"orientation-requested",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"print-quality",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"time-at-completed",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"time-at-creation",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"time-at-processing",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-         }},
-        {IPP_OP_GET_JOBS,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"limit", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"requested-attributes",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"which-jobs", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"my-jobs", {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-originating-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-printer-up-time",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-state-reasons",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"orientation-requested",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"print-quality",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"time-at-completed",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"time-at-creation",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"time-at-processing",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-         }},
-        {IPP_OP_GET_PRINTER_ATTRIBUTES,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requested-attributes",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-format",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"charset-configured",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"charset-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"color-supported",
-              {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
-             {"compression-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"copies-default",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"document-format-default",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-format-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"finishings-default",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"finishings-supported",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"generated-natural-language-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"ipp-versions-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"media-default",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"media-ready", {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"media-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"natural-language-configured",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"operations-supported",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"orientation-requested-default",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"orientation-requested-supported",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"output-bin-default",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"output-bin-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"pages-per-minute",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"pages-per-minute-color",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"pdl-override-supported",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"print-quality-default",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"print-quality-supported",
-              {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"printer-alert",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-alert-description",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-device-id",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-info",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-is-accepting-jobs",
-              {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
-             {"printer-location",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-make-and-model",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-more-info",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-state",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"printer-state-reasons",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-up-time",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"printer-uri-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"queued-job-count",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"sides-default",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"sides-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"uri-authentication-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"uri-security-supported",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_HOLD_JOB,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_PAUSE_PRINTER,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_PRINT_JOB,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"ipp-attribute-fidelity",
-              {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
-             {"document-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"compression",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-format",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"orientation-requested",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"print-quality",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-state-reasons",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_PRINT_URI,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"ipp-attribute-fidelity",
-              {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
-             {"document-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"compression",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-format",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"orientation-requested",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"print-quality",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-state-reasons",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_RELEASE_JOB,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_RESUME_PRINTER,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_SEND_DOCUMENT,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"compression",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-format",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-state-reasons",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_SEND_URI,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"compression",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-format",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"job-state-reasons",
-              {true, cups_ipp_parser::mojom::ValueType::STRING}},
-         }},
-        {IPP_OP_VALIDATE_JOB,
-         {
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"printer-uri",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"requesting-user-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"ipp-attribute-fidelity",
-              {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
-             {"document-name",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"compression",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"document-format",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"orientation-requested",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"print-quality",
-              {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
-             {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-charset",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"attributes-natural-language",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-             {"status-message",
-              {false, cups_ipp_parser::mojom::ValueType::STRING}},
-         }}};
+// Definitions of all known attributes.
+const std::map<std::string, AttributeDefinition> kAttributeDefinitions{
+    {"attributes-charset", {false, ValueType::STRING}},
+    {"attributes-natural-language", {false, ValueType::STRING}},
+    {"auth-info", {true, ValueType::STRING}},
+    {"auth-info-required", {true, ValueType::STRING}},
+    {"charset-configured", {false, ValueType::STRING}},
+    {"charset-supported", {true, ValueType::STRING}},
+    {"color-supported", {false, ValueType::BOOLEAN}},
+    {"compression", {false, ValueType::STRING}},
+    {"compression-supported", {true, ValueType::STRING}},
+    {"copies", {false, ValueType::INTEGER}},
+    {"copies-default", {false, ValueType::INTEGER}},
+    {"copies-supported", {true, ValueType::INTEGER}},
+    {"document-format", {false, ValueType::STRING}},
+    {"document-format-default", {false, ValueType::STRING}},
+    {"document-format-supported", {true, ValueType::STRING}},
+    {"document-name", {false, ValueType::STRING}},
+    {"finishings", {true, ValueType::INTEGER}},
+    {"finishings-default", {true, ValueType::INTEGER}},
+    {"finishings-supported", {true, ValueType::INTEGER}},
+    {"generated-natural-language-supported", {true, ValueType::STRING}},
+    {"ipp-attribute-fidelity", {false, ValueType::BOOLEAN}},
+    {"ipp-versions-supported", {true, ValueType::STRING}},
+    {"job-cancel-after", {false, ValueType::INTEGER}},
+    {"job-hold-until", {false, ValueType::STRING}},
+    {"job-hold-until-default", {false, ValueType::STRING}},
+    {"job-hold-until-supported", {true, ValueType::STRING}},
+    {"job-id", {false, ValueType::INTEGER}},
+    {"job-k-limit", {false, ValueType::INTEGER}},
+    {"job-media-progress", {false, ValueType::INTEGER}},
+    {"job-name", {false, ValueType::STRING}},
+    {"job-originating-host-name", {false, ValueType::STRING}},
+    {"job-originating-user-name", {false, ValueType::STRING}},
+    {"job-page-limit", {false, ValueType::INTEGER}},
+    {"job-printer-state-message", {false, ValueType::STRING}},
+    {"job-printer-state-reasons", {true, ValueType::STRING}},
+    {"job-printer-up-time", {false, ValueType::INTEGER}},
+    {"job-printer-uri", {false, ValueType::STRING}},
+    {"job-priority", {false, ValueType::INTEGER}},
+    {"job-priority-default", {false, ValueType::INTEGER}},
+    {"job-priority-supported", {false, ValueType::INTEGER}},
+    {"job-quota-period", {false, ValueType::INTEGER}},
+    {"job-sheets", {false, ValueType::STRING}},
+    {"job-sheets-default", {false, ValueType::STRING}},
+    {"job-sheets-supported", {true, ValueType::STRING}},
+    {"job-state", {false, ValueType::INTEGER}},
+    {"job-state-reasons", {true, ValueType::STRING}},
+    {"job-uri", {false, ValueType::STRING}},
+    {"last-document", {false, ValueType::BOOLEAN}},
+    {"limit", {false, ValueType::INTEGER}},
+    {"marker-change-time", {false, ValueType::INTEGER}},
+    {"marker-colors", {true, ValueType::STRING}},
+    {"marker-high-levels", {true, ValueType::INTEGER}},
+    {"marker-levels", {true, ValueType::INTEGER}},
+    {"marker-low-levels", {true, ValueType::INTEGER}},
+    {"marker-message", {false, ValueType::STRING}},
+    {"marker-names", {true, ValueType::STRING}},
+    {"marker-types", {true, ValueType::STRING}},
+    {"media", {false, ValueType::STRING}},
+    {"media-default", {false, ValueType::STRING}},
+    {"media-ready", {true, ValueType::STRING}},
+    {"media-supported", {true, ValueType::STRING}},
+    {"member-names", {true, ValueType::STRING}},
+    {"member-uris", {true, ValueType::STRING}},
+    {"multiple-document-handling", {false, ValueType::STRING}},
+    {"multiple-document-handling-default", {false, ValueType::STRING}},
+    {"multiple-document-handling-supported", {true, ValueType::STRING}},
+    {"my-jobs", {false, ValueType::BOOLEAN}},
+    {"natural-language-configured", {false, ValueType::STRING}},
+    {"number-up", {false, ValueType::INTEGER}},
+    {"number-up-default", {false, ValueType::INTEGER}},
+    {"number-up-supported", {true, ValueType::INTEGER}},
+    {"operations-supported", {true, ValueType::INTEGER}},
+    {"orientation-requested", {false, ValueType::INTEGER}},
+    {"orientation-requested-default", {false, ValueType::INTEGER}},
+    {"orientation-requested-supported", {true, ValueType::INTEGER}},
+    {"output-bin", {false, ValueType::STRING}},
+    {"output-bin-default", {false, ValueType::STRING}},
+    {"output-bin-supported", {true, ValueType::STRING}},
+    {"page-border", {false, ValueType::STRING}},
+    {"page-ranges", {true, ValueType::INTEGER}},
+    {"page-ranges-supported", {false, ValueType::BOOLEAN}},
+    {"pages-per-minute", {false, ValueType::INTEGER}},
+    {"pages-per-minute-color", {false, ValueType::INTEGER}},
+    {"pdl-override-supported", {false, ValueType::STRING}},
+    {"print-quality", {false, ValueType::INTEGER}},
+    {"print-quality-default", {false, ValueType::INTEGER}},
+    {"print-quality-supported", {true, ValueType::INTEGER}},
+    {"printer-alert", {true, ValueType::STRING}},
+    {"printer-alert-description", {true, ValueType::STRING}},
+    {"printer-device-id", {false, ValueType::STRING}},
+    {"printer-dns-sd-name", {false, ValueType::STRING}},
+    {"printer-id", {false, ValueType::INTEGER}},
+    {"printer-info", {false, ValueType::STRING}},
+    {"printer-is-accepting-jobs", {false, ValueType::BOOLEAN}},
+    {"printer-location", {false, ValueType::STRING}},
+    {"printer-make-and-model", {false, ValueType::STRING}},
+    {"printer-more-info", {false, ValueType::STRING}},
+    {"printer-name", {false, ValueType::STRING}},
+    {"printer-resolution", {true, ValueType::INTEGER}},
+    {"printer-resolution-default", {true, ValueType::INTEGER}},
+    {"printer-resolution-supported", {true, ValueType::INTEGER}},
+    {"printer-state", {false, ValueType::INTEGER}},
+    {"printer-state-reasons", {true, ValueType::STRING}},
+    {"printer-type", {false, ValueType::INTEGER}},
+    {"printer-type-mask", {false, ValueType::INTEGER}},
+    {"printer-up-time", {false, ValueType::INTEGER}},
+    {"printer-uri", {false, ValueType::STRING}},
+    {"printer-uri-supported", {true, ValueType::STRING}},
+    {"queued-job-count", {false, ValueType::INTEGER}},
+    {"requested-attributes", {true, ValueType::STRING}},
+    {"requesting-user-name", {false, ValueType::STRING}},
+    {"requesting-user-name-allowed", {false, ValueType::STRING}},
+    {"requesting-user-name-denied", {false, ValueType::STRING}},
+    {"sides", {false, ValueType::STRING}},
+    {"sides-default", {false, ValueType::STRING}},
+    {"sides-supported", {true, ValueType::STRING}},
+    {"status-message", {false, ValueType::STRING}},
+    {"time-at-completed", {false, ValueType::INTEGER}},
+    {"time-at-creation", {false, ValueType::INTEGER}},
+    {"time-at-processing", {false, ValueType::INTEGER}},
+    {"uri-authentication-supported", {true, ValueType::STRING}},
+    {"uri-security-supported", {true, ValueType::STRING}},
+    {"which-jobs", {false, ValueType::STRING}}};
+
+// Allowed IPP Operations.
+const std::set<ipp_op_t> kOperationIds{
+    IPP_OP_CANCEL_JOB,         IPP_OP_CREATE_JOB,
+    IPP_OP_CUPS_GET_DEFAULT,   IPP_OP_CUPS_GET_PPD,
+    IPP_OP_CUPS_GET_PRINTERS,  IPP_OP_GET_JOBS,
+    IPP_OP_GET_JOB_ATTRIBUTES, IPP_OP_GET_PRINTER_ATTRIBUTES,
+    IPP_OP_HOLD_JOB,           IPP_OP_PAUSE_PRINTER,
+    IPP_OP_PRINT_JOB,          IPP_OP_PRINT_URI,
+    IPP_OP_RELEASE_JOB,        IPP_OP_RESUME_PRINTER,
+    IPP_OP_SEND_DOCUMENT,      IPP_OP_SEND_URI,
+    IPP_OP_VALIDATE_JOB,
+};
 
 }  // namespace
 
-bool ValidateAttribute(ipp_op_t ipp_oper_id,
-                       const std::string& name,
-                       cups_ipp_parser::mojom::ValueType type,
-                       size_t values_count) {
-  auto it_oper = attributesDefinitions.find(ipp_oper_id);
-  if (it_oper == attributesDefinitions.end()) {
-    return false;
+ValidateAttributeResult ValidateAttribute(ipp_op_t ipp_oper_id,
+                                          const std::string& name,
+                                          ValueType type,
+                                          size_t values_count) {
+  // Ensure |ipp_oper_id| is an allowed operation.
+  if (!base::Contains(kOperationIds, ipp_oper_id)) {
+    return ValidateAttributeResult::kFatalError;
   }
-  auto it_attr = it_oper->second.find(name);
-  if (it_attr == it_oper->second.end()) {
-    return false;
+
+  // Ensure |name| refers to an allowed attribute.
+  auto attr_def = kAttributeDefinitions.find(name);
+  if (attr_def == kAttributeDefinitions.end()) {
+    // TODO(crbug.com/945409): Tell caller to drop this attribute.
+    return ValidateAttributeResult::kUnknownAttribute;
   }
-  if (it_attr->second.type != type) {
-    return false;
-  }
+
+  // Ensure every attribute has some value.
   if (values_count == 0) {
-    return false;
+    return ValidateAttributeResult::kFatalError;
   }
-  if (!it_attr->second.is_a_set && values_count > 1) {
-    return false;
+
+  // Ensure single-valued attributes are single-valued.
+  if (!attr_def->second.multivalued && values_count > 1) {
+    return ValidateAttributeResult::kFatalError;
   }
-  return true;
+
+  // Ensure every attribute was serialized to the correct type.
+  if (attr_def->second.type != type) {
+    return ValidateAttributeResult::kFatalError;
+  }
+  return ValidateAttributeResult::kSuccess;
 }
 
 }  // namespace cups_proxy
diff --git a/chrome/services/cups_proxy/ipp_attribute_validator.h b/chrome/services/cups_proxy/ipp_attribute_validator.h
index 0a75eab..3a236a8c 100644
--- a/chrome/services/cups_proxy/ipp_attribute_validator.h
+++ b/chrome/services/cups_proxy/ipp_attribute_validator.h
@@ -13,20 +13,29 @@
 
 namespace cups_proxy {
 
+enum ValidateAttributeResult {
+  kSuccess = 0,
+
+  // Unknown attribute name.
+  kUnknownAttribute,
+  kFatalError,
+  kMaxValue,
+};
+
 // Validates an attribute |name| of type |type| in operation |ipp_oper_id|.
 // |values_count| represents number of values in the attribute. The following
 // constraints are enforced:
 // - only operations from predefined set are accepted
 // - only attributes from predefined set are accepted
-// - an attribute must be part of given operation (request or response)
-// - a type of the attribute must match the specification
+// - serialization type of the attribute must match the specification
 // - a single-value attribute cannot have more than one value
 // - a set-of-values attribute cannot be empty
-// Returns false <=> at least one of the constraints has been violated.
-bool ValidateAttribute(ipp_op_t ipp_oper_id,
-                       const std::string& name,
-                       cups_ipp_parser::mojom::ValueType type,
-                       size_t values_count);
+// Returns kFatalError <=> at least one of the constraints has been violated.
+ValidateAttributeResult ValidateAttribute(
+    ipp_op_t ipp_oper_id,
+    const std::string& name,
+    cups_ipp_parser::mojom::ValueType type,
+    size_t values_count);
 
 }  // namespace cups_proxy
 
diff --git a/chrome/services/cups_proxy/ipp_validator.cc b/chrome/services/cups_proxy/ipp_validator.cc
index 079501e..f5aa805 100644
--- a/chrome/services/cups_proxy/ipp_validator.cc
+++ b/chrome/services/cups_proxy/ipp_validator.cc
@@ -15,6 +15,7 @@
 
 #include "base/containers/span.h"
 #include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "chrome/services/cups_proxy/ipp_attribute_validator.h"
@@ -25,13 +26,12 @@
 namespace cups_proxy {
 namespace {
 
+using ValueType = cups_ipp_parser::mojom::ValueType;
+
 // Initial version only supports english lcoales.
 // TODO(crbug.com/945409): Extending to supporting arbitrary locales.
 const char kLocaleEnglish[] = "en";
 
-// Following ConvertXxx methods translate IPP attribute values to formats'
-// libCUPS APIs accept.
-
 // Converting to vector<char> for libCUPS API:
 // ippAddBooleans(..., int num_values, const char *values)
 std::vector<char> ConvertBooleans(std::vector<bool> bools) {
@@ -55,22 +55,21 @@
   return ret;
 }
 
-// Depending on |type|, returns the number of values associated with
-// |attr_value|.
+// Depending on |type|, returns the number of values associated with |attr|.
 size_t GetAttributeValuesSize(
     const cups_ipp_parser::mojom::IppAttributePtr& attr) {
   const auto& attr_value = attr->value;
   switch (attr->type) {
-    case cups_ipp_parser::mojom::ValueType::DATE:
+    case ValueType::DATE:
       return 1;
 
-    case cups_ipp_parser::mojom::ValueType::BOOLEAN:
+    case ValueType::BOOLEAN:
       DCHECK(attr_value->is_bools());
       return attr_value->get_bools().size();
-    case cups_ipp_parser::mojom::ValueType::INTEGER:
+    case ValueType::INTEGER:
       DCHECK(attr_value->is_ints());
       return attr_value->get_ints().size();
-    case cups_ipp_parser::mojom::ValueType::STRING:
+    case ValueType::STRING:
       DCHECK(attr_value->is_strings());
       return attr_value->get_strings().size();
 
@@ -121,6 +120,7 @@
 
 base::Optional<std::vector<ipp_converter::HttpHeader>>
 IppValidator::ValidateHttpHeaders(
+    const size_t http_content_length,
     const base::flat_map<std::string, std::string>& headers) {
   // Sane, character-set checks.
   for (const auto& header : headers) {
@@ -130,9 +130,20 @@
     }
   }
 
-  return std::vector<ipp_converter::HttpHeader>(headers.begin(), headers.end());
+  std::vector<ipp_converter::HttpHeader> ret(headers.begin(), headers.end());
+
+  // Update the ContentLength.
+  base::EraseIf(ret, [](const ipp_converter::HttpHeader& header) {
+    return header.first == "Content-Length";
+  });
+  ret.push_back({"Content-Length", base::NumberToString(http_content_length)});
+
+  return ret;
 }
 
+// Note: Since its possible to have valid IPP attributes that our
+// ipp_attribute_validator.cc is unaware of, we drop unknown attributes, rather
+// than fail the request.
 ipp_t* IppValidator::ValidateIppMessage(
     cups_ipp_parser::mojom::IppMessagePtr ipp_message) {
   printing::ScopedIppPtr ipp = printing::WrapIpp(ippNew());
@@ -161,13 +172,20 @@
       return nullptr;
     }
 
-    if (!ValidateAttribute(ipp_oper_id, attribute->name, attribute->type,
-                           num_values)) {
+    auto ret = ValidateAttribute(ipp_oper_id, attribute->name, attribute->type,
+                                 num_values);
+    if (ret == ValidateAttributeResult::kFatalError) {
       return nullptr;
     }
+    if (ret == ValidateAttributeResult::kUnknownAttribute) {
+      // We drop unknown attributes.
+      DVLOG(1) << "CupsProxy validation: dropping unknown attribute "
+               << attribute->name;
+      continue;
+    }
 
     switch (attribute->type) {
-      case cups_ipp_parser::mojom::ValueType::BOOLEAN: {
+      case ValueType::BOOLEAN: {
         DCHECK(attribute->value->is_bools());
         std::vector<char> values =
             ConvertBooleans(attribute->value->get_bools());
@@ -180,7 +198,7 @@
         }
         break;
       }
-      case cups_ipp_parser::mojom::ValueType::DATE: {
+      case ValueType::DATE: {
         DCHECK(attribute->value->is_date());
         std::vector<uint8_t> date = attribute->value->get_date();
 
@@ -195,7 +213,7 @@
         }
         break;
       }
-      case cups_ipp_parser::mojom::ValueType::INTEGER: {
+      case ValueType::INTEGER: {
         DCHECK(attribute->value->is_ints());
         std::vector<int> values = attribute->value->get_ints();
 
@@ -208,7 +226,7 @@
         }
         break;
       }
-      case cups_ipp_parser::mojom::ValueType::STRING: {
+      case ValueType::STRING: {
         DCHECK(attribute->value->is_strings());
 
         // Note: cstrings_values references attribute->value's strings, i.e.
@@ -261,9 +279,7 @@
 }
 
 IppValidator::IppValidator(base::WeakPtr<CupsProxyServiceDelegate> delegate)
-    : delegate_(std::move(delegate)) {
-  DETACH_FROM_SEQUENCE(sequence_checker_);
-}
+    : delegate_(std::move(delegate)) {}
 
 IppValidator::~IppValidator() = default;
 
@@ -275,19 +291,6 @@
     return base::nullopt;
   }
 
-  // Build request line.
-  auto request_line = ValidateHttpRequestLine(
-      to_validate->method, to_validate->endpoint, to_validate->http_version);
-  if (!request_line.has_value()) {
-    return base::nullopt;
-  }
-
-  // Build headers.
-  auto headers = ValidateHttpHeaders(to_validate->headers);
-  if (!headers.has_value()) {
-    return base::nullopt;
-  }
-
   // Build ipp message.
   // Note: Moving ipp here, to_validate->ipp no longer valid below.
   printing::ScopedIppPtr ipp =
@@ -302,6 +305,22 @@
     return base::nullopt;
   }
 
+  // Build request line.
+  auto request_line = ValidateHttpRequestLine(
+      to_validate->method, to_validate->endpoint, to_validate->http_version);
+  if (!request_line.has_value()) {
+    return base::nullopt;
+  }
+
+  // Build headers; must happen after ipp message/data since it requires the
+  // ContentLength.
+  const size_t http_content_length =
+      ippLength(ipp.get()) + to_validate->data.size();
+  auto headers = ValidateHttpHeaders(http_content_length, to_validate->headers);
+  if (!headers.has_value()) {
+    return base::nullopt;
+  }
+
   // Marshall request
   IppRequest ret;
   ret.request_line = std::move(*request_line);
diff --git a/chrome/services/cups_proxy/ipp_validator.h b/chrome/services/cups_proxy/ipp_validator.h
index 03770c7ef..50a1c50 100644
--- a/chrome/services/cups_proxy/ipp_validator.h
+++ b/chrome/services/cups_proxy/ipp_validator.h
@@ -23,8 +23,8 @@
 
 // This class fully validates incoming parsed IPP requests. HTTP metadata
 // validation is handled with net/http. IPP metadata validation is handled
-// largely via libCUPS. This class can be created anywhere, but must be
-// accessed from a sequenced context.
+// largely via libCUPS. This class must be created and accessed from a
+// sequenced context.
 class IppValidator {
  public:
   explicit IppValidator(base::WeakPtr<CupsProxyServiceDelegate> delegate);
@@ -42,6 +42,7 @@
       base::StringPiece http_version);
 
   base::Optional<std::vector<ipp_converter::HttpHeader>> ValidateHttpHeaders(
+      const size_t http_content_length,
       const base::flat_map<std::string, std::string>& headers);
 
   ipp_t* ValidateIppMessage(cups_ipp_parser::mojom::IppMessagePtr ipp_message);
diff --git a/chrome/services/cups_proxy/ipp_validator_unittest.cc b/chrome/services/cups_proxy/ipp_validator_unittest.cc
index e9b528f..26f04cb 100644
--- a/chrome/services/cups_proxy/ipp_validator_unittest.cc
+++ b/chrome/services/cups_proxy/ipp_validator_unittest.cc
@@ -171,11 +171,31 @@
 TEST_F(IppValidatorTest, MissingHeaderValue) {
   auto request = GetBasicIppRequest();
 
-  // Adds new header with an empty name.
+  // Adds new header with an empty value.
   request->headers["arbitrary_valid_header_name"] = "";
   EXPECT_TRUE(RunValidateIppRequest(request));
 }
 
+// Test that we drop unknown attributes and succeed the request.
+TEST_F(IppValidatorTest, UnknownAttribute) {
+  auto request = GetBasicIppRequest();
+
+  // Add fake attribute.
+  std::string fake_attr_name = "fake-attribute-name";
+  IppAttributePtr fake_attr =
+      BuildAttributePtr(fake_attr_name, IPP_TAG_OPERATION, IPP_TAG_TEXT);
+  fake_attr->type = ValueType::STRING;
+  fake_attr->value->set_strings({"fake_attribute_value"});
+  request->ipp->attributes.push_back(std::move(fake_attr));
+
+  auto result = RunValidateIppRequest(request);
+  ASSERT_TRUE(result);
+
+  // Ensure resulting validated IPP request doesn't contain fake_attr_name.
+  ipp_t* ipp = result->ipp.get();
+  EXPECT_FALSE(ippFindAttribute(ipp, fake_attr_name.c_str(), IPP_TAG_TEXT));
+}
+
 // TODO(crbug.com/945409): Test IPP validation.
 
 }  // namespace
diff --git a/chrome/services/cups_proxy/printer_installer.cc b/chrome/services/cups_proxy/printer_installer.cc
index f370406..b41a2fd 100644
--- a/chrome/services/cups_proxy/printer_installer.cc
+++ b/chrome/services/cups_proxy/printer_installer.cc
@@ -22,9 +22,7 @@
 
 PrinterInstaller::PrinterInstaller(
     base::WeakPtr<CupsProxyServiceDelegate> delegate)
-    : delegate_(std::move(delegate)) {
-  DETACH_FROM_SEQUENCE(sequence_checker_);
-}
+    : delegate_(std::move(delegate)) {}
 
 PrinterInstaller::~PrinterInstaller() = default;
 
diff --git a/chrome/services/cups_proxy/printer_installer.h b/chrome/services/cups_proxy/printer_installer.h
index 11bbbff..c026b1f 100644
--- a/chrome/services/cups_proxy/printer_installer.h
+++ b/chrome/services/cups_proxy/printer_installer.h
@@ -28,8 +28,7 @@
 
 // This CupsProxyService internal manager ensures that any printers referenced
 // by an incoming IPP request are installed into the CUPS daemon prior to
-// proxying. This class can be created anywhere, but must be accessed from a
-// sequenced context.
+// proxying. This class must be created and accessed from a sequenced context.
 class PrinterInstaller {
  public:
   explicit PrinterInstaller(base::WeakPtr<CupsProxyServiceDelegate> delegate);
diff --git a/chrome/services/cups_proxy/public/cpp/cups_util.cc b/chrome/services/cups_proxy/public/cpp/cups_util.cc
index da74760..7c061828 100644
--- a/chrome/services/cups_proxy/public/cpp/cups_util.cc
+++ b/chrome/services/cups_proxy/public/cpp/cups_util.cc
@@ -34,9 +34,8 @@
   // Fill in IPP attributes.
   ret.ipp = printing::WrapIpp(ippNewResponse(request.ipp.get()));
   for (const auto& printer : printers) {
-    std::string printer_uri = printing::PrinterUriFromName(printer.id());
-
     // Setting the printer-uri.
+    std::string printer_uri = printing::PrinterUriFromName(printer.id());
     ippAddString(ret.ipp.get(), IPP_TAG_PRINTER, IPP_TAG_TEXT,
                  "printer-uri-supported", nullptr, printer_uri.c_str());
 
@@ -50,6 +49,8 @@
                    "printer-make-and-model", nullptr,
                    printer.make_and_model().c_str());
     }
+
+    ippAddSeparator(ret.ipp.get());
   }
 
   // Add the final content length into headers
@@ -91,7 +92,7 @@
   // The printer id should be the last component of the resource.
   base::StringPiece uuid(resource);
   auto uuid_start = uuid.find_last_of('/');
-  if (uuid_start == base::StringPiece::npos) {
+  if (uuid_start == base::StringPiece::npos || uuid_start + 1 >= uuid.size()) {
     return base::nullopt;
   }
 
@@ -106,8 +107,7 @@
     return base::nullopt;
   }
 
-  endpoint.remove_prefix(last_path + 1);
-  return endpoint.as_string();
+  return endpoint.substr(last_path + 1).as_string();
 }
 
 }  // namespace cups_proxy
diff --git a/chrome/services/cups_proxy/public/cpp/cups_util.h b/chrome/services/cups_proxy/public/cpp/cups_util.h
index a4a518b..c33ad60 100644
--- a/chrome/services/cups_proxy/public/cpp/cups_util.h
+++ b/chrome/services/cups_proxy/public/cpp/cups_util.h
@@ -32,12 +32,11 @@
 // TODO(crbug.com/945409): Expand testing suite.
 base::Optional<IppResponse> BuildGetDestsResponse(
     const IppRequest& request,
-    std::vector<chromeos::Printer> printers);
+    const std::vector<chromeos::Printer>& printers);
 
 // If |ipp| refers to a printer, we return the associated printer_id.
 // Note: Expects the printer id to be embedded in the resource field of the
 // 'printer-uri' IPP attribute.
-// TODO(crbug.com/945409): Expand testing suite.
 base::Optional<std::string> GetPrinterId(ipp_t* ipp);
 
 // Expects |endpoint| to be of the form '/printers/{printer_id}'.
diff --git a/chrome/services/cups_proxy/public/cpp/cups_util_unittest.cc b/chrome/services/cups_proxy/public/cpp/cups_util_unittest.cc
index fe1c384e..0d59350 100644
--- a/chrome/services/cups_proxy/public/cpp/cups_util_unittest.cc
+++ b/chrome/services/cups_proxy/public/cpp/cups_util_unittest.cc
@@ -4,11 +4,14 @@
 
 #include "chrome/services/cups_proxy/public/cpp/cups_util.h"
 
+#include <cups/ipp.h>
+
 #include <string>
 #include <vector>
 
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
+#include "printing/backend/cups_jobs.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -18,14 +21,56 @@
 using ::testing::IsEmpty;
 using ::testing::Not;
 
-const char kPrinterIdPrefix[] = "/printers/";
+const char kEndpointPrefix[] = "/printers/";
 
 // Generated via base::GenerateGUID.
 const char kDefaultPrinterId[] = "fd4c5f2e-7549-43d5-b931-9bf4e4f1bf51";
 
+ipp_t* GetPrinterAttributesRequest(
+    std::string printer_uri = kDefaultPrinterId) {
+  ipp_t* ret = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+  if (!ret) {
+    return nullptr;
+  }
+
+  printer_uri = printing::PrinterUriFromName(printer_uri);
+  ippAddString(ret, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr,
+               printer_uri.c_str());
+  return ret;
+}
+
+TEST(GetPrinterIdTest, SimpleSanityTest) {
+  auto printer_id = GetPrinterId(GetPrinterAttributesRequest());
+  EXPECT_TRUE(printer_id);
+  EXPECT_EQ(*printer_id, kDefaultPrinterId);
+}
+
+// PrinterId's must be non-empty.
+TEST(GetPrinterIdTest, EmptyPrinterId) {
+  EXPECT_FALSE(GetPrinterId(GetPrinterAttributesRequest("")));
+}
+
+TEST(GetPrinterIdTest, MissingPrinterUri) {
+  ipp_t* ipp = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+  EXPECT_FALSE(GetPrinterId(ipp));
+}
+
+// Embedded 'printer-uri' attribute must contain a '/'.
+TEST(GetPrinterIdTest, MissingPathDelimeter) {
+  ipp_t* ret = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+  if (!ret) {
+    return;
+  }
+
+  // Omitting using printing::PrinterUriFromId to correctly embed the uri.
+  ippAddString(ret, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr,
+               kDefaultPrinterId);
+  EXPECT_FALSE(GetPrinterId(ret));
+}
+
 TEST(ParseEndpointForPrinterIdTest, SimpleSanityTest) {
   base::Optional<std::string> printer_id = ParseEndpointForPrinterId(
-      std::string(kPrinterIdPrefix) + kDefaultPrinterId);
+      std::string(kEndpointPrefix) + kDefaultPrinterId);
 
   EXPECT_TRUE(printer_id.has_value());
   EXPECT_THAT(*printer_id, Not(IsEmpty()));
@@ -33,7 +78,7 @@
 
 // PrinterId's must be non-empty.
 TEST(ParseEndpointForPrinterIdTest, EmptyPrinterId) {
-  EXPECT_FALSE(ParseEndpointForPrinterId(kPrinterIdPrefix));
+  EXPECT_FALSE(ParseEndpointForPrinterId(kEndpointPrefix));
 }
 
 // Endpoints must contain a '/'.
diff --git a/chrome/services/cups_proxy/socket_manager.cc b/chrome/services/cups_proxy/socket_manager.cc
index b3ba858..d43c379 100644
--- a/chrome/services/cups_proxy/socket_manager.cc
+++ b/chrome/services/cups_proxy/socket_manager.cc
@@ -73,8 +73,9 @@
   ~SocketRequest();
 
   // Used for writing/reading the IPP request/response.
-  std::vector<uint8_t> response;
   scoped_refptr<net::DrainableIOBuffer> io_buffer;
+
+  std::vector<uint8_t> response;
   SocketManagerCallback cb;
 };
 
@@ -117,7 +118,7 @@
   std::unique_ptr<net::UnixDomainClientSocket> socket_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-  base::WeakPtrFactory<SocketManagerImpl> weak_factory_;
+  base::WeakPtrFactory<SocketManagerImpl> weak_factory_{this};
 };
 
 // Defaults for SocketRequest.
@@ -130,8 +131,7 @@
     base::WeakPtr<CupsProxyServiceDelegate> delegate)
     : main_runner_(base::SequencedTaskRunnerHandle::Get()),
       socket_runner_(delegate->GetIOTaskRunner()),
-      socket_(std::move(socket)),
-      weak_factory_(this) {}
+      socket_(std::move(socket)) {}
 SocketManagerImpl::~SocketManagerImpl() {}
 
 void SocketManagerImpl::ProxyToCups(std::vector<uint8_t> request,
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index d3df184..d9eb468 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -660,6 +660,7 @@
       "//components/resources",
       "//components/safe_browsing:buildflags",
       "//components/safe_browsing/db:test_database_manager",
+      "//components/services/patch/public/mojom",
       "//components/services/quarantine:test_support",
       "//components/signin/core/browser",
       "//components/signin/public/base:signin_buildflags",
@@ -1075,7 +1076,6 @@
       "../browser/sessions/tab_restore_service_browsertest.cc",
       "../browser/sessions/tab_restore_service_load_waiter.cc",
       "../browser/sessions/tab_restore_service_load_waiter.h",
-      "../browser/sharing/click_to_call/click_to_call_browsertest.cc",
       "../browser/signin/consistency_cookie_browsertest.cc",
       "../browser/site_isolation/chrome_site_per_process_browsertest.cc",
       "../browser/site_isolation/site_details_browsertest.cc",
@@ -2991,13 +2991,15 @@
     "../browser/performance_manager/graph/node_attached_data_unittest.cc",
     "../browser/performance_manager/graph/node_base_unittest.cc",
     "../browser/performance_manager/graph/page_node_impl_unittest.cc",
+    "../browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos_unittest.cc",
+    "../browser/performance_manager/graph/policies/working_set_trimmer_policy_unittest.cc",
     "../browser/performance_manager/graph/process_node_impl_unittest.cc",
     "../browser/performance_manager/graph/properties_unittest.cc",
     "../browser/performance_manager/graph/system_node_impl_unittest.cc",
+    "../browser/performance_manager/mechanisms/working_set_trimmer_win_unittest.cc",
     "../browser/performance_manager/observers/graph_observer_unittest.cc",
     "../browser/performance_manager/observers/isolation_context_metrics_unittest.cc",
     "../browser/performance_manager/observers/metrics_collector_unittest.cc",
-    "../browser/performance_manager/observers/working_set_trimmer_observer_win_unittest.cc",
     "../browser/performance_manager/performance_manager_tab_helper_unittest.cc",
     "../browser/performance_manager/performance_manager_test_harness.cc",
     "../browser/performance_manager/performance_manager_test_harness.h",
@@ -3378,6 +3380,8 @@
     "//components/safe_browsing/db",
     "//components/safe_browsing/db:test_database_manager",
     "//components/safe_browsing/password_protection:mock_password_protection",
+    "//components/services/patch/content",
+    "//components/services/unzip/content",
     "//components/spellcheck:buildflags",
     "//components/strings",
     "//components/subresource_filter/core/browser:test_support",
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 0b791869a..afe3670f 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -892,10 +892,6 @@
   return nullptr;
 }
 
-net::URLRequestContextGetter* TestingProfile::GetRequestContext() {
-  return GetDefaultStoragePartition(this)->GetURLRequestContext();
-}
-
 scoped_refptr<network::SharedURLLoaderFactory>
 TestingProfile::GetURLLoaderFactory() {
   return nullptr;
@@ -1045,17 +1041,6 @@
   return ChromeBrowsingDataRemoverDelegateFactory::GetForProfile(this);
 }
 
-net::URLRequestContextGetter* TestingProfile::CreateRequestContext(
-    content::ProtocolHandlerMap* protocol_handlers,
-    content::URLRequestInterceptorScopedVector request_interceptors) {
-  return new net::TestURLRequestContextGetter(
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
-}
-
-net::URLRequestContextGetter* TestingProfile::CreateMediaRequestContext() {
-  return nullptr;
-}
-
 void TestingProfile::SetCorsOriginAccessListForOrigin(
     const url::Origin& source_origin,
     std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index 6dd27277..40f3b2f 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -44,10 +44,6 @@
 #endif  // !defined(OS_ANDROID)
 }  // namespace content
 
-namespace net {
-class URLRequestContextGetter;
-}
-
 namespace policy {
 class PolicyService;
 class ProfilePolicyConnector;
@@ -294,10 +290,6 @@
   content::BackgroundSyncController* GetBackgroundSyncController() override;
   content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
       override;
-  net::URLRequestContextGetter* CreateRequestContext(
-      content::ProtocolHandlerMap* protocol_handlers,
-      content::URLRequestInterceptorScopedVector request_interceptors) override;
-  net::URLRequestContextGetter* CreateMediaRequestContext() override;
   void SetCorsOriginAccessListForOrigin(
       const url::Origin& source_origin,
       std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
@@ -334,7 +326,6 @@
 #if !defined(OS_ANDROID)
   ChromeZoomLevelPrefs* GetZoomLevelPrefs() override;
 #endif  // !defined(OS_ANDROID)
-  net::URLRequestContextGetter* GetRequestContext() override;
   scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
 
   void set_last_session_exited_cleanly(bool value) {
diff --git a/chrome/test/data/local_ntp/customize_menu_browsertest.js b/chrome/test/data/local_ntp/customize_menu_browsertest.js
index 04140333..6a55d0d2 100644
--- a/chrome/test/data/local_ntp/customize_menu_browsertest.js
+++ b/chrome/test/data/local_ntp/customize_menu_browsertest.js
@@ -919,21 +919,14 @@
 
   assertImageSubmenuOpenWithFirstTileSelected();
 
-  // Clicking the image again should deselect it.
-  $('coll_0_img_tile_0').click();
-  assertTrue(
-      $(test.customizeMenu.IDS.BACKGROUNDS_IMAGE_MENU)
-          .getElementsByClassName('selected')
-          .length === 0);
-
-  // Close and reopen the submenu and ensure nothing is selected.
+  // Close and reopen the submenu and ensure the first tile is still selected.
   $(test.customizeMenu.IDS.MENU_BACK).click();
   assertTrue(elementIsVisible(backgroundSubmenu));
   assertFalse(elementIsVisible(backgroundImageSubmenu));
   assertEquals(0, test.customizeMenu.timesCustomBackgroundWasSet);
   $('coll_tile_0').click();
 
-  assertImageSubmenuOpenWithNoTileSelected();
+  assertImageSubmenuOpenWithFirstTileSelected();
 };
 
 /**
@@ -985,21 +978,14 @@
 
   assertImageSubmenuOpenWithFirstTileSelected();
 
-  // Clicking the image again should deselect it.
-  $('coll_0_img_tile_0').click();
-  assertTrue(
-      $(test.customizeMenu.IDS.BACKGROUNDS_IMAGE_MENU)
-          .getElementsByClassName('selected')
-          .length === 0);
-
-  // Close and reopen the submenu and ensure nothing is selected.
+  // Close and reopen the submenu and ensure the tile is still selected.
   $(test.customizeMenu.IDS.MENU_BACK).click();
   assertTrue(elementIsVisible(backgroundSubmenu));
   assertFalse(elementIsVisible(backgroundImageSubmenu));
   assertEquals(0, test.customizeMenu.timesCustomBackgroundWasSet);
   $('coll_tile_0').click();
 
-  assertImageSubmenuOpenWithNoTileSelected();
+  assertImageSubmenuOpenWithFirstTileSelected();
 };
 
 // ******************************* HELPERS *******************************
@@ -1044,6 +1030,7 @@
 
   test.customizeMenu.stubs.replace(chrome.embeddedSearch, 'newTabPage', {
     applyAutogeneratedTheme: applyAutogeneratedTheme,
+    applyDefaultTheme: () => {},
     areShortcutsVisible: test.customizeMenu.areShortcutsVisible,
     confirmThemeChanges: confirmThemeChanges,
     getColorsInfo: getColorsInfo,
diff --git a/chrome/test/data/pdf/accessibility/next-on-line.in b/chrome/test/data/pdf/accessibility/next-on-line.in
new file mode 100644
index 0000000..9579845
--- /dev/null
+++ b/chrome/test/data/pdf/accessibility/next-on-line.in
@@ -0,0 +1,55 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [0 0 200 200]
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /Font <<
+      /F1 4 0 R
+    >>
+  >>
+  /Contents 5 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+{{object 5 0}} <<
+  {{streamlen}}
+>>
+stream
+BT
+/F1 10 Tf
+10 180 Td
+(<<     This     is     a     test     with     >>) Tj
+0 -10 Td
+(<<     multiple     lines     of     text.     >>) Tj
+0 -20 Td
+(Leaving a large space between words) Tj
+0 -10 Td
+(above defeats the a11y text-run logic and) Tj
+0 -10 Td
+(ensures we have multiple runs to test the) Tj
+0 -10 Td
+(next-on-line / previous-on-line attributes.) Tj
+ET
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/chrome/test/data/pdf/accessibility/next-on-line.pdf b/chrome/test/data/pdf/accessibility/next-on-line.pdf
new file mode 100644
index 0000000..091ea37
--- /dev/null
+++ b/chrome/test/data/pdf/accessibility/next-on-line.pdf
@@ -0,0 +1,67 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /MediaBox [0 0 200 200]
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /Font <<
+      /F1 4 0 R
+    >>
+  >>
+  /Contents 5 0 R
+>>
+endobj
+4 0 obj <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+5 0 obj <<
+  /Length 365
+>>
+stream
+BT
+/F1 10 Tf
+10 180 Td
+(<<     This     is     a     test     with     >>) Tj
+0 -10 Td
+(<<     multiple     lines     of     text.     >>) Tj
+0 -20 Td
+(Leaving a large space between words) Tj
+0 -10 Td
+(above defeats the a11y text-run logic and) Tj
+0 -10 Td
+(ensures we have multiple runs to test the) Tj
+0 -10 Td
+(next-on-line / previous-on-line attributes.) Tj
+ET
+endstream
+endobj
+xref
+0 6
+0000000000 65535 f 
+0000000015 00000 n 
+0000000068 00000 n 
+0000000157 00000 n 
+0000000283 00000 n 
+0000000359 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 6
+>>
+startxref
+776
+%%EOF
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index 00e5594..85e4ce0 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -21,8 +21,6 @@
 #include "components/mirroring/service/features.h"
 #include "components/mirroring/service/mirroring_service.h"
 #include "components/safe_browsing/buildflags.h"
-#include "components/services/patch/patch_service.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/service_manager_connection.h"
@@ -205,9 +203,6 @@
 ChromeContentUtilityClient::MaybeCreateMainThreadService(
     const std::string& service_name,
     service_manager::mojom::ServiceRequest request) {
-  if (service_name == patch::mojom::kServiceName)
-    return std::make_unique<patch::PatchService>(std::move(request));
-
 #if BUILDFLAG(ENABLE_PRINTING)
   if (service_name == printing::mojom::kServiceName)
     return printing::CreatePdfCompositorService(std::move(request));
diff --git a/chrome/utility/services.cc b/chrome/utility/services.cc
index 601cbe49..b33775b 100644
--- a/chrome/utility/services.cc
+++ b/chrome/utility/services.cc
@@ -9,6 +9,8 @@
 #include "base/macros.h"
 #include "base/no_destructor.h"
 #include "build/build_config.h"
+#include "components/services/patch/file_patcher_impl.h"
+#include "components/services/patch/public/mojom/file_patcher.mojom.h"
 #include "components/services/unzip/public/mojom/unzipper.mojom.h"
 #include "components/services/unzip/unzipper_impl.h"
 #include "mojo/public/cpp/bindings/service_factory.h"
@@ -25,6 +27,10 @@
 
 namespace {
 
+auto RunFilePatcher(mojo::PendingReceiver<patch::mojom::FilePatcher> receiver) {
+  return std::make_unique<patch::FilePatcherImpl>(std::move(receiver));
+}
+
 auto RunUnzipper(mojo::PendingReceiver<unzip::mojom::Unzipper> receiver) {
   return std::make_unique<unzip::UnzipperImpl>(std::move(receiver));
 }
@@ -49,6 +55,7 @@
 mojo::ServiceFactory* GetMainThreadServiceFactory() {
   // clang-format off
   static base::NoDestructor<mojo::ServiceFactory> factory {
+    RunFilePatcher,
     RunUnzipper,
 #if defined(OS_WIN)
     RunWindowsUtility,
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 8ba2e07..3956769 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -663,10 +663,10 @@
       "//base:base_java",
       "//chromecast/android:libcast_shell_android",
       "//chromecast/browser/android:cast_shell_java",
-      "//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so",
+      "//components/crash/content/app:chrome_crashpad_handler_named_as_so",
     ]
 
-    loadable_modules = [ "$root_out_dir/libcrashpad_handler.so" ]
+    loadable_modules = [ "$root_out_dir/libchrome_crashpad_handler.so" ]
 
     command_line_flags_file = "castshell-command-line"
     enable_multidex = true
diff --git a/chromecast/browser/cast_browser_context.cc b/chromecast/browser/cast_browser_context.cc
index 192f835f..5874450 100644
--- a/chromecast/browser/cast_browser_context.cc
+++ b/chromecast/browser/cast_browser_context.cc
@@ -152,18 +152,6 @@
   return nullptr;
 }
 
-net::URLRequestContextGetter* CastBrowserContext::CreateRequestContext(
-    content::ProtocolHandlerMap* protocol_handlers,
-    content::URLRequestInterceptorScopedVector request_interceptors) {
-  NOTREACHED();
-  return nullptr;
-}
-
-net::URLRequestContextGetter* CastBrowserContext::CreateMediaRequestContext() {
-  NOTREACHED();
-  return nullptr;
-}
-
 void CastBrowserContext::SetCorsOriginAccessListForOrigin(
     const url::Origin& source_origin,
     std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
diff --git a/chromecast/browser/cast_browser_context.h b/chromecast/browser/cast_browser_context.h
index c20a9d9..b509584 100644
--- a/chromecast/browser/cast_browser_context.h
+++ b/chromecast/browser/cast_browser_context.h
@@ -45,11 +45,6 @@
   content::BackgroundSyncController* GetBackgroundSyncController() override;
   content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
       override;
-  net::URLRequestContextGetter* CreateRequestContext(
-      content::ProtocolHandlerMap* protocol_handlers,
-      content::URLRequestInterceptorScopedVector request_interceptors) override;
-  net::URLRequestContextGetter* CreateMediaRequestContext() override;
-
   void SetCorsOriginAccessListForOrigin(
       const url::Origin& source_origin,
       std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index dc18542..5cfe8ee 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -429,8 +429,7 @@
       cast_browser_main_parts_->browser_context();
   host->AddFilter(new extensions::ExtensionMessageFilter(render_process_id,
                                                          browser_context));
-  host->AddFilter(new extensions::IOThreadExtensionMessageFilter(
-      render_process_id, browser_context));
+  host->AddFilter(new extensions::IOThreadExtensionMessageFilter());
   host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(
       render_process_id, browser_context));
   host->AddFilter(
diff --git a/chromecast/browser/cast_extension_url_loader_factory.cc b/chromecast/browser/cast_extension_url_loader_factory.cc
index 462d036..14239a4 100644
--- a/chromecast/browser/cast_extension_url_loader_factory.cc
+++ b/chromecast/browser/cast_extension_url_loader_factory.cc
@@ -94,10 +94,6 @@
         << "The original client shouldn't have been notified of any redirects";
   }
 
-  void ProceedWithResponse() override {
-    network_loader_->ProceedWithResponse();
-  }
-
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {
     network_loader_->SetPriority(priority, intra_priority_value);
diff --git a/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.h b/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.h
index acec0be..b1845f74 100644
--- a/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.h
+++ b/chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.h
@@ -15,7 +15,7 @@
 
 // API function that enables or disables web content accessibility support.
 class AccessibilityPrivateSetNativeAccessibilityEnabledFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetNativeAccessibilityEnabledFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION(
@@ -24,8 +24,7 @@
 };
 
 // API function that sets the location of the accessibility focus ring.
-class AccessibilityPrivateSetFocusRingsFunction
-    : public UIThreadExtensionFunction {
+class AccessibilityPrivateSetFocusRingsFunction : public ExtensionFunction {
   ~AccessibilityPrivateSetFocusRingsFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setFocusRings",
@@ -33,8 +32,7 @@
 };
 
 // API function that sets the location of the accessibility highlights.
-class AccessibilityPrivateSetHighlightsFunction
-    : public UIThreadExtensionFunction {
+class AccessibilityPrivateSetHighlightsFunction : public ExtensionFunction {
   ~AccessibilityPrivateSetHighlightsFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setHighlights",
@@ -43,7 +41,7 @@
 
 // API function that sets keyboard capture mode.
 class AccessibilityPrivateSetKeyboardListenerFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetKeyboardListenerFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setKeyboardListener",
@@ -51,8 +49,7 @@
 };
 
 // API function that darkens or undarkens the screen.
-class AccessibilityPrivateDarkenScreenFunction
-    : public UIThreadExtensionFunction {
+class AccessibilityPrivateDarkenScreenFunction : public ExtensionFunction {
   ~AccessibilityPrivateDarkenScreenFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.darkenScreen",
@@ -61,7 +58,7 @@
 
 // API function that sets the keys to be captured by Switch Access.
 class AccessibilityPrivateSetSwitchAccessKeysFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetSwitchAccessKeysFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setSwitchAccessKeys",
@@ -70,7 +67,7 @@
 
 // API function that sets native ChromeVox ARC support.
 class AccessibilityPrivateSetNativeChromeVoxArcSupportForCurrentAppFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSetNativeChromeVoxArcSupportForCurrentAppFunction()
       override {}
   ResponseAction Run() override;
@@ -81,7 +78,7 @@
 
 // API function that injects key events.
 class AccessibilityPrivateSendSyntheticKeyEventFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
   ~AccessibilityPrivateSendSyntheticKeyEventFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.sendSyntheticKeyEvent",
diff --git a/chromecast/browser/extensions/api/automation_internal/chromecast_automation_internal_api_delegate.cc b/chromecast/browser/extensions/api/automation_internal/chromecast_automation_internal_api_delegate.cc
index be25364..83d2017 100644
--- a/chromecast/browser/extensions/api/automation_internal/chromecast_automation_internal_api_delegate.cc
+++ b/chromecast/browser/extensions/api/automation_internal/chromecast_automation_internal_api_delegate.cc
@@ -59,7 +59,7 @@
 
 content::WebContents*
 ChromecastAutomationInternalApiDelegate::GetActiveWebContents(
-    UIThreadExtensionFunction* function) {
+    ExtensionFunction* function) {
   NOTIMPLEMENTED();
   return nullptr;
 }
diff --git a/chromecast/browser/extensions/api/automation_internal/chromecast_automation_internal_api_delegate.h b/chromecast/browser/extensions/api/automation_internal/chromecast_automation_internal_api_delegate.h
index 3493a54..ba1a5bc 100644
--- a/chromecast/browser/extensions/api/automation_internal/chromecast_automation_internal_api_delegate.h
+++ b/chromecast/browser/extensions/api/automation_internal/chromecast_automation_internal_api_delegate.h
@@ -27,7 +27,7 @@
                   std::string* error_msg) override;
   int GetTabId(content::WebContents* contents) override;
   content::WebContents* GetActiveWebContents(
-      UIThreadExtensionFunction* function) override;
+      ExtensionFunction* function) override;
   void EnableDesktop() override;
   ui::AXTreeID GetAXTreeID() override;
   void SetEventBundleSink(ui::AXEventBundleSink* sink) override;
diff --git a/chromecast/browser/extensions/api/bookmarks/bookmarks_api.cc b/chromecast/browser/extensions/api/bookmarks/bookmarks_api.cc
index 5da96ab..300e3f6 100644
--- a/chromecast/browser/extensions/api/bookmarks/bookmarks_api.cc
+++ b/chromecast/browser/extensions/api/bookmarks/bookmarks_api.cc
@@ -8,12 +8,6 @@
 namespace cast {
 namespace api {
 
-BookmarksFunction::~BookmarksFunction() {}
-
-void BookmarksFunction::Destruct() const {
-  delete this;
-}
-
 BookmarksStubFunction::~BookmarksStubFunction() {}
 
 ExtensionFunction::ResponseAction BookmarksStubFunction::Run() {
diff --git a/chromecast/browser/extensions/api/bookmarks/bookmarks_api.h b/chromecast/browser/extensions/api/bookmarks/bookmarks_api.h
index 90f5d78..b78949b2 100644
--- a/chromecast/browser/extensions/api/bookmarks/bookmarks_api.h
+++ b/chromecast/browser/extensions/api/bookmarks/bookmarks_api.h
@@ -14,15 +14,7 @@
 namespace cast {
 namespace api {
 
-class BookmarksFunction : public ExtensionFunction {
- public:
-  void Destruct() const override;
-
- protected:
-  ~BookmarksFunction() override;
-};
-
-class BookmarksStubFunction : public BookmarksFunction {
+class BookmarksStubFunction : public ExtensionFunction {
  public:
   ResponseAction Run() override;
 
@@ -30,7 +22,7 @@
   ~BookmarksStubFunction() override;
 };
 
-class BookmarksGetFunction : public BookmarksFunction {
+class BookmarksGetFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("bookmarks.get", BOOKMARKS_GET)
 
@@ -40,7 +32,7 @@
   ResponseAction Run() override;
 };
 
-class BookmarksGetChildrenFunction : public BookmarksFunction {
+class BookmarksGetChildrenFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("bookmarks.getChildren", BOOKMARKS_GETCHILDREN)
 
@@ -50,7 +42,7 @@
   ResponseAction Run() override;
 };
 
-class BookmarksGetRecentFunction : public BookmarksFunction {
+class BookmarksGetRecentFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("bookmarks.getRecent", BOOKMARKS_GETRECENT)
 
@@ -60,7 +52,7 @@
   ResponseAction Run() override;
 };
 
-class BookmarksGetTreeFunction : public BookmarksFunction {
+class BookmarksGetTreeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("bookmarks.getTree", BOOKMARKS_GETTREE)
 
@@ -70,7 +62,7 @@
   ResponseAction Run() override;
 };
 
-class BookmarksGetSubTreeFunction : public BookmarksFunction {
+class BookmarksGetSubTreeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("bookmarks.getSubTree", BOOKMARKS_GETSUBTREE)
 
@@ -80,7 +72,7 @@
   ResponseAction Run() override;
 };
 
-class BookmarksSearchFunction : public BookmarksFunction {
+class BookmarksSearchFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("bookmarks.search", BOOKMARKS_SEARCH)
 
diff --git a/chromecast/browser/extensions/api/history/history_api.h b/chromecast/browser/extensions/api/history/history_api.h
index 24a3d61..86ad9e6 100644
--- a/chromecast/browser/extensions/api/history/history_api.h
+++ b/chromecast/browser/extensions/api/history/history_api.h
@@ -14,7 +14,7 @@
 namespace cast {
 namespace api {
 
-class HistoryGetVisitsFunction : public UIThreadExtensionFunction {
+class HistoryGetVisitsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("history.getVisits", HISTORY_GETVISITS)
 
@@ -25,7 +25,7 @@
   ResponseAction Run() override;
 };
 
-class HistorySearchFunction : public UIThreadExtensionFunction {
+class HistorySearchFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("history.search", HISTORY_SEARCH)
 
@@ -36,7 +36,7 @@
   ResponseAction Run() override;
 };
 
-class HistoryAddUrlFunction : public UIThreadExtensionFunction {
+class HistoryAddUrlFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("history.addUrl", HISTORY_ADDURL)
 
@@ -47,7 +47,7 @@
   ResponseAction Run() override;
 };
 
-class HistoryDeleteAllFunction : public UIThreadExtensionFunction {
+class HistoryDeleteAllFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("history.deleteAll", HISTORY_DELETEALL)
 
@@ -58,7 +58,7 @@
   ResponseAction Run() override;
 };
 
-class HistoryDeleteUrlFunction : public UIThreadExtensionFunction {
+class HistoryDeleteUrlFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("history.deleteUrl", HISTORY_DELETEURL)
 
@@ -69,7 +69,7 @@
   ResponseAction Run() override;
 };
 
-class HistoryDeleteRangeFunction : public UIThreadExtensionFunction {
+class HistoryDeleteRangeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("history.deleteRange", HISTORY_DELETERANGE)
 
diff --git a/chromecast/browser/extensions/api/i18n/i18n_api.h b/chromecast/browser/extensions/api/i18n/i18n_api.h
index b7301ca..7d41a85 100644
--- a/chromecast/browser/extensions/api/i18n/i18n_api.h
+++ b/chromecast/browser/extensions/api/i18n/i18n_api.h
@@ -9,7 +9,7 @@
 
 namespace extensions {
 
-class I18nGetAcceptLanguagesFunction : public UIThreadExtensionFunction {
+class I18nGetAcceptLanguagesFunction : public ExtensionFunction {
   ~I18nGetAcceptLanguagesFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("i18n.getAcceptLanguages", I18N_GETACCEPTLANGUAGES)
diff --git a/chromecast/browser/extensions/api/identity/identity_api.h b/chromecast/browser/extensions/api/identity/identity_api.h
index ae8bb98..9781605 100644
--- a/chromecast/browser/extensions/api/identity/identity_api.h
+++ b/chromecast/browser/extensions/api/identity/identity_api.h
@@ -16,7 +16,7 @@
 
 // Returns an OAuth2 access token for a user. See the IDL file for
 // documentation.
-class IdentityGetAuthTokenFunction : public UIThreadExtensionFunction {
+class IdentityGetAuthTokenFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("identity.getAuthToken", UNKNOWN)
 
@@ -33,7 +33,7 @@
 };
 
 // Stub. See the IDL file for documentation.
-class IdentityRemoveCachedAuthTokenFunction : public UIThreadExtensionFunction {
+class IdentityRemoveCachedAuthTokenFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("identity.removeCachedAuthToken", UNKNOWN)
 
diff --git a/chromecast/browser/extensions/api/notifications/notifications_api.cc b/chromecast/browser/extensions/api/notifications/notifications_api.cc
index 3ae67599..73d0f8c 100644
--- a/chromecast/browser/extensions/api/notifications/notifications_api.cc
+++ b/chromecast/browser/extensions/api/notifications/notifications_api.cc
@@ -10,10 +10,6 @@
 namespace cast {
 namespace api {
 
-void NotificationsApiFunction::Destruct() const {
-  delete this;
-}
-
 ExtensionFunction::ResponseAction NotificationsCreateFunction::Run() {
   return RespondNow(Error("Not implemented"));
 }
diff --git a/chromecast/browser/extensions/api/notifications/notifications_api.h b/chromecast/browser/extensions/api/notifications/notifications_api.h
index 63a59ca0..b25208c 100644
--- a/chromecast/browser/extensions/api/notifications/notifications_api.h
+++ b/chromecast/browser/extensions/api/notifications/notifications_api.h
@@ -14,15 +14,7 @@
 namespace cast {
 namespace api {
 
-class NotificationsApiFunction : public ExtensionFunction {
- public:
-  void Destruct() const override;
-
- protected:
-  ~NotificationsApiFunction() override {}
-};
-
-class NotificationsCreateFunction : public NotificationsApiFunction {
+class NotificationsCreateFunction : public ExtensionFunction {
  protected:
   ~NotificationsCreateFunction() override {}
 
@@ -32,7 +24,7 @@
   DECLARE_EXTENSION_FUNCTION("notifications.create", NOTIFICATIONS_CREATE)
 };
 
-class NotificationsUpdateFunction : public NotificationsApiFunction {
+class NotificationsUpdateFunction : public ExtensionFunction {
  protected:
   ~NotificationsUpdateFunction() override {}
 
@@ -42,7 +34,7 @@
   DECLARE_EXTENSION_FUNCTION("notifications.update", NOTIFICATIONS_UPDATE)
 };
 
-class NotificationsClearFunction : public NotificationsApiFunction {
+class NotificationsClearFunction : public ExtensionFunction {
  protected:
   ~NotificationsClearFunction() override {}
 
@@ -52,7 +44,7 @@
   DECLARE_EXTENSION_FUNCTION("notifications.clear", NOTIFICATIONS_CLEAR)
 };
 
-class NotificationsGetAllFunction : public NotificationsApiFunction {
+class NotificationsGetAllFunction : public ExtensionFunction {
  protected:
   ~NotificationsGetAllFunction() override {}
 
@@ -62,8 +54,7 @@
   DECLARE_EXTENSION_FUNCTION("notifications.getAll", NOTIFICATIONS_GET_ALL)
 };
 
-class NotificationsGetPermissionLevelFunction
-    : public NotificationsApiFunction {
+class NotificationsGetPermissionLevelFunction : public ExtensionFunction {
  protected:
   ~NotificationsGetPermissionLevelFunction() override {}
 
diff --git a/chromecast/browser/extensions/api/settings_private/settings_private_api.h b/chromecast/browser/extensions/api/settings_private/settings_private_api.h
index 8980da7..1cec610 100644
--- a/chromecast/browser/extensions/api/settings_private/settings_private_api.h
+++ b/chromecast/browser/extensions/api/settings_private/settings_private_api.h
@@ -14,7 +14,7 @@
 namespace cast {
 
 // Implements the chrome.settingsPrivate.setPref method.
-class SettingsPrivateSetPrefFunction : public UIThreadExtensionFunction {
+class SettingsPrivateSetPrefFunction : public ExtensionFunction {
  public:
   SettingsPrivateSetPrefFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.setPref", SETTINGSPRIVATE_SETPREF)
@@ -22,14 +22,14 @@
  protected:
   ~SettingsPrivateSetPrefFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateSetPrefFunction);
 };
 
 // Implements the chrome.settingsPrivate.getAllPrefs method.
-class SettingsPrivateGetAllPrefsFunction : public UIThreadExtensionFunction {
+class SettingsPrivateGetAllPrefsFunction : public ExtensionFunction {
  public:
   SettingsPrivateGetAllPrefsFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.getAllPrefs",
@@ -38,14 +38,14 @@
  protected:
   ~SettingsPrivateGetAllPrefsFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateGetAllPrefsFunction);
 };
 
 // Implements the chrome.settingsPrivate.getPref method.
-class SettingsPrivateGetPrefFunction : public UIThreadExtensionFunction {
+class SettingsPrivateGetPrefFunction : public ExtensionFunction {
  public:
   SettingsPrivateGetPrefFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.getPref", SETTINGSPRIVATE_GETPREF)
@@ -53,14 +53,14 @@
  protected:
   ~SettingsPrivateGetPrefFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateGetPrefFunction);
 };
 
 // Implements the chrome.settingsPrivate.getDefaultZoom method.
-class SettingsPrivateGetDefaultZoomFunction : public UIThreadExtensionFunction {
+class SettingsPrivateGetDefaultZoomFunction : public ExtensionFunction {
  public:
   SettingsPrivateGetDefaultZoomFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.getDefaultZoom",
@@ -69,14 +69,14 @@
  protected:
   ~SettingsPrivateGetDefaultZoomFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateGetDefaultZoomFunction);
 };
 
 // Implements the chrome.settingsPrivate.setDefaultZoom method.
-class SettingsPrivateSetDefaultZoomFunction : public UIThreadExtensionFunction {
+class SettingsPrivateSetDefaultZoomFunction : public ExtensionFunction {
  public:
   SettingsPrivateSetDefaultZoomFunction() {}
   DECLARE_EXTENSION_FUNCTION("settingsPrivate.setDefaultZoom",
@@ -85,7 +85,7 @@
  protected:
   ~SettingsPrivateSetDefaultZoomFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(SettingsPrivateSetDefaultZoomFunction);
diff --git a/chromecast/browser/extensions/api/tabs/tabs_api.h b/chromecast/browser/extensions/api/tabs/tabs_api.h
index ccc0ac1f..4243c66 100644
--- a/chromecast/browser/extensions/api/tabs/tabs_api.h
+++ b/chromecast/browser/extensions/api/tabs/tabs_api.h
@@ -37,79 +37,79 @@
                             api::tabs::ZoomSettings* zoom_settings);
 
 // Windows
-class WindowsGetFunction : public UIThreadExtensionFunction {
+class WindowsGetFunction : public ExtensionFunction {
   ~WindowsGetFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.get", WINDOWS_GET)
 };
-class WindowsGetCurrentFunction : public UIThreadExtensionFunction {
+class WindowsGetCurrentFunction : public ExtensionFunction {
   ~WindowsGetCurrentFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.getCurrent", WINDOWS_GETCURRENT)
 };
-class WindowsGetLastFocusedFunction : public UIThreadExtensionFunction {
+class WindowsGetLastFocusedFunction : public ExtensionFunction {
   ~WindowsGetLastFocusedFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.getLastFocused", WINDOWS_GETLASTFOCUSED)
 };
-class WindowsGetAllFunction : public UIThreadExtensionFunction {
+class WindowsGetAllFunction : public ExtensionFunction {
   ~WindowsGetAllFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.getAll", WINDOWS_GETALL)
 };
-class WindowsCreateFunction : public UIThreadExtensionFunction {
+class WindowsCreateFunction : public ExtensionFunction {
   ~WindowsCreateFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.create", WINDOWS_CREATE)
 };
-class WindowsUpdateFunction : public UIThreadExtensionFunction {
+class WindowsUpdateFunction : public ExtensionFunction {
   ~WindowsUpdateFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.update", WINDOWS_UPDATE)
 };
-class WindowsRemoveFunction : public UIThreadExtensionFunction {
+class WindowsRemoveFunction : public ExtensionFunction {
   ~WindowsRemoveFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("windows.remove", WINDOWS_REMOVE)
 };
 
 // Tabs
-class TabsGetFunction : public UIThreadExtensionFunction {
+class TabsGetFunction : public ExtensionFunction {
   ~TabsGetFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.get", TABS_GET)
 };
-class TabsGetCurrentFunction : public UIThreadExtensionFunction {
+class TabsGetCurrentFunction : public ExtensionFunction {
   ~TabsGetCurrentFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.getCurrent", TABS_GETCURRENT)
 };
-class TabsGetSelectedFunction : public UIThreadExtensionFunction {
+class TabsGetSelectedFunction : public ExtensionFunction {
   ~TabsGetSelectedFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.getSelected", TABS_GETSELECTED)
 };
-class TabsGetAllInWindowFunction : public UIThreadExtensionFunction {
+class TabsGetAllInWindowFunction : public ExtensionFunction {
   ~TabsGetAllInWindowFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.getAllInWindow", TABS_GETALLINWINDOW)
 };
-class TabsQueryFunction : public UIThreadExtensionFunction {
+class TabsQueryFunction : public ExtensionFunction {
   ~TabsQueryFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.query", TABS_QUERY)
 };
-class TabsCreateFunction : public UIThreadExtensionFunction {
+class TabsCreateFunction : public ExtensionFunction {
   ~TabsCreateFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.create", TABS_CREATE)
 };
-class TabsDuplicateFunction : public UIThreadExtensionFunction {
+class TabsDuplicateFunction : public ExtensionFunction {
   ~TabsDuplicateFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.duplicate", TABS_DUPLICATE)
 };
-class TabsHighlightFunction : public UIThreadExtensionFunction {
+class TabsHighlightFunction : public ExtensionFunction {
   ~TabsHighlightFunction() override {}
   ResponseAction Run() override;
   bool HighlightTab(const std::vector<chromecast::CastWebContents*>& tabs,
@@ -119,7 +119,7 @@
                     std::string* error);
   DECLARE_EXTENSION_FUNCTION("tabs.highlight", TABS_HIGHLIGHT)
 };
-class TabsUpdateFunction : public UIThreadExtensionFunction {
+class TabsUpdateFunction : public ExtensionFunction {
  public:
   TabsUpdateFunction();
 
@@ -140,22 +140,22 @@
 
   DECLARE_EXTENSION_FUNCTION("tabs.update", TABS_UPDATE)
 };
-class TabsMoveFunction : public UIThreadExtensionFunction {
+class TabsMoveFunction : public ExtensionFunction {
   ~TabsMoveFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.move", TABS_MOVE)
 };
-class TabsReloadFunction : public UIThreadExtensionFunction {
+class TabsReloadFunction : public ExtensionFunction {
   ~TabsReloadFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.reload", TABS_RELOAD)
 };
-class TabsRemoveFunction : public UIThreadExtensionFunction {
+class TabsRemoveFunction : public ExtensionFunction {
   ~TabsRemoveFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tabs.remove", TABS_REMOVE)
 };
-class TabsDetectLanguageFunction : public UIThreadExtensionFunction {
+class TabsDetectLanguageFunction : public ExtensionFunction {
  private:
   ~TabsDetectLanguageFunction() override {}
   ResponseAction Run() override;
@@ -163,7 +163,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.detectLanguage", TABS_DETECTLANGUAGE)
 };
 
-class TabsCaptureVisibleTabFunction : public UIThreadExtensionFunction {
+class TabsCaptureVisibleTabFunction : public ExtensionFunction {
  public:
   TabsCaptureVisibleTabFunction();
 
@@ -218,7 +218,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.insertCSS", TABS_INSERTCSS)
 };
 
-class TabsSetZoomFunction : public UIThreadExtensionFunction {
+class TabsSetZoomFunction : public ExtensionFunction {
  private:
   ~TabsSetZoomFunction() override {}
 
@@ -227,7 +227,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.setZoom", TABS_SETZOOM)
 };
 
-class TabsGetZoomFunction : public UIThreadExtensionFunction {
+class TabsGetZoomFunction : public ExtensionFunction {
  private:
   ~TabsGetZoomFunction() override {}
 
@@ -236,7 +236,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.getZoom", TABS_GETZOOM)
 };
 
-class TabsSetZoomSettingsFunction : public UIThreadExtensionFunction {
+class TabsSetZoomSettingsFunction : public ExtensionFunction {
  private:
   ~TabsSetZoomSettingsFunction() override {}
 
@@ -245,7 +245,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.setZoomSettings", TABS_SETZOOMSETTINGS)
 };
 
-class TabsGetZoomSettingsFunction : public UIThreadExtensionFunction {
+class TabsGetZoomSettingsFunction : public ExtensionFunction {
  private:
   ~TabsGetZoomSettingsFunction() override {}
 
@@ -254,7 +254,7 @@
   DECLARE_EXTENSION_FUNCTION("tabs.getZoomSettings", TABS_GETZOOMSETTINGS)
 };
 
-class TabsDiscardFunction : public UIThreadExtensionFunction {
+class TabsDiscardFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("tabs.discard", TABS_DISCARD)
 
diff --git a/chromecast/browser/extensions/api/tts/tts_extension_api.h b/chromecast/browser/extensions/api/tts/tts_extension_api.h
index 5043f28..59f1d8f 100644
--- a/chromecast/browser/extensions/api/tts/tts_extension_api.h
+++ b/chromecast/browser/extensions/api/tts/tts_extension_api.h
@@ -25,44 +25,44 @@
 
 namespace extensions {
 
-class TtsSpeakFunction : public UIThreadExtensionFunction {
+class TtsSpeakFunction : public ExtensionFunction {
  private:
   ~TtsSpeakFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tts.speak", TTS_SPEAK)
 };
 
-class TtsStopSpeakingFunction : public UIThreadExtensionFunction {
+class TtsStopSpeakingFunction : public ExtensionFunction {
  private:
   ~TtsStopSpeakingFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tts.stop", TTS_STOP)
 };
 
-class TtsPauseFunction : public UIThreadExtensionFunction {
+class TtsPauseFunction : public ExtensionFunction {
  private:
   ~TtsPauseFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tts.pause", TTS_PAUSE)
 };
 
-class TtsResumeFunction : public UIThreadExtensionFunction {
+class TtsResumeFunction : public ExtensionFunction {
  private:
   ~TtsResumeFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tts.resume", TTS_RESUME)
 };
 
-class TtsIsSpeakingFunction : public UIThreadExtensionFunction {
+class TtsIsSpeakingFunction : public ExtensionFunction {
  private:
   ~TtsIsSpeakingFunction() override {}
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("tts.isSpeaking", TTS_ISSPEAKING)
 };
 
-class TtsGetVoicesFunction : public UIThreadExtensionFunction {
+class TtsGetVoicesFunction : public ExtensionFunction {
  private:
   ~TtsGetVoicesFunction() override {}
   ResponseAction Run() override;
diff --git a/chromecast/media/audio/capture_service/capture_service_receiver.cc b/chromecast/media/audio/capture_service/capture_service_receiver.cc
index e11ef0a..7891ca6 100644
--- a/chromecast/media/audio/capture_service/capture_service_receiver.cc
+++ b/chromecast/media/audio/capture_service/capture_service_receiver.cc
@@ -9,12 +9,10 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/callback.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chromecast/media/audio/capture_service/capture_service_buildflags.h"
 #include "chromecast/media/audio/capture_service/constants.h"
@@ -47,13 +45,6 @@
 namespace chromecast {
 namespace media {
 
-namespace {
-
-constexpr base::TimeDelta kConnectTimeout = base::TimeDelta::FromSeconds(1);
-constexpr base::TimeDelta kInactivityTimeout = base::TimeDelta::FromSeconds(5);
-
-}  // namespace
-
 class CaptureServiceReceiver::Socket : public SmallMessageSocket {
  public:
   Socket(std::unique_ptr<net::StreamSocket> socket, int channels);
@@ -95,7 +86,8 @@
 void CaptureServiceReceiver::Socket::Start(
     ::media::AudioInputStream::AudioInputCallback* input_callback) {
   input_callback_ = input_callback;
-  inactivity_timer_.Start(FROM_HERE, kInactivityTimeout, this,
+  inactivity_timer_.Start(FROM_HERE, CaptureServiceReceiver::kInactivityTimeout,
+                          this,
                           &CaptureServiceReceiver::Socket::OnInactivityTimeout);
   ReceiveMessages();
 }
@@ -158,6 +150,10 @@
   return true;
 }
 
+// static
+constexpr base::TimeDelta CaptureServiceReceiver::kConnectTimeout;
+constexpr base::TimeDelta CaptureServiceReceiver::kInactivityTimeout;
+
 CaptureServiceReceiver::CaptureServiceReceiver(
     const ::media::AudioParameters& audio_params)
     : audio_params_(audio_params), io_thread_(__func__) {
@@ -241,10 +237,6 @@
     input_callback->OnError();
     connecting_socket_.reset();
   }
-
-  if (!connected_cb_.is_null()) {
-    std::move(connected_cb_).Run();
-  }
 }
 
 void CaptureServiceReceiver::OnConnectTimeout(
@@ -264,11 +256,6 @@
   socket_.reset();
 }
 
-void CaptureServiceReceiver::SetConnectClosureForTest(
-    base::OnceClosure connected_cb) {
-  connected_cb_ = std::move(connected_cb);
-}
-
 void CaptureServiceReceiver::SetTaskRunnerForTest(
     scoped_refptr<base::SequencedTaskRunner> task_runner) {
   task_runner_ = std::move(task_runner);
diff --git a/chromecast/media/audio/capture_service/capture_service_receiver.h b/chromecast/media/audio/capture_service/capture_service_receiver.h
index f8562d4..6d5e988 100644
--- a/chromecast/media/audio/capture_service/capture_service_receiver.h
+++ b/chromecast/media/audio/capture_service/capture_service_receiver.h
@@ -7,10 +7,10 @@
 
 #include <memory>
 
-#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/threading/thread.h"
+#include "base/time/time.h"
 #include "media/audio/audio_io.h"
 #include "media/base/audio_parameters.h"
 
@@ -27,6 +27,14 @@
 
 class CaptureServiceReceiver {
  public:
+  // The timeout for a connecting socket to stop waiting and report error.
+  static constexpr base::TimeDelta kConnectTimeout =
+      base::TimeDelta::FromSeconds(1);
+
+  // The timeout for a connected socket to disconnect due to inactivity.
+  static constexpr base::TimeDelta kInactivityTimeout =
+      base::TimeDelta::FromSeconds(5);
+
   explicit CaptureServiceReceiver(const ::media::AudioParameters& audio_params);
   ~CaptureServiceReceiver();
 
@@ -39,18 +47,8 @@
       ::media::AudioInputStream::AudioInputCallback* input_callback,
       std::unique_ptr<net::StreamSocket> connecting_socket);
 
-  // Unit test can wait for the closure as a async way to run to idle. E.g.,
-  //
-  //   base::RunLoop run_loop;
-  //   SetConnectClosureForTest(run_loop.QuitClosure());
-  //   StartWithSocket(...);
-  //   run_loop.Run();
-  //
-  void SetConnectClosureForTest(base::OnceClosure connected_cb);
-
   // Unit test can set test task runner so as to run test in sync. Must be
-  // called after construction and before any other methods. Do not mix with the
-  // use of SetConnectClosureForTest().
+  // called after construction and before any other methods.
   void SetTaskRunnerForTest(
       scoped_refptr<base::SequencedTaskRunner> task_runner);
 
@@ -75,8 +73,6 @@
   std::unique_ptr<net::StreamSocket> connecting_socket_;
   std::unique_ptr<Socket> socket_;
 
-  base::OnceClosure connected_cb_;
-
   DISALLOW_COPY_AND_ASSIGN(CaptureServiceReceiver);
 };
 
diff --git a/chromecast/media/audio/capture_service/capture_service_receiver_unittest.cc b/chromecast/media/audio/capture_service/capture_service_receiver_unittest.cc
index 99efad0..c17b8ee 100644
--- a/chromecast/media/audio/capture_service/capture_service_receiver_unittest.cc
+++ b/chromecast/media/audio/capture_service/capture_service_receiver_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/big_endian.h"
 #include "base/run_loop.h"
+#include "base/task/post_task.h"
 #include "base/test/scoped_task_environment.h"
 #include "chromecast/media/audio/mock_audio_input_callback.h"
 #include "chromecast/net/mock_stream_socket.h"
@@ -36,11 +37,15 @@
             ::media::AudioParameters::AUDIO_PCM_LINEAR,
             ::media::ChannelLayout::CHANNEL_LAYOUT_MONO,
             16000,
-            160)) {}
+            160)) {
+    receiver_.SetTaskRunnerForTest(base::CreateSequencedTaskRunner(
+        {base::ThreadPool(), base::TaskPriority::USER_BLOCKING}));
+  }
   ~CaptureServiceReceiverTest() override = default;
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_{
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   chromecast::MockAudioInputCallback audio_;
   CaptureServiceReceiver receiver_;
 };
@@ -53,15 +58,14 @@
   EXPECT_CALL(*socket2, Connect(_)).WillOnce(Return(net::OK));
 
   // Sync.
-  base::RunLoop run_loop;
-  receiver_.SetConnectClosureForTest(run_loop.QuitClosure());
   receiver_.StartWithSocket(&audio_, std::move(socket1));
-  run_loop.Run();
+  scoped_task_environment_.RunUntilIdle();
   receiver_.Stop();
 
   // Async.
   receiver_.StartWithSocket(&audio_, std::move(socket2));
   receiver_.Stop();
+  scoped_task_environment_.RunUntilIdle();
 }
 
 TEST_F(CaptureServiceReceiverTest, ConnectFailed) {
@@ -69,15 +73,19 @@
   EXPECT_CALL(*socket, Connect(_)).WillOnce(Return(net::ERR_FAILED));
   EXPECT_CALL(audio_, OnError());
 
-  base::RunLoop run_loop;
-  receiver_.SetConnectClosureForTest(run_loop.QuitClosure());
   receiver_.StartWithSocket(&audio_, std::move(socket));
-  run_loop.Run();
+  scoped_task_environment_.RunUntilIdle();
 }
 
-// TODO(https://crbug.com/946657): Add unit tests for timeout once supporting of
-// MOCK_TIME for threads other than the main thread is available. Also, update
-// the use of task runner in the following tests.
+TEST_F(CaptureServiceReceiverTest, ConnectTimeout) {
+  auto socket = std::make_unique<MockStreamSocket>();
+  EXPECT_CALL(*socket, Connect(_)).WillOnce(Return(net::ERR_IO_PENDING));
+  EXPECT_CALL(audio_, OnError());
+
+  receiver_.StartWithSocket(&audio_, std::move(socket));
+  scoped_task_environment_.FastForwardBy(
+      CaptureServiceReceiver::kConnectTimeout);
+}
 
 TEST_F(CaptureServiceReceiverTest, ReceiveValidMessage) {
   auto socket = std::make_unique<MockStreamSocket>();
@@ -99,8 +107,6 @@
       .WillOnce(Return(net::ERR_IO_PENDING));
   EXPECT_CALL(audio_, OnData(_, _, 1.0 /* volume */));
 
-  receiver_.SetTaskRunnerForTest(
-      scoped_task_environment_.GetMainThreadTaskRunner());
   receiver_.StartWithSocket(&audio_, std::move(socket));
   scoped_task_environment_.RunUntilIdle();
 }
@@ -119,8 +125,6 @@
       }));
   EXPECT_CALL(audio_, OnError());
 
-  receiver_.SetTaskRunnerForTest(
-      scoped_task_environment_.GetMainThreadTaskRunner());
   receiver_.StartWithSocket(&audio_, std::move(socket));
   scoped_task_environment_.RunUntilIdle();
 }
@@ -132,8 +136,6 @@
       .WillOnce(Return(net::ERR_CONNECTION_RESET));
   EXPECT_CALL(audio_, OnError());
 
-  receiver_.SetTaskRunnerForTest(
-      scoped_task_environment_.GetMainThreadTaskRunner());
   receiver_.StartWithSocket(&audio_, std::move(socket));
   scoped_task_environment_.RunUntilIdle();
 }
@@ -144,12 +146,21 @@
   EXPECT_CALL(*socket, Read(_, _, _)).WillOnce(Return(0));
   EXPECT_CALL(audio_, OnError());
 
-  receiver_.SetTaskRunnerForTest(
-      scoped_task_environment_.GetMainThreadTaskRunner());
   receiver_.StartWithSocket(&audio_, std::move(socket));
   scoped_task_environment_.RunUntilIdle();
 }
 
+TEST_F(CaptureServiceReceiverTest, ReceiveTimeout) {
+  auto socket = std::make_unique<MockStreamSocket>();
+  EXPECT_CALL(*socket, Connect(_)).WillOnce(Return(net::OK));
+  EXPECT_CALL(*socket, Read(_, _, _)).WillOnce(Return(net::ERR_IO_PENDING));
+  EXPECT_CALL(audio_, OnError());
+
+  receiver_.StartWithSocket(&audio_, std::move(socket));
+  scoped_task_environment_.FastForwardBy(
+      CaptureServiceReceiver::kInactivityTimeout);
+}
+
 }  // namespace
 }  // namespace capture_service
 }  // namespace media
diff --git a/chromecast/media/cma/backend/loopback_handler.cc b/chromecast/media/cma/backend/loopback_handler.cc
index 8dba8489..8513058 100644
--- a/chromecast/media/cma/backend/loopback_handler.cc
+++ b/chromecast/media/cma/backend/loopback_handler.cc
@@ -239,6 +239,7 @@
     lock_.AssertAcquired();
 
     if (tasks_.size() == kMaxTasks) {
+      task_signal_.Signal();
       return;
     }
     tasks_.emplace_back(0, kSampleFormatF32, 0, 0, 0, nullptr, 0);
@@ -306,7 +307,7 @@
   base::Lock lock_;
   uint32_t buffer_tag_ GUARDED_BY(lock_) = 0;
   std::vector<std::unique_ptr<uint8_t[]>> buffers_ GUARDED_BY(lock_);
-  bool stop_thread_ GUARDED_BY(lock_);
+  bool stop_thread_ GUARDED_BY(lock_) = false;
   base::ConditionVariable task_signal_;
 
   std::vector<Task> tasks_;
diff --git a/chromecast/public/avsettings.h b/chromecast/public/avsettings.h
index fa27f1f..0d13ec8 100644
--- a/chromecast/public/avsettings.h
+++ b/chromecast/public/avsettings.h
@@ -233,7 +233,7 @@
   // supported by Hdmi sink, in which case implementation shall return false
   // without actually setting the content type.
   // This function should only be implemented on HDMI platforms.
-  static bool SetHdmiContentType(HdmiContentType content_type)
+  static CHROMECAST_EXPORT bool SetHdmiContentType(HdmiContentType content_type)
       __attribute__((weak));
 
   // Gets the HDMI latency in microseconds.
diff --git a/chromeos/network/network_handler.h b/chromeos/network/network_handler.h
index c6f4663d..eb5dbcee 100644
--- a/chromeos/network/network_handler.h
+++ b/chromeos/network/network_handler.h
@@ -85,6 +85,7 @@
 
   // Global network configuration services.
   UIProxyConfigService* ui_proxy_config_service();
+  bool has_ui_proxy_config_service() { return ui_proxy_config_service_.get(); }
 
  private:
   NetworkHandler();
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc
index f14c958..fdecabb 100644
--- a/chromeos/services/network_config/cros_network_config.cc
+++ b/chromeos/services/network_config/cros_network_config.cc
@@ -185,7 +185,8 @@
 
   // NetworkHandler and UIProxyConfigService may not exist in tests.
   UIProxyConfigService* ui_proxy_config_service =
-      NetworkHandler::IsInitialized()
+      NetworkHandler::IsInitialized() &&
+              NetworkHandler::Get()->has_ui_proxy_config_service()
           ? NetworkHandler::Get()->ui_proxy_config_service()
           : nullptr;
   result->proxy_mode =
diff --git a/components/chromeos_camera/BUILD.gn b/components/chromeos_camera/BUILD.gn
index afead10..d5ece41d 100644
--- a/components/chromeos_camera/BUILD.gn
+++ b/components/chromeos_camera/BUILD.gn
@@ -179,6 +179,7 @@
     ":mjpeg_decode_accelerator_service",
     "//base",
     "//media:test_support",
+    "//media/capture:chromeos_test_utils",
     "//media/gpu:buildflags",
     "//media/gpu/test:helpers",
     "//media/parsers",
@@ -206,6 +207,7 @@
     deps += [
       "//media/gpu/vaapi",
       "//media/gpu/vaapi:jpeg_decoder_unit_test",
+
       # TODO(crbug.com/986074): we should move this to its own executable, but
       # this would imply creating a new Tast wrapper in Chrome OS. So, for
       # convenience, we make the WebP tests run with the
diff --git a/components/chromeos_camera/mjpeg_decode_accelerator.h b/components/chromeos_camera/mjpeg_decode_accelerator.h
index a85c618..35c704b 100644
--- a/components/chromeos_camera/mjpeg_decode_accelerator.h
+++ b/components/chromeos_camera/mjpeg_decode_accelerator.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include "base/memory/unsafe_shared_memory_region.h"
 #include "media/base/bitstream_buffer.h"
 #include "media/base/video_frame.h"
 
@@ -100,19 +99,22 @@
 
   // Decodes the given bitstream buffer that contains one JPEG frame. It
   // supports at least baseline encoding defined in JPEG ISO/IEC 10918-1. The
-  // decoder will convert the color format to I420 or return UNSUPPORTED_JPEG
-  // if it cannot convert. Client still owns this buffer, but should deallocate
-  // or access the buffer only after receiving a decode callback VideoFrameReady
-  // with the corresponding bitstream_buffer_id, or NotifyError.
+  // decoder will convert the output to |video_frame->format()| or return
+  // PLATFORM_FAILURE if it cannot convert. Client still owns this buffer, but
+  // should deallocate or access the buffer only after receiving a decode
+  // callback VideoFrameReady with the corresponding |bitstream_buffer_id|, or
+  // NotifyError.
   // Parameters:
   //  |bitstream_buffer| contains encoded JPEG frame.
   //  |video_frame| contains an allocated video frame for the output, backed
   //  with an UnsafeSharedMemoryRegion.
   //
-  //  Client is responsible for filling the coded_size of video_frame and
-  //  allocating its backing buffer. For now, only unsafe shared memory backed
-  //  VideoFrames are supported. After decode completes, the decoded JPEG frame
-  //  will be filled into the |video_frame|.  Ownership of the
+  //  Client is responsible for filling the |video_frame->coded_size()|,
+  //  |video_frame->visible_rect()|, and allocating its backing buffer. For
+  //  unsafe shared memory backed VideoFrames, only I420 format is supported.
+  //  For DMA-buf backed VideoFrames, the supported formats depend on the
+  //  underlying hardware implementation. After decode completes, the decoded
+  //  JPEG frame will be filled into the |video_frame|. Ownership of the
   //  |bitstream_buffer| and |video_frame| remains with the client. The client
   //  is not allowed to deallocate them before VideoFrameReady or NotifyError()
   //  is invoked for given id of |bitstream_buffer|, or destructor returns.
diff --git a/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc b/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
index 088b39d..166f7b6 100644
--- a/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
+++ b/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
@@ -7,34 +7,52 @@
 #include <string.h>
 
 #include <memory>
+#include <string>
+#include <utility>
+#include <vector>
 
 #include "base/at_exit.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/memory/shared_memory_mapping.h"
 #include "base/memory/unsafe_shared_memory_region.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/optional.h"
 #include "base/path_service.h"
 #include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
 #include "base/timer/elapsed_timer.h"
 #include "build/build_config.h"
 #include "components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.h"
 #include "components/chromeos_camera/mjpeg_decode_accelerator.h"
 #include "media/base/test_data_util.h"
+#include "media/base/video_frame_layout.h"
+#include "media/capture/video/chromeos/local_gpu_memory_buffer_manager.h"
 #include "media/gpu/buildflags.h"
+#include "media/gpu/format_utils.h"
 #include "media/gpu/test/video_accelerator_unittest_helpers.h"
+#include "media/gpu/test/video_frame_helpers.h"
+#include "media/gpu/video_frame_mapper.h"
+#include "media/gpu/video_frame_mapper_factory.h"
 #include "media/parsers/jpeg_parser.h"
 #include "mojo/core/embedder/embedder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/libyuv/include/libyuv.h"
+#include "ui/gfx/buffer_types.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/native_pixmap_handle.h"
 
 #if BUILDFLAG(USE_VAAPI)
 #include "media/gpu/vaapi/vaapi_wrapper.h"
@@ -114,14 +132,11 @@
   void InitializeSizes(int width, int height) {
     visible_size.SetSize(width, height);
     // We don't expect odd dimensions for camera captures.
-    DCHECK_EQ(0, width % 2);
-    DCHECK_EQ(0, height % 2);
+    ASSERT_EQ(0, width % 2);
+    ASSERT_EQ(0, height % 2);
 
     coded_size.SetSize((visible_size.width() + 1) & ~1,
                        (visible_size.height() + 1) & ~1);
-    // The JPEG decoder will always return the decoded frame in I420 format.
-    output_size =
-        media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, coded_size);
   }
 
   const base::FilePath::StringType& filename() const {
@@ -133,7 +148,6 @@
   std::string data_str;
   gfx::Size visible_size;
   gfx::Size coded_size;
-  size_t output_size;
 };
 
 // Global singleton to hold on to common data and other user-defined options.
@@ -164,6 +178,18 @@
     return media::GetTestDataFilePath(file_path);
   }
 
+  // Creates a zero-initialized shared memory backed VideoFrame.
+  scoped_refptr<media::VideoFrame> CreateShmVideoFrame(
+      media::VideoPixelFormat format,
+      const gfx::Size& coded_size,
+      const gfx::Size& visible_size);
+
+  // Creates a zero-initialized DMA-buf backed VideoFrame.
+  scoped_refptr<media::VideoFrame> CreateDmaBufVideoFrame(
+      media::VideoPixelFormat format,
+      const gfx::Size& coded_size,
+      const gfx::Size& visible_size);
+
   // Used for InputSizeChange test case. The image size should be smaller than
   // |kDefaultJpegFilename|.
   std::unique_ptr<ParsedJpegImage> image_data_1280x720_black_;
@@ -186,6 +212,9 @@
  private:
   const base::FilePath::CharType* user_jpeg_filenames_;
   const base::FilePath::CharType* test_data_path_;
+
+  std::unique_ptr<media::LocalGpuMemoryBufferManager>
+      gpu_memory_buffer_manager_;
 };
 
 void MjpegDecodeAcceleratorTestEnvironment::SetUp() {
@@ -212,6 +241,112 @@
     auto image_data = ParsedJpegImage::CreateFromFile(input_file);
     image_data_user_.push_back(std::move(image_data));
   }
+
+  gpu_memory_buffer_manager_ =
+      std::make_unique<media::LocalGpuMemoryBufferManager>();
+}
+
+scoped_refptr<media::VideoFrame>
+MjpegDecodeAcceleratorTestEnvironment::CreateShmVideoFrame(
+    media::VideoPixelFormat format,
+    const gfx::Size& coded_size,
+    const gfx::Size& visible_size) {
+  size_t data_size = media::VideoFrame::AllocationSize(format, coded_size);
+  auto shm_region = base::UnsafeSharedMemoryRegion::Create(data_size);
+  if (!shm_region.IsValid()) {
+    LOG(ERROR) << "Failed to create shared memory";
+    return nullptr;
+  }
+  base::WritableSharedMemoryMapping shm_mapping = shm_region.Map();
+  if (!shm_mapping.IsValid()) {
+    LOG(ERROR) << "Failed to map shared memory region";
+    return nullptr;
+  }
+  memset(shm_mapping.memory(), 0, data_size);
+
+  scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapExternalData(
+      format, coded_size, gfx::Rect(visible_size), visible_size,
+      shm_mapping.GetMemoryAsSpan<uint8_t>().data(), data_size,
+      base::TimeDelta());
+  if (!frame) {
+    LOG(ERROR) << "Failed to create video frame";
+    return nullptr;
+  }
+  frame->BackWithOwnedSharedMemory(std::move(shm_region),
+                                   std::move(shm_mapping));
+
+  return frame;
+}
+
+scoped_refptr<media::VideoFrame>
+MjpegDecodeAcceleratorTestEnvironment::CreateDmaBufVideoFrame(
+    media::VideoPixelFormat format,
+    const gfx::Size& coded_size,
+    const gfx::Size& visible_size) {
+  if (!gpu_memory_buffer_manager_) {
+    LOG(ERROR) << "GpuMemoryBufferManager is not created" << format;
+    return nullptr;
+  }
+
+  // Create a GpuMemoryBuffer and get a NativePixmapHandle from it.
+  base::Optional<gfx::BufferFormat> gfx_format =
+      media::VideoPixelFormatToGfxBufferFormat(format);
+  if (!gfx_format) {
+    LOG(ERROR) << "Unsupported pixel format: " << format;
+    return nullptr;
+  }
+  std::unique_ptr<gfx::GpuMemoryBuffer> gmb =
+      gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
+          coded_size, *gfx_format, gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE,
+          gpu::kNullSurfaceHandle);
+  if (!gmb) {
+    LOG(ERROR) << "Failed to create GpuMemoryBuffer";
+    return nullptr;
+  }
+  gfx::GpuMemoryBufferHandle gmb_handle = gmb->CloneHandle();
+  if (gmb_handle.type != gfx::NATIVE_PIXMAP) {
+    LOG(ERROR) << "The GpuMemoryBufferHandle doesn't have type NATIVE_PIXMAP";
+    return nullptr;
+  }
+
+  const size_t num_planes = media::VideoFrame::NumPlanes(format);
+  if (gmb_handle.native_pixmap_handle.planes.size() != num_planes) {
+    LOG(ERROR) << "The number of planes of NativePixmapHandle doesn't match "
+                  "the pixel format";
+    return nullptr;
+  }
+
+  // Zero the memory.
+  if (!gmb->Map()) {
+    LOG(ERROR) << "Failed to map GpuMemoryBuffer";
+    return nullptr;
+  }
+  for (size_t i = 0; i < num_planes; i++) {
+    gfx::NativePixmapPlane& plane = gmb_handle.native_pixmap_handle.planes[i];
+    memset(gmb->memory(i), 0, plane.size);
+  }
+  gmb->Unmap();
+
+  // Create a VideoFrame from the NativePixmapHandle.
+  std::vector<media::VideoFrameLayout::Plane> planes;
+  std::vector<base::ScopedFD> dmabuf_fds;
+  for (size_t i = 0; i < num_planes; i++) {
+    gfx::NativePixmapPlane& plane = gmb_handle.native_pixmap_handle.planes[i];
+    planes.emplace_back(base::checked_cast<int32_t>(plane.stride),
+                        base::checked_cast<size_t>(plane.offset),
+                        base::checked_cast<size_t>(plane.size));
+    dmabuf_fds.push_back(std::move(plane.fd));
+  }
+  base::Optional<media::VideoFrameLayout> layout =
+      media::VideoFrameLayout::CreateWithPlanes(format, coded_size,
+                                                std::move(planes));
+  if (!layout) {
+    LOG(ERROR) << "Failed to create VideoFrameLayout";
+    return nullptr;
+  }
+  return media::VideoFrame::WrapExternalDmabufs(
+      *layout, gfx::Rect(visible_size), visible_size, std::move(dmabuf_fds),
+      base::TimeDelta());
 }
 
 enum ClientState {
@@ -227,10 +362,11 @@
   JpegClient(
       const std::vector<ParsedJpegImage*>& test_image_files,
       std::unique_ptr<media::test::ClientStateNotification<ClientState>> note,
+      bool use_dmabuf,
       bool is_skip);
   ~JpegClient() override;
   void CreateJpegDecoder();
-  void StartDecode(int32_t bitstream_buffer_id, bool do_prepare_memory = true);
+  void StartDecode(int32_t bitstream_buffer_id, bool do_prepare_memory);
   void PrepareMemory(int32_t bitstream_buffer_id);
   bool GetSoftwareDecodeResult(int32_t bitstream_buffer_id);
 
@@ -267,23 +403,25 @@
   // Used to notify another thread about the state. JpegClient owns this.
   std::unique_ptr<media::test::ClientStateNotification<ClientState>> note_;
 
+  // Use DMA-buf backed output buffer for hardware decoder.
+  // TODO(kamesan): update the comment when this applies to software decoder.
+  bool use_dmabuf_;
+
   // Skip JDA decode result. Used for testing performance.
   bool is_skip_;
 
   // Mapped memory of input file.
   base::UnsafeSharedMemoryRegion in_shm_;
   base::WritableSharedMemoryMapping in_shm_mapping_;
-  // Mapped memory of output buffer from hardware decoder.
-  base::UnsafeSharedMemoryRegion hw_out_region_;
-  base::WritableSharedMemoryMapping hw_out_mapping_;
-  // Video frame corresponding to the output of the hardware decoder.
+  // Output video frame from the hardware decoder.
+  scoped_refptr<media::VideoFrame> hw_out_dmabuf_frame_;
   scoped_refptr<media::VideoFrame> hw_out_frame_;
-  // Mapped memory of output buffer from software decoder.
-  base::UnsafeSharedMemoryRegion sw_out_shm_;
-  base::WritableSharedMemoryMapping sw_out_mapping_;
-  // Video frame corresponding to the output of the software decoder.
+  // Output video frame from the software decoder.
   scoped_refptr<media::VideoFrame> sw_out_frame_;
 
+  // Video frame mapper used to map |hw_out_dmabuf_frame_| for software access.
+  std::unique_ptr<media::VideoFrameMapper> frame_mapper_;
+
   // This should be the first member to get destroyed because |decoder_|
   // potentially uses other members in the JpegClient instance. For example,
   // as decode tasks finish in a new thread spawned by |decoder_|,
@@ -296,10 +434,12 @@
 JpegClient::JpegClient(
     const std::vector<ParsedJpegImage*>& test_image_files,
     std::unique_ptr<media::test::ClientStateNotification<ClientState>> note,
+    bool use_dmabuf,
     bool is_skip)
     : test_image_files_(test_image_files),
       state_(CS_CREATED),
       note_(std::move(note)),
+      use_dmabuf_(use_dmabuf),
       is_skip_(is_skip) {}
 
 JpegClient::~JpegClient() {}
@@ -344,6 +484,18 @@
     SetState(CS_ERROR);
     return;
   }
+
+  if (use_dmabuf_) {
+    // Map and convert the output frame to I420.
+    ASSERT_TRUE(frame_mapper_);
+    scoped_refptr<media::VideoFrame> mapped_frame =
+        frame_mapper_->Map(hw_out_dmabuf_frame_);
+    ASSERT_TRUE(mapped_frame);
+    hw_out_frame_ = media::test::ConvertVideoFrame(mapped_frame.get(),
+                                                   media::PIXEL_FORMAT_I420);
+    ASSERT_TRUE(hw_out_frame_);
+  }
+
   if (g_save_to_file) {
     SaveToFile(bitstream_buffer_id, hw_out_frame_, "_hw");
     SaveToFile(bitstream_buffer_id, sw_out_frame_, "_sw");
@@ -373,27 +525,31 @@
   if (!in_shm_mapping_.IsValid() || input_size > in_shm_mapping_.size()) {
     in_shm_ = base::UnsafeSharedMemoryRegion::Create(input_size);
     in_shm_mapping_ = in_shm_.Map();
-    LOG_ASSERT(in_shm_mapping_.IsValid());
+    ASSERT_TRUE(in_shm_mapping_.IsValid());
   }
   memcpy(in_shm_mapping_.memory(), image_file->data_str.data(), input_size);
 
-  if (!hw_out_region_.IsValid() ||
-      image_file->output_size > hw_out_mapping_.size()) {
-    hw_out_region_ =
-        base::UnsafeSharedMemoryRegion::Create(image_file->output_size);
-    hw_out_mapping_ = hw_out_region_.Map();
+  if (use_dmabuf_) {
+    // TODO(kamesan): create test cases for more formats when they're used.
+    hw_out_dmabuf_frame_ = g_env->CreateDmaBufVideoFrame(
+        media::PIXEL_FORMAT_NV12, image_file->coded_size,
+        image_file->visible_size);
+    ASSERT_TRUE(hw_out_dmabuf_frame_);
+    frame_mapper_ = media::VideoFrameMapperFactory::CreateMapper(
+        hw_out_dmabuf_frame_->format(), true);
+    ASSERT_TRUE(frame_mapper_);
+  } else {
+    // MJDA only supports I420 format for SHM output buffer.
+    hw_out_frame_ = g_env->CreateShmVideoFrame(media::PIXEL_FORMAT_I420,
+                                               image_file->coded_size,
+                                               image_file->visible_size);
+    ASSERT_TRUE(hw_out_frame_);
   }
-  memset(hw_out_mapping_.memory(), 0, image_file->output_size);
 
-  if (!sw_out_mapping_.IsValid() ||
-      image_file->output_size > sw_out_mapping_.size()) {
-    sw_out_shm_ =
-        base::UnsafeSharedMemoryRegion::Create(image_file->output_size);
-    LOG_ASSERT(sw_out_shm_.IsValid());
-    sw_out_mapping_ = sw_out_shm_.Map();
-    LOG_ASSERT(sw_out_mapping_.IsValid());
-  }
-  memset(sw_out_mapping_.memory(), 0, image_file->output_size);
+  sw_out_frame_ = g_env->CreateShmVideoFrame(media::PIXEL_FORMAT_I420,
+                                             image_file->coded_size,
+                                             image_file->visible_size);
+  ASSERT_TRUE(sw_out_frame_);
 }
 
 void JpegClient::SetState(ClientState new_state) {
@@ -466,13 +622,13 @@
                                 hw_out_frame_->visible_rect().height());
     const size_t columns = media::VideoFrame::Columns(
         plane, media::PIXEL_FORMAT_I420, hw_out_frame_->visible_rect().width());
-    LOG_ASSERT(hw_out_frame_->stride(plane) == sw_out_frame_->stride(plane));
-    const int stride = hw_out_frame_->stride(plane);
+    const int hw_stride = hw_out_frame_->stride(plane);
+    const int sw_stride = sw_out_frame_->stride(plane);
     for (size_t row = 0; row < rows; ++row) {
       for (size_t col = 0; col < columns; ++col)
         mean_abs_difference += std::abs(hw_data[col] - sw_data[col]);
-      hw_data += stride;
-      sw_data += stride;
+      hw_data += hw_stride;
+      sw_data += sw_stride;
     }
     num_samples += rows * columns;
   }
@@ -483,7 +639,7 @@
 
 void JpegClient::StartDecode(int32_t bitstream_buffer_id,
                              bool do_prepare_memory) {
-  DCHECK_LT(static_cast<size_t>(bitstream_buffer_id), test_image_files_.size());
+  ASSERT_LT(static_cast<size_t>(bitstream_buffer_id), test_image_files_.size());
   ParsedJpegImage* image_file = test_image_files_[bitstream_buffer_id];
 
   if (do_prepare_memory)
@@ -494,26 +650,12 @@
   media::BitstreamBuffer bitstream_buffer(
       bitstream_buffer_id, std::move(dup_region), image_file->data_str.size());
 
-  hw_out_frame_ = media::VideoFrame::WrapExternalData(
-      media::PIXEL_FORMAT_I420, image_file->coded_size,
-      gfx::Rect(image_file->visible_size), image_file->visible_size,
-      hw_out_mapping_.GetMemoryAsSpan<uint8_t>().data(),
-      image_file->output_size, base::TimeDelta());
-  hw_out_frame_->BackWithSharedMemory(&hw_out_region_);
-  LOG_ASSERT(hw_out_frame_.get());
-
-  decoder_->Decode(std::move(bitstream_buffer), hw_out_frame_);
+  decoder_->Decode(std::move(bitstream_buffer),
+                   use_dmabuf_ ? hw_out_dmabuf_frame_ : hw_out_frame_);
 }
 
 bool JpegClient::GetSoftwareDecodeResult(int32_t bitstream_buffer_id) {
   ParsedJpegImage* image_file = test_image_files_[bitstream_buffer_id];
-  LOG_ASSERT(sw_out_shm_.IsValid() && sw_out_mapping_.IsValid());
-  sw_out_frame_ = media::VideoFrame::WrapExternalData(
-      media::PIXEL_FORMAT_I420, image_file->coded_size,
-      gfx::Rect(image_file->visible_size), image_file->visible_size,
-      sw_out_mapping_.GetMemoryAsSpan<uint8_t>().data(),
-      image_file->output_size, base::TimeDelta());
-  sw_out_frame_->BackWithSharedMemory(&sw_out_shm_);
   if (libyuv::ConvertToI420(static_cast<uint8_t*>(in_shm_mapping_.memory()),
                             image_file->data_str.size(),
                             sw_out_frame_->data(media::VideoFrame::kYPlane),
@@ -553,7 +695,7 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedJpegClient);
 };
 
-class MjpegDecodeAcceleratorTest : public ::testing::Test {
+class MjpegDecodeAcceleratorTest : public ::testing::TestWithParam<bool> {
  protected:
   MjpegDecodeAcceleratorTest() = default;
 
@@ -583,7 +725,7 @@
     auto client = std::make_unique<JpegClient>(
         images,
         std::make_unique<media::test::ClientStateNotification<ClientState>>(),
-        false /* is_skip */);
+        GetParam() /* use_dmabuf */, false /* is_skip */);
     scoped_clients.emplace_back(
         new ScopedJpegClient(decoder_thread.task_runner(), std::move(client)));
 
@@ -599,7 +741,7 @@
       decoder_thread.task_runner()->PostTask(
           FROM_HERE, base::BindOnce(&JpegClient::StartDecode,
                                     base::Unretained(scoped_client->client()),
-                                    index, true));
+                                    index, true /* do_prepare_memory */));
     }
     if (index < expected_status.size()) {
       for (const auto& scoped_client : scoped_clients) {
@@ -620,7 +762,7 @@
   auto client = std::make_unique<JpegClient>(
       images,
       std::make_unique<media::test::ClientStateNotification<ClientState>>(),
-      true /* is_skip */);
+      GetParam() /* use_dmabuf */, true /* is_skip */);
   auto scoped_client = std::make_unique<ScopedJpegClient>(
       decoder_thread.task_runner(), std::move(client));
 
@@ -634,9 +776,10 @@
   const base::ElapsedTimer timer;
   for (int index = 0; index < decode_times; index++) {
     decoder_thread.task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&JpegClient::StartDecode,
-                                  base::Unretained(scoped_client->client()),
-                                  bitstream_buffer_id, false));
+        FROM_HERE,
+        base::BindOnce(&JpegClient::StartDecode,
+                       base::Unretained(scoped_client->client()),
+                       bitstream_buffer_id, false /* do_prepare_memory */));
     ASSERT_EQ(scoped_client->client()->note()->Wait(), CS_DECODE_PASS);
   }
   const base::TimeDelta elapsed_time = timer.Elapsed();
@@ -650,12 +793,16 @@
 void MjpegDecodeAcceleratorTest::PerfDecodeBySW(
     int decode_times,
     const std::vector<ParsedJpegImage*>& images) {
+  // TODO(kamesan): implement SW decoding into DMA-bufs in
+  // GetSoftwareDecodeResult().
+  if (GetParam())
+    GTEST_SKIP();
   LOG_ASSERT(images.size() == 1);
 
   std::unique_ptr<JpegClient> client = std::make_unique<JpegClient>(
       images,
       std::make_unique<media::test::ClientStateNotification<ClientState>>(),
-      true /* is_skip */);
+      GetParam() /* use_dmabuf */, true /* is_skip */);
 
   const int32_t bitstream_buffer_id = 0;
   client->PrepareMemory(bitstream_buffer_id);
@@ -704,7 +851,7 @@
 }
 
 TEST(JpegClientTest, GetMeanAbsoluteDifference) {
-  JpegClient client(std::vector<ParsedJpegImage*>(), nullptr, false);
+  JpegClient client(std::vector<ParsedJpegImage*>(), nullptr, false, false);
   client.hw_out_frame_ = GetTestDecodedData();
   client.sw_out_frame_ = GetTestDecodedData();
 
@@ -738,7 +885,7 @@
               kMaxAllowedDifference);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, SimpleDecode) {
+TEST_P(MjpegDecodeAcceleratorTest, SimpleDecode) {
   std::vector<ParsedJpegImage*> images;
   for (auto& image : g_env->image_data_user_)
     images.push_back(image.get());
@@ -746,7 +893,7 @@
   TestDecode(images, expected_status);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, MultipleDecoders) {
+TEST_P(MjpegDecodeAcceleratorTest, MultipleDecoders) {
   std::vector<ParsedJpegImage*> images;
   for (auto& image : g_env->image_data_user_)
     images.push_back(image.get());
@@ -754,7 +901,7 @@
   TestDecode(images, expected_status, 3 /* num_concurrent_decoders */);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, InputSizeChange) {
+TEST_P(MjpegDecodeAcceleratorTest, InputSizeChange) {
   // The size of |image_data_1280x720_black_| is smaller than
   // |image_data_1280x720_default_|.
   const std::vector<ParsedJpegImage*> images = {
@@ -765,7 +912,7 @@
   TestDecode(images, expected_status);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, ResolutionChange) {
+TEST_P(MjpegDecodeAcceleratorTest, ResolutionChange) {
   const std::vector<ParsedJpegImage*> images = {
       g_env->image_data_640x368_black_.get(),
       g_env->image_data_1280x720_default_.get(),
@@ -774,7 +921,7 @@
   TestDecode(images, expected_status);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, CodedSizeAlignment) {
+TEST_P(MjpegDecodeAcceleratorTest, CodedSizeAlignment) {
   const std::vector<ParsedJpegImage*> images = {
       g_env->image_data_640x360_black_.get()};
   const std::vector<ClientState> expected_status = {CS_DECODE_PASS};
@@ -782,7 +929,7 @@
 }
 
 // Tests whether different JPEG sampling formats will be decoded correctly.
-TEST_F(MjpegDecodeAcceleratorTest, SamplingFormatChange) {
+TEST_P(MjpegDecodeAcceleratorTest, SamplingFormatChange) {
   const std::vector<ParsedJpegImage*> images = {
       g_env->image_data_640x368_black_.get(),
       g_env->image_data_640x368_422_black_.get()};
@@ -790,14 +937,14 @@
   TestDecode(images, expected_status);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, FailureJpeg) {
+TEST_P(MjpegDecodeAcceleratorTest, FailureJpeg) {
   const std::vector<ParsedJpegImage*> images = {
       g_env->image_data_invalid_.get()};
   const std::vector<ClientState> expected_status = {CS_ERROR};
   TestDecode(images, expected_status);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, KeepDecodeAfterFailure) {
+TEST_P(MjpegDecodeAcceleratorTest, KeepDecodeAfterFailure) {
   const std::vector<ParsedJpegImage*> images = {
       g_env->image_data_invalid_.get(),
       g_env->image_data_1280x720_default_.get()};
@@ -805,7 +952,7 @@
   TestDecode(images, expected_status);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, Abort) {
+TEST_P(MjpegDecodeAcceleratorTest, Abort) {
   constexpr size_t kNumOfJpegToDecode = 5;
   const std::vector<ParsedJpegImage*> images(
       kNumOfJpegToDecode, g_env->image_data_1280x720_default_.get());
@@ -816,7 +963,7 @@
   TestDecode(images, expected_status, 2 /* num_concurrent_decoders */);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, PerfJDA) {
+TEST_P(MjpegDecodeAcceleratorTest, PerfJDA) {
   // Only the first image will be used for perf testing.
   ASSERT_GE(g_env->image_data_user_.size(), 1u);
   const std::vector<ParsedJpegImage*> images = {
@@ -824,7 +971,7 @@
   PerfDecodeByJDA(g_env->perf_decode_times_, images);
 }
 
-TEST_F(MjpegDecodeAcceleratorTest, PerfSW) {
+TEST_P(MjpegDecodeAcceleratorTest, PerfSW) {
   // Only the first image will be used for perf testing.
   ASSERT_GE(g_env->image_data_user_.size(), 1u);
   const std::vector<ParsedJpegImage*> images = {
@@ -832,6 +979,15 @@
   PerfDecodeBySW(g_env->perf_decode_times_, images);
 }
 
+std::string TestParamToString(::testing::TestParamInfo<bool> param_info) {
+  return param_info.param ? "DMABUF" : "SHMEM";
+}
+
+INSTANTIATE_TEST_SUITE_P(,
+                         MjpegDecodeAcceleratorTest,
+                         ::testing::Bool(),
+                         TestParamToString);
+
 }  // namespace
 }  // namespace chromeos_camera
 
@@ -848,7 +1004,7 @@
   LOG_ASSERT(logging::InitLogging(settings));
 
   const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
-  DCHECK(cmd_line);
+  LOG_ASSERT(cmd_line);
 
   const base::FilePath::CharType* jpeg_filenames = nullptr;
   const base::FilePath::CharType* test_data_path = nullptr;
diff --git a/components/crash/content/app/BUILD.gn b/components/crash/content/app/BUILD.gn
index 529131ef..633a18c 100644
--- a/components/crash/content/app/BUILD.gn
+++ b/components/crash/content/app/BUILD.gn
@@ -213,7 +213,7 @@
   }
 }
 
-if (is_mac) {
+if (is_mac || is_android) {
   # We build a chromium-specific crashpad_handler executable so that we can
   # define custom UserStreamDataSources.
   executable("chrome_crashpad_handler") {
@@ -222,15 +222,11 @@
     ]
 
     deps = [
-      "//components/gwp_asan/buildflags",
-      "//third_party/crashpad/crashpad/handler:handler",
+      ":crashpad_handler_main",
+      "//third_party/crashpad/crashpad/handler",
     ]
 
-    if (enable_gwp_asan) {
-      deps += [ "//components/gwp_asan/crash_handler" ]
-    }
-
-    if (is_component_build) {
+    if (is_mac && is_component_build) {
       ldflags = [
         # The handler is in
         # Chromium.app/Contents/Versions/X/Chromium Framework.framework/Versions/A/Helpers/
@@ -257,6 +253,26 @@
   }
 }
 
+if (is_android) {
+  # There is not any normal way to package native executables in an Android APK.
+  # It is normal to package native code as a loadable module but Android's APK
+  # installer will ignore files not named like a shared object, so give the
+  # handler executable an acceptable name.
+  copy("chrome_crashpad_handler_named_as_so") {
+    deps = [
+      ":chrome_crashpad_handler",
+    ]
+
+    sources = [
+      "$root_out_dir/chrome_crashpad_handler",
+    ]
+
+    outputs = [
+      "$root_out_dir/libchrome_crashpad_handler.so",
+    ]
+  }
+}
+
 # This source set provides the functionality required for tests, which on Windows
 # link the export thunks directly into the test binary.
 source_set("test_support") {
diff --git a/components/crash/content/app/chrome_crashpad_handler.cc b/components/crash/content/app/chrome_crashpad_handler.cc
index c4b629d..997f069 100644
--- a/components/crash/content/app/chrome_crashpad_handler.cc
+++ b/components/crash/content/app/chrome_crashpad_handler.cc
@@ -2,22 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <memory>
-
-#include "components/gwp_asan/buildflags/buildflags.h"
-#include "third_party/crashpad/crashpad/handler/handler_main.h"
-#include "third_party/crashpad/crashpad/handler/user_stream_data_source.h"
-
-#if BUILDFLAG(ENABLE_GWP_ASAN)
-#include "components/gwp_asan/crash_handler/crash_handler.h"
-#endif
+// Forward declare this for macOS (it's only defined by crashpad on Android.)
+extern "C" int CrashpadHandlerMain(int argc, char* argv[]);
 
 int main(int argc, char* argv[]) {
-  crashpad::UserStreamDataSources user_stream_data_sources;
-#if BUILDFLAG(ENABLE_GWP_ASAN)
-  user_stream_data_sources.push_back(
-      std::make_unique<gwp_asan::UserStreamDataSource>());
-#endif
-
-  return crashpad::HandlerMain(argc, argv, &user_stream_data_sources);
+  return CrashpadHandlerMain(argc, argv);
 }
diff --git a/components/crash/content/app/crashpad_android.cc b/components/crash/content/app/crashpad_android.cc
index 991120a..06f62e8 100644
--- a/components/crash/content/app/crashpad_android.cc
+++ b/components/crash/content/app/crashpad_android.cc
@@ -397,7 +397,7 @@
   if (!base::PathService::Get(base::DIR_MODULE, exe_dir)) {
     return false;
   }
-  *handler_path = exe_dir->Append("libcrashpad_handler.so");
+  *handler_path = exe_dir->Append("libchrome_crashpad_handler.so");
   return true;
 }
 
diff --git a/components/download/internal/common/download_stats.cc b/components/download/internal/common/download_stats.cc
index 1a141f7..0f5f61a0 100644
--- a/components/download/internal/common/download_stats.cc
+++ b/components/download/internal/common/download_stats.cc
@@ -1235,14 +1235,6 @@
       DownloadContent::MAX);
 }
 
-void RecordDownloadConnectionSecurity(const GURL& download_url,
-                                      const std::vector<GURL>& url_chain) {
-  UMA_HISTOGRAM_ENUMERATION(
-      "Download.TargetConnectionSecurity",
-      CheckDownloadConnectionSecurity(download_url, url_chain),
-      DOWNLOAD_CONNECTION_SECURITY_MAX);
-}
-
 void RecordDownloadContentTypeSecurity(
     const GURL& download_url,
     const std::vector<GURL>& url_chain,
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc
index 4526e9b..c3e41ddd 100644
--- a/components/download/internal/common/in_progress_download_manager.cc
+++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -403,7 +403,6 @@
   std::string mime_type = info->mime_type;
 
   if (info->is_new_download) {
-    RecordDownloadConnectionSecurity(info->url(), info->url_chain);
     RecordDownloadContentTypeSecurity(info->url(), info->url_chain,
                                       info->mime_type, is_origin_secure_cb_);
   }
diff --git a/components/gcm_driver/fake_gcm_profile_service.cc b/components/gcm_driver/fake_gcm_profile_service.cc
index c875d5c..dd4da997 100644
--- a/components/gcm_driver/fake_gcm_profile_service.cc
+++ b/components/gcm_driver/fake_gcm_profile_service.cc
@@ -38,16 +38,6 @@
   void OnDispatchMessage(const std::string& app_id,
                          const IncomingMessage& message);
 
-  // instance_id::FakeGCMDriverForInstanceID overrides:
-  void SendWebPushMessage(const std::string& app_id,
-                          const std::string& authorized_entity,
-                          const std::string& p256dh,
-                          const std::string& auth_secret,
-                          const std::string& fcm_token,
-                          crypto::ECPrivateKey* vapid_key,
-                          gcm::WebPushMessage message,
-                          SendWebPushMessageCallback callback) override;
-
  protected:
   // FakeGCMDriver overrides:
   void RegisterImpl(const std::string& app_id,
@@ -162,21 +152,6 @@
                      app_id, receiver_id, message));
 }
 
-void FakeGCMProfileService::CustomFakeGCMDriver::SendWebPushMessage(
-    const std::string& app_id,
-    const std::string& authorized_entity,
-    const std::string& p256dh,
-    const std::string& auth_secret,
-    const std::string& fcm_token,
-    crypto::ECPrivateKey* vapid_key,
-    gcm::WebPushMessage message,
-    SendWebPushMessageCallback callback) {
-  if (service_->collect_) {
-    service_->last_receiver_id_ = fcm_token;
-    service_->last_web_push_message_ = std::move(message);
-  }
-}
-
 void FakeGCMProfileService::CustomFakeGCMDriver::DoSend(
     const std::string& app_id,
     const std::string& receiver_id,
diff --git a/components/gcm_driver/fake_gcm_profile_service.h b/components/gcm_driver/fake_gcm_profile_service.h
index fd6cd549..8302eb63 100644
--- a/components/gcm_driver/fake_gcm_profile_service.h
+++ b/components/gcm_driver/fake_gcm_profile_service.h
@@ -39,10 +39,6 @@
     return last_sent_message_;
   }
 
-  const WebPushMessage& last_web_push_message() const {
-    return last_web_push_message_;
-  }
-
   const std::string& last_receiver_id() const { return last_receiver_id_; }
 
   const std::string& last_registered_app_id() const {
@@ -73,7 +69,6 @@
   std::list<GCMClient::Result> unregister_responses_;
   OutgoingMessage last_sent_message_;
   std::string last_receiver_id_;
-  WebPushMessage last_web_push_message_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeGCMProfileService);
 };
diff --git a/components/ntp_tiles/OWNERS b/components/ntp_tiles/OWNERS
index ec42eef..5cd35eb 100644
--- a/components/ntp_tiles/OWNERS
+++ b/components/ntp_tiles/OWNERS
@@ -1,6 +1,3 @@
-fhorschig@chromium.org
-jkrcal@chromium.org
+dbeam@chromium.org
 kristipark@chromium.org
-mastiz@chromium.org
-treib@chromium.org
 # COMPONENT: UI>Browser>ContentSuggestions>History
diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc
index 43a47cd..3dc120a0 100644
--- a/components/pdf/renderer/pdf_accessibility_tree.cc
+++ b/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -34,6 +34,10 @@
 // for that text run to be considered to be a heading instead of normal text.
 const double kHeadingFontSizeRatio = 1.2;
 
+// Ratio between the delta-y between two text runs and the median on the page
+// for it to be considered a line break.
+const double kLineSpacingRatio = 0.8;
+
 // Ratio between the line spacing between two lines and the median on the
 // page for that line spacing to be considered a paragraph break.
 const double kParagraphLineSpacingRatio = 1.2;
@@ -122,13 +126,15 @@
   doc_node_->child_ids.push_back(page_node->id);
 
   double heading_font_size_threshold = 0;
+  double paragraph_spacing_threshold = 0;
   double line_spacing_threshold = 0;
-  ComputeParagraphAndHeadingThresholds(text_runs,
-                                       &heading_font_size_threshold,
+  ComputeParagraphAndHeadingThresholds(text_runs, &heading_font_size_threshold,
+                                       &paragraph_spacing_threshold,
                                        &line_spacing_threshold);
 
   ui::AXNodeData* para_node = nullptr;
   ui::AXNodeData* static_text_node = nullptr;
+  ui::AXNodeData* previous_on_line_node = nullptr;
   std::string static_text;
   uint32_t char_index = 0;
   for (size_t i = 0; i < text_runs.size(); ++i) {
@@ -181,6 +187,15 @@
     static_text_node->relative_bounds.bounds.Union(
         inline_text_box_node->relative_bounds.bounds);
 
+    if (previous_on_line_node) {
+      previous_on_line_node->AddIntAttribute(
+          ax::mojom::IntAttribute::kNextOnLineId, inline_text_box_node->id);
+      inline_text_box_node->AddIntAttribute(
+          ax::mojom::IntAttribute::kPreviousOnLineId,
+          previous_on_line_node->id);
+    }
+    previous_on_line_node = inline_text_box_node;
+
     if (i == text_runs.size() - 1) {
       static_text_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
                                            static_text);
@@ -190,13 +205,17 @@
     double line_spacing =
         text_runs[i + 1].bounds.point.y - text_run.bounds.point.y;
     if (text_run.font_size != text_runs[i + 1].font_size ||
-        (line_spacing_threshold > 0 &&
-         line_spacing > line_spacing_threshold)) {
+        (paragraph_spacing_threshold > 0 &&
+         line_spacing > paragraph_spacing_threshold)) {
       static_text_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
                                            static_text);
       para_node = nullptr;
       static_text_node = nullptr;
       static_text.clear();
+      previous_on_line_node = nullptr;
+    } else if (line_spacing_threshold > 0 &&
+               line_spacing > line_spacing_threshold) {
+      previous_on_line_node = nullptr;
     }
   }
 
@@ -276,6 +295,7 @@
 void PdfAccessibilityTree::ComputeParagraphAndHeadingThresholds(
     const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
     double* out_heading_font_size_threshold,
+    double* out_paragraph_spacing_threshold,
     double* out_line_spacing_threshold) {
   // Scan over the font sizes and line spacing within this page and
   // set heuristic thresholds so that text larger than the median font
@@ -300,11 +320,14 @@
           median_font_size * kHeadingFontSizeRatio;
     }
   }
-  if (line_spacings.size() > 4) {
+  if (line_spacings.size() > 0) {
     std::sort(line_spacings.begin(), line_spacings.end());
     double median_line_spacing = line_spacings[line_spacings.size() / 2];
     if (median_line_spacing > kMinimumLineSpacing) {
-      *out_line_spacing_threshold =
+      *out_line_spacing_threshold = median_line_spacing * kLineSpacingRatio;
+    }
+    if (line_spacings.size() > 4) {
+      *out_paragraph_spacing_threshold =
           median_line_spacing * kParagraphLineSpacingRatio;
     }
   }
diff --git a/components/pdf/renderer/pdf_accessibility_tree.h b/components/pdf/renderer/pdf_accessibility_tree.h
index 4c468e6..7cfadb2 100644
--- a/components/pdf/renderer/pdf_accessibility_tree.h
+++ b/components/pdf/renderer/pdf_accessibility_tree.h
@@ -81,6 +81,7 @@
   void ComputeParagraphAndHeadingThresholds(
       const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
       double* out_heading_font_size_threshold,
+      double* out_paragraph_spacing_threshold,
       double* out_line_spacing_threshold);
   std::string GetTextRunCharsAsUTF8(
       const PP_PrivateAccessibilityTextRunInfo& text_run,
diff --git a/components/safe_browsing/db/v4_store.cc b/components/safe_browsing/db/v4_store.cc
index 89668bc..ac3237c 100644
--- a/components/safe_browsing/db/v4_store.cc
+++ b/components/safe_browsing/db/v4_store.cc
@@ -655,8 +655,6 @@
     return UNEXPECTED_MAGIC_NUMBER_FAILURE;
   }
 
-  base::UmaHistogramSparse("SafeBrowsing.V4StoreVersionRead",
-                           file_format.version_number());
   if (file_format.version_number() != kFileVersion) {
     return FILE_VERSION_INCOMPATIBLE_FAILURE;
   }
diff --git a/components/services/patch/BUILD.gn b/components/services/patch/BUILD.gn
index 68354ae4..a7b67cf6 100644
--- a/components/services/patch/BUILD.gn
+++ b/components/services/patch/BUILD.gn
@@ -6,8 +6,6 @@
   sources = [
     "file_patcher_impl.cc",
     "file_patcher_impl.h",
-    "patch_service.cc",
-    "patch_service.h",
   ]
 
   deps = [
@@ -19,6 +17,25 @@
 
   public_deps = [
     "//components/services/patch/public/mojom",
-    "//services/service_manager/public/cpp",
+  ]
+}
+
+source_set("in_process") {
+  # NOTE: In-process file patching is unsafe! Unfortunately on iOS we have no
+  # other choice. On all other platforms, this target is restricted to tests.
+  testonly = !is_ios
+
+  sources = [
+    "in_process_file_patcher.cc",
+    "in_process_file_patcher.h",
+  ]
+
+  deps = [
+    ":lib",
+  ]
+
+  public_deps = [
+    "//components/services/patch/public/mojom",
+    "//mojo/public/cpp/bindings",
   ]
 }
diff --git a/components/services/patch/DEPS b/components/services/patch/DEPS
index ea7209ad8..5b3aea1 100644
--- a/components/services/patch/DEPS
+++ b/components/services/patch/DEPS
@@ -1,6 +1,5 @@
 include_rules = [
   "+components/update_client",
   "+courgette",
-  "+mojo",  # By definition.
-  "+services/service_manager/public",  # Every service talks to Service Manager.
+  "+mojo/public",
 ]
diff --git a/components/services/patch/content/BUILD.gn b/components/services/patch/content/BUILD.gn
new file mode 100644
index 0000000..a2331d18
--- /dev/null
+++ b/components/services/patch/content/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("content") {
+  sources = [
+    "patch_service.cc",
+    "patch_service.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/strings",
+    "//content/public/browser",
+  ]
+
+  public_deps = [
+    "//components/services/patch/public/mojom",
+    "//mojo/public/cpp/bindings",
+  ]
+}
diff --git a/components/services/patch/content/DEPS b/components/services/patch/content/DEPS
new file mode 100644
index 0000000..1c35d9c
--- /dev/null
+++ b/components/services/patch/content/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+content/public/browser",
+]
diff --git a/components/services/patch/content/patch_service.cc b/components/services/patch/content/patch_service.cc
new file mode 100644
index 0000000..07f3670
--- /dev/null
+++ b/components/services/patch/content/patch_service.cc
@@ -0,0 +1,24 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/patch/content/patch_service.h"
+
+#include "base/no_destructor.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/service_process_host.h"
+
+namespace patch {
+
+mojo::PendingRemote<mojom::FilePatcher> LaunchFilePatcher() {
+  mojo::PendingRemote<mojom::FilePatcher> remote;
+  content::ServiceProcessHost::Launch<mojom::FilePatcher>(
+      remote.InitWithNewPipeAndPassReceiver(),
+      content::ServiceProcessHost::Options()
+          .WithSandboxType(service_manager::SANDBOX_TYPE_UTILITY)
+          .WithDisplayName(IDS_PATCH_SERVICE_DISPLAY_NAME)
+          .Pass());
+  return remote;
+}
+
+}  //  namespace patch
diff --git a/components/services/patch/content/patch_service.h b/components/services/patch/content/patch_service.h
new file mode 100644
index 0000000..5710c562
--- /dev/null
+++ b/components/services/patch/content/patch_service.h
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_PATCH_CONTENT_PATCH_SERVICE_H_
+#define COMPONENTS_SERVICES_PATCH_CONTENT_PATCH_SERVICE_H_
+
+#include "base/callback.h"
+#include "components/services/patch/public/mojom/file_patcher.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+
+namespace patch {
+
+// Launches a new instance of the FilePatcher service in an isolated, sandboxed
+// process, and returns a remote interface to control the service. The lifetime
+// of the process is tied to that of the Remote. May be called from any thread.
+mojo::PendingRemote<mojom::FilePatcher> LaunchFilePatcher();
+
+}  // namespace patch
+
+#endif  // COMPONENTS_SERVICES_PATCH_CONTENT_PATCH_SERVICE_H_
diff --git a/components/services/patch/file_patcher_impl.cc b/components/services/patch/file_patcher_impl.cc
index 6c4d3dc..1f0febc 100644
--- a/components/services/patch/file_patcher_impl.cc
+++ b/components/services/patch/file_patcher_impl.cc
@@ -9,9 +9,11 @@
 
 namespace patch {
 
+FilePatcherImpl::FilePatcherImpl() = default;
+
 FilePatcherImpl::FilePatcherImpl(
-    std::unique_ptr<service_manager::ServiceContextRef> service_ref)
-    : service_ref_(std::move(service_ref)) {}
+    mojo::PendingReceiver<mojom::FilePatcher> receiver)
+    : receiver_(this, std::move(receiver)) {}
 
 FilePatcherImpl::~FilePatcherImpl() = default;
 
diff --git a/components/services/patch/file_patcher_impl.h b/components/services/patch/file_patcher_impl.h
index daa49947..5e4caeb 100644
--- a/components/services/patch/file_patcher_impl.h
+++ b/components/services/patch/file_patcher_impl.h
@@ -10,14 +10,20 @@
 #include "base/files/file.h"
 #include "base/macros.h"
 #include "components/services/patch/public/mojom/file_patcher.mojom.h"
-#include "services/service_manager/public/cpp/service_context_ref.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace patch {
 
 class FilePatcherImpl : public mojom::FilePatcher {
  public:
-  explicit FilePatcherImpl(
-      std::unique_ptr<service_manager::ServiceContextRef> service_ref);
+  // This constructor assumes the FilePatcherImpl will be bound to an externally
+  // owned receiver, such as through |mojo::MakeSelfOwnedReceiver()|.
+  FilePatcherImpl();
+
+  // Constructs a FilePatcherImpl bound to |receiver|.
+  explicit FilePatcherImpl(mojo::PendingReceiver<mojom::FilePatcher> receiver);
+
   ~FilePatcherImpl() override;
 
  private:
@@ -31,7 +37,7 @@
                           base::File output_file,
                           PatchFileCourgetteCallback callback) override;
 
-  const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
+  mojo::Receiver<mojom::FilePatcher> receiver_{this};
 
   DISALLOW_COPY_AND_ASSIGN(FilePatcherImpl);
 };
diff --git a/components/services/patch/in_process_file_patcher.cc b/components/services/patch/in_process_file_patcher.cc
new file mode 100644
index 0000000..38e8190
--- /dev/null
+++ b/components/services/patch/in_process_file_patcher.cc
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/patch/in_process_file_patcher.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/task/post_task.h"
+#include "components/services/patch/file_patcher_impl.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+
+namespace patch {
+
+namespace {
+
+void BindInProcessFilePatcher(
+    mojo::PendingReceiver<mojom::FilePatcher> receiver) {
+  mojo::MakeSelfOwnedReceiver(std::make_unique<FilePatcherImpl>(),
+                              std::move(receiver));
+}
+
+}  // namespace
+
+mojo::PendingRemote<mojom::FilePatcher> LaunchInProcessFilePatcher() {
+  mojo::PendingRemote<mojom::FilePatcher> remote;
+  base::CreateSequencedTaskRunnerWithTraits(
+      {base::MayBlock(), base::WithBaseSyncPrimitives()})
+      ->PostTask(FROM_HERE,
+                 base::BindOnce(&BindInProcessFilePatcher,
+                                remote.InitWithNewPipeAndPassReceiver()));
+  return remote;
+}
+
+}  // namespace patch
diff --git a/components/services/patch/in_process_file_patcher.h b/components/services/patch/in_process_file_patcher.h
new file mode 100644
index 0000000..baea5a4
--- /dev/null
+++ b/components/services/patch/in_process_file_patcher.h
@@ -0,0 +1,22 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_PATCH_IN_PROCESS_FILE_PATCHER_H_
+#define COMPONENTS_SERVICES_PATCH_IN_PROCESS_FILE_PATCHER_H_
+
+#include "components/services/patch/public/mojom/file_patcher.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+
+namespace patch {
+
+// Creates an in-process instance of the FilePatcher service on a background
+// sequence and returns a PendingRemote which can be bound to communicate with
+// the service. This should only be used for testing environments or other
+// runtimes where multiprocess is infeasible, such as iOS, or Content
+// dependencies are not allowed.
+mojo::PendingRemote<mojom::FilePatcher> LaunchInProcessFilePatcher();
+
+}  // namespace patch
+
+#endif  // COMPONENTS_SERVICES_PATCH_IN_PROCESS_FILE_PATCHER_H_
diff --git a/components/services/patch/patch_service.cc b/components/services/patch/patch_service.cc
deleted file mode 100644
index c51d705..0000000
--- a/components/services/patch/patch_service.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/services/patch/patch_service.h"
-
-#include "components/services/patch/file_patcher_impl.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace patch {
-
-PatchService::PatchService(service_manager::mojom::ServiceRequest request)
-    : binding_(this, std::move(request)),
-      keepalive_(&binding_, base::TimeDelta::FromSeconds(0)) {}
-
-PatchService::~PatchService() = default;
-
-void PatchService::OnBindInterface(
-    const service_manager::BindSourceInfo& source_info,
-    const std::string& interface_name,
-    mojo::ScopedMessagePipeHandle interface_pipe) {
-  if (interface_name == patch::mojom::FilePatcher::Name_) {
-    mojo::MakeStrongBinding(
-        std::make_unique<FilePatcherImpl>(keepalive_.CreateRef()),
-        patch::mojom::FilePatcherRequest(std::move(interface_pipe)));
-  }
-}
-
-}  //  namespace patch
diff --git a/components/services/patch/patch_service.h b/components/services/patch/patch_service.h
deleted file mode 100644
index 00d7a52..0000000
--- a/components/services/patch/patch_service.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SERVICES_PATCH_PATCH_SERVICE_H_
-#define COMPONENTS_SERVICES_PATCH_PATCH_SERVICE_H_
-
-#include "base/macros.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/cpp/service_keepalive.h"
-
-namespace patch {
-
-class PatchService : public service_manager::Service {
- public:
-  explicit PatchService(service_manager::mojom::ServiceRequest request);
-  ~PatchService() override;
-
-  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
-                       const std::string& interface_name,
-                       mojo::ScopedMessagePipeHandle interface_pipe) override;
-
- private:
-  service_manager::ServiceBinding binding_;
-  service_manager::ServiceKeepalive keepalive_;
-
-  DISALLOW_COPY_AND_ASSIGN(PatchService);
-};
-
-}  // namespace patch
-
-#endif  // COMPONENTS_SERVICES_PATCH_PATCH_SERVICE_H_
diff --git a/components/services/patch/public/cpp/BUILD.gn b/components/services/patch/public/cpp/BUILD.gn
index 3d2081b..5dd93bb 100644
--- a/components/services/patch/public/cpp/BUILD.gn
+++ b/components/services/patch/public/cpp/BUILD.gn
@@ -2,8 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//mojo/public/tools/bindings/mojom.gni")
-
 source_set("cpp") {
   sources = [
     "patch.cc",
@@ -12,20 +10,6 @@
 
   public_deps = [
     "//components/services/patch/public/mojom",
-    "//services/service_manager/public/cpp",
-  ]
-}
-
-source_set("manifest") {
-  sources = [
-    "manifest.cc",
-    "manifest.h",
-  ]
-
-  deps = [
-    "//base",
-    "//components/services/patch/public/mojom",
-    "//components/strings",
-    "//services/service_manager/public/cpp",
+    "//mojo/public/cpp/bindings",
   ]
 }
diff --git a/components/services/patch/public/cpp/OWNERS b/components/services/patch/public/cpp/OWNERS
deleted file mode 100644
index 6faeaa47..0000000
--- a/components/services/patch/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/components/services/patch/public/cpp/manifest.cc b/components/services/patch/public/cpp/manifest.cc
deleted file mode 100644
index dbdc813..0000000
--- a/components/services/patch/public/cpp/manifest.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/services/patch/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "build/build_config.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
-#include "components/services/patch/public/mojom/file_patcher.mojom.h"
-#include "components/strings/grit/components_strings.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace patch {
-
-const service_manager::Manifest& GetManifest() {
-  static base::NoDestructor<service_manager::Manifest> manifest{
-    service_manager::ManifestBuilder()
-        .WithServiceName(mojom::kServiceName)
-        .WithDisplayName(IDS_PATCH_SERVICE_DISPLAY_NAME)
-        .WithOptions(
-            service_manager::ManifestOptionsBuilder()
-#if !defined(OS_IOS)
-                .WithExecutionMode(service_manager::Manifest::ExecutionMode::
-                                       kOutOfProcessBuiltin)
-#endif  // !defined(OS_IOS)
-                .WithSandboxType("utility")
-                .WithInstanceSharingPolicy(
-                    service_manager::Manifest::InstanceSharingPolicy::
-                        kSharedAcrossGroups)
-                .Build())
-        .ExposeCapability(
-            "patch_file",
-            service_manager::Manifest::InterfaceList<mojom::FilePatcher>())
-
-        .Build()
-  };
-  return *manifest;
-}
-
-}  // namespace patch
diff --git a/components/services/patch/public/cpp/manifest.h b/components/services/patch/public/cpp/manifest.h
deleted file mode 100644
index d476dc23..0000000
--- a/components/services/patch/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SERVICES_PATCH_PUBLIC_CPP_MANIFEST_H_
-#define COMPONENTS_SERVICES_PATCH_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace patch {
-
-const service_manager::Manifest& GetManifest();
-
-}  // namespace patch
-
-#endif  // COMPONENTS_SERVICES_PATCH_PUBLIC_CPP_MANIFEST_H_
diff --git a/components/services/patch/public/cpp/patch.cc b/components/services/patch/public/cpp/patch.cc
index 8eaad8c6..60c3a2f 100644
--- a/components/services/patch/public/cpp/patch.cc
+++ b/components/services/patch/public/cpp/patch.cc
@@ -15,10 +15,8 @@
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string16.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
-#include "components/services/patch/public/mojom/file_patcher.mojom.h"
 #include "components/update_client/component_patcher_operation.h"  // nogncheck
-#include "services/service_manager/public/cpp/connector.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace patch {
 
@@ -26,11 +24,12 @@
 
 class PatchParams : public base::RefCounted<PatchParams> {
  public:
-  PatchParams(mojom::FilePatcherPtr file_patcher, PatchCallback callback)
+  PatchParams(mojo::PendingRemote<mojom::FilePatcher> file_patcher,
+              PatchCallback callback)
       : file_patcher_(std::move(file_patcher)),
         callback_(std::move(callback)) {}
 
-  mojom::FilePatcherPtr* file_patcher() { return &file_patcher_; }
+  mojo::Remote<mojom::FilePatcher>& file_patcher() { return file_patcher_; }
 
   PatchCallback TakeCallback() { return std::move(callback_); }
 
@@ -41,7 +40,7 @@
 
   // The FilePatcherPtr is stored so it does not get deleted before the callback
   // runs.
-  mojom::FilePatcherPtr file_patcher_;
+  mojo::Remote<mojom::FilePatcher> file_patcher_;
 
   PatchCallback callback_;
 
@@ -49,7 +48,7 @@
 };
 
 void PatchDone(scoped_refptr<PatchParams> params, int result) {
-  params->file_patcher()->reset();
+  params->file_patcher().reset();
   PatchCallback cb = params->TakeCallback();
   if (!cb.is_null())
     std::move(cb).Run(result);
@@ -57,7 +56,7 @@
 
 }  // namespace
 
-void Patch(service_manager::Connector* connector,
+void Patch(mojo::PendingRemote<mojom::FilePatcher> file_patcher,
            const std::string& operation,
            const base::FilePath& input_path,
            const base::FilePath& patch_path,
@@ -80,28 +79,22 @@
     return;
   }
 
-  mojom::FilePatcherPtr file_patcher;
-  connector->BindInterface(mojom::kServiceName,
-                           mojo::MakeRequest(&file_patcher));
-
   // In order to share |callback| between the connection error handler and the
   // FilePatcher calls, we have to use a context object.
   scoped_refptr<PatchParams> patch_params =
       new PatchParams(std::move(file_patcher), std::move(callback));
 
-  patch_params->file_patcher()->set_connection_error_handler(
+  patch_params->file_patcher().set_disconnect_handler(
       base::BindOnce(&PatchDone, patch_params, /*result=*/-1));
 
   if (operation == update_client::kBsdiff) {
-    (*patch_params->file_patcher())
-        ->PatchFileBsdiff(std::move(input_file), std::move(patch_file),
-                          std::move(output_file),
-                          base::BindOnce(&PatchDone, patch_params));
+    patch_params->file_patcher()->PatchFileBsdiff(
+        std::move(input_file), std::move(patch_file), std::move(output_file),
+        base::BindOnce(&PatchDone, patch_params));
   } else if (operation == update_client::kCourgette) {
-    (*patch_params->file_patcher())
-        ->PatchFileCourgette(std::move(input_file), std::move(patch_file),
-                             std::move(output_file),
-                             base::BindOnce(&PatchDone, patch_params));
+    patch_params->file_patcher()->PatchFileCourgette(
+        std::move(input_file), std::move(patch_file), std::move(output_file),
+        base::BindOnce(&PatchDone, patch_params));
   } else {
     NOTREACHED();
   }
diff --git a/components/services/patch/public/cpp/patch.h b/components/services/patch/public/cpp/patch.h
index 0113745..94c0b197 100644
--- a/components/services/patch/public/cpp/patch.h
+++ b/components/services/patch/public/cpp/patch.h
@@ -8,21 +8,19 @@
 #include <string>
 
 #include "base/callback_forward.h"
+#include "components/services/patch/public/mojom/file_patcher.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace base {
 class FilePath;
 }
 
-namespace service_manager {
-class Connector;
-}
-
 namespace patch {
 
 // Patches |input_abs_path| with |patch_abs_path| using the |operation|
 // algorithm and place the output in |output_abs_path|.
 using PatchCallback = base::OnceCallback<void(int result)>;
-void Patch(service_manager::Connector* connector,
+void Patch(mojo::PendingRemote<mojom::FilePatcher> file_patcher,
            const std::string& operation,
            const base::FilePath& input_abs_path,
            const base::FilePath& patch_abs_path,
diff --git a/components/services/patch/public/mojom/BUILD.gn b/components/services/patch/public/mojom/BUILD.gn
index 6e4f869..b6b49df 100644
--- a/components/services/patch/public/mojom/BUILD.gn
+++ b/components/services/patch/public/mojom/BUILD.gn
@@ -10,13 +10,6 @@
   ]
 
   public_deps = [
-    ":constants",
     "//mojo/public/mojom/base",
   ]
 }
-
-mojom("constants") {
-  sources = [
-    "constants.mojom",
-  ]
-}
diff --git a/components/services/patch/public/mojom/constants.mojom b/components/services/patch/public/mojom/constants.mojom
deleted file mode 100644
index fa5ad3c7..0000000
--- a/components/services/patch/public/mojom/constants.mojom
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module patch.mojom;
-
-const string kServiceName = "patch_service";
diff --git a/components/spellcheck/common/spellcheck_features.cc b/components/spellcheck/common/spellcheck_features.cc
index 4462a2a..0bc03af 100644
--- a/components/spellcheck/common/spellcheck_features.cc
+++ b/components/spellcheck/common/spellcheck_features.cc
@@ -14,7 +14,7 @@
 #if BUILDFLAG(ENABLE_SPELLCHECK)
 
 const base::Feature kSpellingServiceRestApi{"SpellingServiceRestApi",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
+                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
 #if defined(OS_WIN)
 const base::Feature kWinUseBrowserSpellChecker{
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn
index 7636357..8ec4b59 100644
--- a/components/update_client/BUILD.gn
+++ b/components/update_client/BUILD.gn
@@ -39,6 +39,8 @@
   deps = [
     ":update_client",
     "//components/services/patch/public/cpp",
+    "//components/services/patch/public/mojom",
+    "//mojo/public/cpp/bindings",
   ]
 }
 
@@ -155,14 +157,11 @@
     ":unzip_impl",
     "//base",
     "//components/prefs",
-    "//components/services/patch:lib",
+    "//components/services/patch:in_process",
     "//components/services/unzip:in_process",
     "//mojo/public/cpp/bindings",
     "//net:test_support",
     "//services/network:test_support",
-    "//services/service_manager/public/cpp",
-    "//services/service_manager/public/cpp/test:test_support",
-    "//services/service_manager/public/mojom",
     "//testing/gmock",
     "//testing/gtest",
     "//url",
@@ -228,15 +227,13 @@
     "//components/crx_file",
     "//components/prefs",
     "//components/prefs:test_support",
-    "//components/services/patch:lib",
+    "//components/services/patch:in_process",
     "//components/version_info:version_info",
     "//courgette:courgette_lib",
     "//net:test_support",
     "//services/network:test_support",
     "//services/network/public/cpp:cpp",
     "//services/network/public/cpp:cpp_base",
-    "//services/service_manager/public/cpp",
-    "//services/service_manager/public/cpp/test:test_support",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/re2",
diff --git a/components/update_client/DEPS b/components/update_client/DEPS
index b89a744..8353d04 100644
--- a/components/update_client/DEPS
+++ b/components/update_client/DEPS
@@ -7,8 +7,7 @@
   "+components/version_info",
   "+courgette",
   "+crypto",
-  "+mojo",
-  "+services/service_manager/public",
+  "+mojo/public",
   "+third_party/re2",
   "+third_party/zlib",
 ]
diff --git a/components/update_client/component_patcher_unittest.cc b/components/update_client/component_patcher_unittest.cc
index 7320462..016401f 100644
--- a/components/update_client/component_patcher_unittest.cc
+++ b/components/update_client/component_patcher_unittest.cc
@@ -12,8 +12,7 @@
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/values.h"
-#include "components/services/patch/patch_service.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
+#include "components/services/patch/in_process_file_patcher.h"
 #include "components/update_client/component_patcher_operation.h"
 #include "components/update_client/component_patcher_unittest.h"
 #include "components/update_client/patch/patch_impl.h"
@@ -21,7 +20,6 @@
 #include "components/update_client/update_client_errors.h"
 #include "courgette/courgette.h"
 #include "courgette/third_party/bsdiff/bsdiff.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -151,13 +149,10 @@
   command_args->SetString("input", "binary_input.bin");
   command_args->SetString("patch", "binary_courgette_patch.bin");
 
-  // The operation needs a Patcher to access the PatchService.
-  service_manager::TestConnectorFactory connector_factory;
-  patch::PatchService patch_service(
-      connector_factory.RegisterInstance(patch::mojom::kServiceName));
-  scoped_refptr<Patcher> patcher = base::MakeRefCounted<PatchChromiumFactory>(
-                                       connector_factory.CreateConnector())
-                                       ->Create();
+  scoped_refptr<Patcher> patcher =
+      base::MakeRefCounted<PatchChromiumFactory>(
+          base::BindRepeating(&patch::LaunchInProcessFilePatcher))
+          ->Create();
 
   TestCallback callback;
   scoped_refptr<DeltaUpdateOp> op = CreateDeltaUpdateOp("courgette", patcher);
@@ -192,12 +187,10 @@
   command_args->SetString("patch", "binary_bsdiff_patch.bin");
 
   // The operation needs a Patcher to access the PatchService.
-  service_manager::TestConnectorFactory connector_factory;
-  patch::PatchService patch_service(
-      connector_factory.RegisterInstance(patch::mojom::kServiceName));
-  scoped_refptr<Patcher> patcher = base::MakeRefCounted<PatchChromiumFactory>(
-                                       connector_factory.CreateConnector())
-                                       ->Create();
+  scoped_refptr<Patcher> patcher =
+      base::MakeRefCounted<PatchChromiumFactory>(
+          base::BindRepeating(&patch::LaunchInProcessFilePatcher))
+          ->Create();
 
   TestCallback callback;
   scoped_refptr<DeltaUpdateOp> op = CreateDeltaUpdateOp("bsdiff", patcher);
diff --git a/components/update_client/patch/patch_impl.cc b/components/update_client/patch/patch_impl.cc
index dd92cbb..599101f 100644
--- a/components/update_client/patch/patch_impl.cc
+++ b/components/update_client/patch/patch_impl.cc
@@ -6,7 +6,6 @@
 
 #include "components/services/patch/public/cpp/patch.h"
 #include "components/update_client/component_patcher_operation.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 namespace update_client {
 
@@ -14,14 +13,14 @@
 
 class PatcherImpl : public Patcher {
  public:
-  explicit PatcherImpl(std::unique_ptr<service_manager::Connector> connector)
-      : connector_(std::move(connector)) {}
+  explicit PatcherImpl(PatchChromiumFactory::Callback callback)
+      : callback_(std::move(callback)) {}
 
   void PatchBsdiff(const base::FilePath& old_file,
                    const base::FilePath& patch_file,
                    const base::FilePath& destination,
                    PatchCompleteCallback callback) const override {
-    patch::Patch(connector_.get(), update_client::kBsdiff, old_file, patch_file,
+    patch::Patch(callback_.Run(), update_client::kBsdiff, old_file, patch_file,
                  destination, std::move(callback));
   }
 
@@ -29,7 +28,7 @@
                       const base::FilePath& patch_file,
                       const base::FilePath& destination,
                       PatchCompleteCallback callback) const override {
-    patch::Patch(connector_.get(), update_client::kCourgette, old_file,
+    patch::Patch(callback_.Run(), update_client::kCourgette, old_file,
                  patch_file, destination, std::move(callback));
   }
 
@@ -37,17 +36,16 @@
   ~PatcherImpl() override = default;
 
  private:
-  std::unique_ptr<service_manager::Connector> connector_;
+  const PatchChromiumFactory::Callback callback_;
 };
 
 }  // namespace
 
-PatchChromiumFactory::PatchChromiumFactory(
-    std::unique_ptr<service_manager::Connector> connector)
-    : connector_(std::move(connector)) {}
+PatchChromiumFactory::PatchChromiumFactory(Callback callback)
+    : callback_(std::move(callback)) {}
 
 scoped_refptr<Patcher> PatchChromiumFactory::Create() const {
-  return base::MakeRefCounted<PatcherImpl>(connector_->Clone());
+  return base::MakeRefCounted<PatcherImpl>(callback_);
 }
 
 PatchChromiumFactory::~PatchChromiumFactory() = default;
diff --git a/components/update_client/patch/patch_impl.h b/components/update_client/patch/patch_impl.h
index d6abbc1..e76666d 100644
--- a/components/update_client/patch/patch_impl.h
+++ b/components/update_client/patch/patch_impl.h
@@ -7,20 +7,20 @@
 
 #include <memory>
 
+#include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "components/services/patch/public/mojom/file_patcher.mojom.h"
 #include "components/update_client/patcher.h"
-
-namespace service_manager {
-class Connector;
-}
+#include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace update_client {
 
 class PatchChromiumFactory : public PatcherFactory {
  public:
-  explicit PatchChromiumFactory(
-      std::unique_ptr<service_manager::Connector> connector);
+  using Callback =
+      base::RepeatingCallback<mojo::PendingRemote<patch::mojom::FilePatcher>()>;
+  explicit PatchChromiumFactory(Callback callback);
 
   scoped_refptr<Patcher> Create() const override;
 
@@ -28,7 +28,7 @@
   ~PatchChromiumFactory() override;
 
  private:
-  std::unique_ptr<service_manager::Connector> connector_;
+  const Callback callback_;
 
   DISALLOW_COPY_AND_ASSIGN(PatchChromiumFactory);
 };
diff --git a/components/update_client/test_configurator.cc b/components/update_client/test_configurator.cc
index eb4ec77..9365726 100644
--- a/components/update_client/test_configurator.cc
+++ b/components/update_client/test_configurator.cc
@@ -9,7 +9,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/version.h"
 #include "components/prefs/pref_service.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
+#include "components/services/patch/in_process_file_patcher.h"
 #include "components/services/unzip/in_process_unzipper.h"
 #include "components/update_client/activity_data_service.h"
 #include "components/update_client/net/network_chromium.h"
@@ -19,7 +19,6 @@
 #include "components/update_client/unzip/unzip_impl.h"
 #include "components/update_client/unzipper.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "url/gurl.h"
 
 namespace update_client {
@@ -44,17 +43,13 @@
       unzip_factory_(base::MakeRefCounted<update_client::UnzipChromiumFactory>(
           base::BindRepeating(&unzip::LaunchInProcessUnzipper))),
       patch_factory_(base::MakeRefCounted<update_client::PatchChromiumFactory>(
-          connector_factory_.CreateConnector())),
-      patch_service_(
-          connector_factory_.RegisterInstance(patch::mojom::kServiceName)),
+          base::BindRepeating(&patch::LaunchInProcessFilePatcher))),
       test_shared_loader_factory_(
           base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
               &test_url_loader_factory_)),
       network_fetcher_factory_(
           base::MakeRefCounted<NetworkFetcherChromiumFactory>(
-              test_shared_loader_factory_)) {
-  connector_factory_.set_ignore_quit_requests(true);
-}
+              test_shared_loader_factory_)) {}
 
 TestConfigurator::~TestConfigurator() {
 }
diff --git a/components/update_client/test_configurator.h b/components/update_client/test_configurator.h
index 405daf0..69353475 100644
--- a/components/update_client/test_configurator.h
+++ b/components/update_client/test_configurator.h
@@ -15,10 +15,8 @@
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "components/services/patch/patch_service.h"
 #include "components/update_client/configurator.h"
 #include "services/network/test/test_url_loader_factory.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
 #include "url/gurl.h"
 
 class PrefService;
@@ -133,12 +131,9 @@
   GURL ping_url_;
   std::string app_guid_;
 
-  service_manager::TestConnectorFactory connector_factory_;
   scoped_refptr<update_client::UnzipChromiumFactory> unzip_factory_;
   scoped_refptr<update_client::PatchChromiumFactory> patch_factory_;
 
-  patch::PatchService patch_service_;
-
   scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
   network::TestURLLoaderFactory test_url_loader_factory_;
   scoped_refptr<NetworkFetcherFactory> network_fetcher_factory_;
diff --git a/components/viz/common/frame_timing_details.h b/components/viz/common/frame_timing_details.h
index b901f5f..e07e7f8b 100644
--- a/components/viz/common/frame_timing_details.h
+++ b/components/viz/common/frame_timing_details.h
@@ -11,6 +11,8 @@
 
 struct FrameTimingDetails {
   gfx::PresentationFeedback presentation_feedback;
+  base::TimeTicks received_compositor_frame_timestamp;
+  base::TimeTicks draw_start_timestamp;
 };
 
 }  // namespace viz
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index cca345b..356ac6f 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -541,6 +541,22 @@
       UMA_HISTOGRAM_COUNTS_1M("Compositing.DirectRenderer.GL.DrawFrameUs",
                               draw_timer->Elapsed().InMicroseconds());
     }
+
+    std::vector<std::unique_ptr<Surface::PresentationHelper>>
+        presentation_helper_list;
+    for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
+      Surface* surface = surface_manager_->GetSurfaceForId(id_entry.first);
+      if (surface) {
+        std::unique_ptr<Surface::PresentationHelper> helper =
+            surface->TakePresentationHelperForPresentNotification();
+        if (helper) {
+          surface->OnWasDrawn(helper->frame_token(), draw_timer->Begin());
+          presentation_helper_list.push_back(std::move(helper));
+        }
+      }
+    }
+    pending_surfaces_with_presentation_helpers_.emplace_back(
+        std::make_pair(now_time, std::move(presentation_helper_list)));
   } else {
     TRACE_EVENT_INSTANT0("viz", "Draw skipped.", TRACE_EVENT_SCOPE_THREAD);
   }
@@ -560,18 +576,6 @@
           scheduler_->current_frame_time());
     }
 
-    std::vector<std::unique_ptr<Surface::PresentationHelper>>
-        presentation_helper_list;
-    for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
-      Surface* surface = surface_manager_->GetSurfaceForId(id_entry.first);
-      if (surface) {
-        presentation_helper_list.push_back(
-            surface->TakePresentationHelperForPresentNotification());
-      }
-    }
-    pending_surfaces_with_presentation_helpers_.emplace_back(
-        std::make_pair(now_time, std::move(presentation_helper_list)));
-
     ui::LatencyInfo::TraceIntermediateFlowEvents(frame.metadata.latency_info,
                                                  "Display::DrawAndSwap");
 
@@ -692,8 +696,7 @@
       "benchmark,viz", "Display::FrameDisplayed", TRACE_EVENT_SCOPE_THREAD,
       copy_feedback.timestamp);
   for (auto& presentation_helper : presentation_helper_list) {
-    if (presentation_helper)
-      presentation_helper->DidPresent(feedback);
+    presentation_helper->DidPresent(feedback);
   }
   pending_surfaces_with_presentation_helpers_.pop_front();
 }
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index b295397..ad82073 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -150,12 +150,18 @@
   MaybeEvictSurfaces();
 }
 
-void CompositorFrameSinkSupport::OnSurfaceDrawn(Surface* surface) {
+void CompositorFrameSinkSupport::OnSurfaceWillDraw(Surface* surface) {
   if (last_drawn_frame_index_ >= surface->GetActiveFrameIndex())
     return;
   last_drawn_frame_index_ = surface->GetActiveFrameIndex();
 }
 
+void CompositorFrameSinkSupport::OnSurfaceWasDrawn(
+    uint32_t frame_token,
+    base::TimeTicks draw_start_timestamp) {
+  draw_start_times_.emplace(frame_token, draw_start_timestamp);
+}
+
 void CompositorFrameSinkSupport::OnFrameTokenChanged(uint32_t frame_token) {
   frame_sink_manager_->OnFrameTokenChanged(frame_sink_id_, frame_token);
 }
@@ -382,6 +388,10 @@
     UpdateNeedsBeginFramesInternal();
   }
 
+  base::TimeTicks now_time = base::TimeTicks::Now();
+  received_compositor_frame_times_.emplace(frame.metadata.frame_token,
+                                           now_time);
+
   // Ensure no CopyOutputRequests have been submitted if they are banned.
   if (!allow_copy_output_requests_ && frame.HasCopyOutputRequests()) {
     TRACE_EVENT_INSTANT0("viz", "CopyOutputRequests not allowed",
@@ -407,7 +417,8 @@
   }
   for (ui::LatencyInfo& latency : frame.metadata.latency_info) {
     if (latency.latency_components().size() > 0) {
-      latency.AddLatencyNumber(ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT);
+      latency.AddLatencyNumberWithTimestamp(
+          ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, now_time);
     }
   }
 
@@ -558,9 +569,30 @@
     uint32_t presentation_token,
     const gfx::PresentationFeedback& feedback) {
   DCHECK(presentation_token);
+
   FrameTimingDetails details;
   details.presentation_feedback = feedback;
+
+  DCHECK_LT(received_compositor_frame_times_.size(), 25u);
+  auto received_compositor_frame_time =
+      received_compositor_frame_times_.find(presentation_token);
+  DCHECK(received_compositor_frame_time !=
+         received_compositor_frame_times_.end());
+  details.received_compositor_frame_timestamp =
+      received_compositor_frame_time->second;
+  received_compositor_frame_times_.erase(received_compositor_frame_time);
+
+  DCHECK_LT(draw_start_times_.size(), 25u);
+  auto draw_start_time = draw_start_times_.find(presentation_token);
+  if (draw_start_time != draw_start_times_.end()) {
+    details.draw_start_timestamp = draw_start_time->second;
+    draw_start_times_.erase(draw_start_time);
+  } else {
+    DCHECK(feedback.flags & gfx::PresentationFeedback::kFailure);
+  }
+
   frame_timing_details_.emplace(presentation_token, details);
+
   UpdateNeedsBeginFramesInternal();
 }
 
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index 08bded4..a4f0b5b 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -111,7 +111,9 @@
   // SurfaceClient implementation.
   void OnSurfaceActivated(Surface* surface) override;
   void OnSurfaceDestroyed(Surface* surface) override;
-  void OnSurfaceDrawn(Surface* surface) override;
+  void OnSurfaceWillDraw(Surface* surface) override;
+  void OnSurfaceWasDrawn(uint32_t frame_token,
+                         base::TimeTicks draw_start_timestamp) override;
   void RefResources(
       const std::vector<TransferableResource>& resources) override;
   void UnrefResources(const std::vector<ReturnedResource>& resources) override;
@@ -324,6 +326,13 @@
   bool callback_received_receive_ack_ = true;
   uint32_t trace_sequence_ = 0;
 
+  // Map between frame_token and the timestamp when Viz received the
+  // submitted CompositorFrame
+  base::flat_map<uint32_t, base::TimeTicks> received_compositor_frame_times_;
+
+  // Map between frame_token and the timestamp when Viz began DrawAndSwap
+  base::flat_map<uint32_t, base::TimeTicks> draw_start_times_;
+
   FrameTimingDetailsMap frame_timing_details_;
   LocalSurfaceId last_evicted_local_surface_id_;
 
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index e05cd1e3..21de062 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -225,6 +225,7 @@
 
   void SendPresentationFeedback(CompositorFrameSinkSupport* support,
                                 uint32_t frame_token) {
+    support->OnSurfaceWasDrawn(frame_token, base::TimeTicks::Now());
     support->DidPresentCompositorFrame(
         frame_token,
         gfx::PresentationFeedback(base::TimeTicks::Now(),
@@ -1241,4 +1242,87 @@
       GetSurfaceForId(SurfaceId(support_->frame_sink_id(), local_surface_id2)));
 }
 
+// Verifies that invalid hit test region does not get submitted.
+TEST_F(CompositorFrameSinkSupportTest, HitTestRegionValidation) {
+  constexpr FrameSinkId frame_sink_id(1234, 5678);
+  manager_.RegisterFrameSinkId(frame_sink_id, true /* report_activation */);
+  auto support = std::make_unique<CompositorFrameSinkSupport>(
+      &fake_support_client_, &manager_, frame_sink_id, kIsRoot,
+      kNeedsSyncPoints);
+  LocalSurfaceId local_surface_id(6, 1, base::UnguessableToken::Create());
+
+  HitTestRegionList hit_test_region_list;
+
+  // kHitTestAsk not set, async_hit_test_reasons not set.
+  HitTestRegion hit_test_region_1;
+  hit_test_region_1.frame_sink_id = frame_sink_id;
+  hit_test_region_1.flags = HitTestRegionFlags::kHitTestMine;
+  hit_test_region_1.rect.SetRect(100, 100, 200, 400);
+
+  hit_test_region_list.regions.push_back(std::move(hit_test_region_1));
+
+  EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+            0u);
+  support->MaybeSubmitCompositorFrame(
+      local_surface_id, MakeDefaultCompositorFrame(), hit_test_region_list, 0,
+      mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
+  // hit_test_region_1 is valid. Submitted region count increases.
+  EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+            1u);
+  hit_test_region_list.regions.clear();
+
+  // kHitTestAsk set, async_hit_test_reasons not set.
+  HitTestRegion hit_test_region_2;
+  hit_test_region_2.frame_sink_id = frame_sink_id;
+  hit_test_region_2.flags = HitTestRegionFlags::kHitTestAsk;
+  hit_test_region_2.rect.SetRect(400, 100, 300, 400);
+
+  hit_test_region_list.regions.push_back(std::move(hit_test_region_2));
+  EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+            1u);
+  support->MaybeSubmitCompositorFrame(
+      local_surface_id, MakeDefaultCompositorFrame(), hit_test_region_list, 0,
+      mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
+  // hit_test_region_2 is invalid. Submitted region count does not change.
+  EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+            1u);
+
+  // kHitTestAsk not set, async_hit_test_reasons set.
+  HitTestRegion hit_test_region_3;
+  hit_test_region_3.frame_sink_id = frame_sink_id;
+  hit_test_region_3.async_hit_test_reasons =
+      AsyncHitTestReasons::kOverlappedRegion;
+  hit_test_region_3.rect.SetRect(400, 100, 300, 400);
+
+  hit_test_region_list.regions.clear();
+  hit_test_region_list.regions.push_back(std::move(hit_test_region_3));
+  EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+            1u);
+  support->MaybeSubmitCompositorFrame(
+      local_surface_id, MakeDefaultCompositorFrame(), hit_test_region_list, 0,
+      mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
+  // hit_test_region_3 is invalid. Submitted region count does not change.
+  EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+            1u);
+
+  // kHitTestAsk set, async_hit_test_reasons set.
+  HitTestRegion hit_test_region_4;
+  hit_test_region_4.frame_sink_id = frame_sink_id;
+  hit_test_region_4.flags = HitTestRegionFlags::kHitTestAsk;
+  hit_test_region_4.async_hit_test_reasons =
+      AsyncHitTestReasons::kOverlappedRegion;
+  hit_test_region_4.rect.SetRect(400, 100, 300, 400);
+
+  hit_test_region_list.regions.clear();
+  hit_test_region_list.regions.push_back(std::move(hit_test_region_4));
+  EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+            1u);
+  support->MaybeSubmitCompositorFrame(
+      local_surface_id, MakeDefaultCompositorFrame(), hit_test_region_list, 0,
+      mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
+  // hit_test_region_4 is valid. Submitted region count increases.
+  EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+            2u);
+}
+
 }  // namespace viz
diff --git a/components/viz/service/hit_test/hit_test_manager.cc b/components/viz/service/hit_test/hit_test_manager.cc
index 8c2239d..c46e6b8 100644
--- a/components/viz/service/hit_test/hit_test_manager.cc
+++ b/components/viz/service/hit_test/hit_test_manager.cc
@@ -163,6 +163,15 @@
       region.frame_sink_id = FrameSinkId(surface_id.frame_sink_id().client_id(),
                                          region.frame_sink_id.sink_id());
     }
+
+    // Whenever a hit test region is marked as kHitTestAsk there must be a
+    // reason for async hit test and vice versa.
+    if (region.flags & kHitTestAsk) {
+      if (region.async_hit_test_reasons == kNotAsyncHitTest)
+        return false;
+    } else if (region.async_hit_test_reasons != kNotAsyncHitTest) {
+      return false;
+    }
   }
   return true;
 }
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc
index 8498fad..0998764 100644
--- a/components/viz/service/surfaces/surface.cc
+++ b/components/viz/service/surfaces/surface.cc
@@ -26,9 +26,10 @@
 
 namespace viz {
 
-Surface::PresentationHelper::PresentationHelper(base::WeakPtr<Surface> surface,
-                                                uint32_t frame_token)
-    : surface_(std::move(surface)), frame_token_(frame_token) {}
+Surface::PresentationHelper::PresentationHelper(
+    base::WeakPtr<SurfaceClient> surface_client,
+    uint32_t frame_token)
+    : surface_client_(std::move(surface_client)), frame_token_(frame_token) {}
 
 Surface::PresentationHelper::~PresentationHelper() {
   // The class that called TakePresentationHelperForPresentNotification
@@ -39,10 +40,10 @@
 
 void Surface::PresentationHelper::DidPresent(
     const gfx::PresentationFeedback& feedback) {
-  if (surface_ && frame_token_)
-    surface_->DidPresentSurface(frame_token_, feedback);
+  if (surface_client_ && frame_token_)
+    surface_client_->OnSurfacePresented(frame_token_, feedback);
 
-  surface_ = nullptr;
+  surface_client_ = nullptr;
 }
 
 Surface::Surface(const SurfaceInfo& surface_info,
@@ -589,17 +590,11 @@
       !active_frame_data_->will_be_notified_of_presentation) {
     active_frame_data_->will_be_notified_of_presentation = true;
     return std::make_unique<PresentationHelper>(
-        GetWeakPtr(), active_frame_data_->frame.metadata.frame_token);
+        client(), active_frame_data_->frame.metadata.frame_token);
   }
   return nullptr;
 }
 
-void Surface::DidPresentSurface(uint32_t presentation_token,
-                                const gfx::PresentationFeedback& feedback) {
-  if (surface_client_)
-    surface_client_->OnSurfacePresented(presentation_token, feedback);
-}
-
 void Surface::SendAckToClient() {
   if (!active_frame_data_ || active_frame_data_->frame_acked)
     return;
@@ -613,7 +608,7 @@
     return;
   active_frame_data_->frame_drawn = true;
   if (surface_client_)
-    surface_client_->OnSurfaceDrawn(this);
+    surface_client_->OnSurfaceWillDraw(this);
 }
 
 void Surface::NotifyAggregatedDamage(const gfx::Rect& damage_rect,
@@ -642,9 +637,9 @@
 
   // If we won't be getting a presented notification, we'll notify the client
   // when the frame is unref'd.
-  if (!frame_data->will_be_notified_of_presentation)
-    DidPresentSurface(frame_data->frame.metadata.frame_token,
-                      gfx::PresentationFeedback::Failure());
+  if (!frame_data->will_be_notified_of_presentation && surface_client_)
+    surface_client_->OnSurfacePresented(frame_data->frame.metadata.frame_token,
+                                        gfx::PresentationFeedback::Failure());
 }
 
 void Surface::ClearCopyRequests() {
@@ -715,6 +710,14 @@
   MarkAsDrawn();
 }
 
+void Surface::OnWasDrawn(uint32_t frame_token,
+                         base::TimeTicks draw_start_timestamp) {
+  if (!surface_client_)
+    return;
+
+  surface_client_->OnSurfaceWasDrawn(frame_token, draw_start_timestamp);
+}
+
 void Surface::ActivatePendingFrameForInheritedDeadline() {
   DCHECK(HasPendingFrame());
   // Deadline inheritance implies that this surface was blocking the embedder,
diff --git a/components/viz/service/surfaces/surface.h b/components/viz/service/surfaces/surface.h
index c57118ff..21aef17 100644
--- a/components/viz/service/surfaces/surface.h
+++ b/components/viz/service/surfaces/surface.h
@@ -78,13 +78,15 @@
  public:
   class PresentationHelper {
    public:
-    PresentationHelper(base::WeakPtr<Surface> surface, uint32_t frame_token);
+    PresentationHelper(base::WeakPtr<SurfaceClient> surface_client,
+                       uint32_t frame_token);
     ~PresentationHelper();
 
     void DidPresent(const gfx::PresentationFeedback& feedback);
+    uint32_t frame_token() const { return frame_token_; }
 
    private:
-    base::WeakPtr<Surface> surface_;
+    base::WeakPtr<SurfaceClient> surface_client_;
     const uint32_t frame_token_;
 
     DISALLOW_COPY_AND_ASSIGN(PresentationHelper);
@@ -186,8 +188,6 @@
   // PresentationHelper, at the appropriate point in the future.
   std::unique_ptr<Surface::PresentationHelper>
   TakePresentationHelperForPresentNotification();
-  void DidPresentSurface(uint32_t presentation_token,
-                         const gfx::PresentationFeedback& feedback);
   void SendAckToClient();
   void MarkAsDrawn();
   void NotifyAggregatedDamage(const gfx::Rect& damage_rect,
@@ -221,6 +221,10 @@
   // Called when this surface will be included in the next display frame.
   void OnWillBeDrawn();
 
+  // Called after the display compositor finishes drawing the frame
+  // associated with frame_token.
+  void OnWasDrawn(uint32_t frame_token, base::TimeTicks draw_start_timestamp);
+
   // Called when |surface_id| is activated for the first time and its part of a
   // referenced SurfaceRange.
   void OnChildActivatedForActiveFrame(const SurfaceId& surface_id);
diff --git a/components/viz/service/surfaces/surface_client.h b/components/viz/service/surfaces/surface_client.h
index f7b71b2..d46505a8 100644
--- a/components/viz/service/surfaces/surface_client.h
+++ b/components/viz/service/surfaces/surface_client.h
@@ -41,7 +41,11 @@
   virtual void OnSurfaceDestroyed(Surface* surface) = 0;
 
   // Called when a |surface| is about to be drawn.
-  virtual void OnSurfaceDrawn(Surface* surface) = 0;
+  virtual void OnSurfaceWillDraw(Surface* surface) = 0;
+
+  // Called when a |surface| has been successfully drawn.
+  virtual void OnSurfaceWasDrawn(uint32_t frame_token,
+                                 base::TimeTicks draw_start_timestamp) = 0;
 
   // Increments the reference count on resources specified by |resources|.
   virtual void RefResources(
diff --git a/components/viz/test/stub_surface_client.h b/components/viz/test/stub_surface_client.h
index e37e46f..4325d72 100644
--- a/components/viz/test/stub_surface_client.h
+++ b/components/viz/test/stub_surface_client.h
@@ -18,7 +18,9 @@
 
   void OnSurfaceActivated(Surface* surface) override {}
   void OnSurfaceDestroyed(Surface* surface) override {}
-  void OnSurfaceDrawn(Surface* surface) override {}
+  void OnSurfaceWillDraw(Surface* surface) override {}
+  void OnSurfaceWasDrawn(uint32_t frame_token,
+                         base::TimeTicks draw_start_timestamp) override {}
   void RefResources(
       const std::vector<TransferableResource>& resources) override {}
   void UnrefResources(const std::vector<ReturnedResource>& resources) override {
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index b850292..637194d 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1143,8 +1143,6 @@
     "loader/single_request_url_loader_factory.h",
     "loader/source_stream_to_data_pipe.cc",
     "loader/source_stream_to_data_pipe.h",
-    "loader/upload_data_stream_builder.cc",
-    "loader/upload_data_stream_builder.h",
     "loader/webrtc_connections_observer.cc",
     "loader/webrtc_connections_observer.h",
     "locks/lock_manager.cc",
@@ -1291,8 +1289,6 @@
     "net/network_quality_observer_impl.h",
     "net/quota_policy_cookie_store.cc",
     "net/quota_policy_cookie_store.h",
-    "net/view_blob_internals_job_factory.cc",
-    "net/view_blob_internals_job_factory.h",
     "network_service_client.cc",
     "network_service_client.h",
     "network_service_instance_impl.cc",
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 5fce305..577ee93 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -144,26 +144,11 @@
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetNextSibling() const {
-  BrowserAccessibility* next_sibling = InternalGetNextSibling();
-  if (next_sibling)
-    return next_sibling;
-
-  ui::AXNode* parent = node_->GetUnignoredParent();
-  if (!parent) {
-    BrowserAccessibility* parent_tree_parent =
-        manager_->GetParentNodeFromParentTree();
-    if (parent_tree_parent)
-      return parent_tree_parent->PlatformGetChild(1);
-  }
-  return nullptr;
+  return InternalGetNextSibling();
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetPreviousSibling() const {
-  BrowserAccessibility* previous_sibling = InternalGetPreviousSibling();
-  if (!previous_sibling)
-    previous_sibling = PlatformGetRootOfChildTree();
-
-  return previous_sibling;
+  return InternalGetPreviousSibling();
 }
 
 BrowserAccessibility::PlatformChildIterator
@@ -221,9 +206,12 @@
     uint32_t child_index) const {
   BrowserAccessibility* result = nullptr;
 
-  if (child_index == 0 &&
-      HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) {
-    result = PlatformGetRootOfChildTree();
+  if (HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) {
+    // A node should not have both children and a child tree.
+    DCHECK_EQ(node_->children().size(), 0u);
+    // child_trees do not have siblings.
+    if (child_index == 0)
+      result = PlatformGetRootOfChildTree();
   } else {
     result = InternalGetChild(child_index);
   }
@@ -1911,7 +1899,6 @@
 BrowserAccessibility* BrowserAccessibility::PlatformGetRootOfChildTree() const {
   if (!HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId))
     return nullptr;
-
   AXTreeID child_tree_id = AXTreeID::FromString(
       GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId));
   BrowserAccessibilityManager* child_manager =
diff --git a/content/browser/accessibility/browser_accessibility_unittest.cc b/content/browser/accessibility/browser_accessibility_unittest.cc
index 0d3094a4..bc38af9 100644
--- a/content/browser/accessibility/browser_accessibility_unittest.cc
+++ b/content/browser/accessibility/browser_accessibility_unittest.cc
@@ -210,99 +210,149 @@
 
 TEST_F(BrowserAccessibilityTest, PlatformChildIterator) {
   // (i) => node is ignored
+  // Parent Tree
   // 1
   // |__________
   // |     |   |
   // 2(i)  3   4
-  // |_______________________
-  // |   |      |           |
-  // 5   6      7(i)        8(i)
-  // |   |      |________
-  // |   |      |       |
-  // 9   10(i)   11(i)   12
-  //     |      |____
-  //     |      |   |
-  //     13(i)  14  15
-  ui::AXTreeUpdate tree_update;
-  tree_update.root_id = 1;
-  tree_update.nodes.resize(15);
-  tree_update.nodes[0].id = 1;
-  tree_update.nodes[0].child_ids = {2, 3, 4};
+  // |__________________________________
+  // |              |      |           |
+  // 5              6      7(i)        8(i)
+  // |              |      |________
+  // |              |      |       |
+  // Child Tree     9(i)   10(i)   11
+  //                |      |____
+  //                |      |   |
+  //                12(i)  13  14
+  // Child Tree
+  // 1
+  // |_________
+  // |    |   |
+  // 2    3   4
+  //      |
+  //      5
+  ui::AXTreeID parent_tree_id = ui::AXTreeID::CreateNewAXTreeID();
+  ui::AXTreeID child_tree_id = ui::AXTreeID::CreateNewAXTreeID();
 
-  tree_update.nodes[1].id = 2;
-  tree_update.nodes[1].child_ids = {5, 6, 7, 8};
-  tree_update.nodes[1].AddState(ax::mojom::State::kIgnored);
+  ui::AXTreeUpdate parent_tree_update;
+  parent_tree_update.tree_data.tree_id = parent_tree_id;
+  parent_tree_update.has_tree_data = true;
+  parent_tree_update.root_id = 1;
+  parent_tree_update.nodes.resize(14);
+  parent_tree_update.nodes[0].id = 1;
+  parent_tree_update.nodes[0].child_ids = {2, 3, 4};
 
-  tree_update.nodes[2].id = 3;
-  tree_update.nodes[3].id = 4;
+  parent_tree_update.nodes[1].id = 2;
+  parent_tree_update.nodes[1].child_ids = {5, 6, 7, 8};
+  parent_tree_update.nodes[1].AddState(ax::mojom::State::kIgnored);
 
-  tree_update.nodes[4].id = 5;
-  tree_update.nodes[4].child_ids = {9};
+  parent_tree_update.nodes[2].id = 3;
+  parent_tree_update.nodes[3].id = 4;
 
-  tree_update.nodes[5].id = 6;
-  tree_update.nodes[5].child_ids = {10};
+  parent_tree_update.nodes[4].id = 5;
+  parent_tree_update.nodes[4].AddStringAttribute(
+      ax::mojom::StringAttribute::kChildTreeId, child_tree_id.ToString());
 
-  tree_update.nodes[6].id = 7;
-  tree_update.nodes[6].child_ids = {11, 12};
-  tree_update.nodes[6].AddState(ax::mojom::State::kIgnored);
+  parent_tree_update.nodes[5].id = 6;
+  parent_tree_update.nodes[5].child_ids = {9};
 
-  tree_update.nodes[7].id = 8;
-  tree_update.nodes[7].AddState(ax::mojom::State::kIgnored);
+  parent_tree_update.nodes[6].id = 7;
+  parent_tree_update.nodes[6].child_ids = {10, 11};
+  parent_tree_update.nodes[6].AddState(ax::mojom::State::kIgnored);
 
-  tree_update.nodes[8].id = 9;
+  parent_tree_update.nodes[7].id = 8;
+  parent_tree_update.nodes[7].AddState(ax::mojom::State::kIgnored);
 
-  tree_update.nodes[9].id = 10;
-  tree_update.nodes[9].child_ids = {13};
-  tree_update.nodes[9].AddState(ax::mojom::State::kIgnored);
+  parent_tree_update.nodes[8].id = 9;
+  parent_tree_update.nodes[8].child_ids = {12};
+  parent_tree_update.nodes[8].AddState(ax::mojom::State::kIgnored);
 
-  tree_update.nodes[10].id = 11;
-  tree_update.nodes[10].child_ids = {14, 15};
-  tree_update.nodes[10].AddState(ax::mojom::State::kIgnored);
+  parent_tree_update.nodes[9].id = 10;
+  parent_tree_update.nodes[9].child_ids = {13, 14};
+  parent_tree_update.nodes[9].AddState(ax::mojom::State::kIgnored);
 
-  tree_update.nodes[11].id = 12;
+  parent_tree_update.nodes[10].id = 11;
 
-  tree_update.nodes[12].id = 13;
-  tree_update.nodes[12].AddState(ax::mojom::State::kIgnored);
+  parent_tree_update.nodes[11].id = 12;
+  parent_tree_update.nodes[11].AddState(ax::mojom::State::kIgnored);
 
-  tree_update.nodes[13].id = 14;
+  parent_tree_update.nodes[12].id = 13;
 
-  tree_update.nodes[14].id = 15;
+  parent_tree_update.nodes[13].id = 14;
 
-  std::unique_ptr<BrowserAccessibilityManager> manager(
+  ui::AXTreeUpdate child_tree_update;
+  child_tree_update.tree_data.tree_id = child_tree_id;
+  child_tree_update.tree_data.parent_tree_id = parent_tree_id;
+  child_tree_update.has_tree_data = true;
+  child_tree_update.root_id = 1;
+  child_tree_update.nodes.resize(5);
+  child_tree_update.nodes[0].id = 1;
+  child_tree_update.nodes[0].child_ids = {2, 3, 4};
+
+  child_tree_update.nodes[1].id = 2;
+
+  child_tree_update.nodes[2].id = 3;
+  child_tree_update.nodes[2].child_ids = {5};
+
+  child_tree_update.nodes[3].id = 4;
+
+  child_tree_update.nodes[4].id = 5;
+
+  std::unique_ptr<BrowserAccessibilityManager> parent_manager(
       BrowserAccessibilityManager::Create(
-          tree_update, test_browser_accessibility_delegate_.get(),
+          parent_tree_update, test_browser_accessibility_delegate_.get(),
           new BrowserAccessibilityFactory()));
 
-  BrowserAccessibility* root_obj = manager->GetRoot();
+  std::unique_ptr<BrowserAccessibilityManager> child_manager(
+      BrowserAccessibilityManager::Create(
+          child_tree_update, test_browser_accessibility_delegate_.get(),
+          new BrowserAccessibilityFactory()));
+
+  BrowserAccessibility* root_obj = parent_manager->GetRoot();
   // Test traversal
-  // PlatformChildren(root_obj) = {5, 6, 14, 15, 12, 3, 4}
+  // PlatformChildren(root_obj) = {5, 6, 13, 15, 11, 3, 4}
   BrowserAccessibility::PlatformChildIterator platform_iterator =
       root_obj->PlatformChildrenBegin();
   EXPECT_EQ(5, platform_iterator->GetId());
+  EXPECT_EQ(nullptr, platform_iterator->PlatformGetPreviousSibling());
+  EXPECT_EQ(1u, platform_iterator->PlatformChildCount());
+
+  // Test Child-Tree Traversal
+  BrowserAccessibility* child_tree_root =
+      platform_iterator->PlatformGetFirstChild();
+  EXPECT_EQ(1, child_tree_root->GetId());
+  BrowserAccessibility::PlatformChildIterator child_tree_iterator =
+      child_tree_root->PlatformChildrenBegin();
+
+  EXPECT_EQ(2, child_tree_iterator->GetId());
+  ++child_tree_iterator;
+  EXPECT_EQ(3, child_tree_iterator->GetId());
+  ++child_tree_iterator;
+  EXPECT_EQ(4, child_tree_iterator->GetId());
 
   ++platform_iterator;
   EXPECT_EQ(6, platform_iterator->GetId());
 
   ++platform_iterator;
-  EXPECT_EQ(14, platform_iterator->GetId());
+  EXPECT_EQ(13, platform_iterator->GetId());
 
   ++platform_iterator;
-  EXPECT_EQ(15, platform_iterator->GetId());
+  EXPECT_EQ(14, platform_iterator->GetId());
 
   --platform_iterator;
-  EXPECT_EQ(14, platform_iterator->GetId());
+  EXPECT_EQ(13, platform_iterator->GetId());
 
   --platform_iterator;
   EXPECT_EQ(6, platform_iterator->GetId());
 
   ++platform_iterator;
+  EXPECT_EQ(13, platform_iterator->GetId());
+
+  ++platform_iterator;
   EXPECT_EQ(14, platform_iterator->GetId());
 
   ++platform_iterator;
-  EXPECT_EQ(15, platform_iterator->GetId());
-
-  ++platform_iterator;
-  EXPECT_EQ(12, platform_iterator->GetId());
+  EXPECT_EQ(11, platform_iterator->GetId());
 
   ++platform_iterator;
   EXPECT_EQ(3, platform_iterator->GetId());
@@ -314,22 +364,22 @@
   EXPECT_EQ(root_obj->PlatformChildrenEnd(), platform_iterator);
 
   // test empty list
-  // PlatformChildren(2) = {}
-  BrowserAccessibility* node2 = manager->GetFromID(3);
+  // PlatformChildren(3) = {}
+  BrowserAccessibility* node2 = parent_manager->GetFromID(3);
   platform_iterator = node2->PlatformChildrenBegin();
   EXPECT_EQ(node2->PlatformChildrenEnd(), platform_iterator);
 
   // empty list from ignored node
-  // PlatformChildren(7) = {}
-  BrowserAccessibility* node7 = manager->GetFromID(8);
-  platform_iterator = node7->PlatformChildrenBegin();
-  EXPECT_EQ(node7->PlatformChildrenEnd(), platform_iterator);
+  // PlatformChildren(8) = {}
+  BrowserAccessibility* node8 = parent_manager->GetFromID(8);
+  platform_iterator = node8->PlatformChildrenBegin();
+  EXPECT_EQ(node8->PlatformChildrenEnd(), platform_iterator);
 
   // non-empty list from ignored node
-  // PlatformChildren(10) = {14, 15}
-  BrowserAccessibility* node10 = manager->GetFromID(11);
+  // PlatformChildren(10) = {13, 15}
+  BrowserAccessibility* node10 = parent_manager->GetFromID(10);
   platform_iterator = node10->PlatformChildrenBegin();
-  EXPECT_EQ(14, platform_iterator->GetId());
+  EXPECT_EQ(13, platform_iterator->GetId());
 
   // Two UnignoredChildIterators from the same parent at the same position
   // should be equivalent, even in end position.
diff --git a/content/browser/android/content_url_loader_factory.cc b/content/browser/android/content_url_loader_factory.cc
index 2e4227b7..26dd7ef 100644
--- a/content/browser/android/content_url_loader_factory.cc
+++ b/content/browser/android/content_url_loader_factory.cc
@@ -105,7 +105,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override {}
-  void ProceedWithResponse() override {}
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
diff --git a/content/browser/appcache/appcache_fuzzer.cc b/content/browser/appcache/appcache_fuzzer.cc
index 99af899..879bad91a 100644
--- a/content/browser/appcache/appcache_fuzzer.cc
+++ b/content/browser/appcache/appcache_fuzzer.cc
@@ -65,7 +65,6 @@
                        appcache_service, base::FilePath(),
                        /*browser_context=*/nullptr,
                        /*resource_context=*/nullptr,
-                       /*request_context_getter=*/nullptr,
                        /*special_storage_policy=*/nullptr));
     thread_bundle.RunUntilIdle();
   }
diff --git a/content/browser/appcache/appcache_request_handler_unittest.cc b/content/browser/appcache/appcache_request_handler_unittest.cc
index 4255f70..61e1515c 100644
--- a/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -108,78 +108,6 @@
     int request_status_;
   };
 
-  class MockURLRequestJob : public net::URLRequestJob {
-   public:
-    MockURLRequestJob(net::URLRequest* request,
-                      net::NetworkDelegate* network_delegate,
-                      const net::HttpResponseInfo& info)
-        : net::URLRequestJob(request, network_delegate),
-          has_response_info_(true),
-          response_info_(info) {}
-
-    ~MockURLRequestJob() override {}
-
-   protected:
-    void Start() override { NotifyHeadersComplete(); }
-    void GetResponseInfo(net::HttpResponseInfo* info) override {
-      if (!has_response_info_)
-        return;
-      *info = response_info_;
-    }
-
-   private:
-    bool has_response_info_;
-    net::HttpResponseInfo response_info_;
-  };
-
-  class MockURLRequestJobFactory : public net::URLRequestJobFactory {
-   public:
-    MockURLRequestJobFactory() {}
-
-    ~MockURLRequestJobFactory() override { DCHECK(!request_job_); }
-
-    void SetJob(std::unique_ptr<net::URLRequestJob> job) {
-      request_job_ = std::move(job);
-    }
-
-    net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
-        const std::string& scheme,
-        net::URLRequest* request,
-        net::NetworkDelegate* network_delegate) const override {
-      if (request_job_)
-        return request_job_.release();
-
-      // Some of these tests trigger UpdateJobs which start URLRequests.
-      // We short circuit those be returning error jobs.
-      return new net::URLRequestErrorJob(request, network_delegate,
-                                         net::ERR_INTERNET_DISCONNECTED);
-    }
-
-    net::URLRequestJob* MaybeInterceptRedirect(
-        net::URLRequest* request,
-        net::NetworkDelegate* network_delegate,
-        const GURL& location) const override {
-      return nullptr;
-    }
-
-    net::URLRequestJob* MaybeInterceptResponse(
-        net::URLRequest* request,
-        net::NetworkDelegate* network_delegate) const override {
-      return nullptr;
-    }
-
-    bool IsHandledProtocol(const std::string& scheme) const override {
-      return scheme == "http";
-    }
-
-    bool IsSafeRedirectTarget(const GURL& location) const override {
-      return false;
-    }
-
-   private:
-    mutable std::unique_ptr<net::URLRequestJob> request_job_;
-  };
-
   static void SetUpTestCase() {
     thread_bundle_ = std::make_unique<TestBrowserThreadBundle>(
         TestBrowserThreadBundle::REAL_IO_THREAD);
@@ -194,17 +122,11 @@
 
   // Test harness --------------------------------------------------
 
-  AppCacheRequestHandlerTest()
-      : host_(nullptr), request_(nullptr), request_handler_type_(GetParam()) {
+  AppCacheRequestHandlerTest() : host_(nullptr), request_(nullptr) {
     AppCacheRequestHandler::SetRunningInTests(true);
-    if (request_handler_type_ == URLLOADER) {
-      // TODO(http://crbug.com/824840): Enable NavigationLoaderOnUI for these
-      // tests.
-      feature_list_.InitWithFeatures({network::features::kNetworkService},
-                                     {features::kNavigationLoaderOnUI});
-    } else {
-      feature_list_.InitAndDisableFeature(network::features::kNetworkService);
-    }
+    // TODO(http://crbug.com/824840): Enable NavigationLoaderOnUI for these
+    // tests.
+    feature_list_.InitWithFeatures({}, {features::kNavigationLoaderOnUI});
   }
 
   ~AppCacheRequestHandlerTest() {
@@ -226,9 +148,6 @@
   void SetUpTest() {
     DCHECK(io_task_runner_->BelongsToCurrentThread());
     mock_service_ = std::make_unique<MockAppCacheService>();
-    // Initializes URLRequestContext on the IO thread.
-    empty_context_ = std::make_unique<net::URLRequestContext>();
-    mock_service_->set_request_context(empty_context_.get());
     mock_policy_ = std::make_unique<MockAppCachePolicy>();
     mock_service_->set_appcache_policy(mock_policy_.get());
     const auto kHostId = base::UnguessableToken::Create();
@@ -239,13 +158,10 @@
         host_remote_.BindNewPipeAndPassReceiver(), std::move(frontend_remote),
         kHostId, kRenderFrameId, kMockProcessId, GetBadMessageCallback());
     host_ = mock_service_->GetHost(kHostId);
-    job_factory_ = std::make_unique<MockURLRequestJobFactory>();
-    empty_context_->set_job_factory(job_factory_.get());
   }
 
   void TearDownTest() {
     DCHECK(io_task_runner_->BelongsToCurrentThread());
-    appcache_url_request_job_.reset();
     if (appcache_url_loader_job_)
       appcache_url_loader_job_->DeleteIfNeeded();
     appcache_url_loader_job_.reset();
@@ -255,8 +171,6 @@
     mock_service_.reset();
     mock_policy_.reset();
     host_remote_.reset();
-    job_factory_.reset();
-    empty_context_.reset();
     host_ = nullptr;
   }
 
@@ -291,24 +205,15 @@
   }
 
   void SetAppCacheJob(AppCacheJob* job) {
-    appcache_url_request_job_.reset();
     if (appcache_url_loader_job_)
       appcache_url_loader_job_->DeleteIfNeeded();
     appcache_url_loader_job_ = nullptr;
     if (!job)
       return;
-    if (request_handler_type_ == URLREQUEST)
-      appcache_url_request_job_.reset(job->AsURLRequestJob());
-    else
-      appcache_url_loader_job_ = job->AsURLLoaderJob()->GetDerivedWeakPtr();
+    appcache_url_loader_job_ = job->AsURLLoaderJob()->GetDerivedWeakPtr();
   }
 
-  AppCacheJob* job() {
-    if (request_handler_type_ == URLREQUEST)
-      return appcache_url_request_job_.get();
-    else
-      return appcache_url_loader_job_.get();
-  }
+  AppCacheJob* job() { return appcache_url_loader_job_.get(); }
 
   // MainResource_Miss --------------------------------------------------
 
@@ -317,8 +222,8 @@
         base::BindOnce(&AppCacheRequestHandlerTest::Verify_MainResource_Miss,
                        base::Unretained(this)));
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah"), host_,
-                                        ResourceType::kMainFrame));
+    CreateRequestAndHandler(GURL("http://blah"), host_,
+                            ResourceType::kMainFrame);
     EXPECT_TRUE(handler_.get());
 
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
@@ -358,8 +263,8 @@
         base::BindOnce(&AppCacheRequestHandlerTest::Verify_MainResource_Hit,
                        base::Unretained(this)));
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah"), host_,
-                                        ResourceType::kMainFrame));
+    CreateRequestAndHandler(GURL("http://blah"), host_,
+                            ResourceType::kMainFrame);
     EXPECT_TRUE(handler_.get());
 
     mock_storage()->SimulateFindMainResource(
@@ -400,8 +305,8 @@
         &AppCacheRequestHandlerTest::Verify_MainResource_Fallback,
         base::Unretained(this)));
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah"), host_,
-                                        ResourceType::kMainFrame));
+    CreateRequestAndHandler(GURL("http://blah"), host_,
+                            ResourceType::kMainFrame);
     EXPECT_TRUE(handler_.get());
 
     mock_storage()->SimulateFindMainResource(
@@ -424,49 +329,22 @@
     info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
         net::HttpUtil::AssembleRawHeaders(headers));
 
-    if (request_handler_type_ == URLREQUEST) {
-      job_factory_->SetJob(std::make_unique<MockURLRequestJob>(
-          url_request_.get(), nullptr, info));
-      request_->AsURLRequest()->GetURLRequest()->Start();
-      // All our simulation needs to satisfy are the DCHECK's for the request
-      // status and the response code.
-      DCHECK_EQ(net::OK, delegate_.request_status());
-    } else {
-      network::ResourceResponseHead response;
-      response.headers = info.headers;
-      request_->AsURLLoaderRequest()->set_response(response);
-    }
+    network::ResourceResponseHead response;
+    response.headers = info.headers;
+    request_->AsURLLoaderRequest()->set_response(response);
     DCHECK_EQ(response_code, request_->GetResponseCode());
   }
 
   void SimulateResponseInfo(const net::HttpResponseInfo& info) {
-    if (request_handler_type_ == URLREQUEST) {
-      job_factory_->SetJob(std::make_unique<MockURLRequestJob>(
-          url_request_.get(), nullptr, info));
-      request_->AsURLRequest()->GetURLRequest()->Start();
-    } else {
-      network::ResourceResponseHead response;
-      response.headers = info.headers;
-      request_->AsURLLoaderRequest()->set_response(response);
-    }
+    network::ResourceResponseHead response;
+    response.headers = info.headers;
+    request_->AsURLLoaderRequest()->set_response(response);
   }
 
   void Verify_MainResource_Fallback() {
     EXPECT_FALSE(job()->IsWaiting());
     EXPECT_TRUE(job()->IsDeliveringNetworkResponse());
 
-    // The handler expects to the job to tell it that the request is going to
-    // be restarted before it sees the next request.
-    if (request_handler_type_ == URLREQUEST) {
-      handler_->OnPrepareToRestartURLRequest();
-
-      // When the request is restarted, the existing job is dropped so a
-      // real network job gets created. We expect NULL here which will cause
-      // the net library to create a real job.
-      SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
-      EXPECT_FALSE(job());
-    }
-
     // Simulate an http error of the real network job.
     SimulateResponseCode(500);
 
@@ -494,8 +372,8 @@
         &AppCacheRequestHandlerTest::Verify_MainResource_FallbackOverride,
         base::Unretained(this)));
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/fallback-override"),
-                                        host_, ResourceType::kMainFrame));
+    CreateRequestAndHandler(GURL("http://blah/fallback-override"), host_,
+                            ResourceType::kMainFrame);
     EXPECT_TRUE(handler_.get());
 
     mock_storage()->SimulateFindMainResource(
@@ -515,18 +393,6 @@
     EXPECT_FALSE(job()->IsWaiting());
     EXPECT_TRUE(job()->IsDeliveringNetworkResponse());
 
-    // The handler expects to the job to tell it that the request is going to
-    // be restarted before it sees the next request.
-    if (request_handler_type_ == URLREQUEST) {
-      handler_->OnPrepareToRestartURLRequest();
-
-      // When the request is restarted, the existing job is dropped so a
-      // real network job gets created. We expect NULL here which will cause
-      // the net library to create a real job.
-      SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
-      EXPECT_FALSE(job());
-    }
-
     // Simulate an http error of the real network job, but with custom
     // headers that override the fallback behavior.
     const char kOverrideHeaders[] =
@@ -554,8 +420,8 @@
   // SubResource_Miss_WithNoCacheSelected ----------------------------------
 
   void SubResource_Miss_WithNoCacheSelected() {
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     // We avoid creating handler when possible, sub-resource requests are not
     // subject to retrieval from an appcache when there's no associated cache.
     EXPECT_FALSE(handler_.get());
@@ -570,8 +436,8 @@
     // in a network or fallback namespace, should result in a failed request.
     host_->AssociateCompleteCache(MakeNewCache());
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());
 
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
@@ -595,8 +461,8 @@
     host_->pending_selected_cache_id_ = cache->cache_id();
     host_->set_preferred_manifest_url(cache->owning_group()->manifest_url());
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
     EXPECT_TRUE(job());
@@ -623,8 +489,8 @@
     mock_storage()->SimulateFindSubResource(
         AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
     EXPECT_TRUE(job());
@@ -649,8 +515,8 @@
     mock_storage()->SimulateFindSubResource(
         AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
     EXPECT_FALSE(job());
@@ -676,8 +542,8 @@
     mock_storage()->SimulateFindSubResource(
         AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
     EXPECT_FALSE(job());
@@ -704,8 +570,8 @@
     mock_storage()->SimulateFindSubResource(AppCacheEntry(), AppCacheEntry(),
                                             true);
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
     EXPECT_FALSE(job());
@@ -727,8 +593,8 @@
     mock_storage()->SimulateFindSubResource(
         AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());
 
     mock_service_->EraseHost(host_->host_id());
@@ -748,8 +614,8 @@
     // Precondition, the host is waiting on cache selection.
     host_->pending_selected_cache_id_ = 1;
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());
 
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
@@ -759,9 +625,6 @@
     mock_service_->EraseHost(host_->host_id());
     host_ = nullptr;
 
-    if (request_handler_type_ == URLREQUEST) {
-      EXPECT_TRUE(appcache_url_request_job_->has_been_killed());
-    }
     EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
     EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
         nullptr, GURL("http://blah/redirect")));
@@ -778,8 +641,8 @@
     mock_storage()->SimulateFindSubResource(
         AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
     EXPECT_TRUE(job());
@@ -788,9 +651,6 @@
     mock_policy_.reset();
     host_ = nullptr;
 
-    if (request_handler_type_ == URLREQUEST) {
-      EXPECT_TRUE(appcache_url_request_job_->has_been_killed());
-    }
     EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
     EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
         nullptr, GURL("http://blah/redirect")));
@@ -805,8 +665,8 @@
     // Precondition, the host is waiting on cache selection.
     host_->pending_selected_cache_id_ = 1;
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("ftp://blah/"), host_,
-                                        ResourceType::kSubResource));
+    CreateRequestAndHandler(GURL("ftp://blah/"), host_,
+                            ResourceType::kSubResource);
     EXPECT_TRUE(handler_.get());  // we could redirect to http (conceivably)
 
     EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
@@ -820,8 +680,8 @@
   // CanceledRequest -----------------------------
 
   void CanceledRequest() {
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kMainFrame));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kMainFrame);
     EXPECT_TRUE(handler_.get());
 
     SetAppCacheJob(handler_->MaybeLoadResource(nullptr));
@@ -831,19 +691,6 @@
 
     base::WeakPtr<AppCacheJob> weak_job = job()->GetWeakPtr();
 
-    // TODO(ananta/michaeln)
-    // Rewrite this test for URLLoader.
-    if (request_handler_type_ == URLREQUEST) {
-      job_factory_->SetJob(std::move(appcache_url_request_job_));
-
-      request_->AsURLRequest()->GetURLRequest()->Start();
-      ASSERT_TRUE(weak_job);
-      EXPECT_TRUE(weak_job->IsStarted());
-
-      request_->AsURLRequest()->GetURLRequest()->Cancel();
-      ASSERT_FALSE(weak_job);
-    }
-
     EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
 
     TestFinished();
@@ -856,8 +703,8 @@
         base::BindOnce(&AppCacheRequestHandlerTest::Verify_MainResource_Blocked,
                        base::Unretained(this)));
 
-    EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
-                                        ResourceType::kMainFrame));
+    CreateRequestAndHandler(GURL("http://blah/"), host_,
+                            ResourceType::kMainFrame);
     EXPECT_TRUE(handler_.get());
 
     mock_policy_->can_load_return_value_ = false;
@@ -911,30 +758,16 @@
     return reinterpret_cast<MockAppCacheStorage*>(mock_service_->storage());
   }
 
-  bool CreateRequestAndHandler(const GURL& url,
+  void CreateRequestAndHandler(const GURL& url,
                                AppCacheHost* host,
                                ResourceType resource_type) {
-    if (request_handler_type_ == URLREQUEST) {
-      url_request_ = empty_context_->CreateRequest(
-          url, net::DEFAULT_PRIORITY, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
-
-      auto request = std::make_unique<AppCacheURLRequest>(url_request_.get());
-      request_ = request.get();
-      handler_ =
-          host->CreateRequestHandler(std::move(request), resource_type, false);
-      return true;
-    } else if (request_handler_type_ == URLLOADER) {
-      network::ResourceRequest resource_request;
-      resource_request.url = url;
-      resource_request.method = "GET";
-      auto request =
-          std::make_unique<AppCacheURLLoaderRequest>(resource_request);
-      request_ = request.get();
-      handler_ =
-          host->CreateRequestHandler(std::move(request), resource_type, false);
-      return true;
-    }
-    return false;
+    network::ResourceRequest resource_request;
+    resource_request.url = url;
+    resource_request.method = "GET";
+    auto request = std::make_unique<AppCacheURLLoaderRequest>(resource_request);
+    request_ = request.get();
+    handler_ =
+        host->CreateRequestHandler(std::move(request), resource_type, false);
   }
 
   // Data members --------------------------------------------------
@@ -945,19 +778,15 @@
   std::unique_ptr<MockAppCachePolicy> mock_policy_;
   AppCacheHost* host_;
   mojo::Remote<blink::mojom::AppCacheHost> host_remote_;
-  std::unique_ptr<net::URLRequestContext> empty_context_;
-  std::unique_ptr<MockURLRequestJobFactory> job_factory_;
   MockURLRequestDelegate delegate_;
   AppCacheRequest* request_;
   std::unique_ptr<net::URLRequest> url_request_;
   std::unique_ptr<AppCacheRequestHandler> handler_;
-  std::unique_ptr<AppCacheURLRequestJob> appcache_url_request_job_;
   base::WeakPtr<AppCacheURLLoaderJob> appcache_url_loader_job_;
 
   static std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
   static scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
 
-  RequestHandlerType request_handler_type_;
   base::test::ScopedFeatureList feature_list_;
 };
 
@@ -967,80 +796,76 @@
 scoped_refptr<base::SingleThreadTaskRunner>
     AppCacheRequestHandlerTest::io_task_runner_;
 
-TEST_P(AppCacheRequestHandlerTest, MainResource_Miss) {
+TEST_F(AppCacheRequestHandlerTest, MainResource_Miss) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Miss);
 }
 
-TEST_P(AppCacheRequestHandlerTest, MainResource_Hit) {
+TEST_F(AppCacheRequestHandlerTest, MainResource_Hit) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Hit);
 }
 
-TEST_P(AppCacheRequestHandlerTest, MainResource_Fallback) {
+TEST_F(AppCacheRequestHandlerTest, MainResource_Fallback) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Fallback);
 }
 
-TEST_P(AppCacheRequestHandlerTest, MainResource_FallbackOverride) {
+TEST_F(AppCacheRequestHandlerTest, MainResource_FallbackOverride) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_FallbackOverride);
 }
 
-TEST_P(AppCacheRequestHandlerTest, SubResource_Miss_WithNoCacheSelected) {
+TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithNoCacheSelected) {
   RunTestOnIOThread(
       &AppCacheRequestHandlerTest::SubResource_Miss_WithNoCacheSelected);
 }
 
-TEST_P(AppCacheRequestHandlerTest, SubResource_Miss_WithCacheSelected) {
+TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithCacheSelected) {
   RunTestOnIOThread(
       &AppCacheRequestHandlerTest::SubResource_Miss_WithCacheSelected);
 }
 
-TEST_P(AppCacheRequestHandlerTest, SubResource_Miss_WithWaitForCacheSelection) {
+TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithWaitForCacheSelection) {
   RunTestOnIOThread(
       &AppCacheRequestHandlerTest::SubResource_Miss_WithWaitForCacheSelection);
 }
 
-TEST_P(AppCacheRequestHandlerTest, SubResource_Hit) {
+TEST_F(AppCacheRequestHandlerTest, SubResource_Hit) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_Hit);
 }
 
-TEST_P(AppCacheRequestHandlerTest, SubResource_RedirectFallback) {
+TEST_F(AppCacheRequestHandlerTest, SubResource_RedirectFallback) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_RedirectFallback);
 }
 
-TEST_P(AppCacheRequestHandlerTest, SubResource_NoRedirectFallback) {
+TEST_F(AppCacheRequestHandlerTest, SubResource_NoRedirectFallback) {
   RunTestOnIOThread(
       &AppCacheRequestHandlerTest::SubResource_NoRedirectFallback);
 }
 
-TEST_P(AppCacheRequestHandlerTest, SubResource_Network) {
+TEST_F(AppCacheRequestHandlerTest, SubResource_Network) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_Network);
 }
 
-TEST_P(AppCacheRequestHandlerTest, DestroyedHost) {
+TEST_F(AppCacheRequestHandlerTest, DestroyedHost) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedHost);
 }
 
-TEST_P(AppCacheRequestHandlerTest, DestroyedHostWithWaitingJob) {
+TEST_F(AppCacheRequestHandlerTest, DestroyedHostWithWaitingJob) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedHostWithWaitingJob);
 }
 
-TEST_P(AppCacheRequestHandlerTest, DestroyedService) {
+TEST_F(AppCacheRequestHandlerTest, DestroyedService) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedService);
 }
 
-TEST_P(AppCacheRequestHandlerTest, UnsupportedScheme) {
+TEST_F(AppCacheRequestHandlerTest, UnsupportedScheme) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::UnsupportedScheme);
 }
 
-TEST_P(AppCacheRequestHandlerTest, CanceledRequest) {
+TEST_F(AppCacheRequestHandlerTest, CanceledRequest) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::CanceledRequest);
 }
 
-TEST_P(AppCacheRequestHandlerTest, MainResource_Blocked) {
+TEST_F(AppCacheRequestHandlerTest, MainResource_Blocked) {
   RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Blocked);
 }
 
-INSTANTIATE_TEST_SUITE_P(,
-                         AppCacheRequestHandlerTest,
-                         ::testing::Values(URLREQUEST, URLLOADER));
-
 }  // namespace content
diff --git a/content/browser/appcache/appcache_service_impl.cc b/content/browser/appcache/appcache_service_impl.cc
index dcfc1a4..34c935b 100644
--- a/content/browser/appcache/appcache_service_impl.cc
+++ b/content/browser/appcache/appcache_service_impl.cc
@@ -381,7 +381,6 @@
       appcache_policy_(nullptr),
       quota_client_(nullptr),
       quota_manager_proxy_(quota_manager_proxy),
-      request_context_(nullptr),
       force_keep_session_state_(false),
       partition_(std::move(partition)) {
   if (quota_manager_proxy_.get()) {
diff --git a/content/browser/appcache/appcache_service_impl.h b/content/browser/appcache/appcache_service_impl.h
index cd17f3b..fe35330 100644
--- a/content/browser/appcache/appcache_service_impl.h
+++ b/content/browser/appcache/appcache_service_impl.h
@@ -32,10 +32,6 @@
 class FilePath;
 }  // namespace base
 
-namespace net {
-class URLRequestContext;
-}  // namespace net
-
 namespace storage {
 class SpecialStoragePolicy;
 }  // namespace storage
@@ -135,15 +131,6 @@
                              int64_t cache_id,
                              int64_t response_id);
 
-  // Context for use during cache updates, should only be accessed
-  // on the IO thread. We do NOT add a reference to the request context,
-  // it is the callers responsibility to ensure that the pointer
-  // remains valid while set.
-  net::URLRequestContext* request_context() const { return request_context_; }
-  void set_request_context(net::URLRequestContext* context) {
-    request_context_ = context;
-  }
-
   // The appcache policy, may be null, in which case access is always allowed.
   // The service does NOT assume ownership of the policy, it is the callers
   // responsibility to ensure that the pointer remains valid while set.
@@ -233,8 +220,6 @@
   std::map<AsyncHelper*, std::unique_ptr<AsyncHelper>> pending_helpers_;
   // One 'backend' per child process.
   std::map<int, AppCacheBackendImpl*> backends_;
-  // Context for use during cache updates.
-  net::URLRequestContext* request_context_;
   // If true, nothing (not even session-only data) should be deleted on exit.
   bool force_keep_session_state_;
   base::Time last_reinit_time_;
diff --git a/content/browser/appcache/appcache_subresource_url_factory.cc b/content/browser/appcache/appcache_subresource_url_factory.cc
index b305ce0a..ad1eaa1 100644
--- a/content/browser/appcache/appcache_subresource_url_factory.cc
+++ b/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -158,8 +158,6 @@
   }
 
   // network::mojom::URLLoader implementation
-  void ProceedWithResponse() override { NOTREACHED(); }
-
   void ContinueFollowRedirect(
       SingleRequestURLLoaderFactory::RequestHandler handler) {
     if (handler) {
diff --git a/content/browser/appcache/appcache_update_job_unittest.cc b/content/browser/appcache/appcache_update_job_unittest.cc
index ecd6770..5469b163 100644
--- a/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/content/browser/appcache/appcache_update_job_unittest.cc
@@ -3492,7 +3492,6 @@
 
   void MakeService() {
     service_ = std::make_unique<MockAppCacheService>();
-    service_->set_request_context(io_thread_->request_context());
     service_->set_url_loader_factory_getter(loader_factory_getter_.get());
   }
 
diff --git a/content/browser/appcache/appcache_url_loader_job.cc b/content/browser/appcache/appcache_url_loader_job.cc
index 03c23a09..946530b 100644
--- a/content/browser/appcache/appcache_url_loader_job.cc
+++ b/content/browser/appcache/appcache_url_loader_job.cc
@@ -116,12 +116,6 @@
   NOTREACHED() << "appcache never produces redirects";
 }
 
-void AppCacheURLLoaderJob::ProceedWithResponse() {
-  // TODO(arthursonzogni):  Implement this if AppCache starts using the
-  // AppCacheURLLoader before the Network Service has shipped.
-  NOTREACHED();
-}
-
 void AppCacheURLLoaderJob::SetPriority(net::RequestPriority priority,
                                        int32_t intra_priority_value) {}
 void AppCacheURLLoaderJob::PauseReadingBodyFromNet() {}
diff --git a/content/browser/appcache/appcache_url_loader_job.h b/content/browser/appcache/appcache_url_loader_job.h
index 1e2d3a21..575936f6 100644
--- a/content/browser/appcache/appcache_url_loader_job.h
+++ b/content/browser/appcache/appcache_url_loader_job.h
@@ -68,7 +68,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/content/browser/appcache/chrome_appcache_service.cc b/content/browser/appcache/chrome_appcache_service.cc
index 54ae9fb..6fcb628 100644
--- a/content/browser/appcache/chrome_appcache_service.cc
+++ b/content/browser/appcache/chrome_appcache_service.cc
@@ -13,7 +13,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
 #include "net/base/net_errors.h"
-#include "net/url_request/url_request_context_getter.h"
 #include "storage/browser/quota/quota_manager.h"
 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
 
@@ -28,7 +27,6 @@
     const base::FilePath& cache_path,
     BrowserContext* browser_context,
     ResourceContext* resource_context,
-    scoped_refptr<net::URLRequestContextGetter> request_context_getter,
     scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy) {
   DCHECK_CURRENTLY_ON(
       NavigationURLLoaderImpl::GetLoaderRequestControllerThreadID());
@@ -38,14 +36,6 @@
   browser_context_ = browser_context;
   resource_context_ = resource_context;
 
-  // The |request_context_getter| can be NULL in some unit tests.
-  //
-  // TODO(ajwong): TestProfile is difficult to work with. The
-  // SafeBrowsing tests require that GetRequestContext return NULL
-  // so we can't depend on having a non-NULL value here. See crbug/149783.
-  if (request_context_getter)
-    set_request_context(request_context_getter->GetURLRequestContext());
-
   // Init our base class.
   Initialize(cache_path_);
   set_appcache_policy(this);
diff --git a/content/browser/appcache/chrome_appcache_service.h b/content/browser/appcache/chrome_appcache_service.h
index ad7d1586..79e9e19 100644
--- a/content/browser/appcache/chrome_appcache_service.h
+++ b/content/browser/appcache/chrome_appcache_service.h
@@ -25,10 +25,6 @@
 class FilePath;
 }
 
-namespace net {
-class URLRequestContextGetter;
-}
-
 namespace content {
 class BrowserContext;
 class ResourceContext;
@@ -64,7 +60,6 @@
       const base::FilePath& cache_path,
       BrowserContext* browser_context,
       ResourceContext* resource_context,
-      scoped_refptr<net::URLRequestContextGetter> request_context_getter,
       scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy);
 
   void CreateBackend(
diff --git a/content/browser/appcache/chrome_appcache_service_unittest.cc b/content/browser/appcache/chrome_appcache_service_unittest.cc
index aea927f..b62be511 100644
--- a/content/browser/appcache/chrome_appcache_service_unittest.cc
+++ b/content/browser/appcache/chrome_appcache_service_unittest.cc
@@ -79,7 +79,6 @@
                      appcache_service, appcache_path,
                      nullptr /* browser_context */,
                      browser_context_.GetResourceContext(),
-                     base::RetainedRef(browser_context_.GetRequestContext()),
                      std::move(mock_policy)));
   // Steps needed to initialize the storage of AppCache data.
   thread_bundle_.RunUntilIdle();
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc
index 59db93d..d7a706d 100644
--- a/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -1402,8 +1402,9 @@
   CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_);
   auto cache_handle =
       LegacyCacheStorage::From(cache_storage)->GetLoadedCache(kCacheName);
-  base::FilePath index_path =
-      LegacyCacheStorageCache::From(cache_handle)->path().AppendASCII("index");
+  base::FilePath cache_path =
+      LegacyCacheStorageCache::From(cache_handle)->path();
+  base::FilePath index_path = cache_path.AppendASCII("index");
   cache_handle = CacheStorageCacheHandle();
 
   DestroyStorageManager();
@@ -1412,6 +1413,16 @@
   ASSERT_FALSE(index_path.empty());
   ASSERT_EQ(5, base::WriteFile(index_path, "hello", 5));
 
+  // The cache_storage index is written from a background thread and may be
+  // written just after our overwrite of the simple disk_cache index here.
+  // We need the cache directory to have a newer time stamp, though, in order
+  // for the Size() method to actually try calculating the size from the
+  // corrupted simple disk_cache.  Therefore we force the cache directory
+  // to have a much newer time to ensure the cache_storage index is not used
+  // in the following Size() call.
+  base::Time t = base::Time::Now() + base::TimeDelta::FromHours(1);
+  EXPECT_TRUE(base::TouchFile(cache_path, t, t));
+
   CreateStorageManager();
 
   EXPECT_TRUE(Open(origin1_, kCacheName));
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage.cc b/content/browser/cache_storage/legacy/legacy_cache_storage.cc
index a064cef4..b1a4d62c 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage.cc
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage.cc
@@ -571,18 +571,27 @@
       quota_manager_proxy_(quota_manager_proxy),
       owner_(owner),
       cache_storage_manager_(cache_storage_manager) {
-  if (memory_only)
+  if (memory_only) {
     cache_loader_.reset(new MemoryLoader(
         cache_task_runner_.get(), std::move(scheduler_task_runner),
         quota_manager_proxy.get(), blob_context, this, origin, owner));
-  else
-    cache_loader_.reset(new SimpleCacheLoader(
-        origin_path_, cache_task_runner_.get(),
-        std::move(scheduler_task_runner), quota_manager_proxy.get(),
-        blob_context, this, origin, owner));
+    return;
+  }
+
+  cache_loader_.reset(new SimpleCacheLoader(
+      origin_path_, cache_task_runner_.get(), std::move(scheduler_task_runner),
+      quota_manager_proxy.get(), blob_context, this, origin, owner));
+
+#if defined(OS_ANDROID)
+  app_status_listener_ = base::android::ApplicationStatusListener::New(
+      base::BindRepeating(&LegacyCacheStorage::OnApplicationStateChange,
+                          weak_factory_.GetWeakPtr()));
+#endif
 }
 
-LegacyCacheStorage::~LegacyCacheStorage() {}
+LegacyCacheStorage::~LegacyCacheStorage() {
+  FlushIndexIfDirty();
+}
 
 CacheStorageHandle LegacyCacheStorage::CreateHandle() {
   return CacheStorageHandle(weak_factory_.GetWeakPtr());
@@ -810,14 +819,19 @@
 }
 
 void LegacyCacheStorage::ScheduleWriteIndex() {
-  static const int64_t kWriteIndexDelaySecs = 5;
+  // These values are chosen to be equal or greater than the simple disk_cache
+  // index write delays.  We want the cache_storage index to be written last.
+  static const int64_t kWriteIndexDelayMilliseconds = 20050;
+  static const int64_t kWriteIndexBackgroundDelayMilliseconds = 150;
+  int64_t delay_ms = app_on_background_ ? kWriteIndexBackgroundDelayMilliseconds
+                                        : kWriteIndexDelayMilliseconds;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   index_write_task_.Reset(base::BindOnce(&LegacyCacheStorage::WriteIndex,
                                          weak_factory_.GetWeakPtr(),
                                          base::DoNothing::Once<bool>()));
   base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE, index_write_task_.callback(),
-      base::TimeDelta::FromSeconds(kWriteIndexDelaySecs));
+      base::TimeDelta::FromMilliseconds(delay_ms));
 }
 
 void LegacyCacheStorage::WriteIndex(base::OnceCallback<void(bool)> callback) {
@@ -1014,6 +1028,7 @@
       cache_ptr->cache_padding_key()->key()));
 
   CacheStorageCacheHandle handle = cache_ptr->CreateHandle();
+  index_write_task_.Cancel();
   cache_loader_->WriteIndex(
       *cache_index_,
       base::BindOnce(&LegacyCacheStorage::CreateCacheDidWriteIndex,
@@ -1072,6 +1087,7 @@
   DCHECK(scheduler_->IsRunningExclusiveOperation());
   LegacyCacheStorageCache::From(cache_handle)->SetObserver(nullptr);
   cache_index_->DoomCache(cache_name);
+  index_write_task_.Cancel();
   cache_loader_->WriteIndex(
       *cache_index_,
       base::BindOnce(&LegacyCacheStorage::DeleteCacheDidWriteIndex,
@@ -1397,4 +1413,24 @@
   }
 }
 
+void LegacyCacheStorage::FlushIndexIfDirty() {
+  if (!index_write_pending())
+    return;
+  index_write_task_.Cancel();
+  cache_loader_->WriteIndex(*cache_index_, base::DoNothing::Once<bool>());
+}
+
+#if defined(OS_ANDROID)
+void LegacyCacheStorage::OnApplicationStateChange(
+    base::android::ApplicationState state) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
+    app_on_background_ = false;
+  } else if (state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) {
+    app_on_background_ = true;
+    FlushIndexIfDirty();
+  }
+}
+#endif
+
 }  // namespace content
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage.h b/content/browser/cache_storage/legacy/legacy_cache_storage.h
index 14ae5b6..2e68fe9b 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage.h
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage.h
@@ -15,11 +15,16 @@
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
 #include "content/browser/cache_storage/cache_storage.h"
 #include "content/browser/cache_storage/cache_storage_cache_observer.h"
 #include "content/browser/cache_storage/cache_storage_scheduler_types.h"
 #include "content/browser/cache_storage/legacy/legacy_cache_storage_cache.h"
 
+#if defined(OS_ANDROID)
+#include "base/android/application_status_listener.h"
+#endif
+
 namespace base {
 class SequencedTaskRunner;
 }
@@ -260,6 +265,12 @@
   bool InitiateScheduledIndexWriteForTest(
       base::OnceCallback<void(bool)> callback);
 
+  void FlushIndexIfDirty();
+
+#if defined(OS_ANDROID)
+  void OnApplicationStateChange(base::android::ApplicationState state);
+#endif
+
   // Whether or not we've loaded the list of cache names into memory.
   bool initialized_;
   bool initializing_;
@@ -305,6 +316,14 @@
   base::CancelableOnceClosure index_write_task_;
   size_t handle_ref_count_ = 0;
 
+#if defined(OS_ANDROID)
+  std::unique_ptr<base::android::ApplicationStatusListener>
+      app_status_listener_;
+#endif
+
+  // True if running on android and the app is in the background.
+  bool app_on_background_ = false;
+
   SEQUENCE_CHECKER(sequence_checker_);
   base::WeakPtrFactory<LegacyCacheStorage> weak_factory_{this};
 
diff --git a/content/browser/cookie_store/cookie_store_manager_unittest.cc b/content/browser/cookie_store/cookie_store_manager_unittest.cc
index f007ab5..7bde04f 100644
--- a/content/browser/cookie_store/cookie_store_manager_unittest.cc
+++ b/content/browser/cookie_store/cookie_store_manager_unittest.cc
@@ -265,11 +265,6 @@
     storage_partition_impl_ = base::WrapUnique(
         new StoragePartitionImpl(worker_test_helper_->browser_context(),
                                  user_data_directory_.GetPath(), nullptr));
-    if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-      storage_partition_impl_->SetURLRequestContext(
-          worker_test_helper_->browser_context()->CreateRequestContext(
-              nullptr, URLRequestInterceptorScopedVector()));
-    }
     ::network::mojom::NetworkContext* network_context =
         storage_partition_impl_->GetNetworkContext();
     cookie_store_context_->ListenToCookieChanges(
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.cc b/content/browser/devtools/devtools_url_loader_interceptor.cc
index bb5588d..79df0a3 100644
--- a/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -263,7 +263,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
@@ -1294,10 +1293,6 @@
   StartRequest();
 }
 
-void InterceptionJob::ProceedWithResponse() {
-  NOTREACHED();
-}
-
 void InterceptionJob::SetPriority(net::RequestPriority priority,
                                   int32_t intra_priority_value) {
   priority_ = std::make_pair(priority, intra_priority_value);
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index 4d79ccc..0b2f885 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -58,7 +58,6 @@
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_download_manager_delegate.h"
-#include "content/shell/browser/shell_network_delegate.h"
 #include "content/test/content_browser_test_utils_internal.h"
 #include "content/test/test_content_browser_client.h"
 #include "net/dns/mock_host_resolver.h"
@@ -3175,9 +3174,6 @@
   net::EmbeddedTestServer origin_one;
   net::EmbeddedTestServer origin_two;
 
-  // Block third-party cookies.
-  ShellNetworkDelegate::SetBlockThirdPartyCookies(true);
-
   // |url| redirects to a different origin |download| which tries to set a
   // cookie.
   base::StringPairs cookie_header;
diff --git a/content/browser/download/download_utils.cc b/content/browser/download/download_utils.cc
index 55859ee..1d5fc46d 100644
--- a/content/browser/download/download_utils.cc
+++ b/content/browser/download/download_utils.cc
@@ -16,7 +16,6 @@
 #include "components/download/public/common/download_url_parameters.h"
 #include "components/download/public/common/download_utils.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/loader/upload_data_stream_builder.h"
 #include "content/browser/resource_context_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/content/browser/file_url_loader_factory.cc b/content/browser/file_url_loader_factory.cc
index 032692b..9b6e46d 100644
--- a/content/browser/file_url_loader_factory.cc
+++ b/content/browser/file_url_loader_factory.cc
@@ -178,7 +178,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override {}
-  void ProceedWithResponse() override { NOTREACHED(); }
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
@@ -410,7 +409,6 @@
     }
     MaybeDeleteSelf();
   }
-  void ProceedWithResponse() override {}
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
diff --git a/content/browser/fileapi/file_system_url_loader_factory.cc b/content/browser/fileapi/file_system_url_loader_factory.cc
index c6537709..db8f7bca 100644
--- a/content/browser/fileapi/file_system_url_loader_factory.cc
+++ b/content/browser/fileapi/file_system_url_loader_factory.cc
@@ -102,7 +102,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override {}
-  void ProceedWithResponse() override {}
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 48d5dca9..512c3d9 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -1915,22 +1915,6 @@
       // destroyed the NavigationRequest.
       return;
     }
-
-    // Call ProceedWithResponse()
-    // Note: There is no need to call ProceedWithResponse() when the Network
-    // Service is enabled. See https://crbug.com/791049.
-    if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-      // |url_loader_client_endpoints_| is always valid, except in some tests
-      // where the TestNavigationLoader is used.
-      if (url_loader_client_endpoints_) {
-        network::mojom::URLLoaderPtr url_loader(
-            std::move(url_loader_client_endpoints_->url_loader));
-        url_loader->ProceedWithResponse();
-        url_loader_client_endpoints_->url_loader = url_loader.PassInterface();
-      } else {
-        loader_->ProceedWithResponse();
-      }
-    }
   }
 
   // Abort the request if needed. This includes requests that were blocked by
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc
index c2a13ae..79d7e20 100644
--- a/content/browser/indexed_db/database_impl.cc
+++ b/content/browser/indexed_db/database_impl.cc
@@ -320,8 +320,7 @@
   connection_->database()->OpenCursor(
       transaction, object_store_id, index_id,
       std::make_unique<IndexedDBKeyRange>(key_range), direction, key_only,
-      task_type, std::move(aborting_callback), origin_,
-      dispatcher_host_->AsWeakPtr(), idb_runner_);
+      task_type, std::move(aborting_callback), dispatcher_host_->AsWeakPtr());
 }
 
 void DatabaseImpl::Count(
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc
index 360b23d..1605acb 100644
--- a/content/browser/indexed_db/indexed_db_database.cc
+++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -1813,9 +1813,7 @@
     bool key_only,
     blink::mojom::IDBTaskType task_type,
     blink::mojom::IDBDatabase::OpenCursorCallback callback,
-    const url::Origin& origin,
-    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
-    scoped_refptr<base::SequencedTaskRunner> idb_runner) {
+    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host) {
   DCHECK(transaction);
   IDB_TRACE1("IndexedDBDatabase::OpenCursor", "txn.id", transaction->id());
 
@@ -1832,20 +1830,29 @@
       key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
   params->task_type = task_type;
   params->callback = std::move(callback);
-  transaction->ScheduleTask(BindWeakOperation(
-      &IndexedDBDatabase::OpenCursorOperation, AsWeakPtr(), std::move(params),
-      origin, std::move(dispatcher_host), std::move(idb_runner)));
+  transaction->ScheduleTask(
+      BindWeakOperation(&IndexedDBDatabase::OpenCursorOperation, AsWeakPtr(),
+                        std::move(params), std::move(dispatcher_host)));
 }
 
 Status IndexedDBDatabase::OpenCursorOperation(
     std::unique_ptr<OpenCursorOperationParams> params,
-    const url::Origin& origin,
     base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
-    scoped_refptr<base::SequencedTaskRunner> idb_runner,
     IndexedDBTransaction* transaction) {
   IDB_TRACE1("IndexedDBDatabase::OpenCursorOperation", "txn.id",
              transaction->id());
 
+  Status s = Status::OK();
+  if (!dispatcher_host) {
+    IndexedDBDatabaseError error =
+        CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
+                    "Dispatcher not connected.", transaction);
+    std::move(params->callback)
+        .Run(blink::mojom::IDBDatabaseOpenCursorResult::NewErrorResult(
+            blink::mojom::IDBError::New(error.code(), error.message())));
+    return s;
+  }
+
   // The frontend has begun indexing, so this pauses the transaction
   // until the indexing is complete. This can't happen any earlier
   // because we don't want to switch to early mode in case multiple
@@ -1853,7 +1860,6 @@
   if (params->task_type == blink::mojom::IDBTaskType::Preemptive)
     transaction->AddPreemptiveEvent();
 
-  Status s = Status::OK();
   std::unique_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
   if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
     if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
@@ -1897,16 +1903,6 @@
   IndexedDBCursor* cursor_ptr = cursor.get();
   transaction->RegisterOpenCursor(cursor_ptr);
 
-  if (!dispatcher_host) {
-    IndexedDBDatabaseError error =
-        CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
-                    "Dispatcher not connected.", transaction);
-    std::move(params->callback)
-        .Run(blink::mojom::IDBDatabaseOpenCursorResult::NewErrorResult(
-            blink::mojom::IDBError::New(error.code(), error.message())));
-    return s;
-  }
-
   blink::mojom::IDBValuePtr mojo_value;
   std::vector<IndexedDBBlobInfo> blob_info;
   if (cursor_ptr->Value()) {
@@ -1914,8 +1910,6 @@
     blob_info.swap(cursor_ptr->Value()->blob_info);
   }
 
-  auto cursor_impl = std::make_unique<CursorImpl>(
-      std::move(cursor), origin, dispatcher_host.get(), idb_runner);
   if (mojo_value &&
       !IndexedDBCallbacks::CreateAllBlobs(
           dispatcher_host->blob_storage_context(),
@@ -1924,13 +1918,11 @@
     return s;
   }
 
-  blink::mojom::IDBCursorAssociatedPtrInfo ptr_info;
-  auto request = mojo::MakeRequest(&ptr_info);
-  dispatcher_host->AddCursorBinding(std::move(cursor_impl), std::move(request));
   std::move(params->callback)
       .Run(blink::mojom::IDBDatabaseOpenCursorResult::NewValue(
           blink::mojom::IDBDatabaseOpenCursorValue::New(
-              std::move(ptr_info), cursor_ptr->key(), cursor_ptr->primary_key(),
+              dispatcher_host->CreateCursorBinding(std::move(cursor)),
+              cursor_ptr->key(), cursor_ptr->primary_key(),
               std::move(mojo_value))));
   return s;
 }
diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h
index d822c2a..a343030 100644
--- a/content/browser/indexed_db/indexed_db_database.h
+++ b/content/browser/indexed_db/indexed_db_database.h
@@ -195,9 +195,7 @@
                   bool key_only,
                   blink::mojom::IDBTaskType task_type,
                   blink::mojom::IDBDatabase::OpenCursorCallback callback,
-                  const url::Origin& origin,
-                  base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
-                  scoped_refptr<base::SequencedTaskRunner> idb_runner);
+                  base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host);
   void Count(IndexedDBTransaction* transaction,
              int64_t object_store_id,
              int64_t index_id,
@@ -273,9 +271,7 @@
   struct OpenCursorOperationParams;
   leveldb::Status OpenCursorOperation(
       std::unique_ptr<OpenCursorOperationParams> params,
-      const url::Origin& origin,
       base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
-      scoped_refptr<base::SequencedTaskRunner> idb_runner,
       IndexedDBTransaction* transaction);
   leveldb::Status CountOperation(
       int64_t object_store_id,
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index 56d7579..e35949e 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -17,6 +17,7 @@
 #include "content/browser/indexed_db/indexed_db_callbacks.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_cursor.h"
 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
 #include "content/browser/indexed_db/indexed_db_pending_connection.h"
@@ -93,16 +94,21 @@
   database_bindings_.AddBinding(std::move(database), std::move(request));
 }
 
-void IndexedDBDispatcherHost::AddCursorBinding(
-    std::unique_ptr<CursorImpl> cursor,
-    blink::mojom::IDBCursorAssociatedRequest request) {
+blink::mojom::IDBCursorAssociatedPtrInfo
+IndexedDBDispatcherHost::CreateCursorBinding(
+    std::unique_ptr<IndexedDBCursor> cursor) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  auto* cursor_ptr = cursor.get();
-  mojo::BindingId binding_id =
-      cursor_bindings_.AddBinding(std::move(cursor), std::move(request));
-  cursor_ptr->OnRemoveBinding(
+  const auto& context = bindings_.dispatch_context();
+  auto cursor_impl = std::make_unique<CursorImpl>(
+      std::move(cursor), context.origin, this, IDBTaskRunner());
+  auto* cursor_impl_ptr = cursor_impl.get();
+  blink::mojom::IDBCursorAssociatedPtrInfo ptr_info;
+  mojo::BindingId binding_id = cursor_bindings_.AddBinding(
+      std::move(cursor_impl), mojo::MakeRequest(&ptr_info));
+  cursor_impl_ptr->OnRemoveBinding(
       base::BindOnce(&IndexedDBDispatcherHost::RemoveCursorBinding,
                      weak_factory_.GetWeakPtr(), binding_id));
+  return ptr_info;
 }
 
 void IndexedDBDispatcherHost::RemoveCursorBinding(mojo::BindingId binding_id) {
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h
index 02891034..f650974 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -33,8 +33,8 @@
 }
 
 namespace content {
-class CursorImpl;
 class IndexedDBContextImpl;
+class IndexedDBCursor;
 class IndexedDBTransaction;
 
 // Constructed on UI thread.  All remaining calls (including destruction) should
@@ -55,8 +55,8 @@
   void AddDatabaseBinding(std::unique_ptr<blink::mojom::IDBDatabase> database,
                           blink::mojom::IDBDatabaseAssociatedRequest request);
 
-  void AddCursorBinding(std::unique_ptr<CursorImpl> cursor,
-                        blink::mojom::IDBCursorAssociatedRequest request);
+  blink::mojom::IDBCursorAssociatedPtrInfo CreateCursorBinding(
+      std::unique_ptr<IndexedDBCursor> cursor);
   void RemoveCursorBinding(mojo::BindingId binding_id);
 
   void AddTransactionBinding(
diff --git a/content/browser/loader/loader_browsertest.cc b/content/browser/loader/loader_browsertest.cc
index 06b6b07..e3ffe22e5 100644
--- a/content/browser/loader/loader_browsertest.cc
+++ b/content/browser/loader/loader_browsertest.cc
@@ -38,7 +38,6 @@
 #include "content/public/test/url_loader_interceptor.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_content_browser_client.h"
-#include "content/shell/browser/shell_network_delegate.h"
 #include "content/test/test_content_browser_client.h"
 #include "net/base/filename_util.h"
 #include "net/base/load_flags.h"
@@ -575,8 +574,6 @@
       "http://localhost:%u/set_cookie.html", embedded_test_server()->port()));
   GURL url(embedded_test_server()->GetURL("/redirect?" + set_cookie_url));
 
-  ShellNetworkDelegate::SetBlockThirdPartyCookies(true);
-
   CheckTitleTest(url, "cookie set");
 }
 
diff --git a/content/browser/loader/navigation_url_loader.h b/content/browser/loader/navigation_url_loader.h
index 7123394..ecb3e470 100644
--- a/content/browser/loader/navigation_url_loader.h
+++ b/content/browser/loader/navigation_url_loader.h
@@ -73,9 +73,6 @@
                               const net::HttpRequestHeaders& modified_headers,
                               PreviewsState new_previews_state) = 0;
 
-  // Called in response to OnResponseStarted to process the response.
-  virtual void ProceedWithResponse() = 0;
-
  protected:
   NavigationURLLoader() {}
 
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 966d686..e15b6f0 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -1558,8 +1558,6 @@
                      base::Time::Now()));
 }
 
-void NavigationURLLoaderImpl::ProceedWithResponse() {}
-
 void NavigationURLLoaderImpl::OnReceiveResponse(
     scoped_refptr<network::ResourceResponse> response_head,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
diff --git a/content/browser/loader/navigation_url_loader_impl.h b/content/browser/loader/navigation_url_loader_impl.h
index 83683e2..53bd288f 100644
--- a/content/browser/loader/navigation_url_loader_impl.h
+++ b/content/browser/loader/navigation_url_loader_impl.h
@@ -54,7 +54,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       PreviewsState new_previews_state) override;
-  void ProceedWithResponse() override;
 
   void OnReceiveResponse(
       scoped_refptr<network::ResourceResponse> response_head,
diff --git a/content/browser/loader/prefetch_url_loader.cc b/content/browser/loader/prefetch_url_loader.cc
index 1346aa7..41e22fb 100644
--- a/content/browser/loader/prefetch_url_loader.cc
+++ b/content/browser/loader/prefetch_url_loader.cc
@@ -117,11 +117,6 @@
                           base::nullopt);
 }
 
-void PrefetchURLLoader::ProceedWithResponse() {
-  if (loader_)
-    loader_->ProceedWithResponse();
-}
-
 void PrefetchURLLoader::SetPriority(net::RequestPriority priority,
                                     int intra_priority_value) {
   if (loader_)
diff --git a/content/browser/loader/prefetch_url_loader.h b/content/browser/loader/prefetch_url_loader.h
index 0541dd0..809d129 100644
--- a/content/browser/loader/prefetch_url_loader.h
+++ b/content/browser/loader/prefetch_url_loader.h
@@ -94,7 +94,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/content/browser/loader/upload_data_stream_builder.cc b/content/browser/loader/upload_data_stream_builder.cc
deleted file mode 100644
index 01076623..0000000
--- a/content/browser/loader/upload_data_stream_builder.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/upload_data_stream_builder.h"
-
-#include <stdint.h>
-
-#include <limits>
-#include <utility>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "net/base/elements_upload_data_stream.h"
-#include "net/base/upload_bytes_element_reader.h"
-#include "net/base/upload_file_element_reader.h"
-#include "services/network/public/cpp/resource_request_body.h"
-#include "storage/browser/blob/blob_data_handle.h"
-#include "storage/browser/blob/blob_reader.h"
-#include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/blob/upload_blob_element_reader.h"
-
-namespace base {
-class TaskRunner;
-}
-
-namespace disk_cache {
-class Entry;
-}
-
-namespace content {
-namespace {
-
-// A subclass of net::UploadBytesElementReader which owns
-// ResourceRequestBody.
-class BytesElementReader : public net::UploadBytesElementReader {
- public:
-  BytesElementReader(network::ResourceRequestBody* resource_request_body,
-                     const network::DataElement& element)
-      : net::UploadBytesElementReader(element.bytes(), element.length()),
-        resource_request_body_(resource_request_body) {
-    DCHECK_EQ(network::mojom::DataElementType::kBytes, element.type());
-  }
-
-  ~BytesElementReader() override {}
-
- private:
-  scoped_refptr<network::ResourceRequestBody> resource_request_body_;
-
-  DISALLOW_COPY_AND_ASSIGN(BytesElementReader);
-};
-
-// A subclass of net::UploadFileElementReader which owns
-// ResourceRequestBody.
-// This class is necessary to ensure the BlobData and any attached shareable
-// files survive until upload completion.
-class FileElementReader : public net::UploadFileElementReader {
- public:
-  FileElementReader(network::ResourceRequestBody* resource_request_body,
-                    base::TaskRunner* task_runner,
-                    const network::DataElement& element)
-      : net::UploadFileElementReader(task_runner,
-                                     element.path(),
-                                     element.offset(),
-                                     element.length(),
-                                     element.expected_modification_time()),
-        resource_request_body_(resource_request_body) {
-    DCHECK_EQ(network::mojom::DataElementType::kFile, element.type());
-  }
-
-  ~FileElementReader() override {}
-
- private:
-  scoped_refptr<network::ResourceRequestBody> resource_request_body_;
-
-  DISALLOW_COPY_AND_ASSIGN(FileElementReader);
-};
-
-}  // namespace
-
-std::unique_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
-    network::ResourceRequestBody* body,
-    storage::BlobStorageContext* blob_context,
-    storage::FileSystemContext* file_system_context,
-    base::SingleThreadTaskRunner* file_task_runner) {
-  std::vector<std::unique_ptr<net::UploadElementReader>> element_readers;
-  for (const auto& element : *body->elements()) {
-    switch (element.type()) {
-      case network::mojom::DataElementType::kBytes:
-        element_readers.push_back(
-            std::make_unique<BytesElementReader>(body, element));
-        break;
-      case network::mojom::DataElementType::kFile:
-        element_readers.push_back(std::make_unique<FileElementReader>(
-            body, file_task_runner, element));
-        break;
-      case network::mojom::DataElementType::kBlob: {
-        DCHECK_EQ(0ul, element.offset());
-        std::unique_ptr<storage::BlobDataHandle> handle =
-            blob_context->GetBlobDataFromUUID(element.blob_uuid());
-        DCHECK(element.length() == std::numeric_limits<uint64_t>::max() ||
-               element.length() == handle->size());
-        element_readers.push_back(
-            std::make_unique<storage::UploadBlobElementReader>(
-                std::move(handle)));
-        break;
-      }
-      case network::mojom::DataElementType::kRawFile:
-      case network::mojom::DataElementType::kDataPipe:
-      case network::mojom::DataElementType::kChunkedDataPipe:
-      case network::mojom::DataElementType::kUnknown:
-        NOTREACHED();
-        break;
-    }
-  }
-
-  return std::make_unique<net::ElementsUploadDataStream>(
-      std::move(element_readers), body->identifier());
-}
-
-}  // namespace content
diff --git a/content/browser/loader/upload_data_stream_builder.h b/content/browser/loader/upload_data_stream_builder.h
deleted file mode 100644
index c08ff333..0000000
--- a/content/browser/loader/upload_data_stream_builder.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_UPLOAD_DATA_STREAM_BUILDER_H_
-#define CONTENT_BROWSER_LOADER_UPLOAD_DATA_STREAM_BUILDER_H_
-
-#include <memory>
-
-#include "content/common/content_export.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace storage {
-class FileSystemContext;
-}
-
-namespace net {
-class UploadDataStream;
-}
-
-namespace network {
-class ResourceRequestBody;
-}
-
-namespace storage {
-class BlobStorageContext;
-}
-
-namespace content {
-
-class CONTENT_EXPORT UploadDataStreamBuilder {
- public:
-  // Creates a new UploadDataStream from this request body.
-  //
-  // If |body| contains any blob references, the caller is responsible for
-  // making sure them outlive the returned value of UploadDataStream. We do this
-  // by binding the BlobDataHandles of them to ResourceRequestBody in
-  // ResourceDispatcherHostImpl::BeginRequest().
-  //
-  // |file_system_context| is used to create a FileStreamReader for files with
-  // filesystem URLs.  |file_task_runner| is used to perform file operations
-  // when the data gets uploaded.
-  static std::unique_ptr<net::UploadDataStream> Build(
-      network::ResourceRequestBody* body,
-      storage::BlobStorageContext* blob_context,
-      storage::FileSystemContext* file_system_context,
-      base::SingleThreadTaskRunner* file_task_runner);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_LOADER_UPLOAD_DATA_STREAM_BUILDER_H_
diff --git a/content/browser/loader/upload_data_stream_builder_unittest.cc b/content/browser/loader/upload_data_stream_builder_unittest.cc
deleted file mode 100644
index 05e15622..0000000
--- a/content/browser/loader/upload_data_stream_builder_unittest.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/upload_data_stream_builder.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/run_loop.h"
-#include "base/stl_util.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "net/base/upload_bytes_element_reader.h"
-#include "net/base/upload_data_stream.h"
-#include "net/base/upload_file_element_reader.h"
-#include "net/log/net_log_with_source.h"
-#include "services/network/public/cpp/resource_request_body.h"
-#include "storage/browser/blob/blob_data_builder.h"
-#include "storage/browser/blob/blob_data_handle.h"
-#include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/blob/upload_blob_element_reader.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using storage::BlobDataBuilder;
-using storage::BlobDataHandle;
-using storage::BlobStorageContext;
-
-namespace content {
-
-TEST(UploadDataStreamBuilderTest, CreateUploadDataStream) {
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  {
-    scoped_refptr<network::ResourceRequestBody> request_body =
-        new network::ResourceRequestBody;
-
-    const std::string kBlob = "blobuuid";
-    const std::string kBlobData = "blobdata";
-    const char kData[] = "123";
-    const base::FilePath::StringType kFilePath = FILE_PATH_LITERAL("abc");
-    const uint64_t kFileOffset = 10U;
-    const uint64_t kFileLength = 100U;
-    const base::Time kFileTime = base::Time::FromDoubleT(999);
-    const int64_t kIdentifier = 12345;
-
-    BlobStorageContext context;
-    auto builder = std::make_unique<BlobDataBuilder>(kBlob);
-    builder->AppendData(kBlobData);
-    std::unique_ptr<BlobDataHandle> handle =
-        context.AddFinishedBlob(std::move(builder));
-
-    request_body->AppendBytes(kData, base::size(kData) - 1);
-    request_body->AppendFileRange(base::FilePath(kFilePath), kFileOffset,
-                                  kFileLength, kFileTime);
-    request_body->AppendBlob(kBlob);
-    request_body->set_identifier(kIdentifier);
-
-    std::unique_ptr<net::UploadDataStream> upload(
-        UploadDataStreamBuilder::Build(
-            request_body.get(), &context, nullptr,
-            base::ThreadTaskRunnerHandle::Get().get()));
-
-    EXPECT_EQ(kIdentifier, upload->identifier());
-    ASSERT_TRUE(upload->GetElementReaders());
-    ASSERT_EQ(request_body->elements()->size(),
-              upload->GetElementReaders()->size());
-
-    const net::UploadBytesElementReader* r1 =
-        (*upload->GetElementReaders())[0]->AsBytesReader();
-    ASSERT_TRUE(r1);
-    EXPECT_EQ(kData, std::string(r1->bytes(), r1->length()));
-
-    const net::UploadFileElementReader* r2 =
-        (*upload->GetElementReaders())[1]->AsFileReader();
-    ASSERT_TRUE(r2);
-    EXPECT_EQ(kFilePath, r2->path().value());
-    EXPECT_EQ(kFileOffset, r2->range_offset());
-    EXPECT_EQ(kFileLength, r2->range_length());
-    EXPECT_EQ(kFileTime, r2->expected_modification_time());
-
-    const storage::UploadBlobElementReader* r3 =
-        static_cast<storage::UploadBlobElementReader*>(
-            (*upload->GetElementReaders())[2].get());
-    ASSERT_TRUE(r3);
-    EXPECT_EQ("blobuuid", r3->uuid());
-  }
-  // Clean up for ASAN.
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST(UploadDataStreamBuilderTest,
-     WriteUploadDataStreamWithEmptyFileBackedBlob) {
-  base::test::ScopedTaskEnvironment scoped_task_environment_(
-      base::test::ScopedTaskEnvironment::MainThreadType::IO);
-  {
-    base::FilePath test_blob_path;
-    ASSERT_TRUE(base::CreateTemporaryFile(&test_blob_path));
-
-    const uint64_t kZeroLength = 0;
-    base::Time blob_time;
-    ASSERT_TRUE(
-        base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &blob_time));
-    ASSERT_TRUE(base::TouchFile(test_blob_path, blob_time, blob_time));
-
-    BlobStorageContext blob_storage_context;
-
-    // A blob created from an empty file added several times.
-    const std::string blob_id("id-0");
-    std::unique_ptr<BlobDataBuilder> blob_data_builder(
-        new BlobDataBuilder(blob_id));
-    blob_data_builder->AppendFile(test_blob_path, 0, kZeroLength, blob_time);
-    std::unique_ptr<BlobDataHandle> handle =
-        blob_storage_context.AddFinishedBlob(std::move(blob_data_builder));
-
-    scoped_refptr<network::ResourceRequestBody> request_body(
-        new network::ResourceRequestBody());
-    std::unique_ptr<net::UploadDataStream> upload(
-        UploadDataStreamBuilder::Build(
-            request_body.get(), &blob_storage_context, nullptr,
-            base::ThreadTaskRunnerHandle::Get().get()));
-
-    request_body = new network::ResourceRequestBody();
-    request_body->AppendBlob(blob_id);
-    request_body->AppendBlob(blob_id);
-    request_body->AppendBlob(blob_id);
-
-    upload = UploadDataStreamBuilder::Build(
-        request_body.get(), &blob_storage_context, nullptr,
-        base::ThreadTaskRunnerHandle::Get().get());
-    ASSERT_TRUE(upload->GetElementReaders());
-    const auto& readers = *upload->GetElementReaders();
-    ASSERT_EQ(3U, readers.size());
-
-    net::TestCompletionCallback init_callback;
-    ASSERT_EQ(net::ERR_IO_PENDING,
-              upload->Init(init_callback.callback(), net::NetLogWithSource()));
-    EXPECT_EQ(net::OK, init_callback.WaitForResult());
-
-    EXPECT_EQ(kZeroLength, upload->size());
-
-    // Purposely (try to) read more than what is in the stream. If we try to
-    // read zero bytes then UploadDataStream::Read will fail a DCHECK.
-    int kBufferLength = kZeroLength + 1;
-    std::unique_ptr<char[]> buffer(new char[kBufferLength]);
-    scoped_refptr<net::IOBuffer> io_buffer =
-        base::MakeRefCounted<net::WrappedIOBuffer>(buffer.get());
-    net::TestCompletionCallback read_callback;
-    int result =
-        upload->Read(io_buffer.get(), kBufferLength, read_callback.callback());
-    EXPECT_EQ(static_cast<int>(kZeroLength), read_callback.GetResult(result));
-
-    base::DeleteFile(test_blob_path, false);
-  }
-  // Clean up for ASAN.
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST(UploadDataStreamBuilderTest, ResetUploadStreamWithBlob) {
-  base::test::ScopedTaskEnvironment scoped_task_environment_(
-      base::test::ScopedTaskEnvironment::MainThreadType::IO);
-  {
-    scoped_refptr<network::ResourceRequestBody> request_body =
-        new network::ResourceRequestBody;
-
-    const std::string kBlob = "blobuuid";
-    const std::string kBlobData = "blobdata";
-    const int kBlobDataLength = 8;
-    const int64_t kIdentifier = 12345;
-
-    BlobStorageContext blob_storage_context;
-    auto builder = std::make_unique<BlobDataBuilder>(kBlob);
-    builder->AppendData(kBlobData);
-    std::unique_ptr<BlobDataHandle> handle =
-        blob_storage_context.AddFinishedBlob(std::move(builder));
-    request_body->AppendBlob(kBlob);
-    request_body->set_identifier(kIdentifier);
-
-    std::unique_ptr<net::UploadDataStream> upload(
-        UploadDataStreamBuilder::Build(
-            request_body.get(), &blob_storage_context, nullptr,
-            base::ThreadTaskRunnerHandle::Get().get()));
-
-    net::TestCompletionCallback init_callback;
-    ASSERT_EQ(net::OK,
-              upload->Init(init_callback.callback(), net::NetLogWithSource()));
-
-    // Read part of the data.
-    const int kBufferLength = 4;
-    scoped_refptr<net::IOBufferWithSize> buffer =
-        base::MakeRefCounted<net::IOBufferWithSize>(kBufferLength);
-    net::TestCompletionCallback read_callback;
-    int result =
-        upload->Read(buffer.get(), buffer->size(), read_callback.callback());
-    EXPECT_EQ(kBufferLength, read_callback.GetResult(result));
-    EXPECT_EQ(0,
-              std::memcmp(kBlobData.c_str(), buffer->data(), buffer->size()));
-
-    // Reset.
-    ASSERT_EQ(net::OK,
-              upload->Init(init_callback.callback(), net::NetLogWithSource()));
-
-    // Read all the data.
-    buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBlobDataLength);
-    result =
-        upload->Read(buffer.get(), buffer->size(), read_callback.callback());
-    EXPECT_EQ(kBlobDataLength, read_callback.GetResult(result));
-    EXPECT_EQ(0,
-              std::memcmp(kBlobData.c_str(), buffer->data(), buffer->size()));
-  }
-  // Clean up for ASAN.
-  base::RunLoop().RunUntilIdle();
-}
-}  // namespace content
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc
index f765816..e37f4ac 100644
--- a/content/browser/navigation_browsertest.cc
+++ b/content/browser/navigation_browsertest.cc
@@ -51,7 +51,6 @@
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_content_browser_client.h"
 #include "content/shell/browser/shell_download_manager_delegate.h"
-#include "content/shell/browser/shell_network_delegate.h"
 #include "content/test/content_browser_test_utils_internal.h"
 #include "content/test/did_commit_navigation_interceptor.h"
 #include "ipc/ipc_security_test_util.h"
@@ -584,8 +583,6 @@
   const Referrer kSecureReferrer(
       GURL("https://secure-url.com"),
       network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade);
-  ShellNetworkDelegate::SetCancelURLRequestWithPolicyViolatingReferrerHeader(
-      true);
 
   // Navigate to an insecure url with a secure referrer with a policy of no
   // referrer on downgrades. The referrer url should be rewritten right away.
diff --git a/content/browser/net/view_blob_internals_job_factory.cc b/content/browser/net/view_blob_internals_job_factory.cc
deleted file mode 100644
index 409148f..0000000
--- a/content/browser/net/view_blob_internals_job_factory.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2011 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/net/view_blob_internals_job_factory.h"
-
-#include <memory>
-
-#include "base/strings/string_util.h"
-#include "content/public/common/url_constants.h"
-#include "storage/browser/blob/view_blob_internals_job.h"
-
-namespace content {
-
-// static.
-bool ViewBlobInternalsJobFactory::IsSupportedURL(const GURL& url) {
-  return url.SchemeIs(kChromeUIScheme) &&
-         url.host_piece() == kChromeUIBlobInternalsHost;
-}
-
-// static.
-net::URLRequestJob* ViewBlobInternalsJobFactory::CreateJobForRequest(
-    net::URLRequest* request,
-    net::NetworkDelegate* network_delegate,
-    storage::BlobStorageContext* blob_storage_context) {
-  return new storage::ViewBlobInternalsJob(
-      request, network_delegate, blob_storage_context);
-}
-
-}  // namespace content
diff --git a/content/browser/net/view_blob_internals_job_factory.h b/content/browser/net/view_blob_internals_job_factory.h
deleted file mode 100644
index cc8bd14..0000000
--- a/content/browser/net/view_blob_internals_job_factory.h
+++ /dev/null
@@ -1,33 +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_NET_VIEW_BLOB_INTERNALS_JOB_FACTORY_H_
-#define CONTENT_BROWSER_NET_VIEW_BLOB_INTERNALS_JOB_FACTORY_H_
-
-namespace net {
-class NetworkDelegate;
-class URLRequest;
-class URLRequestJob;
-}
-
-namespace storage {
-class BlobStorageContext;
-}
-
-class GURL;
-
-namespace content {
-
-class ViewBlobInternalsJobFactory {
- public:
-  static bool IsSupportedURL(const GURL& url);
-  static net::URLRequestJob* CreateJobForRequest(
-      net::URLRequest* request,
-      net::NetworkDelegate* network_delegate,
-      storage::BlobStorageContext* blob_storage_context);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_NET_VIEW_BLOB_INTERNALS_JOB_FACTORY_H_
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
index 9b4eccf..f22e5fa 100644
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -81,13 +81,21 @@
   host_frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_);
 }
 
+void DelegatedFrameHost::AddObserverForTesting(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void DelegatedFrameHost::RemoveObserverForTesting(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 void DelegatedFrameHost::WasShown(
     const viz::LocalSurfaceId& new_local_surface_id,
     const gfx::Size& new_dip_size,
     const base::Optional<RecordTabSwitchTimeRequest>&
         record_tab_switch_time_request) {
   // Cancel any pending frame eviction and unpause it if paused.
-  frame_eviction_state_ = FrameEvictionState::kNotStarted;
+  SetFrameEvictionStateAndNotifyObservers(FrameEvictionState::kNotStarted);
 
   frame_evictor_->SetVisible(true);
   if (record_tab_switch_time_request && compositor_) {
@@ -181,6 +189,16 @@
       viz::SurfaceId(frame_sink_id_, local_surface_id_), std::move(request));
 }
 
+void DelegatedFrameHost::SetFrameEvictionStateAndNotifyObservers(
+    FrameEvictionState frame_eviction_state) {
+  if (frame_eviction_state_ == frame_eviction_state)
+    return;
+
+  frame_eviction_state_ = frame_eviction_state;
+  for (auto& obs : observers_)
+    obs.OnFrameEvictionStateChanged(frame_eviction_state_);
+}
+
 bool DelegatedFrameHost::CanCopyFromCompositingSurface() const {
   return local_surface_id_.is_valid();
 }
@@ -373,7 +391,8 @@
   // CrOS overview mode.
   if (client_->ShouldShowStaleContentOnEviction() &&
       !stale_content_layer_->has_external_content()) {
-    frame_eviction_state_ = FrameEvictionState::kPendingEvictionRequests;
+    SetFrameEvictionStateAndNotifyObservers(
+        FrameEvictionState::kPendingEvictionRequests);
     auto callback =
         base::BindOnce(&DelegatedFrameHost::DidCopyStaleContent, GetWeakPtr());
 
@@ -399,7 +418,7 @@
   DCHECK_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE);
 
   DCHECK_NE(frame_eviction_state_, FrameEvictionState::kNotStarted);
-  frame_eviction_state_ = FrameEvictionState::kNotStarted;
+  SetFrameEvictionStateAndNotifyObservers(FrameEvictionState::kNotStarted);
   ContinueDelegatedFrameEviction();
 
   auto transfer_resource = viz::TransferableResource::MakeGL(
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h
index c01fba1..7fe79a1 100644
--- a/content/browser/renderer_host/delegated_frame_host.h
+++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -69,6 +69,19 @@
       public viz::mojom::CompositorFrameSinkClient,
       public viz::HostFrameSinkClient {
  public:
+  enum class FrameEvictionState {
+    kNotStarted = 0,          // Frame eviction is ready.
+    kPendingEvictionRequests  // Frame eviction is paused with pending requests.
+  };
+
+  class Observer {
+   public:
+    virtual void OnFrameEvictionStateChanged(FrameEvictionState new_state) = 0;
+
+   protected:
+    virtual ~Observer() = default;
+  };
+
   // |should_register_frame_sink_id| flag indicates whether DelegatedFrameHost
   // is responsible for registering the associated FrameSinkId with the
   // compositor or not. This is set only on non-aura platforms, since aura is
@@ -78,6 +91,9 @@
                      bool should_register_frame_sink_id);
   ~DelegatedFrameHost() override;
 
+  void AddObserverForTesting(Observer* observer);
+  void RemoveObserverForTesting(Observer* observer);
+
   // ui::CompositorObserver implementation.
   void OnCompositingShuttingDown(ui::Compositor* compositor) override;
 
@@ -173,6 +189,14 @@
     return weak_factory_.GetWeakPtr();
   }
 
+  const ui::Layer* stale_content_layer() const {
+    return stale_content_layer_.get();
+  }
+
+  FrameEvictionState frame_eviction_state() const {
+    return frame_eviction_state_;
+  }
+
  private:
   friend class DelegatedFrameHostClient;
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraBrowserTest,
@@ -200,6 +224,9 @@
       viz::CopyOutputRequest::ResultFormat format,
       viz::CopyOutputRequest::CopyOutputRequestCallback callback);
 
+  void SetFrameEvictionStateAndNotifyObservers(
+      FrameEvictionState frame_eviction_state);
+
   const viz::FrameSinkId frame_sink_id_;
   DelegatedFrameHostClient* const client_;
   const bool enable_viz_;
@@ -231,11 +258,6 @@
 
   viz::LocalSurfaceId first_local_surface_id_after_navigation_;
 
-  enum class FrameEvictionState {
-    kNotStarted = 0,          // Frame eviction is ready.
-    kPendingEvictionRequests  // Frame eviction is paused with pending requests.
-  };
-
   FrameEvictionState frame_eviction_state_ = FrameEvictionState::kNotStarted;
 
   // Layer responsible for displaying the stale content for the DFHC when the
@@ -245,6 +267,8 @@
 
   TabSwitchTimeRecorder tab_switch_time_recorder_;
 
+  base::ObserverList<Observer>::Unchecked observers_;
+
   base::WeakPtrFactory<DelegatedFrameHost> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(DelegatedFrameHost);
diff --git a/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc b/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
index 23c33146..303ac35 100644
--- a/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
+++ b/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
@@ -22,7 +22,6 @@
 #include "media/audio/fake_audio_manager.h"
 #include "media/audio/test_audio_thread.h"
 #include "media/base/media_switches.h"
-#include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -54,25 +53,16 @@
     : public TestBrowserContext {
  public:
   TestBrowserContextWithRealURLRequestContextGetter() {
-    request_context_ = base::MakeRefCounted<net::TestURLRequestContextGetter>(
-        base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
     salt_ = TestBrowserContext::GetMediaDeviceIDSalt();
   }
 
   ~TestBrowserContextWithRealURLRequestContextGetter() override {}
 
-  net::URLRequestContextGetter* CreateRequestContext(
-      ProtocolHandlerMap* protocol_handlers,
-      URLRequestInterceptorScopedVector request_interceptors) override {
-    return request_context_.get();
-  }
-
   std::string GetMediaDeviceIDSalt() override { return salt_; }
 
   void set_media_device_id_salt(std::string salt) { salt_ = std::move(salt); }
 
  private:
-  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
   std::string salt_;
 };
 
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
index e46d977..4ba4b8e 100644
--- a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -124,6 +124,13 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (host_)
     host_->RemoveInstanceObserver(instance_, this);
+#if defined(OS_CHROMEOS)
+  // Close the firewall hole on UI thread if there is one.
+  if (firewall_hole_) {
+    BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE,
+                              std::move(firewall_hole_));
+  }
+#endif  // defined(OS_CHROMEOS)
   --g_num_tcp_filter_instances;
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index e8525fa4..9b3ad73 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1508,9 +1508,9 @@
   if (overscroll_controller_)
     overscroll_controller_->Enable();
 
-  if (delegated_frame_host_ &&
-      (delegated_frame_host_->IsPrimarySurfaceEvicted() ||
-       !local_surface_id_allocator_.HasValidLocalSurfaceIdAllocation())) {
+  if ((delegated_frame_host_ &&
+       delegated_frame_host_->IsPrimarySurfaceEvicted()) ||
+      !local_surface_id_allocator_.HasValidLocalSurfaceIdAllocation()) {
     ui::WindowAndroidCompositor* compositor =
         view_.GetWindowAndroid() ? view_.GetWindowAndroid()->GetCompositor()
                                  : nullptr;
@@ -1521,7 +1521,9 @@
             : cc::DeadlinePolicy::UseDefaultDeadline(),
         base::nullopt);
     // If we navigated while hidden, we need to update the fallback surface only
-    // after we've completed navigation, and embedded the new surface.
+    // after we've completed navigation, and embedded the new surface. The
+    // |delegated_frame_host_| is always valid when |navigation_while_hidden_|
+    // is set to true.
     if (navigation_while_hidden_) {
       navigation_while_hidden_ = false;
       delegated_frame_host_->DidNavigate();
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 4d11c0d..51cd2d1 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -459,6 +459,8 @@
 
   class WindowAncestorObserver;
   friend class WindowAncestorObserver;
+  friend void VerifyStaleContentOnFrameEviction(
+      RenderWidgetHostView* render_widget_host_view);
 
   // Allocate a new FrameSinkId if this object is the platform view of a
   // RenderWidgetHostViewGuest. This FrameSinkId will not be actually used in
diff --git a/content/browser/service_worker/service_worker_installed_script_loader.cc b/content/browser/service_worker/service_worker_installed_script_loader.cc
index 16232a7..075337cd 100644
--- a/content/browser/service_worker/service_worker_installed_script_loader.cc
+++ b/content/browser/service_worker/service_worker_installed_script_loader.cc
@@ -128,11 +128,6 @@
   NOTREACHED();
 }
 
-void ServiceWorkerInstalledScriptLoader::ProceedWithResponse() {
-  // This function should only be called for navigations.
-  NOTREACHED();
-}
-
 void ServiceWorkerInstalledScriptLoader::SetPriority(
     net::RequestPriority priority,
     int32_t intra_priority_value) {
diff --git a/content/browser/service_worker/service_worker_installed_script_loader.h b/content/browser/service_worker/service_worker_installed_script_loader.h
index a23cadd..62145d7 100644
--- a/content/browser/service_worker/service_worker_installed_script_loader.h
+++ b/content/browser/service_worker/service_worker_installed_script_loader.h
@@ -57,7 +57,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc
index 1b1fa14..4b447c9 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -417,12 +417,6 @@
   NOTIMPLEMENTED();
 }
 
-void ServiceWorkerNavigationLoader::ProceedWithResponse() {
-  // ServiceWorkerNavigationLoader doesn't need to wait for
-  // ProceedWithResponse() since it doesn't use MojoAsyncResourceHandler to load
-  // the resource request.
-}
-
 void ServiceWorkerNavigationLoader::SetPriority(net::RequestPriority priority,
                                                 int32_t intra_priority_value) {
   NOTIMPLEMENTED();
diff --git a/content/browser/service_worker/service_worker_navigation_loader.h b/content/browser/service_worker/service_worker_navigation_loader.h
index 674e6f1..a211038 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.h
+++ b/content/browser/service_worker/service_worker_navigation_loader.h
@@ -134,7 +134,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/content/browser/service_worker/service_worker_new_script_loader.cc b/content/browser/service_worker/service_worker_new_script_loader.cc
index 21f662b..74c6dac 100644
--- a/content/browser/service_worker/service_worker_new_script_loader.cc
+++ b/content/browser/service_worker/service_worker_new_script_loader.cc
@@ -257,10 +257,6 @@
   NOTREACHED();
 }
 
-void ServiceWorkerNewScriptLoader::ProceedWithResponse() {
-  NOTREACHED();
-}
-
 void ServiceWorkerNewScriptLoader::SetPriority(net::RequestPriority priority,
                                                int32_t intra_priority_value) {
   if (network_loader_)
diff --git a/content/browser/service_worker/service_worker_new_script_loader.h b/content/browser/service_worker/service_worker_new_script_loader.h
index 79f7a180..05dace4 100644
--- a/content/browser/service_worker/service_worker_new_script_loader.h
+++ b/content/browser/service_worker/service_worker_new_script_loader.h
@@ -134,7 +134,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc
index cddf1af..93c56823 100644
--- a/content/browser/storage_partition_impl_map.cc
+++ b/content/browser/storage_partition_impl_map.cc
@@ -48,8 +48,6 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "crypto/sha2.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
 #include "services/network/public/cpp/features.h"
 #include "storage/browser/blob/blob_storage_context.h"
 #include "storage/browser/blob/blob_url_request_job_factory.h"
@@ -388,44 +386,6 @@
   StoragePartitionImpl* partition = partition_ptr.get();
   partitions_[partition_config] = std::move(partition_ptr);
 
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    ChromeBlobStorageContext* blob_storage_context =
-        ChromeBlobStorageContext::GetFor(browser_context_);
-    ProtocolHandlerMap protocol_handlers;
-    protocol_handlers[url::kBlobScheme] =
-        std::make_unique<BlobProtocolHandler>(blob_storage_context);
-    protocol_handlers[url::kFileSystemScheme] = CreateFileSystemProtocolHandler(
-        partition_domain, partition->GetFileSystemContext());
-    for (const auto& scheme : URLDataManagerBackend::GetWebUISchemes()) {
-      protocol_handlers[scheme] = URLDataManagerBackend::CreateProtocolHandler(
-          browser_context_->GetResourceContext(), blob_storage_context);
-    }
-
-    URLRequestInterceptorScopedVector request_interceptors;
-
-    auto devtools_interceptor =
-        DevToolsURLRequestInterceptor::MaybeCreate(browser_context_);
-    if (devtools_interceptor)
-      request_interceptors.push_back(std::move(devtools_interceptor));
-    request_interceptors.push_back(std::make_unique<AppCacheInterceptor>());
-
-    // These calls must happen after StoragePartitionImpl::Create().
-    partition->SetURLRequestContext(browser_context_->CreateRequestContext(
-        &protocol_handlers, std::move(request_interceptors)));
-
-    // A separate media cache isn't used with the network service.
-    partition->SetMediaURLRequestContext(
-        browser_context_->CreateMediaRequestContext());
-
-    // This needs to happen after SetURLRequestContext() since we need this
-    // code path only for non-NetworkService cases where NetworkContext needs to
-    // be initialized using |url_request_context_|, which is initialized by
-    // SetURLRequestContext().
-    DCHECK(partition->url_loader_factory_getter());
-    DCHECK(partition->url_request_context_);
-    partition->url_loader_factory_getter()->HandleFactoryRequests();
-  }
-
   // Arm the serviceworker cookie change observation API.
   partition->GetCookieStoreContext()->ListenToCookieChanges(
       partition->GetNetworkContext(), /*success_callback=*/base::DoNothing());
@@ -532,16 +492,12 @@
     InitializeResourceContext(browser_context_);
   }
 
-  scoped_refptr<net::URLRequestContextGetter> request_context_getter;
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
-    request_context_getter = partition->GetURLRequestContext();
-
   if (NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()) {
     partition->GetAppCacheService()->InitializeOnLoaderThread(
         in_memory ? base::FilePath()
                   : partition->GetPath().Append(kAppCacheDirname),
         browser_context_, nullptr /* resource_context */,
-        request_context_getter, browser_context_->GetSpecialStoragePolicy());
+        browser_context_->GetSpecialStoragePolicy());
   }
 
   // Check first to avoid memory leak in unittests.
@@ -555,7 +511,7 @@
               in_memory ? base::FilePath()
                         : partition->GetPath().Append(kAppCacheDirname),
               nullptr /* browser_context */,
-              browser_context_->GetResourceContext(), request_context_getter,
+              browser_context_->GetResourceContext(),
               base::RetainedRef(browser_context_->GetSpecialStoragePolicy())));
     }
 
@@ -571,12 +527,11 @@
     if (!NavigationURLLoaderImpl::IsNavigationLoaderOnUIEnabled()) {
       base::PostTaskWithTraits(
           FROM_HERE, {BrowserThread::IO},
-          base::BindOnce(
-              &PrefetchURLLoaderService::InitializeResourceContext,
-              partition->GetPrefetchURLLoaderService(),
-              browser_context_->GetResourceContext(), request_context_getter,
-              base::RetainedRef(
-                  ChromeBlobStorageContext::GetFor(browser_context_))));
+          base::BindOnce(&PrefetchURLLoaderService::InitializeResourceContext,
+                         partition->GetPrefetchURLLoaderService(),
+                         browser_context_->GetResourceContext(), nullptr,
+                         base::RetainedRef(ChromeBlobStorageContext::GetFor(
+                             browser_context_))));
     }
 
     base::PostTaskWithTraits(
diff --git a/content/browser/web_package/prefetched_signed_exchange_cache.cc b/content/browser/web_package/prefetched_signed_exchange_cache.cc
index 3486a587..d4d0d65 100644
--- a/content/browser/web_package/prefetched_signed_exchange_cache.cc
+++ b/content/browser/web_package/prefetched_signed_exchange_cache.cc
@@ -105,7 +105,6 @@
                       const base::Optional<GURL>& new_url) override {
     NOTREACHED();
   }
-  void ProceedWithResponse() override { NOTREACHED(); }
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override {
     // There is nothing to do, because this class just calls OnReceiveRedirect.
@@ -146,17 +145,7 @@
     response_.encoded_data_length = 0;
     if (is_navigation_request) {
       client_->OnReceiveResponse(response_);
-      // There are two situations we need to call SendResponseBody() in advance:
-      //
-      // 1. When Network Service is enabled, ProceedWithResponse() will not be
-      //    called. See https://crbug.com/791049.
-      //
-      // 2. When NavigationImmediateResponseBody is enabled, see
-      //    https://crbug.com/831155.
-      if (base::FeatureList::IsEnabled(network::features::kNetworkService) ||
-          IsNavigationImmediateResponseBodyEnabled()) {
-        SendResponseBody();
-      }
+      SendResponseBody();
       return;
     }
 
@@ -243,14 +232,7 @@
                       const base::Optional<GURL>& new_url) override {
     NOTREACHED();
   }
-  void ProceedWithResponse() override {
-    DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
 
-    // If NavigationImmediateResponseBody is enabled, SendResponseBody() has
-    // already been called in the constructor.
-    if (!IsNavigationImmediateResponseBodyEnabled())
-      SendResponseBody();
-  }
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override {
     // There is nothing to do, because there is no prioritization mechanism for
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc b/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
index 5f8025e..7687fd3 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
+++ b/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
@@ -86,7 +86,6 @@
                void(const std::vector<std::string>&,
                     const net::HttpRequestHeaders&,
                     const base::Optional<GURL>&));
-  MOCK_METHOD0(ProceedWithResponse, void());
   MOCK_METHOD2(SetPriority,
                void(net::RequestPriority priority,
                     int32_t intra_priority_value));
diff --git a/content/browser/web_package/signed_exchange_loader.cc b/content/browser/web_package/signed_exchange_loader.cc
index 61601df..5e7b361 100644
--- a/content/browser/web_package/signed_exchange_loader.cc
+++ b/content/browser/web_package/signed_exchange_loader.cc
@@ -102,24 +102,6 @@
   if (outer_response_body)
     OnStartLoadingResponseBody(std::move(outer_response_body));
 
-  // TODO(https://crbug.com/791049): Remove this when NetworkService is
-  // enabled by default.
-  if (url_loader_options_ &
-      network::mojom::kURLLoadOptionPauseOnResponseStarted) {
-    // We don't propagate the response to the navigation request and its
-    // throttles, therefore we need to call this here internally in order to
-    // move it forward.
-    //
-    // ProceedWithResponse() is used when the network service is disabled to
-    // prevent the InterceptingResourceHandler (used for download) from
-    // intercepting the load before the NavigationRequest allowed it.
-    // See https://crbug.com/791049.
-    //
-    // Special care has been taken not to resume the InterceptingResourceHandler
-    // by mistake in https://crbug.com/896659.
-    url_loader_->ProceedWithResponse();
-  }
-
   // Bind the endpoint with |this| to get the body DataPipe.
   url_loader_client_binding_.Bind(std::move(endpoints->url_loader_client));
 
@@ -207,13 +189,6 @@
   NOTREACHED();
 }
 
-void SignedExchangeLoader::ProceedWithResponse() {
-  DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
-  DCHECK(url_loader_options_ &
-         network::mojom::kURLLoadOptionPauseOnResponseStarted);
-  // ProceedWithResponse() has already been called in the constructor.
-}
-
 void SignedExchangeLoader::SetPriority(net::RequestPriority priority,
                                        int intra_priority_value) {
   url_loader_->SetPriority(priority, intra_priority_value);
diff --git a/content/browser/web_package/signed_exchange_loader.h b/content/browser/web_package/signed_exchange_loader.h
index 56a070e..68580d87 100644
--- a/content/browser/web_package/signed_exchange_loader.h
+++ b/content/browser/web_package/signed_exchange_loader.h
@@ -97,7 +97,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/content/browser/web_package/signed_exchange_loader_unittest.cc b/content/browser/web_package/signed_exchange_loader_unittest.cc
index 7154970..f8ff0c0 100644
--- a/content/browser/web_package/signed_exchange_loader_unittest.cc
+++ b/content/browser/web_package/signed_exchange_loader_unittest.cc
@@ -85,7 +85,6 @@
                  void(const std::vector<std::string>&,
                       const net::HttpRequestHeaders&,
                       const base::Optional<GURL>&));
-    MOCK_METHOD0(ProceedWithResponse, void());
     MOCK_METHOD2(SetPriority,
                  void(net::RequestPriority priority,
                       int32_t intra_priority_value));
diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc
index 9004a16a..13a53c5 100644
--- a/content/browser/webui/url_data_manager_backend.cc
+++ b/content/browser/webui/url_data_manager_backend.cc
@@ -22,7 +22,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/net/view_blob_internals_job_factory.h"
 #include "content/browser/resource_context_impl.h"
 #include "content/browser/webui/shared_resources_data_source.h"
 #include "content/browser/webui/url_data_source_impl.h"
@@ -64,341 +63,6 @@
   return base::Contains(schemes, scheme);
 }
 
-// Returns a value of 'Origin:' header for the |request| if the header is set.
-// Otherwise returns an empty string.
-std::string GetOriginHeaderValue(const net::URLRequest* request) {
-  std::string result;
-  if (request->extra_request_headers().GetHeader(
-          net::HttpRequestHeaders::kOrigin, &result))
-    return result;
-  net::HttpRequestHeaders headers;
-  if (request->GetFullRequestHeaders(&headers))
-    headers.GetHeader(net::HttpRequestHeaders::kOrigin, &result);
-  return result;
-}
-
-// Copy data from source buffer into IO buffer destination.
-// TODO(groby): Very similar to URLRequestSimpleJob, unify at some point.
-void CopyData(const scoped_refptr<net::IOBuffer>& buf,
-              int buf_size,
-              const scoped_refptr<base::RefCountedMemory>& data,
-              int64_t data_offset) {
-  memcpy(buf->data(), data->front() + data_offset, buf_size);
-}
-
-}  // namespace
-
-// URLRequestChromeJob is a net::URLRequestJob that manages running
-// chrome-internal resource requests asynchronously.
-// It hands off URL requests to ChromeURLDataManager, which asynchronously
-// calls back once the data is available.
-class URLRequestChromeJob : public net::URLRequestJob {
- public:
-  URLRequestChromeJob(net::URLRequest* request,
-                      net::NetworkDelegate* network_delegate,
-                      URLDataManagerBackend* backend);
-
-  // net::URLRequestJob implementation.
-  void Start() override;
-  void Kill() override;
-  int ReadRawData(net::IOBuffer* buf, int buf_size) override;
-  bool GetMimeType(std::string* mime_type) const override;
-  void GetResponseInfo(net::HttpResponseInfo* info) override;
-  std::unique_ptr<net::SourceStream> SetUpSourceStream() override;
-
-  // Used to notify that the requested data's |mime_type| is ready.
-  void MimeTypeAvailable(const std::string& mime_type);
-
-  // Called by ChromeURLDataManager to notify us that the data blob is ready
-  // for us.  |bytes| may be null, indicating an error.
-  void DataAvailable(base::RefCountedMemory* bytes);
-
-  void set_is_gzipped(bool is_gzipped) {
-    is_gzipped_ = is_gzipped;
-  }
-
-  void SetSource(scoped_refptr<URLDataSourceImpl> source) { source_ = source; }
-
- private:
-  ~URLRequestChromeJob() override;
-
-  // Helper for Start(), to let us start asynchronously.
-  // (This pattern is shared by most net::URLRequestJob implementations.)
-  void StartAsync();
-
-  // Post a task to copy |data_| to |buf_| on a worker thread, to avoid browser
-  // jank. (|data_| might be mem-mapped, so a memcpy can trigger file ops).
-  int PostReadTask(scoped_refptr<net::IOBuffer> buf, int buf_size);
-
-  // The actual data we're serving.  NULL until it's been fetched.
-  scoped_refptr<base::RefCountedMemory> data_;
-
-  // The current offset into the data that we're handing off to our
-  // callers via the Read interfaces.
-  int data_offset_;
-
-  // When DataAvailable() is called with a null argument, indicating an error,
-  // this is set accordingly to a code for ReadRawData() to return.
-  net::Error data_available_status_;
-
-  // For async reads, we keep around a pointer to the buffer that
-  // we're reading into.
-  scoped_refptr<net::IOBuffer> pending_buf_;
-  int pending_buf_size_;
-  std::string mime_type_;
-
-  // True when gzip encoding should be used. NOTE: this requires the original
-  // resources in resources.pak use compress="gzip".
-  bool is_gzipped_;
-
-  // The URLDataSourceImpl that is servicing this request. This is a shared
-  // pointer so that the request can continue to be served even if the source is
-  // detached from the backend that initially owned it.
-  scoped_refptr<URLDataSourceImpl> source_;
-
-  // The backend is owned by net::URLRequestContext and always outlives us.
-  URLDataManagerBackend* const backend_;
-
-  base::WeakPtrFactory<URLRequestChromeJob> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(URLRequestChromeJob);
-};
-
-URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request,
-                                         net::NetworkDelegate* network_delegate,
-                                         URLDataManagerBackend* backend)
-    : net::URLRequestJob(request, network_delegate),
-      data_offset_(0),
-      data_available_status_(net::OK),
-      pending_buf_size_(0),
-      is_gzipped_(false),
-      backend_(backend) {
-  DCHECK(backend);
-}
-
-URLRequestChromeJob::~URLRequestChromeJob() {
-  CHECK(!backend_->HasPendingJob(this));
-}
-
-void URLRequestChromeJob::Start() {
-  const GURL url = request_->url();
-
-  // Start reading asynchronously so that all error reporting and data
-  // callbacks happen as they would for network requests.
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&URLRequestChromeJob::StartAsync,
-                                weak_factory_.GetWeakPtr()));
-
-  TRACE_EVENT_ASYNC_BEGIN1("browser", "DataManager:Request", this, "URL",
-      url.possibly_invalid_spec());
-}
-
-void URLRequestChromeJob::Kill() {
-  weak_factory_.InvalidateWeakPtrs();
-  backend_->RemoveRequest(this);
-  URLRequestJob::Kill();
-}
-
-bool URLRequestChromeJob::GetMimeType(std::string* mime_type) const {
-  *mime_type = mime_type_;
-  return !mime_type_.empty();
-}
-
-void URLRequestChromeJob::GetResponseInfo(net::HttpResponseInfo* info) {
-  DCHECK(!info->headers.get());
-  URLDataSourceImpl* source = backend_->GetDataSourceFromURL(request()->url());
-  std::string path;
-  URLDataManagerBackend::URLToRequestPath(request()->url(), &path);
-  info->headers = URLDataManagerBackend::GetHeaders(
-      source, path, GetOriginHeaderValue(request()));
-  if (is_gzipped_)
-    info->headers->AddHeader("Content-Encoding: gzip");
-}
-
-std::unique_ptr<net::SourceStream> URLRequestChromeJob::SetUpSourceStream() {
-  std::unique_ptr<net::SourceStream> source_stream =
-      net::URLRequestJob::SetUpSourceStream();
-
-  if (is_gzipped_) {
-    source_stream = net::GzipSourceStream::Create(std::move(source_stream),
-                                                  net::SourceStream::TYPE_GZIP);
-  }
-
-  // The URLRequestJob and the SourceStreams we are creating are owned by the
-  // same parent URLRequest, thus it is safe to pass the replacements via a raw
-  // pointer.
-  const ui::TemplateReplacements* replacements = nullptr;
-  if (source_)
-    replacements = source_->GetReplacements();
-  if (replacements) {
-    // It is safe to pass the raw replacements directly to the source stream, as
-    // both this URLRequestChromeJob and the I18nSourceStream are owned by the
-    // same root URLRequest. The replacements are owned by the URLDataSourceImpl
-    // which we keep alive via |source_|, ensuring its lifetime is also bound
-    // to the safe URLRequest.
-    source_stream = ui::I18nSourceStream::Create(
-        std::move(source_stream), net::SourceStream::TYPE_NONE, replacements);
-  }
-
-  return source_stream;
-}
-
-void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) {
-  mime_type_ = mime_type;
-}
-
-void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) {
-  TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this);
-  DCHECK(!data_);
-
-  if (!bytes) {
-    NotifyStartError(
-        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED));
-    return;
-  }
-
-  if (bytes)
-    set_expected_content_size(bytes->size());
-
-  // We notify headers are complete unusually late for these jobs, because we
-  // need to have |bytes| first to report an accurate expected content size.
-  // Otherwise, we cannot support <video> streaming.
-  NotifyHeadersComplete();
-
-  // The job can be cancelled after sending the headers.
-  if (is_done())
-    return;
-
-  // All further requests will be satisfied from the passed-in data.
-  data_ = bytes;
-  if (!bytes)
-    data_available_status_ = net::ERR_FAILED;
-
-  if (pending_buf_) {
-    // The request has already been marked async.
-    int result = bytes ? PostReadTask(pending_buf_, pending_buf_size_)
-                       : data_available_status_;
-    pending_buf_ = nullptr;
-    if (result != net::ERR_IO_PENDING)
-      ReadRawDataComplete(result);
-  }
-}
-
-int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) {
-  DCHECK(!pending_buf_.get());
-
-  // Handle the cases when DataAvailable() has already been called.
-  if (data_available_status_ != net::OK)
-    return data_available_status_;
-  if (data_)
-    return PostReadTask(buf, buf_size);
-
-  // DataAvailable() has not been called yet.  Mark the request as async.
-  pending_buf_ = buf;
-  pending_buf_size_ = buf_size;
-  return net::ERR_IO_PENDING;
-}
-
-int URLRequestChromeJob::PostReadTask(scoped_refptr<net::IOBuffer> buf,
-                                      int buf_size) {
-  DCHECK(buf);
-  DCHECK(data_);
-  CHECK(buf->data());
-
-  int remaining = data_->size() - data_offset_;
-  if (buf_size > remaining)
-    buf_size = remaining;
-
-  if (buf_size == 0)
-    return 0;
-
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-      base::BindOnce(&CopyData, base::RetainedRef(buf), buf_size, data_,
-                     data_offset_),
-      base::BindOnce(&URLRequestChromeJob::ReadRawDataComplete,
-                     weak_factory_.GetWeakPtr(), buf_size));
-  data_offset_ += buf_size;
-
-  return net::ERR_IO_PENDING;
-}
-
-void URLRequestChromeJob::StartAsync() {
-  if (!request_)
-    return;
-
-  if (!backend_->StartRequest(request_, this)) {
-    NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
-                                           net::ERR_INVALID_URL));
-  }
-}
-
-namespace {
-
-class ChromeProtocolHandler
-    : public net::URLRequestJobFactory::ProtocolHandler {
- public:
-  ChromeProtocolHandler(ResourceContext* resource_context,
-                        ChromeBlobStorageContext* blob_storage_context)
-      : resource_context_(resource_context),
-        blob_storage_context_(blob_storage_context) {}
-  ~ChromeProtocolHandler() override {}
-
-  net::URLRequestJob* MaybeCreateJob(
-      net::URLRequest* request,
-      net::NetworkDelegate* network_delegate) const override {
-    DCHECK(request);
-
-    // Next check for chrome://blob-internals/, which uses its own job type.
-    if (ViewBlobInternalsJobFactory::IsSupportedURL(request->url())) {
-      return ViewBlobInternalsJobFactory::CreateJobForRequest(
-          request, network_delegate, blob_storage_context_->context());
-    }
-
-    // Check for chrome://network-error/, which uses its own job type.
-    if (request->url().SchemeIs(kChromeUIScheme) &&
-        request->url().host_piece() == kChromeUINetworkErrorHost) {
-      // Get the error code passed in via the request URL path.
-      std::basic_string<char> error_code_string =
-          request->url().path().substr(1);
-
-      int error_code;
-      if (base::StringToInt(error_code_string, &error_code)) {
-        // Check for a valid error code.
-        if (URLDataManagerBackend::IsValidNetworkErrorCode(error_code) &&
-            error_code != net::Error::ERR_IO_PENDING) {
-          return new net::URLRequestErrorJob(request, network_delegate,
-                                             error_code);
-        }
-      }
-    }
-
-    // Check for chrome://dino which is an alias for chrome://network-error/-106
-    if (request->url().SchemeIs(kChromeUIScheme) &&
-        request->url().host() == kChromeUIDinoHost) {
-      return new net::URLRequestErrorJob(request, network_delegate,
-                                         net::Error::ERR_INTERNET_DISCONNECTED);
-    }
-
-    // Fall back to using a custom handler
-    return new URLRequestChromeJob(
-        request, network_delegate,
-        GetURLDataManagerForResourceContext(resource_context_));
-  }
-
-  bool IsSafeRedirectTarget(const GURL& location) const override {
-    return false;
-  }
-
- private:
-  // These members are owned by ProfileIOData, which owns this ProtocolHandler.
-  ResourceContext* const resource_context_;
-
-  ChromeBlobStorageContext* blob_storage_context_;
-
-  DISALLOW_COPY_AND_ASSIGN(ChromeProtocolHandler);
-};
-
 }  // namespace
 
 URLDataManagerBackend::URLDataManagerBackend() : next_request_id_(0) {
@@ -409,16 +73,6 @@
 
 URLDataManagerBackend::~URLDataManagerBackend() = default;
 
-// static
-std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
-URLDataManagerBackend::CreateProtocolHandler(
-    ResourceContext* resource_context,
-    ChromeBlobStorageContext* blob_storage_context) {
-  DCHECK(resource_context);
-  return std::make_unique<ChromeProtocolHandler>(resource_context,
-                                                 blob_storage_context);
-}
-
 void URLDataManagerBackend::AddDataSource(
     URLDataSourceImpl* source) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -443,76 +97,6 @@
       ->AddLocalizedStrings(update);
 }
 
-bool URLDataManagerBackend::HasPendingJob(
-    URLRequestChromeJob* job) const {
-  for (auto i = pending_requests_.begin(); i != pending_requests_.end(); ++i) {
-    if (i->second == job)
-      return true;
-  }
-  return false;
-}
-
-bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
-                                         URLRequestChromeJob* job) {
-  // NOTE: this duplicates code in web_ui_url_loader_factory.cc's
-  // StartURLLoader.
-  if (!CheckURLIsValid(request->url()))
-    return false;
-
-  URLDataSourceImpl* source = GetDataSourceFromURL(request->url());
-  if (!source)
-    return false;
-
-  ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
-  if (!source->source()->ShouldServiceRequest(
-          request->url(), info ? info->GetContext() : nullptr,
-          info ? info->GetChildID() : -1)) {
-    return false;
-  }
-
-  std::string path;
-  URLToRequestPath(request->url(), &path);
-
-  // Save this request so we know where to send the data.
-  RequestID request_id = next_request_id_++;
-  pending_requests_.insert(std::make_pair(request_id, job));
-
-  job->set_is_gzipped(source->source()->IsGzipped(path));
-
-  // TODO(dschuyler): improve filtering of which resource to run template
-  // replacements upon.
-  std::string mime_type = source->source()->GetMimeType(path);
-  if (mime_type == "text/html")
-    job->SetSource(source);
-
-  job->MimeTypeAvailable(mime_type);
-
-  // Look up additional request info to pass down.
-  ResourceRequestInfo::WebContentsGetter wc_getter;
-  if (info)
-    wc_getter = info->GetWebContentsGetterForRequest();
-
-  // Forward along the request to the data source.
-  scoped_refptr<base::SingleThreadTaskRunner> target_runner =
-      source->source()->TaskRunnerForRequestPath(path);
-  if (!target_runner) {
-    // The DataSource is agnostic to which thread StartDataRequest is called
-    // on for this path.  Call directly into it from this thread, the IO
-    // thread.
-    source->source()->StartDataRequest(
-        path, std::move(wc_getter),
-        base::Bind(&URLDataSourceImpl::SendResponse, source, request_id));
-  } else {
-    // The DataSource wants StartDataRequest to be called on a specific thread,
-    // usually the UI thread, for this path.
-    target_runner->PostTask(
-        FROM_HERE, base::BindOnce(&URLDataManagerBackend::CallStartRequest,
-                                  base::RetainedRef(source), path,
-                                  std::move(wc_getter), request_id));
-  }
-  return true;
-}
-
 URLDataSourceImpl* URLDataManagerBackend::GetDataSourceFromURL(
     const GURL& url) {
   // The input usually looks like: chrome://source_name/extra_bits?foo
@@ -531,40 +115,6 @@
   return nullptr;
 }
 
-void URLDataManagerBackend::CallStartRequest(
-    scoped_refptr<URLDataSourceImpl> source,
-    const std::string& path,
-    const ResourceRequestInfo::WebContentsGetter& wc_getter,
-    int request_id) {
-  source->source()->StartDataRequest(
-      path,
-      wc_getter,
-      base::Bind(&URLDataSourceImpl::SendResponse, source, request_id));
-}
-
-void URLDataManagerBackend::RemoveRequest(URLRequestChromeJob* job) {
-  // Remove the request from our list of pending requests.
-  // If/when the source sends the data that was requested, the data will just
-  // be thrown away.
-  for (auto i = pending_requests_.begin(); i != pending_requests_.end(); ++i) {
-    if (i->second == job) {
-      pending_requests_.erase(i);
-      return;
-    }
-  }
-}
-
-void URLDataManagerBackend::DataAvailable(RequestID request_id,
-                                          base::RefCountedMemory* bytes) {
-  // Forward this data on to the pending net::URLRequest, if it exists.
-  auto i = pending_requests_.find(request_id);
-  if (i != pending_requests_.end()) {
-    URLRequestChromeJob* job = i->second;
-    pending_requests_.erase(i);
-    job->DataAvailable(bytes);
-  }
-}
-
 scoped_refptr<net::HttpResponseHeaders> URLDataManagerBackend::GetHeaders(
     URLDataSourceImpl* source_impl,
     const std::string& path,
diff --git a/content/browser/webui/url_data_manager_backend.h b/content/browser/webui/url_data_manager_backend.h
index 463bc9a..0dabd1f 100644
--- a/content/browser/webui/url_data_manager_backend.h
+++ b/content/browser/webui/url_data_manager_backend.h
@@ -28,11 +28,9 @@
 
 namespace content {
 
-class ChromeBlobStorageContext;
 class ResourceContext;
 class URLDataManagerBackend;
 class URLDataSourceImpl;
-class URLRequestChromeJob;
 
 // URLDataManagerBackend is used internally by ChromeURLDataManager on the IO
 // thread. In most cases you can use the API in ChromeURLDataManager and ignore
@@ -44,13 +42,6 @@
   URLDataManagerBackend();
   ~URLDataManagerBackend() override;
 
-  // Invoked to create the protocol handler for chrome://. Called on the UI
-  // thread.
-  CONTENT_EXPORT static std::unique_ptr<
-      net::URLRequestJobFactory::ProtocolHandler>
-  CreateProtocolHandler(ResourceContext* resource_context,
-                        ChromeBlobStorageContext* blob_storage_context);
-
   // Adds a DataSource to the collection of data sources.
   void AddDataSource(URLDataSourceImpl* source);
 
@@ -86,41 +77,12 @@
   static std::vector<std::string> GetWebUISchemes();
 
  private:
-  friend class URLRequestChromeJob;
-
   typedef std::map<std::string,
       scoped_refptr<URLDataSourceImpl> > DataSourceMap;
-  typedef std::map<RequestID, URLRequestChromeJob*> PendingRequestMap;
-
-  // Called by the job when it's starting up.
-  // Returns false if |url| is not a URL managed by this object.
-  bool StartRequest(const net::URLRequest* request, URLRequestChromeJob* job);
-
-  // Helper function to call StartDataRequest on |source|'s delegate. This is
-  // needed because while we want to call URLDataSourceDelegate's method, we
-  // need to add a refcount on the source.
-  static void CallStartRequest(
-      scoped_refptr<URLDataSourceImpl> source,
-      const std::string& path,
-      const ResourceRequestInfo::WebContentsGetter& wc_getter,
-      int request_id);
-
-  // Remove a request from the list of pending requests.
-  void RemoveRequest(URLRequestChromeJob* job);
-
-  // Returns true if the job exists in |pending_requests_|. False otherwise.
-  // Called by ~URLRequestChromeJob to verify that |pending_requests_| is kept
-  // up to date.
-  bool HasPendingJob(URLRequestChromeJob* job) const;
 
   // Custom sources of data, keyed by source path (e.g. "favicon").
   DataSourceMap data_sources_;
 
-  // All pending URLRequestChromeJobs, keyed by ID of the request.
-  // URLRequestChromeJob calls into this object when it's constructed and
-  // destructed to ensure that the pointers in this map remain valid.
-  PendingRequestMap pending_requests_;
-
   // The ID we'll use for the next request we receive.
   RequestID next_request_id_;
 
diff --git a/content/browser/webui/url_data_manager_backend_unittest.cc b/content/browser/webui/url_data_manager_backend_unittest.cc
deleted file mode 100644
index ce79d27..0000000
--- a/content/browser/webui/url_data_manager_backend_unittest.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/webui/url_data_manager_backend.h"
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/test/mock_resource_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "content/public/test/test_utils.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_response_info.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job.h"
-#include "net/url_request/url_request_job_factory_impl.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class CancelAfterFirstReadURLRequestDelegate : public net::TestDelegate {
- public:
-  CancelAfterFirstReadURLRequestDelegate() {}
-
-  ~CancelAfterFirstReadURLRequestDelegate() override {}
-
-  void OnResponseStarted(net::URLRequest* request, int net_error) override {
-    DCHECK_NE(net::ERR_IO_PENDING, net_error);
-    // net::TestDelegate will start the first read.
-    TestDelegate::OnResponseStarted(request, net_error);
-    request->Cancel();
-  }
-
-  void OnReadCompleted(net::URLRequest* request, int bytes_read) override {
-    // Read should have been cancelled.
-    EXPECT_EQ(net::ERR_ABORTED, bytes_read);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CancelAfterFirstReadURLRequestDelegate);
-};
-
-class UrlDataManagerBackendTest : public testing::Test {
- public:
-  UrlDataManagerBackendTest()
-      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
-    // URLRequestJobFactory takes ownership of the passed in ProtocolHandler.
-    url_request_job_factory_.SetProtocolHandler(
-        kChromeUIScheme, URLDataManagerBackend::CreateProtocolHandler(
-                             &resource_context_, nullptr));
-    url_request_context_.set_job_factory(&url_request_job_factory_);
-  }
-
-  std::unique_ptr<net::URLRequest> CreateRequest(
-      net::URLRequest::Delegate* delegate,
-      const char* origin) {
-    std::unique_ptr<net::URLRequest> request =
-        url_request_context_.CreateRequest(
-            GetWebUIURL("resources/css/text_defaults.css"), net::HIGHEST,
-            delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
-    request->SetExtraRequestHeaderByName("Origin", origin, true);
-    return request;
-  }
-
- protected:
-  TestBrowserThreadBundle thread_bundle_;
-  MockResourceContext resource_context_;
-  net::URLRequestJobFactoryImpl url_request_job_factory_;
-  net::URLRequestContext url_request_context_;
-  net::TestDelegate delegate_;
-};
-
-TEST_F(UrlDataManagerBackendTest, AccessControlAllowOriginChromeUrl) {
-  std::unique_ptr<net::URLRequest> request(
-      CreateRequest(&delegate_, GetWebUIURLString("webui").c_str()));
-  request->Start();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(request->response_headers()->HasHeaderValue(
-      "Access-Control-Allow-Origin", GetWebUIURLString("webui").c_str()));
-}
-
-TEST_F(UrlDataManagerBackendTest, AccessControlAllowOriginNonChromeUrl) {
-  std::unique_ptr<net::URLRequest> request(
-      CreateRequest(&delegate_, "http://www.example.com"));
-  request->Start();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(request->response_headers()->HasHeaderValue(
-      "Access-Control-Allow-Origin", "null"));
-}
-
-// Check that the URLRequest isn't passed headers after cancellation.
-TEST_F(UrlDataManagerBackendTest, CancelBeforeResponseStarts) {
-  std::unique_ptr<net::URLRequest> request(
-      CreateRequest(&delegate_, GetWebUIURLString("webui").c_str()));
-  request->Start();
-  request->Cancel();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(net::URLRequestStatus::CANCELED, request->status().status());
-  EXPECT_EQ(1, delegate_.response_started_count());
-}
-
-// Check that the URLRequest isn't passed data after cancellation.
-TEST_F(UrlDataManagerBackendTest, CancelAfterFirstReadStarted) {
-  CancelAfterFirstReadURLRequestDelegate cancel_delegate;
-  std::unique_ptr<net::URLRequest> request(
-      CreateRequest(&cancel_delegate, GetWebUIURLString("webui").c_str()));
-  request->Start();
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(net::URLRequestStatus::CANCELED, request->status().status());
-  EXPECT_EQ(1, cancel_delegate.response_started_count());
-  EXPECT_EQ("", cancel_delegate.data_received());
-}
-
-// Check for a network error page request via chrome://network-error/.
-TEST_F(UrlDataManagerBackendTest, ChromeNetworkErrorPageRequest) {
-  std::unique_ptr<net::URLRequest> error_request =
-      url_request_context_.CreateRequest(GetWebUIURL("network-error/-105"),
-                                         net::HIGHEST, &delegate_,
-                                         TRAFFIC_ANNOTATION_FOR_TESTS);
-  error_request->Start();
-  base::RunLoop().Run();
-  EXPECT_EQ(net::URLRequestStatus::FAILED, error_request->status().status());
-  EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, error_request->status().error());
-}
-
-// Check for an invalid network error page request via chrome://network-error/.
-TEST_F(UrlDataManagerBackendTest, ChromeNetworkErrorPageRequestFailed) {
-  std::unique_ptr<net::URLRequest> error_request =
-      url_request_context_.CreateRequest(
-          GetWebUIURL("network-error/-123456789"), net::HIGHEST, &delegate_,
-          TRAFFIC_ANNOTATION_FOR_TESTS);
-  error_request->Start();
-  base::RunLoop().Run();
-  EXPECT_EQ(net::URLRequestStatus::FAILED, error_request->status().status());
-  EXPECT_EQ(net::ERR_INVALID_URL, error_request->status().error());
-}
-
-}  // namespace content
diff --git a/content/browser/webui/url_data_source_impl.cc b/content/browser/webui/url_data_source_impl.cc
index 1395376..4b1c213 100644
--- a/content/browser/webui/url_data_source_impl.cc
+++ b/content/browser/webui/url_data_source_impl.cc
@@ -24,41 +24,10 @@
 URLDataSourceImpl::~URLDataSourceImpl() {
 }
 
-void URLDataSourceImpl::SendResponse(
-    int request_id,
-    scoped_refptr<base::RefCountedMemory> bytes) {
-  if (URLDataManager::IsScheduledForDeletion(this)) {
-    // We're scheduled for deletion. Servicing the request would result in
-    // this->AddRef being invoked, even though the ref count is 0 and 'this' is
-    // about to be deleted. If the AddRef were allowed through, when 'this' is
-    // released it would be deleted again.
-    //
-    // This scenario occurs with DataSources that make history requests. Such
-    // DataSources do a history query in |StartDataRequest| and the request is
-    // live until the object is deleted (history requests don't up the ref
-    // count). This means it's entirely possible for the DataSource to invoke
-    // |SendResponse| between the time when there are no more refs and the time
-    // when the object is deleted.
-    return;
-  }
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::IO},
-      base::BindOnce(&URLDataSourceImpl::SendResponseOnIOThread, this,
-                     request_id, std::move(bytes)));
-}
-
 bool URLDataSourceImpl::IsWebUIDataSourceImpl() const {
   return false;
 }
 
-void URLDataSourceImpl::SendResponseOnIOThread(
-    int request_id,
-    scoped_refptr<base::RefCountedMemory> bytes) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (backend_)
-    backend_->DataAvailable(request_id, bytes.get());
-}
-
 const ui::TemplateReplacements* URLDataSourceImpl::GetReplacements() const {
   return nullptr;
 }
diff --git a/content/browser/webui/url_data_source_impl.h b/content/browser/webui/url_data_source_impl.h
index 538db76..d03dd0b 100644
--- a/content/browser/webui/url_data_source_impl.h
+++ b/content/browser/webui/url_data_source_impl.h
@@ -15,10 +15,6 @@
 #include "content/common/content_export.h"
 #include "ui/base/template_expressions.h"
 
-namespace base {
-class RefCountedMemory;
-}
-
 namespace content {
 class URLDataManagerBackend;
 class URLDataSource;
@@ -57,12 +53,6 @@
   URLDataSourceImpl(const std::string& source_name,
                     std::unique_ptr<URLDataSource> source);
 
-  // Report that a request has resulted in the data |bytes|.
-  // If the request can't be satisfied, pass NULL for |bytes| to indicate
-  // the request is over.
-  virtual void SendResponse(int request_id,
-                            scoped_refptr<base::RefCountedMemory> bytes);
-
   const std::string& source_name() const { return source_name_; }
   URLDataSource* source() const { return source_.get(); }
 
@@ -79,12 +69,6 @@
   friend class URLDataManagerBackend;
   friend class base::DeleteHelper<URLDataSourceImpl>;
 
-  // SendResponse invokes this on the IO thread. Notifies the backend to
-  // handle the actual work of sending the data.
-  virtual void SendResponseOnIOThread(
-      int request_id,
-      scoped_refptr<base::RefCountedMemory> bytes);
-
   // The name of this source.
   // E.g., for favicons, this could be "favicon", which results in paths for
   // specific resources like "favicon/34" getting sent to this source.
diff --git a/content/browser/worker_host/worker_script_loader.cc b/content/browser/worker_host/worker_script_loader.cc
index 2269b2fb..d1e8465 100644
--- a/content/browser/worker_host/worker_script_loader.cc
+++ b/content/browser/worker_host/worker_script_loader.cc
@@ -233,11 +233,6 @@
   Start();
 }
 
-void WorkerScriptLoader::ProceedWithResponse() {
-  // Only for navigations.
-  NOTREACHED();
-}
-
 // Below we make a small effort to support the other URLLoader functions by
 // forwarding to the current |url_loader_| if any, but don't bother queuing
 // state or propagating state to a new URLLoader upon redirect.
diff --git a/content/browser/worker_host/worker_script_loader.h b/content/browser/worker_host/worker_script_loader.h
index 5328ef2..a39d326 100644
--- a/content/browser/worker_host/worker_script_loader.h
+++ b/content/browser/worker_host/worker_script_loader.h
@@ -83,7 +83,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index 7485b5b..bd81bb3 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -488,6 +488,8 @@
     {"calendarPicker.js", IDR_CALENDAR_PICKER_JS, ui::SCALE_FACTOR_NONE, true},
     {"calendarPicker.css", IDR_CALENDAR_PICKER_CSS, ui::SCALE_FACTOR_NONE,
      true},
+    {"calendar_picker_refresh.css", IDR_CALENDAR_PICKER_REFRESH_CSS,
+     ui::SCALE_FACTOR_NONE, true},
     {"listPicker.js", IDR_LIST_PICKER_JS, ui::SCALE_FACTOR_NONE, true},
     {"listPicker.css", IDR_LIST_PICKER_CSS, ui::SCALE_FACTOR_NONE, true},
     {"pickerButton.css", IDR_PICKER_BUTTON_CSS, ui::SCALE_FACTOR_NONE, true},
diff --git a/content/common/mime_sniffing_url_loader.cc b/content/common/mime_sniffing_url_loader.cc
index 0a92ed2..2f3dea9 100644
--- a/content/common/mime_sniffing_url_loader.cc
+++ b/content/common/mime_sniffing_url_loader.cc
@@ -151,12 +151,6 @@
   NOTREACHED();
 }
 
-void MimeSniffingURLLoader::ProceedWithResponse() {
-  if (state_ == State::kAborted)
-    return;
-  source_url_loader_->ProceedWithResponse();
-}
-
 void MimeSniffingURLLoader::SetPriority(net::RequestPriority priority,
                                         int32_t intra_priority_value) {
   if (state_ == State::kAborted)
diff --git a/content/common/mime_sniffing_url_loader.h b/content/common/mime_sniffing_url_loader.h
index fdea9ec0..b3687c9 100644
--- a/content/common/mime_sniffing_url_loader.h
+++ b/content/common/mime_sniffing_url_loader.h
@@ -98,7 +98,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/content/common/throttling_url_loader_unittest.cc b/content/common/throttling_url_loader_unittest.cc
index 4b0a9c8..3135ba8 100644
--- a/content/common/throttling_url_loader_unittest.cc
+++ b/content/common/throttling_url_loader_unittest.cc
@@ -123,8 +123,6 @@
     headers_modified_on_redirect_ = modified_headers;
   }
 
-  void ProceedWithResponse() override {}
-
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
 
diff --git a/content/public/app/content_renderer_manifest.cc b/content/public/app/content_renderer_manifest.cc
index 3ffdc19..30b6f1f 100644
--- a/content/public/app/content_renderer_manifest.cc
+++ b/content/public/app/content_renderer_manifest.cc
@@ -68,7 +68,6 @@
                   "blink.mojom.EngagementClient", "blink.mojom.ImageDownloader",
                   "blink.mojom.InstallationService",
                   "blink.mojom.ManifestManager",
-                  "blink.mojom.MediaDevicesListener",
                   "blink.mojom.MediaStreamDeviceObserver",
                   "blink.mojom.TextSuggestionBackend",
                   "blink.mojom.WebLaunchService",
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h
index ac77359..116ff8d 100644
--- a/content/public/browser/browser_context.h
+++ b/content/public/browser/browser_context.h
@@ -57,10 +57,6 @@
 class VideoDecodePerfHistory;
 }
 
-namespace net {
-class URLRequestContextGetter;
-}
-
 namespace storage {
 class BlobStorageContext;
 class SpecialStoragePolicy;
@@ -304,15 +300,6 @@
   // called once per context. It's valid to return nullptr.
   virtual BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate() = 0;
 
-  // Creates the main net::URLRequestContextGetter. It's called only once.
-  virtual net::URLRequestContextGetter* CreateRequestContext(
-      ProtocolHandlerMap* protocol_handlers,
-      URLRequestInterceptorScopedVector request_interceptors) = 0;
-
-  // Creates the main net::URLRequestContextGetter for media resources. It's
-  // called only once.
-  virtual net::URLRequestContextGetter* CreateMediaRequestContext() = 0;
-
   // Sets CORS origin access lists.
   virtual void SetCorsOriginAccessListForOrigin(
       const url::Origin& source_origin,
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index f31ac49..bfc1b43 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -137,6 +137,7 @@
 #endif
 
 #if defined(USE_AURA)
+#include "content/browser/renderer_host/delegated_frame_host.h"
 #include "content/browser/renderer_host/overscroll_controller.h"
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "ui/aura/test/window_event_dispatcher_test_api.h"
@@ -3092,6 +3093,78 @@
   return raw_mock;
 }
 
+namespace {
+
+// This class interacts with the internals of the DelegatedFrameHost without
+// exposing them in the header.
+class EvictionStateWaiter : public DelegatedFrameHost::Observer {
+ public:
+  EvictionStateWaiter(DelegatedFrameHost* delegated_frame_host)
+      : delegated_frame_host_(delegated_frame_host) {
+    delegated_frame_host_->AddObserverForTesting(this);
+  }
+
+  ~EvictionStateWaiter() override {
+    delegated_frame_host_->RemoveObserverForTesting(this);
+  }
+
+  void WaitForEvictionState(DelegatedFrameHost::FrameEvictionState state) {
+    if (delegated_frame_host_->frame_eviction_state() == state)
+      return;
+
+    waited_eviction_state_ = state;
+    base::RunLoop run_loop;
+    quit_closure_ = run_loop.QuitClosure();
+    run_loop.Run();
+  }
+
+  // DelegatedFrameHost::Observer:
+  void OnFrameEvictionStateChanged(
+      DelegatedFrameHost::FrameEvictionState new_state) override {
+    if (!quit_closure_.is_null() && (new_state == waited_eviction_state_))
+      std::move(quit_closure_).Run();
+  }
+
+ private:
+  DelegatedFrameHost* delegated_frame_host_;
+  DelegatedFrameHost::FrameEvictionState waited_eviction_state_;
+  base::OnceClosure quit_closure_;
+
+  DISALLOW_COPY_AND_ASSIGN(EvictionStateWaiter);
+};
+
+}  // namespace
+
+void VerifyStaleContentOnFrameEviction(
+    RenderWidgetHostView* render_widget_host_view) {
+  auto* render_widget_host_view_aura =
+      static_cast<RenderWidgetHostViewAura*>(render_widget_host_view);
+  DelegatedFrameHost* delegated_frame_host =
+      render_widget_host_view_aura->GetDelegatedFrameHost();
+
+  // Initially there should be no stale content set.
+  EXPECT_FALSE(
+      delegated_frame_host->stale_content_layer()->has_external_content());
+  EXPECT_EQ(delegated_frame_host->frame_eviction_state(),
+            DelegatedFrameHost::FrameEvictionState::kNotStarted);
+
+  // Hide the view and evict the frame, and expect that stale content will be
+  // set.
+  EvictionStateWaiter waiter{delegated_frame_host};
+  render_widget_host_view_aura->WasOccluded();
+  static_cast<viz::FrameEvictorClient*>(delegated_frame_host)
+      ->EvictDelegatedFrame();
+  EXPECT_EQ(delegated_frame_host->frame_eviction_state(),
+            DelegatedFrameHost::FrameEvictionState::kPendingEvictionRequests);
+  // Wait until the stale frame content is copied and set onto the layer, i.e.
+  // the eviction state changes from kPendingEvictionRequests back to
+  // kNotStarted.
+  waiter.WaitForEvictionState(
+      DelegatedFrameHost::FrameEvictionState::kNotStarted);
+  EXPECT_TRUE(
+      delegated_frame_host->stale_content_layer()->has_external_content());
+}
+
 #endif  // defined(USE_AURA)
 
 ContextMenuFilter::ContextMenuFilter()
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index 26333783..917183c 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -1589,6 +1589,12 @@
   // Waits until the mock receives a consumed GestureScrollUpdate.
   virtual void WaitForConsumedScroll() = 0;
 };
+
+// Tests that a |render_widget_host_view| stores a stale content when its frame
+// gets evicted. |render_widget_host_view| has to be a RenderWidgetHostViewAura.
+void VerifyStaleContentOnFrameEviction(
+    RenderWidgetHostView* render_widget_host_view);
+
 #endif  // defined(USE_AURA)
 
 // This class filters for FrameHostMsg_ContextMenu messages coming in
diff --git a/content/public/test/content_cert_verifier_browser_test.cc b/content/public/test/content_cert_verifier_browser_test.cc
index c07ae9ae..2763fb54 100644
--- a/content/public/test/content_cert_verifier_browser_test.cc
+++ b/content/public/test/content_cert_verifier_browser_test.cc
@@ -4,8 +4,6 @@
 
 #include "content/public/test/content_cert_verifier_browser_test.h"
 
-#include "content/shell/browser/shell_url_request_context_getter.h"
-
 namespace content {
 
 CertVerifierBrowserTest::CertVerifierBrowserTest() = default;
@@ -24,9 +22,6 @@
   if (mock_cert_verifier_disabled_)
     return;
 
-  ShellURLRequestContextGetter::SetCertVerifierForTesting(
-      mock_cert_verifier_.mock_cert_verifier_internal());
-
   mock_cert_verifier_.SetUpInProcessBrowserTestFixture();
 }
 
@@ -34,7 +29,6 @@
   if (mock_cert_verifier_disabled_)
     return;
 
-  ShellURLRequestContextGetter::SetCertVerifierForTesting(nullptr);
   mock_cert_verifier_.TearDownInProcessBrowserTestFixture();
 }
 
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 2a6e3f4..7c3f1623 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -159,7 +159,7 @@
   base::WeakPtrFactory<FakeWebURLLoader> weak_factory_{this};
 };
 
-class FakeWebURLLoaderFactory : public blink::WebURLLoaderFactory {
+class FakeWebURLLoaderFactory : public blink::WebURLLoaderFactoryForTest {
  public:
   std::unique_ptr<blink::WebURLLoader> CreateURLLoader(
       const WebURLRequest&,
@@ -167,6 +167,10 @@
           task_runner_handle) override {
     return std::make_unique<FakeWebURLLoader>(std::move(task_runner_handle));
   }
+
+  std::unique_ptr<WebURLLoaderFactoryForTest> Clone() override {
+    return std::make_unique<FakeWebURLLoaderFactory>();
+  }
 };
 
 // Converts |ascii_character| into |key_code| and returns true on success.
diff --git a/content/public/test/test_browser_context.cc b/content/public/test/test_browser_context.cc
index 8e6100c..d41747c 100644
--- a/content/public/test/test_browser_context.cc
+++ b/content/public/test/test_browser_context.cc
@@ -16,36 +16,9 @@
 #include "content/public/test/mock_resource_context.h"
 #include "content/test/mock_background_sync_controller.h"
 #include "content/test/mock_ssl_host_state_delegate.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_test_util.h"
 #include "storage/browser/quota/special_storage_policy.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace {
-
-class TestContextURLRequestContextGetter : public net::URLRequestContextGetter {
- public:
-  TestContextURLRequestContextGetter()
-      : null_task_runner_(new base::NullTaskRunner) {
-  }
-
-  net::URLRequestContext* GetURLRequestContext() override { return &context_; }
-
-  scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
-      const override {
-    return null_task_runner_;
-  }
-
- private:
-  ~TestContextURLRequestContextGetter() override {}
-
-  net::TestURLRequestContext context_;
-  scoped_refptr<base::SingleThreadTaskRunner> null_task_runner_;
-};
-
-}  // namespace
-
 namespace content {
 
 TestBrowserContext::TestBrowserContext(
@@ -94,13 +67,6 @@
   permission_controller_delegate_ = std::move(delegate);
 }
 
-net::URLRequestContextGetter* TestBrowserContext::GetRequestContext() {
-  if (!request_context_.get()) {
-    request_context_ = new TestContextURLRequestContextGetter();
-  }
-  return request_context_.get();
-}
-
 base::FilePath TestBrowserContext::GetPath() {
   return browser_context_dir_.GetPath();
 }
@@ -172,15 +138,4 @@
   return nullptr;
 }
 
-net::URLRequestContextGetter* TestBrowserContext::CreateRequestContext(
-      content::ProtocolHandlerMap* protocol_handlers,
-      content::URLRequestInterceptorScopedVector request_interceptors) {
-  request_interceptors_ = std::move(request_interceptors);
-  return GetRequestContext();
-}
-
-net::URLRequestContextGetter* TestBrowserContext::CreateMediaRequestContext() {
-  return nullptr;
-}
-
 }  // namespace content
diff --git a/content/public/test/test_browser_context.h b/content/public/test/test_browser_context.h
index 2314463..1a489a19 100644
--- a/content/public/test/test_browser_context.h
+++ b/content/public/test/test_browser_context.h
@@ -36,7 +36,6 @@
   void SetSpecialStoragePolicy(storage::SpecialStoragePolicy* policy);
   void SetPermissionControllerDelegate(
       std::unique_ptr<PermissionControllerDelegate> delegate);
-  net::URLRequestContextGetter* GetRequestContext();
 
   // Allow clients to make this an incognito context.
   void set_is_off_the_record(bool is_off_the_record) {
@@ -61,16 +60,10 @@
   BackgroundFetchDelegate* GetBackgroundFetchDelegate() override;
   BackgroundSyncController* GetBackgroundSyncController() override;
   BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate() override;
-  net::URLRequestContextGetter* CreateRequestContext(
-      ProtocolHandlerMap* protocol_handlers,
-      URLRequestInterceptorScopedVector request_interceptors) override;
-  net::URLRequestContextGetter* CreateMediaRequestContext() override;
 
  private:
   // Hold a reference here because BrowserContext owns lifetime.
-  URLRequestInterceptorScopedVector request_interceptors_;
   base::ScopedTempDir browser_context_dir_;
-  scoped_refptr<net::URLRequestContextGetter> request_context_;
   std::unique_ptr<MockResourceContext> resource_context_;
   scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
   std::unique_ptr<MockSSLHostStateDelegate> ssl_host_state_delegate_;
diff --git a/content/renderer/DEPS b/content/renderer/DEPS
index fa79e26..d486d6c 100644
--- a/content/renderer/DEPS
+++ b/content/renderer/DEPS
@@ -45,5 +45,6 @@
   ],
   ".*_(unit|pixel|perf)test.*\.cc": [
     "+components/viz/test",
+    "+third_party/blink/renderer/platform/testing",
   ],
 }
diff --git a/content/renderer/loader/child_url_loader_factory_bundle.cc b/content/renderer/loader/child_url_loader_factory_bundle.cc
index e2cc1ad..03f53de 100644
--- a/content/renderer/loader/child_url_loader_factory_bundle.cc
+++ b/content/renderer/loader/child_url_loader_factory_bundle.cc
@@ -44,8 +44,6 @@
                                  base::nullopt /* new_url */);
   }
 
-  void ProceedWithResponse() override { loader_sink_->ProceedWithResponse(); }
-
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {
     loader_sink_->SetPriority(priority, intra_priority_value);
diff --git a/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc b/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
index 870ec81..1df32284 100644
--- a/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
+++ b/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
@@ -28,6 +28,7 @@
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/web/web_heap.h"
 #include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "third_party/webrtc/api/media_stream_interface.h"
 
 using testing::Return;
@@ -100,9 +101,6 @@
 
  protected:
   WebRtcAudioRendererTest() : source_(new MockAudioRendererSource()) {
-    blink::Platform::SetCurrentPlatformForTesting(
-        &audio_device_factory_platform_);
-
     blink::WebVector<blink::WebMediaStreamTrack> dummy_tracks;
     stream_.Initialize(blink::WebString::FromUTF8("new stream"), dummy_tracks,
                        dummy_tracks);
@@ -116,7 +114,7 @@
         nullptr, base::UnguessableToken::Create(), device_id);
 
     EXPECT_CALL(
-        audio_device_factory_platform_,
+        *audio_device_factory_platform_,
         MockNewAudioRendererSink(_, nullptr /*blink::WebLocalFrame*/, _))
         .Times(testing::AtLeast(1));
     EXPECT_CALL(*this, MockCreateAudioRendererSink(
@@ -182,7 +180,8 @@
     blink::WebHeap::CollectAllGarbageForTesting();
   }
 
-  AudioDeviceFactoryTestingPlatformSupport audio_device_factory_platform_;
+  blink::ScopedTestingPlatformSupport<AudioDeviceFactoryTestingPlatformSupport>
+      audio_device_factory_platform_;
   const base::Optional<base::UnguessableToken> kAudioProcessingId =
       base::UnguessableToken::Create();
   base::test::ScopedTaskEnvironment task_environment_{
diff --git a/content/renderer/pepper/pepper_video_capture_host.cc b/content/renderer/pepper/pepper_video_capture_host.cc
index 0a84c54..e85a337 100644
--- a/content/renderer/pepper/pepper_video_capture_host.cc
+++ b/content/renderer/pepper/pepper_video_capture_host.cc
@@ -217,11 +217,11 @@
     {
       EnterResourceNoLock<PPB_Buffer_API> enter2(res, true);
       DCHECK(enter2.succeeded());
-      base::SharedMemory* shm;
+      base::UnsafeSharedMemoryRegion* shm;
       int32_t result = enter2.object()->GetSharedMemory(&shm);
       DCHECK(result == PP_OK);
       params.AppendHandle(ppapi::proxy::SerializedHandle(
-          dispatcher->ShareSharedMemoryHandleWithRemote(shm->handle()), size));
+          dispatcher->ShareUnsafeSharedMemoryRegionWithRemote(*shm)));
     }
   }
 
diff --git a/content/renderer/pepper/ppb_buffer_impl.cc b/content/renderer/pepper/ppb_buffer_impl.cc
index 3da947a..e14c01f 100644
--- a/content/renderer/pepper/ppb_buffer_impl.cc
+++ b/content/renderer/pepper/ppb_buffer_impl.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "content/common/pepper_file_util.h"
 #include "content/renderer/render_thread_impl.h"
+#include "mojo/public/cpp/base/shared_memory_utils.h"
 #include "ppapi/c/dev/ppb_buffer_dev.h"
 #include "ppapi/c/pp_bool.h"
 #include "ppapi/c/pp_errors.h"
@@ -51,9 +52,8 @@
   if (size == 0)
     return false;
   size_ = size;
-  shared_memory_.reset(
-      RenderThread::Get()->HostAllocateSharedMemoryBuffer(size).release());
-  return shared_memory_.get() != nullptr;
+  shared_memory_ = mojo::CreateUnsafeSharedMemoryRegion(size);
+  return shared_memory_.IsValid();
 }
 
 PP_Bool PPB_Buffer_Impl::Describe(uint32_t* size_in_bytes) {
@@ -62,24 +62,26 @@
 }
 
 PP_Bool PPB_Buffer_Impl::IsMapped() {
-  return PP_FromBool(!!shared_memory_->memory());
+  return PP_FromBool(shared_mapping_.IsValid());
 }
 
 void* PPB_Buffer_Impl::Map() {
   DCHECK(size_);
-  DCHECK(shared_memory_.get());
-  if (map_count_++ == 0)
-    shared_memory_->Map(size_);
-  return shared_memory_->memory();
+  DCHECK(shared_memory_.IsValid());
+  if (map_count_++ == 0) {
+    DCHECK(!shared_mapping_.IsValid());
+    shared_mapping_ = shared_memory_.Map();
+  }
+  return shared_mapping_.memory();
 }
 
 void PPB_Buffer_Impl::Unmap() {
   if (--map_count_ == 0)
-    shared_memory_->Unmap();
+    shared_mapping_ = {};
 }
 
-int32_t PPB_Buffer_Impl::GetSharedMemory(base::SharedMemory** shm) {
-  *shm = shared_memory_.get();
+int32_t PPB_Buffer_Impl::GetSharedMemory(base::UnsafeSharedMemoryRegion** shm) {
+  *shm = &shared_memory_;
   return PP_OK;
 }
 
diff --git a/content/renderer/pepper/ppb_buffer_impl.h b/content/renderer/pepper/ppb_buffer_impl.h
index b0e7f16..9b33e81 100644
--- a/content/renderer/pepper/ppb_buffer_impl.h
+++ b/content/renderer/pepper/ppb_buffer_impl.h
@@ -11,7 +11,8 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "base/memory/unsafe_shared_memory_region.h"
 #include "ppapi/shared_impl/resource.h"
 #include "ppapi/thunk/ppb_buffer_api.h"
 
@@ -26,7 +27,9 @@
 
   virtual PPB_Buffer_Impl* AsPPB_Buffer_Impl();
 
-  base::SharedMemory* shared_memory() const { return shared_memory_.get(); }
+  const base::UnsafeSharedMemoryRegion& shared_memory() const {
+    return shared_memory_;
+  }
   uint32_t size() const { return size_; }
 
   // Resource overrides.
@@ -39,7 +42,7 @@
   void Unmap() override;
 
   // Trusted.
-  int32_t GetSharedMemory(base::SharedMemory** shm) override;
+  int32_t GetSharedMemory(base::UnsafeSharedMemoryRegion** shm) override;
 
  private:
   ~PPB_Buffer_Impl() override;
@@ -47,7 +50,8 @@
   explicit PPB_Buffer_Impl(PP_Instance instance);
   bool Init(uint32_t size);
 
-  std::unique_ptr<base::SharedMemory> shared_memory_;
+  base::UnsafeSharedMemoryRegion shared_memory_;
+  base::WritableSharedMemoryMapping shared_mapping_;
   uint32_t size_;
   int map_count_;
 
diff --git a/content/renderer/pepper/ppb_video_decoder_impl.cc b/content/renderer/pepper/ppb_video_decoder_impl.cc
index bc85f004..b3892053 100644
--- a/content/renderer/pepper/ppb_video_decoder_impl.cc
+++ b/content/renderer/pepper/ppb_video_decoder_impl.cc
@@ -164,9 +164,9 @@
   DCHECK_GE(bitstream_buffer->id, 0);
   // TODO(crbug.com/844456): The shared memory buffer probably can be read-only,
   // but only after PPB_Buffer_Impl is updated to deal with that.
-  media::BitstreamBuffer decode_buffer(
-      bitstream_buffer->id, buffer->shared_memory()->handle(),
-      false /* read_only */, bitstream_buffer->size);
+  media::BitstreamBuffer decode_buffer(bitstream_buffer->id,
+                                       buffer->shared_memory().Duplicate(),
+                                       buffer->shared_memory().GetSize());
   if (!SetBitstreamBufferCallback(bitstream_buffer->id, callback))
     return PP_ERROR_BADARGUMENT;
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 22354433..acebcca 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -7461,8 +7461,24 @@
   if (!RenderThreadImpl::current()) {
     // Some tests (e.g. RenderViewTests) do not have RenderThreadImpl,
     // and must create a factory override instead.
-    DCHECK(web_url_loader_factory_override_for_test_);
-    return std::move(web_url_loader_factory_override_for_test_);
+    if (web_url_loader_factory_override_for_test_)
+      return web_url_loader_factory_override_for_test_->Clone();
+
+    // If the override does not exist, try looking in the ancestor chain since
+    // we might have created child frames and asked them to create a URL loader
+    // factory.
+    for (auto* ancestor = GetWebFrame()->Parent(); ancestor;
+         ancestor = ancestor->Parent()) {
+      RenderFrameImpl* ancestor_frame = RenderFrameImpl::FromWebFrame(ancestor);
+      if (ancestor_frame &&
+          ancestor_frame->web_url_loader_factory_override_for_test_) {
+        return ancestor_frame->web_url_loader_factory_override_for_test_
+            ->Clone();
+      }
+    }
+    // At this point we can't create anything.
+    NOTREACHED();
+    return nullptr;
   }
   return std::make_unique<FrameURLLoaderFactory>(weak_factory_.GetWeakPtr());
 }
@@ -7763,7 +7779,7 @@
 }
 
 void RenderFrameImpl::SetWebURLLoaderFactoryOverrideForTest(
-    std::unique_ptr<blink::WebURLLoaderFactory> factory) {
+    std::unique_ptr<blink::WebURLLoaderFactoryForTest> factory) {
   web_url_loader_factory_override_for_test_ = std::move(factory);
 }
 
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 2665312b..f78f012 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -1009,7 +1009,7 @@
   // Used in tests to install a fake WebURLLoaderFactory via
   // RenderViewTest::CreateFakeWebURLLoaderFactory().
   void SetWebURLLoaderFactoryOverrideForTest(
-      std::unique_ptr<blink::WebURLLoaderFactory> factory);
+      std::unique_ptr<blink::WebURLLoaderFactoryForTest> factory);
 
  protected:
   explicit RenderFrameImpl(CreateParams params);
@@ -1790,7 +1790,7 @@
   class MHTMLBodyLoaderClient;
   std::unique_ptr<MHTMLBodyLoaderClient> mhtml_body_loader_client_;
 
-  std::unique_ptr<blink::WebURLLoaderFactory>
+  std::unique_ptr<blink::WebURLLoaderFactoryForTest>
       web_url_loader_factory_override_for_test_;
 
   base::WeakPtrFactory<RenderFrameImpl> weak_factory_{this};
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc
index 17bf4a2..b6a8215 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -683,10 +683,6 @@
   StartRequest(resource_request_);
 }
 
-void ServiceWorkerSubresourceLoader::ProceedWithResponse() {
-  NOTREACHED();
-}
-
 void ServiceWorkerSubresourceLoader::SetPriority(net::RequestPriority priority,
                                                  int intra_priority_value) {
   // Not supported (do nothing).
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.h b/content/renderer/service_worker/service_worker_subresource_loader.h
index 52474e0e..4d6adef 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.h
+++ b/content/renderer/service_worker/service_worker_subresource_loader.h
@@ -108,7 +108,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index e42a042..bc7c22a 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -137,8 +137,6 @@
     "browser/shell_javascript_dialog_manager.h",
     "browser/shell_javascript_dialog_win.cc",
     "browser/shell_mac.mm",
-    "browser/shell_network_delegate.cc",
-    "browser/shell_network_delegate.h",
     "browser/shell_permission_manager.cc",
     "browser/shell_permission_manager.h",
     "browser/shell_platform_data_aura.cc",
@@ -149,8 +147,6 @@
     "browser/shell_quota_permission_context.h",
     "browser/shell_speech_recognition_manager_delegate.cc",
     "browser/shell_speech_recognition_manager_delegate.h",
-    "browser/shell_url_request_context_getter.cc",
-    "browser/shell_url_request_context_getter.h",
     "browser/shell_web_contents_view_delegate.h",
     "browser/shell_web_contents_view_delegate_android.cc",
     "browser/shell_web_contents_view_delegate_creator.h",
@@ -205,8 +201,6 @@
     "browser/web_test/web_test_permission_manager.h",
     "browser/web_test/web_test_push_messaging_service.cc",
     "browser/web_test/web_test_push_messaging_service.h",
-    "browser/web_test/web_test_url_request_context_getter.cc",
-    "browser/web_test/web_test_url_request_context_getter.h",
     "common/power_monitor_test_impl.cc",
     "common/power_monitor_test_impl.h",
     "common/shell_content_client.cc",
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn
index a7b88a4..bf80a1a5 100644
--- a/content/shell/android/BUILD.gn
+++ b/content/shell/android/BUILD.gn
@@ -170,12 +170,12 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//components/crash/android:java",
+    "//components/crash/content/app:chrome_crashpad_handler_named_as_so",
     "//content/public/android:content_java",
     "//content/public/test/android:android_test_message_pump_support_java",
     "//media/capture/video/android:capture_java",
     "//net/android:net_java",
     "//services/shape_detection:shape_detection_java",
-    "//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so",
     "//third_party/mesa_headers",
     "//ui/android:ui_java",
   ]
@@ -183,7 +183,7 @@
   android_manifest = content_shell_manifest
   android_manifest_dep = ":content_shell_manifest"
   shared_libraries = [ ":libcontent_shell_content_view" ]
-  loadable_modules = [ "$root_out_dir/libcrashpad_handler.so" ]
+  loadable_modules = [ "$root_out_dir/libchrome_crashpad_handler.so" ]
   command_line_flags_file = "content-shell-command-line"
 }
 
diff --git a/content/shell/browser/shell_browser_context.cc b/content/shell/browser/shell_browser_context.cc
index 4fbce0e..4477ce8 100644
--- a/content/shell/browser/shell_browser_context.cc
+++ b/content/shell/browser/shell_browser_context.cc
@@ -81,12 +81,6 @@
       BrowserThread::IO, FROM_HERE, resource_context_.release());
   }
   ShutdownStoragePartitions();
-  if (url_request_getter_) {
-    base::PostTaskWithTraits(
-        FROM_HERE, {BrowserThread::IO},
-        base::BindOnce(&ShellURLRequestContextGetter::NotifyContextShuttingDown,
-                       url_request_getter_));
-  }
 }
 
 void ShellBrowserContext::InitWhileIOAllowed() {
@@ -169,31 +163,6 @@
   return download_manager_delegate_.get();
 }
 
-ShellURLRequestContextGetter*
-ShellBrowserContext::CreateURLRequestContextGetter(
-    ProtocolHandlerMap* protocol_handlers,
-    URLRequestInterceptorScopedVector request_interceptors) {
-  return new ShellURLRequestContextGetter(
-      ignore_certificate_errors_, off_the_record_, GetPath(),
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
-      protocol_handlers, std::move(request_interceptors));
-}
-
-net::URLRequestContextGetter* ShellBrowserContext::CreateRequestContext(
-    ProtocolHandlerMap* protocol_handlers,
-    URLRequestInterceptorScopedVector request_interceptors) {
-  DCHECK(!url_request_getter_.get());
-  url_request_getter_ = CreateURLRequestContextGetter(
-      protocol_handlers, std::move(request_interceptors));
-  return url_request_getter_.get();
-}
-
-net::URLRequestContextGetter*
-    ShellBrowserContext::CreateMediaRequestContext()  {
-  DCHECK(url_request_getter_.get());
-  return url_request_getter_.get();
-}
-
 ResourceContext* ShellBrowserContext::GetResourceContext()  {
   return resource_context_.get();
 }
diff --git a/content/shell/browser/shell_browser_context.h b/content/shell/browser/shell_browser_context.h
index b43d818..df8c0bc 100644
--- a/content/shell/browser/shell_browser_context.h
+++ b/content/shell/browser/shell_browser_context.h
@@ -14,8 +14,6 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/resource_context.h"
-#include "content/shell/browser/shell_url_request_context_getter.h"
-#include "net/url_request/url_request_job_factory.h"
 
 class SimpleFactoryKey;
 
@@ -60,10 +58,6 @@
   BackgroundFetchDelegate* GetBackgroundFetchDelegate() override;
   BackgroundSyncController* GetBackgroundSyncController() override;
   BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate() override;
-  net::URLRequestContextGetter* CreateRequestContext(
-      ProtocolHandlerMap* protocol_handlers,
-      URLRequestInterceptorScopedVector request_interceptors) override;
-  net::URLRequestContextGetter* CreateMediaRequestContext() override;
 
  protected:
   // Contains URLRequestContextGetter required for resource loading.
@@ -76,19 +70,6 @@
     DISALLOW_COPY_AND_ASSIGN(ShellResourceContext);
   };
 
-  ShellURLRequestContextGetter* url_request_context_getter() {
-    return url_request_getter_.get();
-  }
-
-  // Used by ShellBrowserContext to initiate and set different types of
-  // URLRequestContextGetter.
-  virtual ShellURLRequestContextGetter* CreateURLRequestContextGetter(
-      ProtocolHandlerMap* protocol_handlers,
-      URLRequestInterceptorScopedVector request_interceptors);
-  void set_url_request_context_getter(ShellURLRequestContextGetter* getter) {
-    url_request_getter_ = getter;
-  }
-
   bool ignore_certificate_errors() const { return ignore_certificate_errors_; }
 
   std::unique_ptr<ShellResourceContext> resource_context_;
@@ -106,9 +87,6 @@
   bool off_the_record_;
   base::FilePath path_;
   BrowserPluginGuestManager* guest_manager_;
-  scoped_refptr<ShellURLRequestContextGetter> url_request_getter_;
-  std::map<base::FilePath, scoped_refptr<ShellURLRequestContextGetter>>
-      isolated_url_request_getters_;
   std::unique_ptr<SimpleFactoryKey> key_;
 
   DISALLOW_COPY_AND_ASSIGN(ShellBrowserContext);
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc
index de6c8746..37a5be30 100644
--- a/content/shell/browser/shell_content_browser_client.cc
+++ b/content/shell/browser/shell_content_browser_client.cc
@@ -37,7 +37,6 @@
 #include "content/shell/browser/shell_browser_main_parts.h"
 #include "content/shell/browser/shell_devtools_manager_delegate.h"
 #include "content/shell/browser/shell_quota_permission_context.h"
-#include "content/shell/browser/shell_url_request_context_getter.h"
 #include "content/shell/browser/shell_web_contents_view_delegate_creator.h"
 #include "content/shell/common/power_monitor_test.mojom.h"
 #include "content/shell/common/shell_switches.h"
@@ -357,7 +356,7 @@
 }
 
 std::string ShellContentBrowserClient::GetAcceptLangs(BrowserContext* context) {
-  return ShellURLRequestContextGetter::GetAcceptLanguages();
+  return "en-us,en";
 }
 
 std::string ShellContentBrowserClient::GetDefaultDownloadName() {
diff --git a/content/shell/browser/shell_network_delegate.cc b/content/shell/browser/shell_network_delegate.cc
deleted file mode 100644
index ba8bd5df..0000000
--- a/content/shell/browser/shell_network_delegate.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/shell/browser/shell_network_delegate.h"
-
-#include "base/command_line.h"
-#include "base/strings/string_util.h"
-#include "content/public/common/content_switches.h"
-#include "net/base/net_errors.h"
-#include "net/base/static_cookie_policy.h"
-#include "net/url_request/url_request.h"
-
-namespace content {
-
-namespace {
-bool g_block_third_party_cookies = false;
-bool g_cancel_requests_with_referrer_policy_violation = false;
-}
-
-ShellNetworkDelegate::ShellNetworkDelegate() {
-}
-
-ShellNetworkDelegate::~ShellNetworkDelegate() {
-}
-
-void ShellNetworkDelegate::SetBlockThirdPartyCookies(bool block) {
-  g_block_third_party_cookies = block;
-}
-
-void ShellNetworkDelegate::SetCancelURLRequestWithPolicyViolatingReferrerHeader(
-    bool cancel) {
-  g_cancel_requests_with_referrer_policy_violation = cancel;
-}
-
-bool ShellNetworkDelegate::OnCanGetCookies(const net::URLRequest& request,
-                                           const net::CookieList& cookie_list,
-                                           bool allowed_from_caller) {
-  net::StaticCookiePolicy::Type policy_type = g_block_third_party_cookies ?
-      net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
-      net::StaticCookiePolicy::ALLOW_ALL_COOKIES;
-  net::StaticCookiePolicy policy(policy_type);
-  int rv = policy.CanAccessCookies(request.url(), request.site_for_cookies());
-  return allowed_from_caller && rv == net::OK;
-}
-
-bool ShellNetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
-                                          const net::CanonicalCookie& cookie,
-                                          net::CookieOptions* options,
-                                          bool allowed_from_caller) {
-  net::StaticCookiePolicy::Type policy_type = g_block_third_party_cookies ?
-      net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
-      net::StaticCookiePolicy::ALLOW_ALL_COOKIES;
-  net::StaticCookiePolicy policy(policy_type);
-  int rv = policy.CanAccessCookies(request.url(), request.site_for_cookies());
-  return allowed_from_caller && rv == net::OK;
-}
-
-bool ShellNetworkDelegate::OnCanAccessFile(
-    const net::URLRequest& request,
-    const base::FilePath& original_path,
-    const base::FilePath& absolute_path) const {
-  return true;
-}
-
-bool ShellNetworkDelegate::OnCancelURLRequestWithPolicyViolatingReferrerHeader(
-    const net::URLRequest& request,
-    const GURL& target_url,
-    const GURL& referrer_url) const {
-  return g_cancel_requests_with_referrer_policy_violation;
-}
-
-}  // namespace content
diff --git a/content/shell/browser/shell_network_delegate.h b/content/shell/browser/shell_network_delegate.h
deleted file mode 100644
index 3e33d9af..0000000
--- a/content/shell/browser/shell_network_delegate.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_SHELL_BROWSER_SHELL_NETWORK_DELEGATE_H_
-#define CONTENT_SHELL_BROWSER_SHELL_NETWORK_DELEGATE_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "net/base/network_delegate_impl.h"
-
-namespace content {
-
-class ShellNetworkDelegate : public net::NetworkDelegateImpl {
- public:
-  ShellNetworkDelegate();
-  ~ShellNetworkDelegate() override;
-
-  static void SetBlockThirdPartyCookies(bool block);
-  static void SetCancelURLRequestWithPolicyViolatingReferrerHeader(bool cancel);
-
- private:
-  // net::NetworkDelegate implementation.
-  bool OnCanGetCookies(const net::URLRequest& request,
-                       const net::CookieList& cookie_list,
-                       bool allowed_from_caller) override;
-  bool OnCanSetCookie(const net::URLRequest& request,
-                      const net::CanonicalCookie& cookie,
-                      net::CookieOptions* options,
-                      bool allowed_from_caller) override;
-  bool OnCanAccessFile(const net::URLRequest& request,
-                       const base::FilePath& original_path,
-                       const base::FilePath& absolute_path) const override;
-  bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(
-      const net::URLRequest& request,
-      const GURL& target_url,
-      const GURL& referrer_url) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(ShellNetworkDelegate);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_SHELL_BROWSER_SHELL_NETWORK_DELEGATE_H_
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc
deleted file mode 100644
index fc37df047..0000000
--- a/content/shell/browser/shell_url_request_context_getter.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/shell/browser/shell_url_request_context_getter.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/task/post_task.h"
-#include "build/build_config.h"
-#include "components/network_session_configurator/browser/network_session_configurator.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/cookie_store_factory.h"
-#include "content/public/common/content_switches.h"
-#include "content/shell/browser/shell_content_browser_client.h"
-#include "content/shell/browser/shell_network_delegate.h"
-#include "content/shell/common/shell_content_client.h"
-#include "content/shell/common/shell_switches.h"
-#include "content/shell/common/web_test/web_test_switches.h"
-#include "net/cert/cert_verifier.h"
-#include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/ct_policy_status.h"
-#include "net/cookies/cookie_store.h"
-#include "net/http/http_network_session.h"
-#include "net/net_buildflags.h"
-#include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_resolution_service.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_builder.h"
-#include "services/network/public/cpp/features.h"
-#include "services/network/public/cpp/network_switches.h"
-#include "url/url_constants.h"
-
-#if BUILDFLAG(ENABLE_REPORTING)
-#include "net/reporting/reporting_policy.h"
-#include "net/reporting/reporting_service.h"
-#endif  // BUILDFLAG(ENABLE_REPORTING)
-
-namespace content {
-namespace {
-
-net::CertVerifier* g_cert_verifier_for_testing = nullptr;
-
-// A CertVerifier that forwards all requests to
-// |g_cert_verifier_for_profile_io_data_testing|. This is used to allow
-// BrowserContexts to have their own std::unique_ptr<net::CertVerifier> while
-// forwarding calls to the shared verifier.
-class WrappedCertVerifierForTesting : public net::CertVerifier {
- public:
-  WrappedCertVerifierForTesting() = default;
-  ~WrappedCertVerifierForTesting() override = default;
-
-  // CertVerifier implementation
-  int Verify(const RequestParams& params,
-             net::CertVerifyResult* verify_result,
-             net::CompletionOnceCallback callback,
-             std::unique_ptr<Request>* out_req,
-             const net::NetLogWithSource& net_log) override {
-    verify_result->Reset();
-    if (!g_cert_verifier_for_testing)
-      return net::ERR_FAILED;
-    return g_cert_verifier_for_testing->Verify(
-        params, verify_result, std::move(callback), out_req, net_log);
-  }
-  void SetConfig(const Config& config) override {
-    if (!g_cert_verifier_for_testing)
-      return;
-    return g_cert_verifier_for_testing->SetConfig(config);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WrappedCertVerifierForTesting);
-};
-}  // namespace
-
-ShellURLRequestContextGetter::ShellURLRequestContextGetter(
-    bool ignore_certificate_errors,
-    bool off_the_record,
-    const base::FilePath& base_path,
-    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
-    ProtocolHandlerMap* protocol_handlers,
-    URLRequestInterceptorScopedVector request_interceptors)
-    : ignore_certificate_errors_(ignore_certificate_errors),
-      off_the_record_(off_the_record),
-      shut_down_(false),
-      base_path_(base_path),
-      io_task_runner_(std::move(io_task_runner)),
-      request_interceptors_(std::move(request_interceptors)) {
-  // Must first be created on the UI thread.
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  std::swap(protocol_handlers_, *protocol_handlers);
-
-  // We must create the proxy config service on the UI loop on Linux because it
-  // must synchronously run on the glib message loop. This will be passed to
-  // the URLRequestContextStorage on the IO thread in GetURLRequestContext().
-  proxy_config_service_ = GetProxyConfigService();
-}
-
-ShellURLRequestContextGetter::~ShellURLRequestContextGetter() {}
-
-void ShellURLRequestContextGetter::NotifyContextShuttingDown() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  shut_down_ = true;
-  URLRequestContextGetter::NotifyContextShuttingDown();
-  url_request_context_ = nullptr;  // deletes it
-}
-
-std::string ShellURLRequestContextGetter::GetAcceptLanguages() {
-  return "en-us,en";
-}
-
-void ShellURLRequestContextGetter::SetCertVerifierForTesting(
-    net::CertVerifier* cert_verifier) {
-  g_cert_verifier_for_testing = cert_verifier;
-}
-
-std::unique_ptr<net::NetworkDelegate>
-ShellURLRequestContextGetter::CreateNetworkDelegate() {
-  return std::make_unique<ShellNetworkDelegate>();
-}
-
-std::unique_ptr<net::CertVerifier>
-ShellURLRequestContextGetter::GetCertVerifier() {
-  if (g_cert_verifier_for_testing)
-    return std::make_unique<WrappedCertVerifierForTesting>();
-  return net::CertVerifier::CreateDefault(/*cert_net_fetcher=*/nullptr);
-}
-
-std::unique_ptr<net::ProxyConfigService>
-ShellURLRequestContextGetter::GetProxyConfigService() {
-  return net::ProxyResolutionService::CreateSystemProxyConfigService(
-      io_task_runner_);
-}
-
-std::unique_ptr<net::ProxyResolutionService>
-ShellURLRequestContextGetter::GetProxyService() {
-  // TODO(jam): use v8 if possible, look at chrome code.
-  return nullptr;
-}
-
-net::URLRequestContext* ShellURLRequestContextGetter::GetURLRequestContext() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  if (shut_down_)
-    return nullptr;
-
-  if (!url_request_context_) {
-    const base::CommandLine& command_line =
-        *base::CommandLine::ForCurrentProcess();
-
-    net::URLRequestContextBuilder builder;
-    net::NetLog* net_log = nullptr;
-    builder.set_network_delegate(CreateNetworkDelegate());
-    std::unique_ptr<net::CookieStore> cookie_store =
-        CreateCookieStore(CookieStoreConfig(), net_log);
-    builder.SetCookieStore(std::move(cookie_store));
-    builder.set_accept_language(GetAcceptLanguages());
-    builder.set_user_agent(GetShellUserAgent());
-
-    builder.SetCertVerifier(GetCertVerifier());
-
-    std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service =
-        GetProxyService();
-    if (proxy_resolution_service) {
-      builder.set_proxy_resolution_service(std::move(proxy_resolution_service));
-    } else {
-      builder.set_proxy_config_service(std::move(proxy_config_service_));
-    }
-
-    net::URLRequestContextBuilder::HttpCacheParams cache_params;
-    if (!off_the_record_) {
-      cache_params.path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
-      cache_params.type = net::URLRequestContextBuilder::HttpCacheParams::DISK;
-    } else {
-      cache_params.type =
-          net::URLRequestContextBuilder::HttpCacheParams::IN_MEMORY;
-    }
-    builder.EnableHttpCache(cache_params);
-
-    net::HttpNetworkSession::Params network_session_params;
-    network_session_configurator::ParseCommandLineAndFieldTrials(
-        command_line, false /* is_quic_force_disabled */,
-        GetShellUserAgent() /* quic_user_agent_id */, &network_session_params);
-    network_session_params.ignore_certificate_errors =
-        ignore_certificate_errors_;
-    builder.set_http_network_session_params(network_session_params);
-
-    builder.set_host_mapping_rules(command_line.GetSwitchValueASCII(
-        network::switches::kHostResolverRules));
-
-    // Keep ProtocolHandlers added in sync with
-    // ShellContentBrowserClient::IsHandledURL().
-
-    for (auto& protocol_handler : protocol_handlers_) {
-      builder.SetProtocolHandler(protocol_handler.first,
-                                 std::move(protocol_handler.second));
-    }
-    protocol_handlers_.clear();
-
-    builder.set_data_enabled(true);
-
-#if !BUILDFLAG(DISABLE_FILE_SUPPORT)
-    builder.set_file_enabled(true);
-#endif
-
-    // Set up interceptors in the reverse order.
-    builder.SetInterceptors(std::move(request_interceptors_));
-
-#if BUILDFLAG(ENABLE_REPORTING)
-    if (base::FeatureList::IsEnabled(network::features::kReporting)) {
-      std::unique_ptr<net::ReportingPolicy> reporting_policy =
-          net::ReportingPolicy::Create();
-      if (command_line.HasSwitch(switches::kRunWebTests))
-        reporting_policy->delivery_interval =
-            kReportingDeliveryIntervalTimeForWebTests;
-      builder.set_reporting_policy(std::move(reporting_policy));
-    }
-
-    builder.set_network_error_logging_enabled(
-        base::FeatureList::IsEnabled(network::features::kNetworkErrorLogging));
-#endif  // BUILDFLAG(ENABLE_REPORTING)
-
-    builder.set_enable_brotli(true);
-
-    url_request_context_ = builder.Build();
-  }
-
-  return url_request_context_.get();
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-    ShellURLRequestContextGetter::GetNetworkTaskRunner() const {
-  return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
-}
-
-}  // namespace content
diff --git a/content/shell/browser/shell_url_request_context_getter.h b/content/shell/browser/shell_url_request_context_getter.h
deleted file mode 100644
index eec78ad..0000000
--- a/content/shell/browser/shell_url_request_context_getter.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_SHELL_BROWSER_SHELL_URL_REQUEST_CONTEXT_GETTER_H_
-#define CONTENT_SHELL_BROWSER_SHELL_URL_REQUEST_CONTEXT_GETTER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_interceptor.h"
-#include "net/url_request/url_request_job_factory.h"
-
-namespace net {
-class CertVerifier;
-class NetworkDelegate;
-class ProxyConfigService;
-class ProxyResolutionService;
-class URLRequestContext;
-}
-
-namespace content {
-
-class ShellURLRequestContextGetter : public net::URLRequestContextGetter {
- public:
-  ShellURLRequestContextGetter(
-      bool ignore_certificate_errors,
-      bool off_the_record,
-      const base::FilePath& base_path,
-      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
-      ProtocolHandlerMap* protocol_handlers,
-      URLRequestInterceptorScopedVector request_interceptors);
-
-  // net::URLRequestContextGetter implementation.
-  net::URLRequestContext* GetURLRequestContext() override;
-  scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
-      const override;
-
-  void NotifyContextShuttingDown();
-
-  static std::string GetAcceptLanguages();
-
-  // Sets a global CertVerifier to use when initializing all BrowserContexts.
-  static void SetCertVerifierForTesting(net::CertVerifier* cert_verifier);
-
- protected:
-  ~ShellURLRequestContextGetter() override;
-
-  // Used by subclasses to create their own implementation of NetworkDelegate
-  // and net::ProxyResolutionService.
-  virtual std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate();
-  virtual std::unique_ptr<net::CertVerifier> GetCertVerifier();
-  // GetProxyConfigService() and GetProxyService() are mutually exclusive.
-  // if the subclass returns something in GetProxyService(), the return
-  // ProxyConfigService will not be used. Called on the UI thread, unlike other
-  // virtual methods.
-  virtual std::unique_ptr<net::ProxyConfigService> GetProxyConfigService();
-  // If this returns nullptr, the URLRequestContextBuilder will create the
-  // service.
-  virtual std::unique_ptr<net::ProxyResolutionService> GetProxyService();
-
- private:
-  bool ignore_certificate_errors_;
-  bool off_the_record_;
-  bool shut_down_;
-  base::FilePath base_path_;
-  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
-  std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
-  std::unique_ptr<net::URLRequestContext> url_request_context_;
-  ProtocolHandlerMap protocol_handlers_;
-  URLRequestInterceptorScopedVector request_interceptors_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShellURLRequestContextGetter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_SHELL_BROWSER_SHELL_URL_REQUEST_CONTEXT_GETTER_H_
diff --git a/content/shell/browser/web_test/blink_test_controller.cc b/content/shell/browser/web_test/blink_test_controller.cc
index 75e70f2..b2ee3b5 100644
--- a/content/shell/browser/web_test/blink_test_controller.cc
+++ b/content/shell/browser/web_test/blink_test_controller.cc
@@ -61,7 +61,6 @@
 #include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_content_browser_client.h"
 #include "content/shell/browser/shell_devtools_frontend.h"
-#include "content/shell/browser/shell_network_delegate.h"
 #include "content/shell/browser/web_test/devtools_protocol_test_bindings.h"
 #include "content/shell/browser/web_test/fake_bluetooth_chooser.h"
 #include "content/shell/browser/web_test/test_info_extractor.h"
@@ -1362,17 +1361,11 @@
 }
 
 void BlinkTestController::OnBlockThirdPartyCookies(bool block) {
-  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    ShellBrowserContext* browser_context =
-        ShellContentBrowserClient::Get()->browser_context();
-    browser_context->GetDefaultStoragePartition(browser_context)
-        ->GetCookieManagerForBrowserProcess()
-        ->BlockThirdPartyCookies(block);
-  } else {
-    base::PostTaskWithTraits(
-        FROM_HERE, {BrowserThread::IO},
-        base::BindOnce(ShellNetworkDelegate::SetBlockThirdPartyCookies, block));
-  }
+  ShellBrowserContext* browser_context =
+      ShellContentBrowserClient::Get()->browser_context();
+  browser_context->GetDefaultStoragePartition(browser_context)
+      ->GetCookieManagerForBrowserProcess()
+      ->BlockThirdPartyCookies(block);
 }
 
 mojom::WebTestControlAssociatedPtr& BlinkTestController::GetWebTestControlPtr(
diff --git a/content/shell/browser/web_test/web_test_browser_context.cc b/content/shell/browser/web_test/web_test_browser_context.cc
index 05ad83f..4b3f4d5 100644
--- a/content/shell/browser/web_test/web_test_browser_context.cc
+++ b/content/shell/browser/web_test/web_test_browser_context.cc
@@ -16,13 +16,11 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/push_messaging_service.h"
 #include "content/public/browser/resource_context.h"
-#include "content/shell/browser/shell_url_request_context_getter.h"
 #include "content/shell/browser/web_test/web_test_background_fetch_delegate.h"
 #include "content/shell/browser/web_test/web_test_content_index_provider.h"
 #include "content/shell/browser/web_test/web_test_download_manager_delegate.h"
 #include "content/shell/browser/web_test/web_test_permission_manager.h"
 #include "content/shell/browser/web_test/web_test_push_messaging_service.h"
-#include "content/shell/browser/web_test/web_test_url_request_context_getter.h"
 #include "content/test/mock_background_sync_controller.h"
 #include "services/device/public/cpp/test/scoped_geolocation_overrider.h"
 
@@ -48,16 +46,6 @@
   BrowserContext::NotifyWillBeDestroyed(this);
 }
 
-ShellURLRequestContextGetter*
-WebTestBrowserContext::CreateURLRequestContextGetter(
-    ProtocolHandlerMap* protocol_handlers,
-    URLRequestInterceptorScopedVector request_interceptors) {
-  return new WebTestURLRequestContextGetter(
-      ignore_certificate_errors(), IsOffTheRecord(), GetPath(),
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
-      protocol_handlers, std::move(request_interceptors));
-}
-
 DownloadManagerDelegate* WebTestBrowserContext::GetDownloadManagerDelegate() {
   if (!download_manager_delegate_) {
     download_manager_delegate_.reset(new WebTestDownloadManagerDelegate());
diff --git a/content/shell/browser/web_test/web_test_browser_context.h b/content/shell/browser/web_test/web_test_browser_context.h
index 45bf4e0..054c2360 100644
--- a/content/shell/browser/web_test/web_test_browser_context.h
+++ b/content/shell/browser/web_test/web_test_browser_context.h
@@ -39,11 +39,6 @@
 
   WebTestPermissionManager* GetWebTestPermissionManager();
 
- protected:
-  ShellURLRequestContextGetter* CreateURLRequestContextGetter(
-      ProtocolHandlerMap* protocol_handlers,
-      URLRequestInterceptorScopedVector request_interceptors) override;
-
  private:
   std::unique_ptr<WebTestPushMessagingService> push_messaging_service_;
   std::unique_ptr<PermissionControllerDelegate> permission_manager_;
diff --git a/content/shell/browser/web_test/web_test_message_filter.cc b/content/shell/browser/web_test/web_test_message_filter.cc
index 9fb4f8d..463c3b0 100644
--- a/content/shell/browser/web_test/web_test_message_filter.cc
+++ b/content/shell/browser/web_test/web_test_message_filter.cc
@@ -18,7 +18,6 @@
 #include "content/public/test/web_test_support.h"
 #include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_content_browser_client.h"
-#include "content/shell/browser/shell_network_delegate.h"
 #include "content/shell/browser/web_test/blink_test_controller.h"
 #include "content/shell/browser/web_test/web_test_browser_context.h"
 #include "content/shell/browser/web_test/web_test_content_browser_client.h"
diff --git a/content/shell/browser/web_test/web_test_url_request_context_getter.cc b/content/shell/browser/web_test/web_test_url_request_context_getter.cc
deleted file mode 100644
index f97bdf9..0000000
--- a/content/shell/browser/web_test/web_test_url_request_context_getter.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/shell/browser/web_test/web_test_url_request_context_getter.h"
-
-#include <utility>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/shell/browser/shell_network_delegate.h"
-#include "content/shell/common/web_test/web_test_switches.h"
-#include "net/cert/cert_verifier.h"
-#include "net/proxy_resolution/proxy_resolution_service.h"
-#include "services/network/ignore_errors_cert_verifier.h"
-
-namespace content {
-
-WebTestURLRequestContextGetter::WebTestURLRequestContextGetter(
-    bool ignore_certificate_errors,
-    bool off_the_record,
-    const base::FilePath& base_path,
-    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
-    ProtocolHandlerMap* protocol_handlers,
-    URLRequestInterceptorScopedVector request_interceptors)
-    : ShellURLRequestContextGetter(ignore_certificate_errors,
-                                   off_the_record,
-                                   base_path,
-                                   std::move(io_task_runner),
-                                   protocol_handlers,
-                                   std::move(request_interceptors)) {
-  // Must first be created on the UI thread.
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-WebTestURLRequestContextGetter::~WebTestURLRequestContextGetter() {}
-
-std::unique_ptr<net::NetworkDelegate>
-WebTestURLRequestContextGetter::CreateNetworkDelegate() {
-  ShellNetworkDelegate::SetBlockThirdPartyCookies(false);
-  return base::WrapUnique(new ShellNetworkDelegate);
-}
-
-std::unique_ptr<net::CertVerifier>
-WebTestURLRequestContextGetter::GetCertVerifier() {
-  return network::IgnoreErrorsCertVerifier::MaybeWrapCertVerifier(
-      *base::CommandLine::ForCurrentProcess(), switches::kRunWebTests,
-      net::CertVerifier::CreateDefault(/*cert_net_fetcher=*/nullptr));
-}
-
-std::unique_ptr<net::ProxyConfigService>
-WebTestURLRequestContextGetter::GetProxyConfigService() {
-  return nullptr;
-}
-
-std::unique_ptr<net::ProxyResolutionService>
-WebTestURLRequestContextGetter::GetProxyService() {
-  return net::ProxyResolutionService::CreateDirect();
-}
-
-}  // namespace content
diff --git a/content/shell/browser/web_test/web_test_url_request_context_getter.h b/content/shell/browser/web_test/web_test_url_request_context_getter.h
deleted file mode 100644
index 825742a..0000000
--- a/content/shell/browser/web_test/web_test_url_request_context_getter.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_URL_REQUEST_CONTEXT_GETTER_H_
-#define CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_URL_REQUEST_CONTEXT_GETTER_H_
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/shell/browser/shell_url_request_context_getter.h"
-#include "net/url_request/url_request_job_factory.h"
-
-namespace net {
-class NetworkDelegate;
-class ProxyConfigService;
-}  // namespace net
-
-namespace content {
-
-class WebTestURLRequestContextGetter : public ShellURLRequestContextGetter {
- public:
-  WebTestURLRequestContextGetter(
-      bool ignore_certificate_errors,
-      bool off_the_record,
-      const base::FilePath& base_path,
-      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
-      ProtocolHandlerMap* protocol_handlers,
-      URLRequestInterceptorScopedVector request_interceptors);
-
- protected:
-  ~WebTestURLRequestContextGetter() override;
-
-  // ShellURLRequestContextGetter implementation.
-  std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate() override;
-  std::unique_ptr<net::CertVerifier> GetCertVerifier() override;
-  std::unique_ptr<net::ProxyConfigService> GetProxyConfigService() override;
-  std::unique_ptr<net::ProxyResolutionService> GetProxyService() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebTestURLRequestContextGetter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_URL_REQUEST_CONTEXT_GETTER_H_
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 16dc51b..be952ae 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1647,7 +1647,6 @@
     "../browser/loader/navigation_url_loader_impl_unittest.cc",
     "../browser/loader/navigation_url_loader_unittest.cc",
     "../browser/loader/source_stream_to_data_pipe_unittest.cc",
-    "../browser/loader/upload_data_stream_builder_unittest.cc",
     "../browser/manifest/manifest_icon_downloader_unittest.cc",
     "../browser/media/audible_metrics_unittest.cc",
     "../browser/media/audio_input_stream_broker_unittest.cc",
@@ -1830,7 +1829,6 @@
     "../browser/webrtc/webrtc_internals_message_handler_unittest.cc",
     "../browser/webrtc/webrtc_internals_unittest.cc",
     "../browser/websockets/websocket_manager_unittest.cc",
-    "../browser/webui/url_data_manager_backend_unittest.cc",
     "../browser/webui/web_ui_data_source_unittest.cc",
     "../browser/webui/web_ui_message_handler_unittest.cc",
     "../browser/worker_host/mock_shared_worker.cc",
@@ -2237,10 +2235,7 @@
       "../renderer/java/gin_java_bridge_value_converter_unittest.cc",
       "../renderer/media/android/stream_texture_wrapper_impl_unittest.cc",
     ]
-    sources -= [
-      "../browser/tracing/tracing_ui_unittest.cc",
-      "../browser/webui/url_data_manager_backend_unittest.cc",
-    ]
+    sources -= [ "../browser/tracing/tracing_ui_unittest.cc" ]
 
     deps += [
       "//base:base_java_unittest_support",
diff --git a/content/test/test_navigation_url_loader.cc b/content/test/test_navigation_url_loader.cc
index 9e80f1a..1b6bae7d 100644
--- a/content/test/test_navigation_url_loader.cc
+++ b/content/test/test_navigation_url_loader.cc
@@ -25,9 +25,7 @@
     NavigationURLLoaderDelegate* delegate)
     : request_info_(std::move(request_info)),
       delegate_(delegate),
-      redirect_count_(0),
-      response_proceeded_(false) {
-}
+      redirect_count_(0) {}
 
 void TestNavigationURLLoader::FollowRedirect(
     const std::vector<std::string>& removed_headers,
@@ -36,10 +34,6 @@
   redirect_count_++;
 }
 
-void TestNavigationURLLoader::ProceedWithResponse() {
-  response_proceeded_ = true;
-}
-
 void TestNavigationURLLoader::SimulateServerRedirect(const GURL& redirect_url) {
   net::RedirectInfo redirect_info;
   redirect_info.status_code = 302;
diff --git a/content/test/test_navigation_url_loader.h b/content/test/test_navigation_url_loader.h
index fbd0810..b4f50741 100644
--- a/content/test/test_navigation_url_loader.h
+++ b/content/test/test_navigation_url_loader.h
@@ -37,7 +37,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       PreviewsState new_previews_state) override;
-  void ProceedWithResponse() override;
 
   NavigationRequestInfo* request_info() const { return request_info_.get(); }
 
@@ -55,15 +54,12 @@
 
   int redirect_count() { return redirect_count_; }
 
-  bool response_proceeded() { return response_proceeded_; }
-
  private:
   ~TestNavigationURLLoader() override;
 
   std::unique_ptr<NavigationRequestInfo> request_info_;
   NavigationURLLoaderDelegate* delegate_;
   int redirect_count_;
-  bool response_proceeded_;
 };
 
 }  // namespace content
diff --git a/content/utility/utility_thread_impl.cc b/content/utility/utility_thread_impl.cc
index 885e896..7d1232c 100644
--- a/content/utility/utility_thread_impl.cc
+++ b/content/utility/utility_thread_impl.cc
@@ -12,6 +12,7 @@
 #include "base/command_line.h"
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
 #include "base/sequenced_task_runner.h"
 #include "build/build_config.h"
 #include "content/child/child_process.h"
@@ -60,6 +61,11 @@
                                    main_thread_task_runner_.get());
   }
 
+  static base::Optional<ServiceBinderImpl>& GetInstanceStorage() {
+    static base::NoDestructor<base::Optional<ServiceBinderImpl>> storage;
+    return *storage;
+  }
+
  private:
   void OnServicePipeClosed(mojo::SimpleWatcher* which,
                            MojoResult result,
@@ -74,11 +80,18 @@
     // No more services running in this process.
     if (service_pipe_watchers_.empty()) {
       main_thread_task_runner_->PostTask(
-          FROM_HERE,
-          base::BindOnce([] { UtilityThread::Get()->ReleaseProcess(); }));
+          FROM_HERE, base::BindOnce(&ServiceBinderImpl::ShutDownProcess));
     }
   }
 
+  static void ShutDownProcess() {
+    // Ensure that shutdown also tears down |this|. This is necessary to support
+    // multiple tests in the same test suite using out-of-process services via
+    // the InProcessUtilityThreadHelper.
+    GetInstanceStorage().reset();
+    UtilityThread::Get()->ReleaseProcess();
+  }
+
   const scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
 
   // These trap signals on any (unowned) primordial service pipes. We don't
@@ -92,10 +105,13 @@
 };
 
 ChildThreadImpl::Options::ServiceBinder GetServiceBinder() {
-  static base::NoDestructor<ServiceBinderImpl> binder(
-      base::ThreadTaskRunnerHandle::Get());
+  auto& storage = ServiceBinderImpl::GetInstanceStorage();
+  // NOTE: This may already be initialized from a previous call if we're in
+  // single-process mode.
+  if (!storage)
+    storage.emplace(base::ThreadTaskRunnerHandle::Get());
   return base::BindRepeating(&ServiceBinderImpl::BindServiceInterface,
-                             base::Unretained(binder.get()));
+                             base::Unretained(&storage.value()));
 }
 
 }  // namespace
diff --git a/docs/android_native_libraries.md b/docs/android_native_libraries.md
index 6fe246c9..ce221d1 100644
--- a/docs/android_native_libraries.md
+++ b/docs/android_native_libraries.md
@@ -19,9 +19,9 @@
    dump is requested (e.g. after a crash), a Crashpad handler process is started
    to produce a dump.
  * Chrome and ChromeModern (Android J through M):
-   * libcrashpad_handler.so is a standalone executable containing all of the
-     crash dumping code. It is stored compressed and extracted automatically by
-     the system, allowing it to be directly executed to produce a crash dump.
+   * libchrome_crashpad_handler.so is a standalone executable containing all of
+     the crash dumping code. It is stored compressed and extracted automatically
+     by the system, allowing it to be directly executed to produce a crash dump.
  * Monochrome (N through P) and SystemWebView (L through P):
     * All of the Crashpad code is linked into the package's main native library
       (e.g. libmonochrome.so). When a dump is requested, /system/bin/app_process
diff --git a/docs/clang_code_coverage_wrapper.md b/docs/clang_code_coverage_wrapper.md
index 70a6408c..b95260c0 100644
--- a/docs/clang_code_coverage_wrapper.md
+++ b/docs/clang_code_coverage_wrapper.md
@@ -75,5 +75,5 @@
 [//build/toolchain/clang_code_coverage_wrapper.py]: ../build/toolchain/clang_code_coverage_wrapper.py
 [code_coverage.md]: testing/code_coverage.md
 [//tools/code_coverage/coverage.py]: ../tools/code_coverage/coverage.py
-[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
+[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Infra%3ETest%3ECodeCoverage
 [code-coverage group]: https://groups.google.com/a/chromium.org/forum/#!forum/code-coverage
diff --git a/docs/testing/code_coverage.md b/docs/testing/code_coverage.md
index 5fd5290..f872e65 100644
--- a/docs/testing/code_coverage.md
+++ b/docs/testing/code_coverage.md
@@ -256,8 +256,7 @@
 Usually this is not a critical issue, but in general we tend not to have any
 warnings. Please check the list of [known issues], and if there is a similar
 bug, leave a comment with the command you run, the output you get, and Chromium
-revision you use. Otherwise, please [file a new issue] providing the same
-information.
+revision you use. Otherwise, please [file a bug] providing the same information.
 
 ### How do crashes affect code coverage?
 
@@ -348,11 +347,10 @@
 [clang roll]: https://crbug.com/841908
 [dead code example]: https://chromium.googlesource.com/chromium/src/+/ac6e09311fcc7e734be2ef21a9ccbbe04c4c4706
 [documentation]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
-[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
-[file a new issue]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
+[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Infra%3ETest%3ECodeCoverage
 [gerrit coverage view]: images/code_coverage_annotations.png
 [guide]: http://llvm.org/docs/CommandGuide/llvm-cov.html
 [How do crashes affect code coverage?]: #how-do-crashes-affect-code-coverage
-[known issues]: https://bugs.chromium.org/p/chromium/issues/list?q=component:Tools%3ECodeCoverage
+[known issues]: https://bugs.chromium.org/p/chromium/issues/list?q=component:Infra%3ETest%3ECodeCoverage
 [tools link]: https://storage.googleapis.com/chromium-browser-clang-staging/
 [test suite]: https://cs.chromium.org/chromium/src/tools/code_coverage/test_suite.txt
diff --git a/docs/testing/code_coverage_in_gerrit.md b/docs/testing/code_coverage_in_gerrit.md
index 1954104..a9b7f7f 100644
--- a/docs/testing/code_coverage_in_gerrit.md
+++ b/docs/testing/code_coverage_in_gerrit.md
@@ -54,7 +54,7 @@
 [choose_tryjobs]: images/code_coverage_choose_tryjobs.png
 [linux_coverage_rel]: images/code_coverage_linux_coverage_rel.png
 [code_coverage_annotations]: images/code_coverage_annotations.png
-[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Tools%3ECodeCoverage
+[file a bug]: https://bugs.chromium.org/p/chromium/issues/entry?components=Infra%3ETest%3ECodeCoverage
 [code-coverage group]: https://groups.google.com/a/chromium.org/forum/#!forum/code-coverage
 [code_coverage.md]: code_coverage.md
 [clang_code_coverage_wrapper]: clang_code_coverage_wrapper.md
diff --git a/docs/vscode.md b/docs/vscode.md
index 0dff926..e3f23a6e 100644
--- a/docs/vscode.md
+++ b/docs/vscode.md
@@ -84,7 +84,7 @@
   // If you would rather just increase the size of the font:
   //"terminal.integrated.fontSize": 15
   // If you would rather decrease the size of the font:
-  //"terminal.integrated.fontSize": 15
+  //"terminal.integrated.fontSize": 13
 }
 ```
 
@@ -266,6 +266,19 @@
 There are some useful snippets provided in
 [//tools/vscode/cpp.json5](/tools/vscode/cpp.json5).
 
+You can either install them in your user profile (path may vary depending on the
+platform):
+```
+$ cp tools/vscode/cpp.json5 ~/.config/Code/User/snippets/cpp.json
+```
+
+Or install them as project snippets after installing the [Project
+Snippets](https://marketplace.visualstudio.com/items?itemName=rebornix.project-snippets)
+extension:
+```
+$ cp tools/vscode/cpp.json5 .vscode/snippets/cpp.json
+```
+
 ### Tips
 
 #### The `out` folder
diff --git a/extensions/browser/api/alarms/alarms_api.h b/extensions/browser/api/alarms/alarms_api.h
index 20f5cd5..8b2a406 100644
--- a/extensions/browser/api/alarms/alarms_api.h
+++ b/extensions/browser/api/alarms/alarms_api.h
@@ -17,7 +17,7 @@
 struct Alarm;
 using AlarmList = std::vector<std::unique_ptr<Alarm>>;
 
-class AlarmsCreateFunction : public UIThreadExtensionFunction {
+class AlarmsCreateFunction : public ExtensionFunction {
  public:
   AlarmsCreateFunction();
   // Use |clock| instead of the default clock. Does not take ownership
@@ -27,7 +27,7 @@
  protected:
   ~AlarmsCreateFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
   DECLARE_EXTENSION_FUNCTION("alarms.create", ALARMS_CREATE)
  private:
@@ -36,11 +36,11 @@
   base::Clock* const clock_;
 };
 
-class AlarmsGetFunction : public UIThreadExtensionFunction {
+class AlarmsGetFunction : public ExtensionFunction {
  protected:
   ~AlarmsGetFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -48,11 +48,11 @@
   DECLARE_EXTENSION_FUNCTION("alarms.get", ALARMS_GET)
 };
 
-class AlarmsGetAllFunction : public UIThreadExtensionFunction {
+class AlarmsGetAllFunction : public ExtensionFunction {
  protected:
   ~AlarmsGetAllFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -60,11 +60,11 @@
   DECLARE_EXTENSION_FUNCTION("alarms.getAll", ALARMS_GETALL)
 };
 
-class AlarmsClearFunction : public UIThreadExtensionFunction {
+class AlarmsClearFunction : public ExtensionFunction {
  protected:
   ~AlarmsClearFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -72,11 +72,11 @@
   DECLARE_EXTENSION_FUNCTION("alarms.clear", ALARMS_CLEAR)
 };
 
-class AlarmsClearAllFunction : public UIThreadExtensionFunction {
+class AlarmsClearAllFunction : public ExtensionFunction {
  protected:
   ~AlarmsClearAllFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
diff --git a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc
index 354fe40..33a1d48 100644
--- a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc
+++ b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc
@@ -124,7 +124,7 @@
 
 bool AppCurrentWindowInternalExtensionFunction::PreRunValidation(
     std::string* error) {
-  if (!UIThreadExtensionFunction::PreRunValidation(error))
+  if (!ExtensionFunction::PreRunValidation(error))
     return false;
 
   AppWindowRegistry* registry = AppWindowRegistry::Get(browser_context());
diff --git a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.h b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.h
index 72ddd534..4f69356 100644
--- a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.h
+++ b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.h
@@ -11,8 +11,7 @@
 
 class AppWindow;
 
-class AppCurrentWindowInternalExtensionFunction
-    : public UIThreadExtensionFunction {
+class AppCurrentWindowInternalExtensionFunction : public ExtensionFunction {
  protected:
   ~AppCurrentWindowInternalExtensionFunction() override {}
 
diff --git a/extensions/browser/api/app_window/app_window_api.h b/extensions/browser/api/app_window/app_window_api.h
index e8511581..2a34681 100644
--- a/extensions/browser/api/app_window/app_window_api.h
+++ b/extensions/browser/api/app_window/app_window_api.h
@@ -16,7 +16,7 @@
 }
 }
 
-class AppWindowCreateFunction : public UIThreadExtensionFunction {
+class AppWindowCreateFunction : public ExtensionFunction {
  public:
   AppWindowCreateFunction();
   DECLARE_EXTENSION_FUNCTION("app.window.create", APP_WINDOW_CREATE)
diff --git a/extensions/browser/api/async_api_function.cc b/extensions/browser/api/async_api_function.cc
index efc60cbff17..0d98aa8 100644
--- a/extensions/browser/api/async_api_function.cc
+++ b/extensions/browser/api/async_api_function.cc
@@ -81,7 +81,7 @@
 }
 
 const std::string& AsyncApiFunction::GetError() const {
-  return error_.empty() ? UIThreadExtensionFunction::GetError() : error_;
+  return error_.empty() ? ExtensionFunction::GetError() : error_;
 }
 
 void AsyncApiFunction::WorkOnWorkThread() {
@@ -102,7 +102,7 @@
     response = results_ ? ErrorWithArguments(std::move(results_), error_)
                         : Error(error_);
   }
-  UIThreadExtensionFunction::Respond(std::move(response));
+  ExtensionFunction::Respond(std::move(response));
 }
 
 }  // namespace extensions
diff --git a/extensions/browser/api/async_api_function.h b/extensions/browser/api/async_api_function.h
index 222de6f..8007991 100644
--- a/extensions/browser/api/async_api_function.h
+++ b/extensions/browser/api/async_api_function.h
@@ -13,7 +13,7 @@
 
 // AsyncApiFunction provides convenient thread management for APIs that need to
 // do essentially all their work on a thread other than the UI thread.
-class AsyncApiFunction : public UIThreadExtensionFunction {
+class AsyncApiFunction : public ExtensionFunction {
  protected:
   AsyncApiFunction();
   ~AsyncApiFunction() override;
@@ -36,7 +36,7 @@
   // Respond. Guaranteed to happen on UI thread.
   virtual bool Respond() = 0;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() final;
 
  protected:
diff --git a/extensions/browser/api/audio/audio_api.h b/extensions/browser/api/audio/audio_api.h
index fe07004..7316913 100644
--- a/extensions/browser/api/audio/audio_api.h
+++ b/extensions/browser/api/audio/audio_api.h
@@ -56,7 +56,7 @@
   DISALLOW_COPY_AND_ASSIGN(AudioAPI);
 };
 
-class AudioGetInfoFunction : public UIThreadExtensionFunction {
+class AudioGetInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("audio.getInfo", AUDIO_GETINFO)
 
@@ -65,7 +65,7 @@
   ResponseAction Run() override;
 };
 
-class AudioGetDevicesFunction : public UIThreadExtensionFunction {
+class AudioGetDevicesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("audio.getDevices", AUDIO_GETDEVICES)
 
@@ -74,7 +74,7 @@
   ResponseAction Run() override;
 };
 
-class AudioSetActiveDevicesFunction : public UIThreadExtensionFunction {
+class AudioSetActiveDevicesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("audio.setActiveDevices", AUDIO_SETACTIVEDEVICES)
 
@@ -83,7 +83,7 @@
   ResponseAction Run() override;
 };
 
-class AudioSetPropertiesFunction : public UIThreadExtensionFunction {
+class AudioSetPropertiesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("audio.setProperties", AUDIO_SETPROPERTIES)
 
@@ -92,7 +92,7 @@
   ResponseAction Run() override;
 };
 
-class AudioSetMuteFunction : public UIThreadExtensionFunction {
+class AudioSetMuteFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("audio.setMute", AUDIO_SETMUTE)
 
@@ -101,7 +101,7 @@
   ResponseAction Run() override;
 };
 
-class AudioGetMuteFunction : public UIThreadExtensionFunction {
+class AudioGetMuteFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("audio.getMute", AUDIO_GETMUTE)
 
diff --git a/extensions/browser/api/automation_internal/automation_internal_api.h b/extensions/browser/api/automation_internal/automation_internal_api.h
index 45c6dda..afb052f 100644
--- a/extensions/browser/api/automation_internal/automation_internal_api.h
+++ b/extensions/browser/api/automation_internal/automation_internal_api.h
@@ -29,7 +29,7 @@
 namespace extensions {
 
 // Implementation of the chrome.automation API.
-class AutomationInternalEnableTabFunction : public UIThreadExtensionFunction {
+class AutomationInternalEnableTabFunction : public ExtensionFunction {
   DECLARE_EXTENSION_FUNCTION("automationInternal.enableTab",
                              AUTOMATIONINTERNAL_ENABLETAB)
  protected:
@@ -38,8 +38,7 @@
   ExtensionFunction::ResponseAction Run() override;
 };
 
-class AutomationInternalPerformActionFunction
-    : public UIThreadExtensionFunction {
+class AutomationInternalPerformActionFunction : public ExtensionFunction {
   DECLARE_EXTENSION_FUNCTION("automationInternal.performAction",
                              AUTOMATIONINTERNAL_PERFORMACTION)
  protected:
@@ -54,7 +53,7 @@
       ui::AXActionData* data);
 };
 
-class AutomationInternalEnableFrameFunction : public UIThreadExtensionFunction {
+class AutomationInternalEnableFrameFunction : public ExtensionFunction {
   DECLARE_EXTENSION_FUNCTION("automationInternal.enableFrame",
                              AUTOMATIONINTERNAL_ENABLEFRAME)
 
@@ -64,8 +63,7 @@
   ExtensionFunction::ResponseAction Run() override;
 };
 
-class AutomationInternalEnableDesktopFunction
-    : public UIThreadExtensionFunction {
+class AutomationInternalEnableDesktopFunction : public ExtensionFunction {
   DECLARE_EXTENSION_FUNCTION("automationInternal.enableDesktop",
                              AUTOMATIONINTERNAL_ENABLEDESKTOP)
  protected:
@@ -74,8 +72,7 @@
   ResponseAction Run() override;
 };
 
-class AutomationInternalQuerySelectorFunction
-    : public UIThreadExtensionFunction {
+class AutomationInternalQuerySelectorFunction : public ExtensionFunction {
   DECLARE_EXTENSION_FUNCTION("automationInternal.querySelector",
                              AUTOMATIONINTERNAL_QUERYSELECTOR)
 
diff --git a/extensions/browser/api/automation_internal/automation_internal_api_delegate.h b/extensions/browser/api/automation_internal/automation_internal_api_delegate.h
index 485aaea..11668fc 100644
--- a/extensions/browser/api/automation_internal/automation_internal_api_delegate.h
+++ b/extensions/browser/api/automation_internal/automation_internal_api_delegate.h
@@ -10,7 +10,7 @@
 #include "extensions/common/extension_id.h"
 #include "extensions/common/extension_messages.h"
 
-class UIThreadExtensionFunction;
+class ExtensionFunction;
 
 namespace extensions {
 class AutomationInternalApiDelegate;
@@ -52,7 +52,7 @@
   virtual int GetTabId(content::WebContents* contents) = 0;
   // Retrieves the active web contents.
   virtual content::WebContents* GetActiveWebContents(
-      UIThreadExtensionFunction* function) = 0;
+      ExtensionFunction* function) = 0;
   // Starts managing automation nodes on the desktop.
   virtual void EnableDesktop() = 0;
   // Gets the ax tree id for the nodes being managed for the desktop.
diff --git a/extensions/browser/api/bluetooth/bluetooth_extension_function.h b/extensions/browser/api/bluetooth/bluetooth_extension_function.h
index 56e5063..2c49cba 100644
--- a/extensions/browser/api/bluetooth/bluetooth_extension_function.h
+++ b/extensions/browser/api/bluetooth/bluetooth_extension_function.h
@@ -22,7 +22,7 @@
 // Base class for bluetooth extension functions. This class initializes
 // bluetooth adapter and calls (on the UI thread) DoWork() implemented by
 // individual bluetooth extension functions.
-class BluetoothExtensionFunction : public UIThreadExtensionFunction {
+class BluetoothExtensionFunction : public ExtensionFunction {
  public:
   BluetoothExtensionFunction();
 
diff --git a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_api.h b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_api.h
index 346fd0cf..ed00b5f 100644
--- a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_api.h
+++ b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_api.h
@@ -90,7 +90,7 @@
 // Base class for bluetoothLowEnergy API functions. This class handles some of
 // the common logic involved in all API functions, such as checking for
 // platform support and returning the correct error.
-class BluetoothLowEnergyExtensionFunction : public UIThreadExtensionFunction {
+class BluetoothLowEnergyExtensionFunction : public ExtensionFunction {
  public:
   BluetoothLowEnergyExtensionFunction();
 
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
index 742c5711..9a97947d 100644
--- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
+++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
@@ -124,7 +124,7 @@
 BluetoothSocketAsyncApiFunction::~BluetoothSocketAsyncApiFunction() {}
 
 bool BluetoothSocketAsyncApiFunction::PreRunValidation(std::string* error) {
-  if (!UIThreadExtensionFunction::PreRunValidation(error))
+  if (!ExtensionFunction::PreRunValidation(error))
     return false;
 
   if (!BluetoothManifestData::CheckSocketPermitted(extension())) {
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h
index 5d9a4af..cee888cd 100644
--- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h
+++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h
@@ -39,14 +39,14 @@
 // thread while providing methods to manage resources of that class. This
 // follows the pattern of AsyncApiFunction, but does not derive from it,
 // because BluetoothApiSocket methods must be called on the UI Thread.
-class BluetoothSocketAsyncApiFunction : public UIThreadExtensionFunction {
+class BluetoothSocketAsyncApiFunction : public ExtensionFunction {
  public:
   BluetoothSocketAsyncApiFunction();
 
  protected:
   ~BluetoothSocketAsyncApiFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   bool PreRunValidation(std::string* error) override;
 
   content::BrowserThread::ID work_thread_id() const;
@@ -84,7 +84,7 @@
  protected:
   ~BluetoothSocketUpdateFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -102,7 +102,7 @@
  protected:
   ~BluetoothSocketSetPausedFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -126,7 +126,7 @@
   virtual int socket_id() const = 0;
   virtual const std::string& uuid() const = 0;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
   bool PreRunValidation(std::string* error) override;
 
@@ -206,7 +206,7 @@
  protected:
   ~BluetoothSocketAbstractConnectFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   bool PreRunValidation(std::string* error) override;
   ResponseAction Run() override;
 
@@ -251,7 +251,7 @@
  protected:
   ~BluetoothSocketDisconnectFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -269,7 +269,7 @@
  protected:
   ~BluetoothSocketCloseFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -285,7 +285,7 @@
  protected:
   ~BluetoothSocketSendFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -309,7 +309,7 @@
  protected:
   ~BluetoothSocketGetInfoFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -327,7 +327,7 @@
  protected:
   ~BluetoothSocketGetSocketsFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
diff --git a/extensions/browser/api/cec_private/cec_private_api.cc b/extensions/browser/api/cec_private/cec_private_api.cc
index 936a789..6fb6172 100644
--- a/extensions/browser/api/cec_private/cec_private_api.cc
+++ b/extensions/browser/api/cec_private/cec_private_api.cc
@@ -58,7 +58,7 @@
 
 // Only allow calls from kiosk mode extensions.
 bool CecPrivateFunction::PreRunValidation(std::string* error) {
-  if (!UIThreadExtensionFunction::PreRunValidation(error))
+  if (!ExtensionFunction::PreRunValidation(error))
     return false;
 
   if (KioskModeInfo::IsKioskEnabled(extension()))
diff --git a/extensions/browser/api/cec_private/cec_private_api.h b/extensions/browser/api/cec_private/cec_private_api.h
index 6a2029b5..a1c8fae 100644
--- a/extensions/browser/api/cec_private/cec_private_api.h
+++ b/extensions/browser/api/cec_private/cec_private_api.h
@@ -14,7 +14,7 @@
 namespace extensions {
 namespace api {
 
-class CecPrivateFunction : public UIThreadExtensionFunction {
+class CecPrivateFunction : public ExtensionFunction {
  public:
   CecPrivateFunction();
 
diff --git a/extensions/browser/api/clipboard/clipboard_api.h b/extensions/browser/api/clipboard/clipboard_api.h
index ecd6a69..67b2726 100644
--- a/extensions/browser/api/clipboard/clipboard_api.h
+++ b/extensions/browser/api/clipboard/clipboard_api.h
@@ -37,7 +37,7 @@
   content::BrowserContext* const browser_context_;
 };
 
-class ClipboardSetImageDataFunction : public UIThreadExtensionFunction {
+class ClipboardSetImageDataFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("clipboard.setImageData", CLIPBOARD_SETIMAGEDATA)
 
diff --git a/extensions/browser/api/declarative/declarative_api.h b/extensions/browser/api/declarative/declarative_api.h
index ceaa341..e50aa5d 100644
--- a/extensions/browser/api/declarative/declarative_api.h
+++ b/extensions/browser/api/declarative/declarative_api.h
@@ -29,7 +29,7 @@
 }  // namespace events
 }  // namespace api
 
-class RulesFunction : public UIThreadExtensionFunction {
+class RulesFunction : public ExtensionFunction {
  public:
   RulesFunction();
 
diff --git a/extensions/browser/api/declarative_net_request/declarative_net_request_api.cc b/extensions/browser/api/declarative_net_request/declarative_net_request_api.cc
index cdac88d..6d26296 100644
--- a/extensions/browser/api/declarative_net_request/declarative_net_request_api.cc
+++ b/extensions/browser/api/declarative_net_request/declarative_net_request_api.cc
@@ -106,7 +106,7 @@
 
 bool DeclarativeNetRequestUpdateAllowedPagesFunction::PreRunValidation(
     std::string* error) {
-  return UIThreadExtensionFunction::PreRunValidation(error) &&
+  return ExtensionFunction::PreRunValidation(error) &&
          HasRegisteredRuleset(browser_context(), extension_id(), error);
 }
 
@@ -155,7 +155,7 @@
 
 bool DeclarativeNetRequestGetAllowedPagesFunction::PreRunValidation(
     std::string* error) {
-  return UIThreadExtensionFunction::PreRunValidation(error) &&
+  return ExtensionFunction::PreRunValidation(error) &&
          HasRegisteredRuleset(browser_context(), extension_id(), error);
 }
 
@@ -193,7 +193,7 @@
 
 bool DeclarativeNetRequestUpdateDynamicRulesFunction::PreRunValidation(
     std::string* error) {
-  return UIThreadExtensionFunction::PreRunValidation(error) &&
+  return ExtensionFunction::PreRunValidation(error) &&
          HasRegisteredRuleset(browser_context(), extension_id(), error);
 }
 
@@ -260,7 +260,7 @@
 
 bool DeclarativeNetRequestGetDynamicRulesFunction::PreRunValidation(
     std::string* error) {
-  return UIThreadExtensionFunction::PreRunValidation(error) &&
+  return ExtensionFunction::PreRunValidation(error) &&
          HasRegisteredRuleset(browser_context(), extension_id(), error);
 }
 
diff --git a/extensions/browser/api/declarative_net_request/declarative_net_request_api.h b/extensions/browser/api/declarative_net_request/declarative_net_request_api.h
index c3b7f3c..5f5e3dc1 100644
--- a/extensions/browser/api/declarative_net_request/declarative_net_request_api.h
+++ b/extensions/browser/api/declarative_net_request/declarative_net_request_api.h
@@ -26,7 +26,7 @@
 
 // Helper base class to update the set of allowed pages.
 class DeclarativeNetRequestUpdateAllowedPagesFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  protected:
   enum class Action {
     ADD,     // Add allowed pages.
@@ -87,8 +87,7 @@
 
 // Implements the "declarativeNetRequest.getAllowedPages" extension
 // function.
-class DeclarativeNetRequestGetAllowedPagesFunction
-    : public UIThreadExtensionFunction {
+class DeclarativeNetRequestGetAllowedPagesFunction : public ExtensionFunction {
  public:
   DeclarativeNetRequestGetAllowedPagesFunction();
   DECLARE_EXTENSION_FUNCTION("declarativeNetRequest.getAllowedPages",
@@ -106,7 +105,7 @@
 };
 
 class DeclarativeNetRequestUpdateDynamicRulesFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  protected:
   DeclarativeNetRequestUpdateDynamicRulesFunction();
   ~DeclarativeNetRequestUpdateDynamicRulesFunction() override;
@@ -157,8 +156,7 @@
   DISALLOW_COPY_AND_ASSIGN(DeclarativeNetRequestRemoveDynamicRulesFunction);
 };
 
-class DeclarativeNetRequestGetDynamicRulesFunction
-    : public UIThreadExtensionFunction {
+class DeclarativeNetRequestGetDynamicRulesFunction : public ExtensionFunction {
  public:
   DeclarativeNetRequestGetDynamicRulesFunction();
   DECLARE_EXTENSION_FUNCTION("declarativeNetRequest.getDynamicRules",
@@ -178,8 +176,7 @@
   DISALLOW_COPY_AND_ASSIGN(DeclarativeNetRequestGetDynamicRulesFunction);
 };
 
-class DeclarativeNetRequestGetMatchedRulesFunction
-    : public UIThreadExtensionFunction {
+class DeclarativeNetRequestGetMatchedRulesFunction : public ExtensionFunction {
  public:
   DeclarativeNetRequestGetMatchedRulesFunction();
   DECLARE_EXTENSION_FUNCTION("declarativeNetRequest.getMatchedRules",
@@ -196,7 +193,7 @@
 };
 
 class DeclarativeNetRequestSetActionCountAsBadgeTextFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DeclarativeNetRequestSetActionCountAsBadgeTextFunction();
   DECLARE_EXTENSION_FUNCTION("declarativeNetRequest.setActionCountAsBadgeText",
diff --git a/extensions/browser/api/diagnostics/diagnostics_api.h b/extensions/browser/api/diagnostics/diagnostics_api.h
index 9f45b96..d566dec 100644
--- a/extensions/browser/api/diagnostics/diagnostics_api.h
+++ b/extensions/browser/api/diagnostics/diagnostics_api.h
@@ -14,7 +14,7 @@
 
 namespace extensions {
 
-class DiagnosticsSendPacketFunction : public UIThreadExtensionFunction {
+class DiagnosticsSendPacketFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("diagnostics.sendPacket", DIAGNOSTICS_SENDPACKET)
 
@@ -23,7 +23,7 @@
  protected:
   ~DiagnosticsSendPacketFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
diff --git a/extensions/browser/api/display_source/display_source_api.h b/extensions/browser/api/display_source/display_source_api.h
index d36e630..1f0a34ce 100644
--- a/extensions/browser/api/display_source/display_source_api.h
+++ b/extensions/browser/api/display_source/display_source_api.h
@@ -11,8 +11,7 @@
 
 namespace extensions {
 
-class DisplaySourceGetAvailableSinksFunction
-    : public UIThreadExtensionFunction {
+class DisplaySourceGetAvailableSinksFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("displaySource.getAvailableSinks",
                              DISPLAYSOURCE_GETAVAILABLESINKS)
@@ -29,8 +28,7 @@
   DISALLOW_COPY_AND_ASSIGN(DisplaySourceGetAvailableSinksFunction);
 };
 
-class DisplaySourceRequestAuthenticationFunction
-    : public UIThreadExtensionFunction {
+class DisplaySourceRequestAuthenticationFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("displaySource.requestAuthentication",
                              DISPLAYSOURCE_REQUESTAUTHENTICATION)
diff --git a/extensions/browser/api/dns/dns_api.h b/extensions/browser/api/dns/dns_api.h
index 65e57334..2c63292b1 100644
--- a/extensions/browser/api/dns/dns_api.h
+++ b/extensions/browser/api/dns/dns_api.h
@@ -15,7 +15,7 @@
 
 namespace extensions {
 
-class DnsResolveFunction : public UIThreadExtensionFunction,
+class DnsResolveFunction : public ExtensionFunction,
                            public network::ResolveHostClientBase {
  public:
   DECLARE_EXTENSION_FUNCTION("dns.resolve", DNS_RESOLVE)
@@ -25,7 +25,7 @@
  protected:
   ~DnsResolveFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
diff --git a/extensions/browser/api/document_scan/document_scan_api.h b/extensions/browser/api/document_scan/document_scan_api.h
index b8ac8b7..ba490af 100644
--- a/extensions/browser/api/document_scan/document_scan_api.h
+++ b/extensions/browser/api/document_scan/document_scan_api.h
@@ -17,7 +17,7 @@
 namespace extensions {
 namespace api {
 
-class DocumentScanScanFunction : public UIThreadExtensionFunction {
+class DocumentScanScanFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("documentScan.scan", DOCUMENT_SCAN_SCAN)
   DocumentScanScanFunction();
@@ -25,7 +25,7 @@
  protected:
   ~DocumentScanScanFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
diff --git a/extensions/browser/api/execute_code_function.h b/extensions/browser/api/execute_code_function.h
index ceb911a..1971898 100644
--- a/extensions/browser/api/execute_code_function.h
+++ b/extensions/browser/api/execute_code_function.h
@@ -17,7 +17,7 @@
 // Base class for javascript code injection.
 // This is used by both chrome.webview.executeScript and
 // chrome.tabs.executeScript.
-class ExecuteCodeFunction : public UIThreadExtensionFunction {
+class ExecuteCodeFunction : public ExtensionFunction {
  public:
   ExecuteCodeFunction();
 
diff --git a/extensions/browser/api/feedback_private/feedback_private_api.h b/extensions/browser/api/feedback_private/feedback_private_api.h
index 9c526d4..af2d73f 100644
--- a/extensions/browser/api/feedback_private/feedback_private_api.h
+++ b/extensions/browser/api/feedback_private/feedback_private_api.h
@@ -68,7 +68,7 @@
 };
 
 // Feedback strings.
-class FeedbackPrivateGetStringsFunction : public UIThreadExtensionFunction {
+class FeedbackPrivateGetStringsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("feedbackPrivate.getStrings",
                              FEEDBACKPRIVATE_GETSTRINGS)
@@ -88,7 +88,7 @@
   static base::Closure* test_callback_;
 };
 
-class FeedbackPrivateGetUserEmailFunction : public UIThreadExtensionFunction {
+class FeedbackPrivateGetUserEmailFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("feedbackPrivate.getUserEmail",
                              FEEDBACKPRIVATE_GETUSEREMAIL)
@@ -98,8 +98,7 @@
   ResponseAction Run() override;
 };
 
-class FeedbackPrivateGetSystemInformationFunction
-    : public UIThreadExtensionFunction {
+class FeedbackPrivateGetSystemInformationFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("feedbackPrivate.getSystemInformation",
                              FEEDBACKPRIVATE_GETSYSTEMINFORMATION)
@@ -114,7 +113,7 @@
 
 // This function only reads from actual log sources on Chrome OS. On other
 // platforms, it just returns EmptyResponse().
-class FeedbackPrivateReadLogSourceFunction : public UIThreadExtensionFunction {
+class FeedbackPrivateReadLogSourceFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("feedbackPrivate.readLogSource",
                              FEEDBACKPRIVATE_READLOGSOURCE)
@@ -130,7 +129,7 @@
 #endif  // defined(OS_CHROMEOS)
 };
 
-class FeedbackPrivateSendFeedbackFunction : public UIThreadExtensionFunction {
+class FeedbackPrivateSendFeedbackFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("feedbackPrivate.sendFeedback",
                              FEEDBACKPRIVATE_SENDFEEDBACK)
@@ -146,8 +145,7 @@
   void OnCompleted(api::feedback_private::LandingPageType type, bool success);
 };
 
-class FeedbackPrivateLoginFeedbackCompleteFunction
-    : public UIThreadExtensionFunction {
+class FeedbackPrivateLoginFeedbackCompleteFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("feedbackPrivate.loginFeedbackComplete",
                              FEEDBACKPRIVATE_LOGINFEEDBACKCOMPLETE)
diff --git a/extensions/browser/api/file_system/file_system_api.h b/extensions/browser/api/file_system/file_system_api.h
index db62bab..7df036a 100644
--- a/extensions/browser/api/file_system/file_system_api.h
+++ b/extensions/browser/api/file_system/file_system_api.h
@@ -41,7 +41,7 @@
 
 }  // namespace file_system_api
 
-class FileSystemGetDisplayPathFunction : public UIThreadExtensionFunction {
+class FileSystemGetDisplayPathFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystem.getDisplayPath",
                              FILESYSTEM_GETDISPLAYPATH)
@@ -51,7 +51,7 @@
   ResponseAction Run() override;
 };
 
-class FileSystemEntryFunction : public UIThreadExtensionFunction {
+class FileSystemEntryFunction : public ExtensionFunction {
  protected:
   FileSystemEntryFunction();
 
@@ -104,7 +104,7 @@
   base::FilePath path_;
 };
 
-class FileSystemIsWritableEntryFunction : public UIThreadExtensionFunction {
+class FileSystemIsWritableEntryFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystem.isWritableEntry",
                              FILESYSTEM_ISWRITABLEENTRY)
@@ -180,7 +180,7 @@
   base::FilePath initial_path_;
 };
 
-class FileSystemRetainEntryFunction : public UIThreadExtensionFunction {
+class FileSystemRetainEntryFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystem.retainEntry", FILESYSTEM_RETAINENTRY)
 
@@ -198,7 +198,7 @@
                        std::unique_ptr<base::File::Info> file_info);
 };
 
-class FileSystemIsRestorableFunction : public UIThreadExtensionFunction {
+class FileSystemIsRestorableFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystem.isRestorable", FILESYSTEM_ISRESTORABLE)
 
@@ -218,7 +218,7 @@
 
 #if !defined(OS_CHROMEOS)
 // Stub for non Chrome OS operating systems.
-class FileSystemRequestFileSystemFunction : public UIThreadExtensionFunction {
+class FileSystemRequestFileSystemFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystem.requestFileSystem",
                              FILESYSTEM_REQUESTFILESYSTEM)
@@ -226,12 +226,12 @@
  protected:
   ~FileSystemRequestFileSystemFunction() override {}
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ExtensionFunction::ResponseAction Run() override;
 };
 
 // Stub for non Chrome OS operating systems.
-class FileSystemGetVolumeListFunction : public UIThreadExtensionFunction {
+class FileSystemGetVolumeListFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystem.getVolumeList",
                              FILESYSTEM_GETVOLUMELIST)
@@ -239,13 +239,13 @@
  protected:
   ~FileSystemGetVolumeListFunction() override {}
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ExtensionFunction::ResponseAction Run() override;
 };
 
 #else
 // Requests a file system for the specified volume id.
-class FileSystemRequestFileSystemFunction : public UIThreadExtensionFunction {
+class FileSystemRequestFileSystemFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystem.requestFileSystem",
                              FILESYSTEM_REQUESTFILESYSTEM)
@@ -254,7 +254,7 @@
  protected:
   ~FileSystemRequestFileSystemFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ExtensionFunction::ResponseAction Run() override;
 
  private:
@@ -265,7 +265,7 @@
 };
 
 // Requests a list of available volumes.
-class FileSystemGetVolumeListFunction : public UIThreadExtensionFunction {
+class FileSystemGetVolumeListFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileSystem.getVolumeList",
                              FILESYSTEM_GETVOLUMELIST)
@@ -274,7 +274,7 @@
  protected:
   ~FileSystemGetVolumeListFunction() override;
 
-  // UIThreadExtensionFunction overrides.
+  // ExtensionFunction overrides.
   ExtensionFunction::ResponseAction Run() override;
 
  private:
diff --git a/extensions/browser/api/file_system/file_system_delegate.h b/extensions/browser/api/file_system/file_system_delegate.h
index f8f63c9..4835a7e 100644
--- a/extensions/browser/api/file_system/file_system_delegate.h
+++ b/extensions/browser/api/file_system/file_system_delegate.h
@@ -16,7 +16,7 @@
 #include "extensions/common/api/file_system.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 
-class UIThreadExtensionFunction;
+class ExtensionFunction;
 
 namespace base {
 class FilePath;
@@ -53,7 +53,7 @@
   // Shows a dialog to prompt the user to select files/directories. Returns
   // false if the dialog cannot be shown, i.e. there is no valid WebContents.
   virtual bool ShowSelectFileDialog(
-      scoped_refptr<UIThreadExtensionFunction> extension_function,
+      scoped_refptr<ExtensionFunction> extension_function,
       ui::SelectFileDialog::Type type,
       const base::FilePath& default_path,
       const ui::SelectFileDialog::FileTypeInfo* file_types,
@@ -82,14 +82,13 @@
 
   // Grants or denies an extension's request for access to the named file
   // system. May prompt the user for consent.
-  virtual void RequestFileSystem(
-      content::BrowserContext* browser_context,
-      scoped_refptr<UIThreadExtensionFunction> requester,
-      const Extension& extension,
-      std::string volume_id,
-      bool writable,
-      const FileSystemCallback& success_callback,
-      const ErrorCallback& error_callback) = 0;
+  virtual void RequestFileSystem(content::BrowserContext* browser_context,
+                                 scoped_refptr<ExtensionFunction> requester,
+                                 const Extension& extension,
+                                 std::string volume_id,
+                                 bool writable,
+                                 const FileSystemCallback& success_callback,
+                                 const ErrorCallback& error_callback) = 0;
 
   // Immediately calls VolumeListCallback or ErrorCallback.
   virtual void GetVolumeList(content::BrowserContext* browser_context,
diff --git a/extensions/browser/api/guest_view/app_view/app_view_guest_internal_api.h b/extensions/browser/api/guest_view/app_view/app_view_guest_internal_api.h
index 04a5117..26d07b5 100644
--- a/extensions/browser/api/guest_view/app_view/app_view_guest_internal_api.h
+++ b/extensions/browser/api/guest_view/app_view/app_view_guest_internal_api.h
@@ -10,8 +10,7 @@
 
 namespace extensions {
 
-class AppViewGuestInternalAttachFrameFunction
-    : public UIThreadExtensionFunction {
+class AppViewGuestInternalAttachFrameFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("appViewGuestInternal.attachFrame",
                              APPVIEWINTERNAL_ATTACHFRAME)
@@ -25,8 +24,7 @@
   DISALLOW_COPY_AND_ASSIGN(AppViewGuestInternalAttachFrameFunction);
 };
 
-class AppViewGuestInternalDenyRequestFunction
-    : public UIThreadExtensionFunction {
+class AppViewGuestInternalDenyRequestFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("appViewGuestInternal.denyRequest",
                              APPVIEWINTERNAL_DENYREQUEST)
diff --git a/extensions/browser/api/guest_view/extension_view/extension_view_internal_api.h b/extensions/browser/api/guest_view/extension_view/extension_view_internal_api.h
index 86b3b932..6dbd6a6 100644
--- a/extensions/browser/api/guest_view/extension_view/extension_view_internal_api.h
+++ b/extensions/browser/api/guest_view/extension_view/extension_view_internal_api.h
@@ -14,8 +14,7 @@
 
 // An abstract base class for async extensionview APIs. It does a process ID
 // check in PreRunValidation.
-class ExtensionViewInternalExtensionFunction
-    : public UIThreadExtensionFunction {
+class ExtensionViewInternalExtensionFunction : public ExtensionFunction {
  public:
   ExtensionViewInternalExtensionFunction() {}
 
@@ -40,14 +39,14 @@
   ~ExtensionViewInternalLoadSrcFunction() override {}
 
  private:
-  // UIThreadExtensionFunction implementation.
+  // ExtensionFunction implementation.
   ResponseAction Run() final;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionViewInternalLoadSrcFunction);
 };
 
 // Parses a src and determines whether or not it is valid.
-class ExtensionViewInternalParseSrcFunction : public UIThreadExtensionFunction {
+class ExtensionViewInternalParseSrcFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("extensionViewInternal.parseSrc",
                              EXTENSIONVIEWINTERNAL_PARSESRC)
@@ -57,7 +56,7 @@
   ~ExtensionViewInternalParseSrcFunction() override {}
 
  private:
-  // UIThreadExtensionFunction implementation.
+  // ExtensionFunction implementation.
   ResponseAction Run() final;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionViewInternalParseSrcFunction);
diff --git a/extensions/browser/api/guest_view/guest_view_internal_api.h b/extensions/browser/api/guest_view/guest_view_internal_api.h
index 6d5b0e5..0f39562 100644
--- a/extensions/browser/api/guest_view/guest_view_internal_api.h
+++ b/extensions/browser/api/guest_view/guest_view_internal_api.h
@@ -10,7 +10,7 @@
 
 namespace extensions {
 
-class GuestViewInternalCreateGuestFunction : public UIThreadExtensionFunction {
+class GuestViewInternalCreateGuestFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("guestViewInternal.createGuest",
                              GUESTVIEWINTERNAL_CREATEGUEST)
@@ -19,7 +19,7 @@
  protected:
   ~GuestViewInternalCreateGuestFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() final;
 
  private:
@@ -27,7 +27,7 @@
   DISALLOW_COPY_AND_ASSIGN(GuestViewInternalCreateGuestFunction);
 };
 
-class GuestViewInternalDestroyGuestFunction : public UIThreadExtensionFunction {
+class GuestViewInternalDestroyGuestFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("guestViewInternal.destroyGuest",
                              GUESTVIEWINTERNAL_DESTROYGUEST)
@@ -36,7 +36,7 @@
  protected:
   ~GuestViewInternalDestroyGuestFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() final;
 
  private:
@@ -44,7 +44,7 @@
   DISALLOW_COPY_AND_ASSIGN(GuestViewInternalDestroyGuestFunction);
 };
 
-class GuestViewInternalSetSizeFunction : public UIThreadExtensionFunction {
+class GuestViewInternalSetSizeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("guestViewInternal.setSize",
                              GUESTVIEWINTERNAL_SETAUTOSIZE)
@@ -54,7 +54,7 @@
  protected:
   ~GuestViewInternalSetSizeFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() final;
 
  private:
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
index dac7336e..985ba0c 100644
--- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
+++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
@@ -266,7 +266,7 @@
 namespace extensions {
 
 bool WebViewInternalExtensionFunction::PreRunValidation(std::string* error) {
-  if (!UIThreadExtensionFunction::PreRunValidation(error))
+  if (!ExtensionFunction::PreRunValidation(error))
     return false;
 
   int instance_id = 0;
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h
index f5cba26e..4112588 100644
--- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h
+++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h
@@ -20,7 +20,7 @@
 // abuse by normal renderer processes.
 namespace extensions {
 
-class WebViewInternalExtensionFunction : public UIThreadExtensionFunction {
+class WebViewInternalExtensionFunction : public ExtensionFunction {
  public:
   WebViewInternalExtensionFunction() {}
 
@@ -42,7 +42,7 @@
  protected:
   ~WebViewInternalCaptureVisibleRegionFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -69,7 +69,7 @@
  protected:
   ~WebViewInternalNavigateFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalNavigateFunction);
@@ -143,8 +143,7 @@
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalInsertCSSFunction);
 };
 
-class WebViewInternalAddContentScriptsFunction
-    : public UIThreadExtensionFunction {
+class WebViewInternalAddContentScriptsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webViewInternal.addContentScripts",
                              WEBVIEWINTERNAL_ADDCONTENTSCRIPTS)
@@ -160,8 +159,7 @@
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalAddContentScriptsFunction);
 };
 
-class WebViewInternalRemoveContentScriptsFunction
-    : public UIThreadExtensionFunction {
+class WebViewInternalRemoveContentScriptsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("webViewInternal.removeContentScripts",
                              WEBVIEWINTERNAL_REMOVECONTENTSCRIPTS)
@@ -171,7 +169,7 @@
  protected:
   ~WebViewInternalRemoveContentScriptsFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -187,7 +185,7 @@
  protected:
   ~WebViewInternalSetNameFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalSetNameFunction);
@@ -204,7 +202,7 @@
  protected:
   ~WebViewInternalSetAllowTransparencyFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalSetAllowTransparencyFunction);
@@ -221,7 +219,7 @@
  protected:
   ~WebViewInternalSetAllowScalingFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalSetAllowScalingFunction);
@@ -236,7 +234,7 @@
  protected:
   ~WebViewInternalSetZoomFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalSetZoomFunction);
@@ -251,7 +249,7 @@
  protected:
   ~WebViewInternalGetZoomFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalGetZoomFunction);
@@ -268,7 +266,7 @@
  protected:
   ~WebViewInternalSetZoomModeFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalSetZoomModeFunction);
@@ -285,7 +283,7 @@
  protected:
   ~WebViewInternalGetZoomModeFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalGetZoomModeFunction);
@@ -304,7 +302,7 @@
   ~WebViewInternalFindFunction() override;
 
  private:
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalFindFunction);
@@ -321,7 +319,7 @@
  protected:
   ~WebViewInternalStopFindingFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalStopFindingFunction);
@@ -338,7 +336,7 @@
  protected:
   ~WebViewInternalLoadDataWithBaseUrlFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalLoadDataWithBaseUrlFunction);
@@ -353,7 +351,7 @@
  protected:
   ~WebViewInternalGoFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalGoFunction);
@@ -368,7 +366,7 @@
  protected:
   ~WebViewInternalReloadFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalReloadFunction);
@@ -385,7 +383,7 @@
  protected:
   ~WebViewInternalSetPermissionFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalSetPermissionFunction);
@@ -402,7 +400,7 @@
  protected:
   ~WebViewInternalOverrideUserAgentFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalOverrideUserAgentFunction);
@@ -417,7 +415,7 @@
  protected:
   ~WebViewInternalStopFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalStopFunction);
@@ -434,7 +432,7 @@
  protected:
   ~WebViewInternalSetAudioMutedFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalSetAudioMutedFunction);
@@ -451,7 +449,7 @@
  protected:
   ~WebViewInternalIsAudioMutedFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalIsAudioMutedFunction);
@@ -468,7 +466,7 @@
  protected:
   ~WebViewInternalGetAudioStateFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalGetAudioStateFunction);
@@ -485,7 +483,7 @@
  protected:
   ~WebViewInternalTerminateFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalTerminateFunction);
@@ -502,7 +500,7 @@
  protected:
   ~WebViewInternalClearDataFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -530,7 +528,7 @@
  protected:
   ~WebViewInternalSetSpatialNavigationEnabledFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalSetSpatialNavigationEnabledFunction);
@@ -547,7 +545,7 @@
  protected:
   ~WebViewInternalIsSpatialNavigationEnabledFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewInternalIsSpatialNavigationEnabledFunction);
diff --git a/extensions/browser/api/hid/hid_api.h b/extensions/browser/api/hid/hid_api.h
index 3605643..bd90473e 100644
--- a/extensions/browser/api/hid/hid_api.h
+++ b/extensions/browser/api/hid/hid_api.h
@@ -23,7 +23,7 @@
 
 class DevicePermissionsPrompt;
 
-class HidGetDevicesFunction : public UIThreadExtensionFunction {
+class HidGetDevicesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("hid.getDevices", HID_GETDEVICES)
 
@@ -40,7 +40,7 @@
   DISALLOW_COPY_AND_ASSIGN(HidGetDevicesFunction);
 };
 
-class HidGetUserSelectedDevicesFunction : public UIThreadExtensionFunction {
+class HidGetUserSelectedDevicesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("hid.getUserSelectedDevices",
                              HID_GETUSERSELECTEDDEVICES)
@@ -60,7 +60,7 @@
   DISALLOW_COPY_AND_ASSIGN(HidGetUserSelectedDevicesFunction);
 };
 
-class HidConnectFunction : public UIThreadExtensionFunction {
+class HidConnectFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("hid.connect", HID_CONNECT)
 
@@ -79,7 +79,7 @@
   DISALLOW_COPY_AND_ASSIGN(HidConnectFunction);
 };
 
-class HidDisconnectFunction : public UIThreadExtensionFunction {
+class HidDisconnectFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("hid.disconnect", HID_DISCONNECT)
 
@@ -96,7 +96,7 @@
 
 // Base class for extension functions that start some asynchronous work after
 // looking up a HidConnection.
-class HidConnectionIoFunction : public UIThreadExtensionFunction {
+class HidConnectionIoFunction : public ExtensionFunction {
  public:
   HidConnectionIoFunction();
 
diff --git a/extensions/browser/api/idle/idle_api.h b/extensions/browser/api/idle/idle_api.h
index 954cf4a..3562ddb 100644
--- a/extensions/browser/api/idle/idle_api.h
+++ b/extensions/browser/api/idle/idle_api.h
@@ -11,14 +11,14 @@
 namespace extensions {
 
 // Implementation of the chrome.idle.queryState API.
-class IdleQueryStateFunction : public UIThreadExtensionFunction {
+class IdleQueryStateFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("idle.queryState", IDLE_QUERYSTATE)
 
  protected:
   ~IdleQueryStateFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -26,7 +26,7 @@
 };
 
 // Implementation of the chrome.idle.setDetectionInterval API.
-class IdleSetDetectionIntervalFunction : public UIThreadExtensionFunction {
+class IdleSetDetectionIntervalFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("idle.setDetectionInterval",
                              IDLE_SETDETECTIONINTERVAL)
@@ -34,18 +34,18 @@
  protected:
   ~IdleSetDetectionIntervalFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
-class IdleGetAutoLockDelayFunction : public UIThreadExtensionFunction {
+class IdleGetAutoLockDelayFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("idle.getAutoLockDelay", IDLE_GETAUTOLOCKDELAY)
 
  protected:
   ~IdleGetAutoLockDelayFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 };
 
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_data_api.h b/extensions/browser/api/lock_screen_data/lock_screen_data_api.h
index 94d0a36..521905c 100644
--- a/extensions/browser/api/lock_screen_data/lock_screen_data_api.h
+++ b/extensions/browser/api/lock_screen_data/lock_screen_data_api.h
@@ -18,7 +18,7 @@
 class DataItem;
 }  // namespace lock_screen_data
 
-class LockScreenDataCreateFunction : public UIThreadExtensionFunction {
+class LockScreenDataCreateFunction : public ExtensionFunction {
  public:
   LockScreenDataCreateFunction();
 
@@ -34,7 +34,7 @@
   DISALLOW_COPY_AND_ASSIGN(LockScreenDataCreateFunction);
 };
 
-class LockScreenDataGetAllFunction : public UIThreadExtensionFunction {
+class LockScreenDataGetAllFunction : public ExtensionFunction {
  public:
   LockScreenDataGetAllFunction();
 
@@ -49,7 +49,7 @@
   DISALLOW_COPY_AND_ASSIGN(LockScreenDataGetAllFunction);
 };
 
-class LockScreenDataGetContentFunction : public UIThreadExtensionFunction {
+class LockScreenDataGetContentFunction : public ExtensionFunction {
  public:
   LockScreenDataGetContentFunction();
 
@@ -66,7 +66,7 @@
   DISALLOW_COPY_AND_ASSIGN(LockScreenDataGetContentFunction);
 };
 
-class LockScreenDataSetContentFunction : public UIThreadExtensionFunction {
+class LockScreenDataSetContentFunction : public ExtensionFunction {
  public:
   LockScreenDataSetContentFunction();
 
@@ -82,7 +82,7 @@
   DISALLOW_COPY_AND_ASSIGN(LockScreenDataSetContentFunction);
 };
 
-class LockScreenDataDeleteFunction : public UIThreadExtensionFunction {
+class LockScreenDataDeleteFunction : public ExtensionFunction {
  public:
   LockScreenDataDeleteFunction();
 
diff --git a/extensions/browser/api/management/management_api.h b/extensions/browser/api/management/management_api.h
index 9648478d..7b802e4 100644
--- a/extensions/browser/api/management/management_api.h
+++ b/extensions/browser/api/management/management_api.h
@@ -26,7 +26,7 @@
 class ExtensionRegistry;
 class RequirementsChecker;
 
-class ManagementGetAllFunction : public UIThreadExtensionFunction {
+class ManagementGetAllFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.getAll", MANAGEMENT_GETALL)
 
@@ -37,7 +37,7 @@
   ResponseAction Run() override;
 };
 
-class ManagementGetFunction : public UIThreadExtensionFunction {
+class ManagementGetFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.get", MANAGEMENT_GET)
 
@@ -48,7 +48,7 @@
   ResponseAction Run() override;
 };
 
-class ManagementGetSelfFunction : public UIThreadExtensionFunction {
+class ManagementGetSelfFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.getSelf", MANAGEMENT_GETSELF)
 
@@ -59,8 +59,7 @@
   ResponseAction Run() override;
 };
 
-class ManagementGetPermissionWarningsByIdFunction
-    : public UIThreadExtensionFunction {
+class ManagementGetPermissionWarningsByIdFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.getPermissionWarningsById",
                              MANAGEMENT_GETPERMISSIONWARNINGSBYID)
@@ -73,7 +72,7 @@
 };
 
 class ManagementGetPermissionWarningsByManifestFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.getPermissionWarningsByManifest",
                              MANAGEMENT_GETPERMISSIONWARNINGSBYMANIFEST)
@@ -89,7 +88,7 @@
   ResponseAction Run() override;
 };
 
-class ManagementLaunchAppFunction : public UIThreadExtensionFunction {
+class ManagementLaunchAppFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.launchApp", MANAGEMENT_LAUNCHAPP)
 
@@ -100,7 +99,7 @@
   ResponseAction Run() override;
 };
 
-class ManagementSetEnabledFunction : public UIThreadExtensionFunction {
+class ManagementSetEnabledFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.setEnabled", MANAGEMENT_SETENABLED)
 
@@ -124,7 +123,7 @@
   std::unique_ptr<RequirementsChecker> requirements_checker_;
 };
 
-class ManagementUninstallFunctionBase : public UIThreadExtensionFunction {
+class ManagementUninstallFunctionBase : public ExtensionFunction {
  public:
   ManagementUninstallFunctionBase();
 
@@ -169,7 +168,7 @@
   ResponseAction Run() override;
 };
 
-class ManagementCreateAppShortcutFunction : public UIThreadExtensionFunction {
+class ManagementCreateAppShortcutFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.createAppShortcut",
                              MANAGEMENT_CREATEAPPSHORTCUT)
@@ -186,7 +185,7 @@
   ResponseAction Run() override;
 };
 
-class ManagementSetLaunchTypeFunction : public UIThreadExtensionFunction {
+class ManagementSetLaunchTypeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.setLaunchType",
                              MANAGEMENT_SETLAUNCHTYPE)
@@ -197,7 +196,7 @@
   ResponseAction Run() override;
 };
 
-class ManagementGenerateAppForLinkFunction : public UIThreadExtensionFunction {
+class ManagementGenerateAppForLinkFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.generateAppForLink",
                              MANAGEMENT_GENERATEAPPFORLINK)
@@ -215,8 +214,7 @@
   std::unique_ptr<AppForLinkDelegate> app_for_link_delegate_;
 };
 
-class ManagementInstallReplacementWebAppFunction
-    : public UIThreadExtensionFunction {
+class ManagementInstallReplacementWebAppFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("management.installReplacementWebApp",
                              MANAGEMENT_INSTALLREPLACEMENTWEBAPP)
diff --git a/extensions/browser/api/media_perception_private/media_perception_private_api.h b/extensions/browser/api/media_perception_private/media_perception_private_api.h
index bb11a4a..a2bc396 100644
--- a/extensions/browser/api/media_perception_private/media_perception_private_api.h
+++ b/extensions/browser/api/media_perception_private/media_perception_private_api.h
@@ -11,8 +11,7 @@
 
 namespace extensions {
 
-class MediaPerceptionPrivateGetStateFunction
-    : public UIThreadExtensionFunction {
+class MediaPerceptionPrivateGetStateFunction : public ExtensionFunction {
  public:
   MediaPerceptionPrivateGetStateFunction();
   DECLARE_EXTENSION_FUNCTION("mediaPerceptionPrivate.getState",
@@ -29,8 +28,7 @@
   DISALLOW_COPY_AND_ASSIGN(MediaPerceptionPrivateGetStateFunction);
 };
 
-class MediaPerceptionPrivateSetStateFunction
-    : public UIThreadExtensionFunction {
+class MediaPerceptionPrivateSetStateFunction : public ExtensionFunction {
  public:
   MediaPerceptionPrivateSetStateFunction();
   DECLARE_EXTENSION_FUNCTION("mediaPerceptionPrivate.setState",
@@ -47,8 +45,7 @@
   DISALLOW_COPY_AND_ASSIGN(MediaPerceptionPrivateSetStateFunction);
 };
 
-class MediaPerceptionPrivateGetDiagnosticsFunction
-    : public UIThreadExtensionFunction {
+class MediaPerceptionPrivateGetDiagnosticsFunction : public ExtensionFunction {
  public:
   MediaPerceptionPrivateGetDiagnosticsFunction();
   DECLARE_EXTENSION_FUNCTION("mediaPerceptionPrivate.getDiagnostics",
@@ -67,7 +64,7 @@
 };
 
 class MediaPerceptionPrivateSetAnalyticsComponentFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   MediaPerceptionPrivateSetAnalyticsComponentFunction();
   DECLARE_EXTENSION_FUNCTION("mediaPerceptionPrivate.setAnalyticsComponent",
@@ -87,7 +84,7 @@
 };
 
 class MediaPerceptionPrivateSetComponentProcessStateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   MediaPerceptionPrivateSetComponentProcessStateFunction();
   DECLARE_EXTENSION_FUNCTION("mediaPerceptionPrivate.setComponentProcessState",
diff --git a/extensions/browser/api/metrics_private/metrics_private_api.h b/extensions/browser/api/metrics_private/metrics_private_api.h
index d0d51a7..afe87fa 100644
--- a/extensions/browser/api/metrics_private/metrics_private_api.h
+++ b/extensions/browser/api/metrics_private/metrics_private_api.h
@@ -15,7 +15,7 @@
 namespace extensions {
 
 class MetricsPrivateGetIsCrashReportingEnabledFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("metricsPrivate.getIsCrashReportingEnabled",
                              METRICSPRIVATE_GETISCRASHRECORDINGENABLED)
@@ -27,7 +27,7 @@
   ResponseAction Run() override;
 };
 
-class MetricsPrivateGetFieldTrialFunction : public UIThreadExtensionFunction {
+class MetricsPrivateGetFieldTrialFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("metricsPrivate.getFieldTrial",
                              METRICSPRIVATE_GETFIELDTRIAL)
@@ -39,8 +39,7 @@
   ResponseAction Run() override;
 };
 
-class MetricsPrivateGetVariationParamsFunction
-    : public UIThreadExtensionFunction {
+class MetricsPrivateGetVariationParamsFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("metricsPrivate.getVariationParams",
                              METRICSPRIVATE_GETVARIATIONPARAMS)
@@ -52,8 +51,7 @@
   ResponseAction Run() override;
 };
 
-class MetricsPrivateRecordUserActionFunction
-    : public UIThreadExtensionFunction {
+class MetricsPrivateRecordUserActionFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("metricsPrivate.recordUserAction",
                              METRICSPRIVATE_RECORDUSERACTION)
@@ -65,7 +63,7 @@
   ResponseAction Run() override;
 };
 
-class MetricsHistogramHelperFunction : public UIThreadExtensionFunction {
+class MetricsHistogramHelperFunction : public ExtensionFunction {
  protected:
   ~MetricsHistogramHelperFunction() override {}
   void RecordValue(const std::string& name,
diff --git a/extensions/browser/api/networking_config/networking_config_api.h b/extensions/browser/api/networking_config/networking_config_api.h
index 3ba9805..eb4c4eb 100644
--- a/extensions/browser/api/networking_config/networking_config_api.h
+++ b/extensions/browser/api/networking_config/networking_config_api.h
@@ -11,8 +11,7 @@
 
 namespace extensions {
 
-class NetworkingConfigSetNetworkFilterFunction
-    : public UIThreadExtensionFunction {
+class NetworkingConfigSetNetworkFilterFunction : public ExtensionFunction {
  public:
   NetworkingConfigSetNetworkFilterFunction();
 
@@ -30,8 +29,7 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkingConfigSetNetworkFilterFunction);
 };
 
-class NetworkingConfigFinishAuthenticationFunction
-    : public UIThreadExtensionFunction {
+class NetworkingConfigFinishAuthenticationFunction : public ExtensionFunction {
  public:
   NetworkingConfigFinishAuthenticationFunction();
 
diff --git a/extensions/browser/api/networking_private/networking_private_api.h b/extensions/browser/api/networking_private/networking_private_api.h
index 0d473c76..591c8ec 100644
--- a/extensions/browser/api/networking_private/networking_private_api.h
+++ b/extensions/browser/api/networking_private/networking_private_api.h
@@ -30,8 +30,7 @@
 }  // namespace networking_private
 
 // Implements the chrome.networkingPrivate.getProperties method.
-class NetworkingPrivateGetPropertiesFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateGetPropertiesFunction : public ExtensionFunction {
  public:
   NetworkingPrivateGetPropertiesFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getProperties",
@@ -51,8 +50,7 @@
 };
 
 // Implements the chrome.networkingPrivate.getManagedProperties method.
-class NetworkingPrivateGetManagedPropertiesFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateGetManagedPropertiesFunction : public ExtensionFunction {
  public:
   NetworkingPrivateGetManagedPropertiesFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getManagedProperties",
@@ -72,7 +70,7 @@
 };
 
 // Implements the chrome.networkingPrivate.getState method.
-class NetworkingPrivateGetStateFunction : public UIThreadExtensionFunction {
+class NetworkingPrivateGetStateFunction : public ExtensionFunction {
  public:
   NetworkingPrivateGetStateFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getState",
@@ -92,8 +90,7 @@
 };
 
 // Implements the chrome.networkingPrivate.setProperties method.
-class NetworkingPrivateSetPropertiesFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateSetPropertiesFunction : public ExtensionFunction {
  public:
   NetworkingPrivateSetPropertiesFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.setProperties",
@@ -113,8 +110,7 @@
 };
 
 // Implements the chrome.networkingPrivate.createNetwork method.
-class NetworkingPrivateCreateNetworkFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateCreateNetworkFunction : public ExtensionFunction {
  public:
   NetworkingPrivateCreateNetworkFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.createNetwork",
@@ -134,8 +130,7 @@
 };
 
 // Implements the chrome.networkingPrivate.createNetwork method.
-class NetworkingPrivateForgetNetworkFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateForgetNetworkFunction : public ExtensionFunction {
  public:
   NetworkingPrivateForgetNetworkFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.forgetNetwork",
@@ -155,7 +150,7 @@
 };
 
 // Implements the chrome.networkingPrivate.getNetworks method.
-class NetworkingPrivateGetNetworksFunction : public UIThreadExtensionFunction {
+class NetworkingPrivateGetNetworksFunction : public ExtensionFunction {
  public:
   NetworkingPrivateGetNetworksFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getNetworks",
@@ -175,8 +170,7 @@
 };
 
 // Implements the chrome.networkingPrivate.getVisibleNetworks method.
-class NetworkingPrivateGetVisibleNetworksFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateGetVisibleNetworksFunction : public ExtensionFunction {
  public:
   NetworkingPrivateGetVisibleNetworksFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getVisibleNetworks",
@@ -197,7 +191,7 @@
 
 // Implements the chrome.networkingPrivate.getEnabledNetworkTypes method.
 class NetworkingPrivateGetEnabledNetworkTypesFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   NetworkingPrivateGetEnabledNetworkTypesFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getEnabledNetworkTypes",
@@ -214,8 +208,7 @@
 };
 
 // Implements the chrome.networkingPrivate.getDeviceStates method.
-class NetworkingPrivateGetDeviceStatesFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateGetDeviceStatesFunction : public ExtensionFunction {
  public:
   NetworkingPrivateGetDeviceStatesFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getDeviceStates",
@@ -232,8 +225,7 @@
 };
 
 // Implements the chrome.networkingPrivate.enableNetworkType method.
-class NetworkingPrivateEnableNetworkTypeFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateEnableNetworkTypeFunction : public ExtensionFunction {
  public:
   NetworkingPrivateEnableNetworkTypeFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.enableNetworkType",
@@ -250,8 +242,7 @@
 };
 
 // Implements the chrome.networkingPrivate.disableNetworkType method.
-class NetworkingPrivateDisableNetworkTypeFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateDisableNetworkTypeFunction : public ExtensionFunction {
  public:
   NetworkingPrivateDisableNetworkTypeFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.disableNetworkType",
@@ -268,8 +259,7 @@
 };
 
 // Implements the chrome.networkingPrivate.requestNetworkScan method.
-class NetworkingPrivateRequestNetworkScanFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateRequestNetworkScanFunction : public ExtensionFunction {
  public:
   NetworkingPrivateRequestNetworkScanFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.requestNetworkScan",
@@ -286,7 +276,7 @@
 };
 
 // Implements the chrome.networkingPrivate.startConnect method.
-class NetworkingPrivateStartConnectFunction : public UIThreadExtensionFunction {
+class NetworkingPrivateStartConnectFunction : public ExtensionFunction {
  public:
   NetworkingPrivateStartConnectFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.startConnect",
@@ -306,8 +296,7 @@
 };
 
 // Implements the chrome.networkingPrivate.startDisconnect method.
-class NetworkingPrivateStartDisconnectFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateStartDisconnectFunction : public ExtensionFunction {
  public:
   NetworkingPrivateStartDisconnectFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.startDisconnect",
@@ -327,8 +316,7 @@
 };
 
 // Implements the chrome.networkingPrivate.startActivate method.
-class NetworkingPrivateStartActivateFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateStartActivateFunction : public ExtensionFunction {
  public:
   NetworkingPrivateStartActivateFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.startActivate",
@@ -348,8 +336,7 @@
 };
 
 // Implements the chrome.networkingPrivate.verifyDestination method.
-class NetworkingPrivateVerifyDestinationFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateVerifyDestinationFunction : public ExtensionFunction {
  public:
   NetworkingPrivateVerifyDestinationFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.verifyDestination",
@@ -369,8 +356,7 @@
 };
 
 // Implements the chrome.networkingPrivate.verifyAndEncryptData method.
-class NetworkingPrivateVerifyAndEncryptDataFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateVerifyAndEncryptDataFunction : public ExtensionFunction {
  public:
   NetworkingPrivateVerifyAndEncryptDataFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.verifyAndEncryptData",
@@ -391,7 +377,7 @@
 
 // Implements the chrome.networkingPrivate.setWifiTDLSEnabledState method.
 class NetworkingPrivateSetWifiTDLSEnabledStateFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   NetworkingPrivateSetWifiTDLSEnabledStateFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.setWifiTDLSEnabledState",
@@ -411,8 +397,7 @@
 };
 
 // Implements the chrome.networkingPrivate.getWifiTDLSStatus method.
-class NetworkingPrivateGetWifiTDLSStatusFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateGetWifiTDLSStatusFunction : public ExtensionFunction {
  public:
   NetworkingPrivateGetWifiTDLSStatusFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getWifiTDLSStatus",
@@ -432,7 +417,7 @@
 };
 
 class NetworkingPrivateGetCaptivePortalStatusFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   NetworkingPrivateGetCaptivePortalStatusFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getCaptivePortalStatus",
@@ -451,8 +436,7 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateGetCaptivePortalStatusFunction);
 };
 
-class NetworkingPrivateUnlockCellularSimFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateUnlockCellularSimFunction : public ExtensionFunction {
  public:
   NetworkingPrivateUnlockCellularSimFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.unlockCellularSim",
@@ -471,8 +455,7 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateUnlockCellularSimFunction);
 };
 
-class NetworkingPrivateSetCellularSimStateFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateSetCellularSimStateFunction : public ExtensionFunction {
  public:
   NetworkingPrivateSetCellularSimStateFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.setCellularSimState",
@@ -492,7 +475,7 @@
 };
 
 class NetworkingPrivateSelectCellularMobileNetworkFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   NetworkingPrivateSelectCellularMobileNetworkFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.selectCellularMobileNetwork",
@@ -512,8 +495,7 @@
       NetworkingPrivateSelectCellularMobileNetworkFunction);
 };
 
-class NetworkingPrivateGetGlobalPolicyFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateGetGlobalPolicyFunction : public ExtensionFunction {
  public:
   NetworkingPrivateGetGlobalPolicyFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getGlobalPolicy",
@@ -529,8 +511,7 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateGetGlobalPolicyFunction);
 };
 
-class NetworkingPrivateGetCertificateListsFunction
-    : public UIThreadExtensionFunction {
+class NetworkingPrivateGetCertificateListsFunction : public ExtensionFunction {
  public:
   NetworkingPrivateGetCertificateListsFunction() {}
   DECLARE_EXTENSION_FUNCTION("networkingPrivate.getCertificateLists",
diff --git a/extensions/browser/api/power/power_api.h b/extensions/browser/api/power/power_api.h
index 3acfe421..4ccf6c0 100644
--- a/extensions/browser/api/power/power_api.h
+++ b/extensions/browser/api/power/power_api.h
@@ -25,7 +25,7 @@
 namespace extensions {
 
 // Implementation of the chrome.power.requestKeepAwake API.
-class PowerRequestKeepAwakeFunction : public UIThreadExtensionFunction {
+class PowerRequestKeepAwakeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("power.requestKeepAwake", POWER_REQUESTKEEPAWAKE)
 
@@ -37,7 +37,7 @@
 };
 
 // Implementation of the chrome.power.releaseKeepAwake API.
-class PowerReleaseKeepAwakeFunction : public UIThreadExtensionFunction {
+class PowerReleaseKeepAwakeFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("power.releaseKeepAwake", POWER_RELEASEKEEPAWAKE)
 
diff --git a/extensions/browser/api/power/power_api_unittest.cc b/extensions/browser/api/power/power_api_unittest.cc
index f371bbaa..8a74267 100644
--- a/extensions/browser/api/power/power_api_unittest.cc
+++ b/extensions/browser/api/power/power_api_unittest.cc
@@ -171,12 +171,11 @@
   bool CallFunction(FunctionType type,
                     const std::string& args,
                     const extensions::Extension* extension) {
-    scoped_refptr<UIThreadExtensionFunction> function(
-        type == REQUEST ?
-        static_cast<UIThreadExtensionFunction*>(
-            new PowerRequestKeepAwakeFunction) :
-        static_cast<UIThreadExtensionFunction*>(
-            new PowerReleaseKeepAwakeFunction));
+    scoped_refptr<ExtensionFunction> function(
+        type == REQUEST
+            ? static_cast<ExtensionFunction*>(new PowerRequestKeepAwakeFunction)
+            : static_cast<ExtensionFunction*>(
+                  new PowerReleaseKeepAwakeFunction));
     function->set_extension(extension);
     return api_test_utils::RunFunction(function.get(), args, browser_context());
   }
diff --git a/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h b/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h
index 12540ff..dc1aef5d 100644
--- a/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h
+++ b/extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h
@@ -90,7 +90,7 @@
 };
 
 class PrinterProviderInternalReportPrintResultFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   PrinterProviderInternalReportPrintResultFunction();
 
@@ -107,7 +107,7 @@
 };
 
 class PrinterProviderInternalReportPrinterCapabilityFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   PrinterProviderInternalReportPrinterCapabilityFunction();
 
@@ -124,8 +124,7 @@
       PrinterProviderInternalReportPrinterCapabilityFunction);
 };
 
-class PrinterProviderInternalReportPrintersFunction
-    : public UIThreadExtensionFunction {
+class PrinterProviderInternalReportPrintersFunction : public ExtensionFunction {
  public:
   PrinterProviderInternalReportPrintersFunction();
 
@@ -140,8 +139,7 @@
   DISALLOW_COPY_AND_ASSIGN(PrinterProviderInternalReportPrintersFunction);
 };
 
-class PrinterProviderInternalGetPrintDataFunction
-    : public UIThreadExtensionFunction {
+class PrinterProviderInternalGetPrintDataFunction : public ExtensionFunction {
  public:
   PrinterProviderInternalGetPrintDataFunction();
 
@@ -161,7 +159,7 @@
 };
 
 class PrinterProviderInternalReportUsbPrinterInfoFunction
-    : public UIThreadExtensionFunction {
+    : public ExtensionFunction {
  public:
   PrinterProviderInternalReportUsbPrinterInfoFunction();
 
diff --git a/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc b/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc
index a963b45..030edb0 100644
--- a/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc
+++ b/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc
@@ -166,7 +166,7 @@
   }
 
  private:
-  std::string RunFunctionGetError(UIThreadExtensionFunction* function,
+  std::string RunFunctionGetError(ExtensionFunction* function,
                                   const Extension* extension,
                                   const std::string& args) {
     scoped_refptr<ExtensionFunction> function_owner(function);
diff --git a/extensions/browser/api/runtime/runtime_api.h b/extensions/browser/api/runtime/runtime_api.h
index eba7145d..3dcda83a 100644
--- a/extensions/browser/api/runtime/runtime_api.h
+++ b/extensions/browser/api/runtime/runtime_api.h
@@ -217,7 +217,7 @@
                                      UninstallReason reason);
 };
 
-class RuntimeGetBackgroundPageFunction : public UIThreadExtensionFunction {
+class RuntimeGetBackgroundPageFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("runtime.getBackgroundPage",
                              RUNTIME_GETBACKGROUNDPAGE)
@@ -231,7 +231,7 @@
       std::unique_ptr<LazyContextTaskQueue::ContextInfo> context_info);
 };
 
-class RuntimeOpenOptionsPageFunction : public UIThreadExtensionFunction {
+class RuntimeOpenOptionsPageFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("runtime.openOptionsPage", RUNTIME_OPENOPTIONSPAGE)
 
@@ -240,7 +240,7 @@
   ResponseAction Run() override;
 };
 
-class RuntimeSetUninstallURLFunction : public UIThreadExtensionFunction {
+class RuntimeSetUninstallURLFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("runtime.setUninstallURL", RUNTIME_SETUNINSTALLURL)
 
@@ -249,7 +249,7 @@
   ResponseAction Run() override;
 };
 
-class RuntimeReloadFunction : public UIThreadExtensionFunction {
+class RuntimeReloadFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("runtime.reload", RUNTIME_RELOAD)
 
@@ -258,7 +258,7 @@
   ResponseAction Run() override;
 };
 
-class RuntimeRequestUpdateCheckFunction : public UIThreadExtensionFunction {
+class RuntimeRequestUpdateCheckFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("runtime.requestUpdateCheck",
                              RUNTIME_REQUESTUPDATECHECK)
@@ -271,7 +271,7 @@
   void CheckComplete(const RuntimeAPIDelegate::UpdateCheckResult& result);
 };
 
-class RuntimeRestartFunction : public UIThreadExtensionFunction {
+class RuntimeRestartFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("runtime.restart", RUNTIME_RESTART)
 
@@ -280,7 +280,7 @@
   ResponseAction Run() override;
 };
 
-class RuntimeRestartAfterDelayFunction : public UIThreadExtensionFunction {
+class RuntimeRestartAfterDelayFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("runtime.restartAfterDelay",
                              RUNTIME_RESTARTAFTERDELAY)
@@ -290,7 +290,7 @@
   ResponseAction Run() override;
 };
 
-class RuntimeGetPlatformInfoFunction : public UIThreadExtensionFunction {
+class RuntimeGetPlatformInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("runtime.getPlatformInfo", RUNTIME_GETPLATFORMINFO)
 
@@ -299,8 +299,7 @@
   ResponseAction Run() override;
 };
 
-class RuntimeGetPackageDirectoryEntryFunction
-    : public UIThreadExtensionFunction {
+class RuntimeGetPackageDirectoryEntryFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("runtime.getPackageDirectoryEntry",
                              RUNTIME_GETPACKAGEDIRECTORYENTRY)
diff --git a/extensions/browser/api/serial/serial_api.h b/extensions/browser/api/serial/serial_api.h
index d38d7ee..1551c60 100644
--- a/extensions/browser/api/serial/serial_api.h
+++ b/extensions/browser/api/serial/serial_api.h
@@ -39,7 +39,7 @@
   ApiResourceManager<SerialConnection>* manager_;
 };
 
-class SerialGetDevicesFunction : public UIThreadExtensionFunction {
+class SerialGetDevicesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("serial.getDevices", SERIAL_GETDEVICES)
 
diff --git a/extensions/browser/api/socket/socket_api.h b/extensions/browser/api/socket/socket_api.h
index c37ecd1..2d41eb7 100644
--- a/extensions/browser/api/socket/socket_api.h
+++ b/extensions/browser/api/socket/socket_api.h
@@ -461,14 +461,14 @@
   std::unique_ptr<api::socket::GetInfo::Params> params_;
 };
 
-class SocketGetNetworkListFunction : public UIThreadExtensionFunction {
+class SocketGetNetworkListFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("socket.getNetworkList", SOCKET_GETNETWORKLIST)
 
  protected:
   ~SocketGetNetworkListFunction() override {}
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
diff --git a/extensions/browser/api/storage/storage_api.h b/extensions/browser/api/storage/storage_api.h
index e6b532c..b30de8f 100644
--- a/extensions/browser/api/storage/storage_api.h
+++ b/extensions/browser/api/storage/storage_api.h
@@ -17,7 +17,7 @@
 namespace extensions {
 
 // Superclass of all settings functions.
-class SettingsFunction : public UIThreadExtensionFunction {
+class SettingsFunction : public ExtensionFunction {
  protected:
   SettingsFunction();
   ~SettingsFunction() override;
diff --git a/extensions/browser/api/system_cpu/system_cpu_api.h b/extensions/browser/api/system_cpu/system_cpu_api.h
index 3890edc..849b0a6 100644
--- a/extensions/browser/api/system_cpu/system_cpu_api.h
+++ b/extensions/browser/api/system_cpu/system_cpu_api.h
@@ -9,7 +9,7 @@
 
 namespace extensions {
 
-class SystemCpuGetInfoFunction : public UIThreadExtensionFunction {
+class SystemCpuGetInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("system.cpu.getInfo", SYSTEM_CPU_GETINFO)
   SystemCpuGetInfoFunction();
@@ -17,7 +17,7 @@
  private:
   ~SystemCpuGetInfoFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   void OnGetCpuInfoCompleted(bool success);
diff --git a/extensions/browser/api/system_display/system_display_api.cc b/extensions/browser/api/system_display/system_display_api.cc
index 9857cb4d..982906b 100644
--- a/extensions/browser/api/system_display/system_display_api.cc
+++ b/extensions/browser/api/system_display/system_display_api.cc
@@ -148,7 +148,7 @@
   return observers_.empty();
 }
 
-bool HasAutotestPrivate(const UIThreadExtensionFunction& function) {
+bool HasAutotestPrivate(const ExtensionFunction& function) {
   return function.extension() &&
          function.extension()->permissions_data()->HasAPIPermission(
              APIPermission::kAutoTestPrivate);
@@ -156,7 +156,7 @@
 
 #if defined(OS_CHROMEOS)
 // |edid| is available only to Chrome OS kiosk mode applications.
-bool ShouldRestrictEdidInformation(const UIThreadExtensionFunction& function) {
+bool ShouldRestrictEdidInformation(const ExtensionFunction& function) {
   if (function.extension()) {
     return !(HasAutotestPrivate(function) ||
              KioskModeInfo::IsKioskEnabled(function.extension()));
@@ -169,7 +169,7 @@
 }  // namespace
 
 bool SystemDisplayCrOSRestrictedFunction::PreRunValidation(std::string* error) {
-  if (!UIThreadExtensionFunction::PreRunValidation(error))
+  if (!ExtensionFunction::PreRunValidation(error))
     return false;
 
 #if !defined(OS_CHROMEOS)
diff --git a/extensions/browser/api/system_display/system_display_api.h b/extensions/browser/api/system_display/system_display_api.h
index ccbea34..3949aaa 100644
--- a/extensions/browser/api/system_display/system_display_api.h
+++ b/extensions/browser/api/system_display/system_display_api.h
@@ -12,7 +12,7 @@
 
 namespace extensions {
 
-class SystemDisplayCrOSRestrictedFunction : public UIThreadExtensionFunction {
+class SystemDisplayCrOSRestrictedFunction : public ExtensionFunction {
  public:
   static const char kCrosOnlyError[];
   static const char kKioskOnlyError[];
@@ -26,9 +26,9 @@
   virtual bool ShouldRestrictToKioskAndWebUI();
 };
 
-// This function inherits from UIThreadExtensionFunction because, unlike the
+// This function inherits from ExtensionFunction because, unlike the
 // rest of this API, it's available on all platforms.
-class SystemDisplayGetInfoFunction : public UIThreadExtensionFunction {
+class SystemDisplayGetInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("system.display.getInfo", SYSTEM_DISPLAY_GETINFO)
 
diff --git a/extensions/browser/api/system_memory/system_memory_api.h b/extensions/browser/api/system_memory/system_memory_api.h
index 00866d9..fe307ca 100644
--- a/extensions/browser/api/system_memory/system_memory_api.h
+++ b/extensions/browser/api/system_memory/system_memory_api.h
@@ -10,7 +10,7 @@
 
 namespace extensions {
 
-class SystemMemoryGetInfoFunction : public UIThreadExtensionFunction {
+class SystemMemoryGetInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("system.memory.getInfo", SYSTEM_MEMORY_GETINFO)
   SystemMemoryGetInfoFunction();
@@ -18,7 +18,7 @@
  private:
   ~SystemMemoryGetInfoFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
   void OnGetMemoryInfoCompleted(bool success);
diff --git a/extensions/browser/api/system_network/system_network_api.h b/extensions/browser/api/system_network/system_network_api.h
index 15ddabb..22d030e7 100644
--- a/extensions/browser/api/system_network/system_network_api.h
+++ b/extensions/browser/api/system_network/system_network_api.h
@@ -14,8 +14,7 @@
 namespace extensions {
 namespace api {
 
-class SystemNetworkGetNetworkInterfacesFunction
-    : public UIThreadExtensionFunction {
+class SystemNetworkGetNetworkInterfacesFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("system.network.getNetworkInterfaces",
                              SYSTEM_NETWORK_GETNETWORKINTERFACES)
diff --git a/extensions/browser/api/system_power_source/system_power_source_api.h b/extensions/browser/api/system_power_source/system_power_source_api.h
index 523e9a00..0ea3474 100644
--- a/extensions/browser/api/system_power_source/system_power_source_api.h
+++ b/extensions/browser/api/system_power_source/system_power_source_api.h
@@ -41,8 +41,7 @@
   DISALLOW_COPY_AND_ASSIGN(SystemPowerSourceAPI);
 };
 
-class SystemPowerSourceGetPowerSourceInfoFunction
-    : public UIThreadExtensionFunction {
+class SystemPowerSourceGetPowerSourceInfoFunction : public ExtensionFunction {
  public:
   SystemPowerSourceGetPowerSourceInfoFunction();
 
@@ -58,8 +57,7 @@
   DISALLOW_COPY_AND_ASSIGN(SystemPowerSourceGetPowerSourceInfoFunction);
 };
 
-class SystemPowerSourceRequestStatusUpdateFunction
-    : public UIThreadExtensionFunction {
+class SystemPowerSourceRequestStatusUpdateFunction : public ExtensionFunction {
  public:
   SystemPowerSourceRequestStatusUpdateFunction();
 
diff --git a/extensions/browser/api/system_storage/system_storage_api.h b/extensions/browser/api/system_storage/system_storage_api.h
index 23d5dde2a..fa0338aa 100644
--- a/extensions/browser/api/system_storage/system_storage_api.h
+++ b/extensions/browser/api/system_storage/system_storage_api.h
@@ -14,7 +14,7 @@
 
 // Implementation of the systeminfo.storage.get API. It is an asynchronous
 // call relative to browser UI thread.
-class SystemStorageGetInfoFunction : public UIThreadExtensionFunction {
+class SystemStorageGetInfoFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("system.storage.getInfo", SYSTEM_STORAGE_GETINFO)
   SystemStorageGetInfoFunction();
@@ -28,7 +28,7 @@
   void OnGetStorageInfoCompleted(bool success);
 };
 
-class SystemStorageEjectDeviceFunction : public UIThreadExtensionFunction {
+class SystemStorageEjectDeviceFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("system.storage.ejectDevice",
                              SYSTEM_STORAGE_EJECTDEVICE)
@@ -46,8 +46,7 @@
   void HandleResponse(storage_monitor::StorageMonitor::EjectStatus status);
 };
 
-class SystemStorageGetAvailableCapacityFunction
-    : public UIThreadExtensionFunction {
+class SystemStorageGetAvailableCapacityFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("system.storage.getAvailableCapacity",
                              SYSTEM_STORAGE_GETAVAILABLECAPACITY)
diff --git a/extensions/browser/api/test/test_api.cc b/extensions/browser/api/test/test_api.cc
index de1295a..01e9d167 100644
--- a/extensions/browser/api/test/test_api.cc
+++ b/extensions/browser/api/test/test_api.cc
@@ -38,7 +38,7 @@
 TestExtensionFunction::~TestExtensionFunction() {}
 
 bool TestExtensionFunction::PreRunValidation(std::string* error) {
-  if (!UIThreadExtensionFunction::PreRunValidation(error))
+  if (!ExtensionFunction::PreRunValidation(error))
     return false;
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) {
     *error = kNotTestProcessError;
diff --git a/extensions/browser/api/test/test_api.h b/extensions/browser/api/test/test_api.h
index 3fc88cd..c8ba5b82 100644
--- a/extensions/browser/api/test/test_api.h
+++ b/extensions/browser/api/test/test_api.h
@@ -20,7 +20,7 @@
 
 // A function that is only available in tests.
 // Prior to running, checks that we are in a testing process.
-class TestExtensionFunction : public UIThreadExtensionFunction {
+class TestExtensionFunction : public ExtensionFunction {
  protected:
   ~TestExtensionFunction() override;
 
@@ -61,7 +61,7 @@
   ResponseAction Run() override;
 };
 
-class TestSendMessageFunction : public UIThreadExtensionFunction {
+class TestSendMessageFunction : public ExtensionFunction {
  public:
   TestSendMessageFunction();
   DECLARE_EXTENSION_FUNCTION("test.sendMessage", UNKNOWN)
diff --git a/extensions/browser/api/usb/usb_api.h b/extensions/browser/api/usb/usb_api.h
index d73c3f97..7b531ce3 100644
--- a/extensions/browser/api/usb/usb_api.h
+++ b/extensions/browser/api/usb/usb_api.h
@@ -27,7 +27,7 @@
 class DevicePermissionsManager;
 class UsbDeviceResource;
 
-class UsbExtensionFunction : public UIThreadExtensionFunction {
+class UsbExtensionFunction : public ExtensionFunction {
  protected:
   UsbExtensionFunction();
   ~UsbExtensionFunction() override;
@@ -171,7 +171,7 @@
   DISALLOW_COPY_AND_ASSIGN(UsbGetConfigurationsFunction);
 };
 
-class UsbRequestAccessFunction : public UIThreadExtensionFunction {
+class UsbRequestAccessFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("usb.requestAccess", USB_REQUESTACCESS)
 
diff --git a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h
index 74e3ee0..3bff3ac 100644
--- a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h
+++ b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h
@@ -11,8 +11,7 @@
 
 namespace extensions {
 
-class VirtualKeyboardRestrictFeaturesFunction
-    : public UIThreadExtensionFunction {
+class VirtualKeyboardRestrictFeaturesFunction : public ExtensionFunction {
  public:
   VirtualKeyboardRestrictFeaturesFunction();
 
@@ -21,7 +20,7 @@
 
  protected:
   ~VirtualKeyboardRestrictFeaturesFunction() override = default;
-  // UIThreadExtensionFunction override:
+  // ExtensionFunction override:
   ResponseAction Run() override;
 
  private:
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
index efa172a..9366a56 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
@@ -38,7 +38,7 @@
 }  // namespace
 
 bool VirtualKeyboardPrivateFunction::PreRunValidation(std::string* error) {
-  if (!UIThreadExtensionFunction::PreRunValidation(error))
+  if (!ExtensionFunction::PreRunValidation(error))
     return false;
 
   VirtualKeyboardAPI* api =
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h
index 5227d3b..d9eda1b 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h
@@ -21,7 +21,7 @@
 
 class VirtualKeyboardDelegate;
 
-class VirtualKeyboardPrivateFunction : public UIThreadExtensionFunction {
+class VirtualKeyboardPrivateFunction : public ExtensionFunction {
  public:
   bool PreRunValidation(std::string* error) override;
 
diff --git a/extensions/browser/api/vpn_provider/vpn_provider_api.h b/extensions/browser/api/vpn_provider/vpn_provider_api.h
index 0a3b4bf..3f73331a 100644
--- a/extensions/browser/api/vpn_provider/vpn_provider_api.h
+++ b/extensions/browser/api/vpn_provider/vpn_provider_api.h
@@ -11,7 +11,7 @@
 
 namespace extensions {
 
-class VpnThreadExtensionFunction : public UIThreadExtensionFunction {
+class VpnThreadExtensionFunction : public ExtensionFunction {
  public:
   void SignalCallCompletionSuccess();
   void SignalCallCompletionSuccessWithId(const std::string& configuration_id);
diff --git a/extensions/browser/api/web_request/web_request_api.h b/extensions/browser/api/web_request/web_request_api.h
index a8ff718..9d040ff 100644
--- a/extensions/browser/api/web_request/web_request_api.h
+++ b/extensions/browser/api/web_request/web_request_api.h
@@ -750,7 +750,7 @@
   DISALLOW_COPY_AND_ASSIGN(ExtensionWebRequestEventRouter);
 };
 
-class WebRequestInternalFunction : public UIThreadExtensionFunction {
+class WebRequestInternalFunction : public ExtensionFunction {
  public:
   WebRequestInternalFunction() {}
 
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
index 95d47c3..644d52c 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -232,12 +232,6 @@
   RestartInternal();
 }
 
-void WebRequestProxyingURLLoaderFactory::InProgressRequest::
-    ProceedWithResponse() {
-  if (target_loader_.is_bound())
-    target_loader_->ProceedWithResponse();
-}
-
 void WebRequestProxyingURLLoaderFactory::InProgressRequest::SetPriority(
     net::RequestPriority priority,
     int32_t intra_priority_value) {
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
index 83352e0b..0d8f0731 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
@@ -61,7 +61,6 @@
     void FollowRedirect(const std::vector<std::string>& removed_headers,
                         const net::HttpRequestHeaders& modified_headers,
                         const base::Optional<GURL>& new_url) override;
-    void ProceedWithResponse() override;
     void SetPriority(net::RequestPriority priority,
                      int32_t intra_priority_value) override;
     void PauseReadingBodyFromNet() override;
diff --git a/extensions/browser/api/webcam_private/webcam_private_api.h b/extensions/browser/api/webcam_private/webcam_private_api.h
index 6d36c80..ae519aa 100644
--- a/extensions/browser/api/webcam_private/webcam_private_api.h
+++ b/extensions/browser/api/webcam_private/webcam_private_api.h
@@ -80,7 +80,7 @@
 void BrowserContextKeyedAPIFactory<WebcamPrivateAPI>
     ::DeclareFactoryDependencies();
 
-class WebcamPrivateOpenSerialWebcamFunction : public UIThreadExtensionFunction {
+class WebcamPrivateOpenSerialWebcamFunction : public ExtensionFunction {
  public:
   WebcamPrivateOpenSerialWebcamFunction();
   DECLARE_EXTENSION_FUNCTION("webcamPrivate.openSerialWebcam",
@@ -89,7 +89,7 @@
  protected:
   ~WebcamPrivateOpenSerialWebcamFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -98,7 +98,7 @@
   DISALLOW_COPY_AND_ASSIGN(WebcamPrivateOpenSerialWebcamFunction);
 };
 
-class WebcamPrivateCloseWebcamFunction : public UIThreadExtensionFunction {
+class WebcamPrivateCloseWebcamFunction : public ExtensionFunction {
  public:
   WebcamPrivateCloseWebcamFunction();
   DECLARE_EXTENSION_FUNCTION("webcamPrivate.closeWebcam",
@@ -107,14 +107,14 @@
  protected:
   ~WebcamPrivateCloseWebcamFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(WebcamPrivateCloseWebcamFunction);
 };
 
-class WebcamPrivateSetFunction : public UIThreadExtensionFunction {
+class WebcamPrivateSetFunction : public ExtensionFunction {
  public:
   WebcamPrivateSetFunction();
   DECLARE_EXTENSION_FUNCTION("webcamPrivate.set", WEBCAMPRIVATE_SET)
@@ -122,7 +122,7 @@
  protected:
   ~WebcamPrivateSetFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -134,7 +134,7 @@
   DISALLOW_COPY_AND_ASSIGN(WebcamPrivateSetFunction);
 };
 
-class WebcamPrivateGetFunction : public UIThreadExtensionFunction {
+class WebcamPrivateGetFunction : public ExtensionFunction {
  public:
   WebcamPrivateGetFunction();
   DECLARE_EXTENSION_FUNCTION("webcamPrivate.get", WEBCAMPRIVATE_GET)
@@ -142,7 +142,7 @@
  protected:
   ~WebcamPrivateGetFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
@@ -185,7 +185,7 @@
   DISALLOW_COPY_AND_ASSIGN(WebcamPrivateGetFunction);
 };
 
-class WebcamPrivateResetFunction : public UIThreadExtensionFunction {
+class WebcamPrivateResetFunction : public ExtensionFunction {
  public:
   WebcamPrivateResetFunction();
   DECLARE_EXTENSION_FUNCTION("webcamPrivate.reset", WEBCAMPRIVATE_RESET)
@@ -193,7 +193,7 @@
  protected:
   ~WebcamPrivateResetFunction() override;
 
-  // UIThreadExtensionFunction:
+  // ExtensionFunction:
   ResponseAction Run() override;
 
  private:
diff --git a/extensions/browser/api_test_utils.cc b/extensions/browser/api_test_utils.cc
index 3d95cd59f..b32757b 100644
--- a/extensions/browser/api_test_utils.cc
+++ b/extensions/browser/api_test_utils.cc
@@ -36,7 +36,7 @@
 
 namespace api_test_utils {
 
-SendResponseHelper::SendResponseHelper(UIThreadExtensionFunction* function) {
+SendResponseHelper::SendResponseHelper(ExtensionFunction* function) {
   function->set_has_callback(true);
   function->set_response_callback(
       base::Bind(&SendResponseHelper::OnResponse, base::Unretained(this)));
@@ -89,7 +89,7 @@
 }
 
 std::unique_ptr<base::Value> RunFunctionWithDelegateAndReturnSingleResult(
-    scoped_refptr<UIThreadExtensionFunction> function,
+    scoped_refptr<ExtensionFunction> function,
     const std::string& args,
     content::BrowserContext* context,
     std::unique_ptr<extensions::ExtensionFunctionDispatcher> dispatcher,
@@ -103,7 +103,7 @@
 }
 
 std::unique_ptr<base::Value> RunFunctionWithDelegateAndReturnSingleResult(
-    scoped_refptr<UIThreadExtensionFunction> function,
+    scoped_refptr<ExtensionFunction> function,
     std::unique_ptr<base::ListValue> args,
     content::BrowserContext* context,
     std::unique_ptr<extensions::ExtensionFunctionDispatcher> dispatcher,
@@ -121,14 +121,14 @@
 }
 
 std::unique_ptr<base::Value> RunFunctionAndReturnSingleResult(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args,
     content::BrowserContext* context) {
   return RunFunctionAndReturnSingleResult(function, args, context, NONE);
 }
 
 std::unique_ptr<base::Value> RunFunctionAndReturnSingleResult(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args,
     content::BrowserContext* context,
     RunFunctionFlags flags) {
@@ -139,13 +139,13 @@
       function, args, context, std::move(dispatcher), flags);
 }
 
-std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
+std::string RunFunctionAndReturnError(ExtensionFunction* function,
                                       const std::string& args,
                                       content::BrowserContext* context) {
   return RunFunctionAndReturnError(function, args, context, NONE);
 }
 
-std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
+std::string RunFunctionAndReturnError(ExtensionFunction* function,
                                       const std::string& args,
                                       content::BrowserContext* context,
                                       RunFunctionFlags flags) {
@@ -164,7 +164,7 @@
   return function->GetError();
 }
 
-bool RunFunction(UIThreadExtensionFunction* function,
+bool RunFunction(ExtensionFunction* function,
                  const std::string& args,
                  content::BrowserContext* context) {
   std::unique_ptr<ExtensionFunctionDispatcher> dispatcher(
@@ -173,7 +173,7 @@
 }
 
 bool RunFunction(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args,
     content::BrowserContext* context,
     std::unique_ptr<extensions::ExtensionFunctionDispatcher> dispatcher,
@@ -186,7 +186,7 @@
 }
 
 bool RunFunction(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     std::unique_ptr<base::ListValue> args,
     content::BrowserContext* context,
     std::unique_ptr<extensions::ExtensionFunctionDispatcher> dispatcher,
diff --git a/extensions/browser/api_test_utils.h b/extensions/browser/api_test_utils.h
index 77c823f..fb94e4c 100644
--- a/extensions/browser/api_test_utils.h
+++ b/extensions/browser/api_test_utils.h
@@ -35,7 +35,7 @@
 // A helper class to handle waiting for a function response.
 class SendResponseHelper {
  public:
-  explicit SendResponseHelper(UIThreadExtensionFunction* function);
+  explicit SendResponseHelper(ExtensionFunction* function);
   ~SendResponseHelper();
 
   bool has_response() { return response_.get() != nullptr; }
@@ -75,13 +75,13 @@
 // current test if |function| returns an error. Takes ownership of
 // |function|. The caller takes ownership of the result.
 std::unique_ptr<base::Value> RunFunctionWithDelegateAndReturnSingleResult(
-    scoped_refptr<UIThreadExtensionFunction> function,
+    scoped_refptr<ExtensionFunction> function,
     const std::string& args,
     content::BrowserContext* context,
     std::unique_ptr<ExtensionFunctionDispatcher> dispatcher,
     RunFunctionFlags flags);
 std::unique_ptr<base::Value> RunFunctionWithDelegateAndReturnSingleResult(
-    scoped_refptr<UIThreadExtensionFunction> function,
+    scoped_refptr<ExtensionFunction> function,
     std::unique_ptr<base::ListValue> args,
     content::BrowserContext* context,
     std::unique_ptr<ExtensionFunctionDispatcher> dispatcher,
@@ -90,11 +90,11 @@
 // RunFunctionWithDelegateAndReturnSingleResult, except with a NULL
 // implementation of the Delegate.
 std::unique_ptr<base::Value> RunFunctionAndReturnSingleResult(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args,
     content::BrowserContext* context);
 std::unique_ptr<base::Value> RunFunctionAndReturnSingleResult(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args,
     content::BrowserContext* context,
     RunFunctionFlags flags);
@@ -102,11 +102,11 @@
 // Run |function| with |args| and return the resulting error. Adds an error to
 // the current test if |function| returns a result. Takes ownership of
 // |function|.
-std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
+std::string RunFunctionAndReturnError(ExtensionFunction* function,
                                       const std::string& args,
                                       content::BrowserContext* context,
                                       RunFunctionFlags flags);
-std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
+std::string RunFunctionAndReturnError(ExtensionFunction* function,
                                       const std::string& args,
                                       content::BrowserContext* context);
 
@@ -120,15 +120,15 @@
 // TODO(aa): I'm concerned that this style won't scale to all the bits and bobs
 // we're going to need to frob for all the different extension functions. But
 // we can refactor when we see what is needed.
-bool RunFunction(UIThreadExtensionFunction* function,
+bool RunFunction(ExtensionFunction* function,
                  const std::string& args,
                  content::BrowserContext* context);
-bool RunFunction(UIThreadExtensionFunction* function,
+bool RunFunction(ExtensionFunction* function,
                  const std::string& args,
                  content::BrowserContext* context,
                  std::unique_ptr<ExtensionFunctionDispatcher> dispatcher,
                  RunFunctionFlags flags);
-bool RunFunction(UIThreadExtensionFunction* function,
+bool RunFunction(ExtensionFunction* function,
                  std::unique_ptr<base::ListValue> args,
                  content::BrowserContext* context,
                  std::unique_ptr<ExtensionFunctionDispatcher> dispatcher,
diff --git a/extensions/browser/api_unittest.cc b/extensions/browser/api_unittest.cc
index 186b6d3d..e4ad721 100644
--- a/extensions/browser/api_unittest.cc
+++ b/extensions/browser/api_unittest.cc
@@ -58,7 +58,7 @@
 }
 
 std::unique_ptr<base::Value> ApiUnitTest::RunFunctionAndReturnValue(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args) {
   function->set_extension(extension());
   if (contents_)
@@ -68,7 +68,7 @@
 }
 
 std::unique_ptr<base::DictionaryValue>
-ApiUnitTest::RunFunctionAndReturnDictionary(UIThreadExtensionFunction* function,
+ApiUnitTest::RunFunctionAndReturnDictionary(ExtensionFunction* function,
                                             const std::string& args) {
   base::Value* value = RunFunctionAndReturnValue(function, args).release();
   base::DictionaryValue* dict = NULL;
@@ -83,7 +83,7 @@
 }
 
 std::unique_ptr<base::ListValue> ApiUnitTest::RunFunctionAndReturnList(
-    UIThreadExtensionFunction* function,
+    ExtensionFunction* function,
     const std::string& args) {
   base::Value* value = RunFunctionAndReturnValue(function, args).release();
   base::ListValue* list = NULL;
@@ -97,16 +97,15 @@
   return std::unique_ptr<base::ListValue>(list);
 }
 
-std::string ApiUnitTest::RunFunctionAndReturnError(
-    UIThreadExtensionFunction* function,
-    const std::string& args) {
+std::string ApiUnitTest::RunFunctionAndReturnError(ExtensionFunction* function,
+                                                   const std::string& args) {
   function->set_extension(extension());
   if (contents_)
     function->SetRenderFrameHost(contents_->GetMainFrame());
   return utils::RunFunctionAndReturnError(function, args, browser_context());
 }
 
-void ApiUnitTest::RunFunction(UIThreadExtensionFunction* function,
+void ApiUnitTest::RunFunction(ExtensionFunction* function,
                               const std::string& args) {
   RunFunctionAndReturnValue(function, args);
 }
diff --git a/extensions/browser/api_unittest.h b/extensions/browser/api_unittest.h
index 72c71f8..33de01ea 100644
--- a/extensions/browser/api_unittest.h
+++ b/extensions/browser/api_unittest.h
@@ -22,7 +22,7 @@
 class WebContents;
 }
 
-class UIThreadExtensionFunction;
+class ExtensionFunction;
 
 namespace extensions {
 
@@ -60,29 +60,28 @@
 
   // Return the function result as a base::Value.
   std::unique_ptr<base::Value> RunFunctionAndReturnValue(
-      UIThreadExtensionFunction* function,
+      ExtensionFunction* function,
       const std::string& args);
 
   // Return the function result as a base::DictionaryValue, or NULL.
   // This will EXPECT-fail if the result is not a DictionaryValue.
   std::unique_ptr<base::DictionaryValue> RunFunctionAndReturnDictionary(
-      UIThreadExtensionFunction* function,
+      ExtensionFunction* function,
       const std::string& args);
 
   // Return the function result as a base::ListValue, or NULL.
   // This will EXPECT-fail if the result is not a ListValue.
   std::unique_ptr<base::ListValue> RunFunctionAndReturnList(
-      UIThreadExtensionFunction* function,
+      ExtensionFunction* function,
       const std::string& args);
 
   // Return an error thrown from the function, if one exists.
   // This will EXPECT-fail if any result is returned from the function.
-  std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
+  std::string RunFunctionAndReturnError(ExtensionFunction* function,
                                         const std::string& args);
 
   // Run the function and ignore any result.
-  void RunFunction(UIThreadExtensionFunction* function,
-                   const std::string& args);
+  void RunFunction(ExtensionFunction* function, const std::string& args);
 
  private:
   sync_preferences::TestingPrefServiceSyncable testing_pref_service_;
diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc
index cdb59c5..642d9ccb 100644
--- a/extensions/browser/app_window/app_window.cc
+++ b/extensions/browser/app_window/app_window.cc
@@ -454,6 +454,10 @@
   app_delegate_->ExitPictureInPicture();
 }
 
+bool AppWindow::ShouldShowStaleContentOnEviction(content::WebContents* source) {
+  return true;
+}
+
 bool AppWindow::OnMessageReceived(const IPC::Message& message,
                                   content::RenderFrameHost* render_frame_host) {
   bool handled = true;
diff --git a/extensions/browser/app_window/app_window.h b/extensions/browser/app_window/app_window.h
index c12d125..2d78220 100644
--- a/extensions/browser/app_window/app_window.h
+++ b/extensions/browser/app_window/app_window.h
@@ -451,6 +451,7 @@
       const viz::SurfaceId& surface_id,
       const gfx::Size& natural_size) override;
   void ExitPictureInPicture() override;
+  bool ShouldShowStaleContentOnEviction(content::WebContents* source) override;
 
   // content::WebContentsObserver implementation.
   bool OnMessageReceived(const IPC::Message& message,
diff --git a/extensions/browser/app_window/app_window_browsertest.cc b/extensions/browser/app_window/app_window_browsertest.cc
index b409cd8..b05be56 100644
--- a/extensions/browser/app_window/app_window_browsertest.cc
+++ b/extensions/browser/app_window/app_window_browsertest.cc
@@ -66,6 +66,18 @@
   CloseAppWindow(app_window);
 }
 
+#if defined(OS_CHROMEOS)
+
+IN_PROC_BROWSER_TEST_F(AppWindowBrowserTest, ShouldShowStaleContentOnEviction) {
+  AppWindow* app_window = CreateTestAppWindow("{}");
+  // Helper function as this test requires inspecting a number of content::
+  // internal objects.
+  content::VerifyStaleContentOnFrameEviction(
+      app_window->web_contents()->GetRenderWidgetHostView());
+}
+
+#endif  // defined(OS_CHROMEOS)
+
 }  // namespace
 
 }  // namespace extensions
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc
index 7bf63da..51ad258 100644
--- a/extensions/browser/extension_function.cc
+++ b/extensions/browser/extension_function.cc
@@ -254,22 +254,16 @@
 // static
 const char ExtensionFunction::kUnknownErrorDoNotUse[] = "Unknown error.";
 
-// static
-void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
-  x->Destruct();
-}
-
 // Helper class to track the lifetime of ExtensionFunction's RenderFrameHost and
 // notify the function when it is deleted, as well as forwarding any messages
 // to the ExtensionFunction.
-class UIThreadExtensionFunction::RenderFrameHostTracker
+class ExtensionFunction::RenderFrameHostTracker
     : public content::WebContentsObserver {
  public:
-  explicit RenderFrameHostTracker(UIThreadExtensionFunction* function)
+  explicit RenderFrameHostTracker(ExtensionFunction* function)
       : content::WebContentsObserver(
             WebContents::FromRenderFrameHost(function->render_frame_host())),
-        function_(function) {
-  }
+        function_(function) {}
 
  private:
   // content::WebContentsObserver:
@@ -285,34 +279,27 @@
         function_->OnMessageReceived(message);
   }
 
-  UIThreadExtensionFunction* function_;  // Owns us.
+  ExtensionFunction* function_;  // Owns us.
 
   DISALLOW_COPY_AND_ASSIGN(RenderFrameHostTracker);
 };
 
-ExtensionFunction::ExtensionFunction()
-    : request_id_(-1),
-      profile_id_(NULL),
-      name_(""),
-      has_callback_(false),
-      include_incognito_information_(false),
-      user_gesture_(false),
-      bad_message_(false),
-      histogram_value_(extensions::functions::UNKNOWN),
-      source_context_type_(Feature::UNSPECIFIED_CONTEXT),
-      source_process_id_(-1),
-      service_worker_version_id_(blink::mojom::kInvalidServiceWorkerVersionId),
-      did_respond_(false) {}
+ExtensionFunction::ExtensionFunction() = default;
 
 ExtensionFunction::~ExtensionFunction() {
-}
+  if (dispatcher() && (render_frame_host() || is_from_service_worker())) {
+    dispatcher()->OnExtensionFunctionCompleted(
+        extension(), is_from_service_worker(), name());
+  }
 
-UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() {
-  return NULL;
-}
-
-IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
-  return NULL;
+  // The extension function should always respond to avoid leaks in the
+  // renderer, dangling callbacks, etc. The exception is if the system is
+  // shutting down.
+  extensions::ExtensionsBrowserClient* browser_client =
+      extensions::ExtensionsBrowserClient::Get();
+  DCHECK(!browser_client || browser_client->IsShuttingDown() || did_respond() ||
+         ignore_all_did_respond_for_testing_do_not_use)
+      << name();
 }
 
 bool ExtensionFunction::HasPermission() const {
@@ -323,6 +310,36 @@
   return availability.is_available();
 }
 
+bool ExtensionFunction::PreRunValidation(std::string* error) {
+  // TODO(crbug.com/625646) This is a partial fix to avoid crashes when certain
+  // extension functions run during shutdown. Browser or Notification creation
+  // for example create a ScopedKeepAlive, which hit a CHECK if the browser is
+  // shutting down. This fixes the current problem as the known issues happen
+  // through synchronous calls from Run(), but posted tasks will not be covered.
+  // A possible fix would involve refactoring ExtensionFunction: unrefcount
+  // here and use weakptrs for the tasks, then have it owned by something that
+  // will be destroyed naturally in the course of shut down.
+  if (extensions::ExtensionsBrowserClient::Get()->IsShuttingDown()) {
+    *error = "The browser is shutting down.";
+    return false;
+  }
+
+  return true;
+}
+
+ExtensionFunction::ResponseAction ExtensionFunction::RunWithValidation() {
+  std::string error;
+  if (!PreRunValidation(&error)) {
+    DCHECK(!error.empty() || bad_message_);
+    return bad_message_ ? ValidationFailure(this) : RespondNow(Error(error));
+  }
+  return Run();
+}
+
+bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
+  return false;
+}
+
 void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
   error_ = violation_error;
   SendResponseImpl(false);
@@ -344,12 +361,44 @@
 
 void ExtensionFunction::SetBadMessage() {
   bad_message_ = true;
+
+  if (render_frame_host()) {
+    ReceivedBadMessage(render_frame_host()->GetProcess(),
+                       is_from_service_worker()
+                           ? extensions::bad_message::EFD_BAD_MESSAGE_WORKER
+                           : extensions::bad_message::EFD_BAD_MESSAGE,
+                       histogram_value());
+  }
 }
 
 bool ExtensionFunction::user_gesture() const {
   return user_gesture_ || UserGestureForTests::GetInstance()->HaveGesture();
 }
 
+bool ExtensionFunction::OnMessageReceived(const IPC::Message& message) {
+  return false;
+}
+
+void ExtensionFunction::SetRenderFrameHost(
+    content::RenderFrameHost* render_frame_host) {
+  // An extension function from Service Worker does not have a RenderFrameHost.
+  if (is_from_service_worker()) {
+    DCHECK(!render_frame_host);
+    return;
+  }
+
+  DCHECK_NE(render_frame_host_ == nullptr, render_frame_host == nullptr);
+  render_frame_host_ = render_frame_host;
+  tracker_.reset(render_frame_host ? new RenderFrameHostTracker(this)
+                                   : nullptr);
+}
+
+content::WebContents* ExtensionFunction::GetSenderWebContents() {
+  return render_frame_host_
+             ? content::WebContents::FromRenderFrameHost(render_frame_host_)
+             : nullptr;
+}
+
 ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() {
   return ResponseValue(
       new ArgumentListResponseValue(this, std::make_unique<base::ListValue>()));
@@ -443,21 +492,11 @@
   SendResponseImpl(result->Apply());
 }
 
-bool ExtensionFunction::PreRunValidation(std::string* error) {
-  return true;
-}
-
-ExtensionFunction::ResponseAction ExtensionFunction::RunWithValidation() {
-  std::string error;
-  if (!PreRunValidation(&error)) {
-    DCHECK(!error.empty() || bad_message_);
-    return bad_message_ ? ValidationFailure(this) : RespondNow(Error(error));
+void ExtensionFunction::OnResponded() {
+  if (!transferred_blob_uuids_.empty()) {
+    render_frame_host_->Send(
+        new ExtensionMsg_TransferBlobs(transferred_blob_uuids_));
   }
-  return Run();
-}
-
-bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
-  return false;
 }
 
 bool ExtensionFunction::HasOptionalArgument(size_t index) {
@@ -465,6 +504,20 @@
   return args_->Get(index, &value) && !value->is_none();
 }
 
+void ExtensionFunction::WriteToConsole(blink::mojom::ConsoleMessageLevel level,
+                                       const std::string& message) {
+  // Only the main frame handles dev tools messages.
+  WebContents::FromRenderFrameHost(render_frame_host_)
+      ->GetMainFrame()
+      ->AddMessageToConsole(level, message);
+}
+
+void ExtensionFunction::SetTransferredBlobUUIDs(
+    const std::vector<std::string>& blob_uuids) {
+  DCHECK(transferred_blob_uuids_.empty());  // Should only be called once.
+  transferred_blob_uuids_ = blob_uuids;
+}
+
 void ExtensionFunction::SendResponseImpl(bool success) {
   DCHECK(!response_callback_.is_null());
   DCHECK(!did_respond_) << name_;
@@ -487,137 +540,6 @@
   OnResponded();
 }
 
-UIThreadExtensionFunction::UIThreadExtensionFunction()
-    : context_(nullptr), render_frame_host_(nullptr) {}
-
-UIThreadExtensionFunction::~UIThreadExtensionFunction() {
-  if (dispatcher() && (render_frame_host() || is_from_service_worker())) {
-    dispatcher()->OnExtensionFunctionCompleted(
-        extension(), is_from_service_worker(), name());
-  }
-
-  // The extension function should always respond to avoid leaks in the
-  // renderer, dangling callbacks, etc. The exception is if the system is
-  // shutting down.
-  // TODO(devlin): Duplicate this check in IOThreadExtensionFunction. It's
-  // tricky because checking IsShuttingDown has to be called from the UI thread.
-  extensions::ExtensionsBrowserClient* browser_client =
-      extensions::ExtensionsBrowserClient::Get();
-  DCHECK(!browser_client || browser_client->IsShuttingDown() || did_respond() ||
-         ignore_all_did_respond_for_testing_do_not_use)
-      << name();
-}
-
-UIThreadExtensionFunction*
-UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
-  return this;
-}
-
-bool UIThreadExtensionFunction::PreRunValidation(std::string* error) {
-  if (!ExtensionFunction::PreRunValidation(error))
-    return false;
-
-  // TODO(crbug.com/625646) This is a partial fix to avoid crashes when certain
-  // extension functions run during shutdown. Browser or Notification creation
-  // for example create a ScopedKeepAlive, which hit a CHECK if the browser is
-  // shutting down. This fixes the current problem as the known issues happen
-  // through synchronous calls from Run(), but posted tasks will not be covered.
-  // A possible fix would involve refactoring ExtensionFunction: unrefcount
-  // here and use weakptrs for the tasks, then have it owned by something that
-  // will be destroyed naturally in the course of shut down.
-  if (extensions::ExtensionsBrowserClient::Get()->IsShuttingDown()) {
-    *error = "The browser is shutting down.";
-    return false;
-  }
-
-  return true;
-}
-
-void UIThreadExtensionFunction::SetBadMessage() {
-  ExtensionFunction::SetBadMessage();
-
-  if (render_frame_host()) {
-    ReceivedBadMessage(render_frame_host()->GetProcess(),
-                       is_from_service_worker()
-                           ? extensions::bad_message::EFD_BAD_MESSAGE_WORKER
-                           : extensions::bad_message::EFD_BAD_MESSAGE,
-                       histogram_value());
-  }
-}
-
-bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) {
-  return false;
-}
-
-void UIThreadExtensionFunction::Destruct() const {
-  BrowserThread::DeleteOnUIThread::Destruct(this);
-}
-
-void UIThreadExtensionFunction::SetRenderFrameHost(
-    content::RenderFrameHost* render_frame_host) {
-  // An extension function from Service Worker does not have a RenderFrameHost.
-  if (is_from_service_worker()) {
-    DCHECK(!render_frame_host);
-    return;
-  }
-
-  DCHECK_NE(render_frame_host_ == nullptr, render_frame_host == nullptr);
-  render_frame_host_ = render_frame_host;
-  tracker_.reset(
-      render_frame_host ? new RenderFrameHostTracker(this) : nullptr);
-}
-
-content::WebContents* UIThreadExtensionFunction::GetSenderWebContents() {
-  return render_frame_host_ ?
-      content::WebContents::FromRenderFrameHost(render_frame_host_) : nullptr;
-}
-
-void UIThreadExtensionFunction::OnResponded() {
-  if (!transferred_blob_uuids_.empty()) {
-    render_frame_host_->Send(
-        new ExtensionMsg_TransferBlobs(transferred_blob_uuids_));
-  }
-}
-
-void UIThreadExtensionFunction::SetTransferredBlobUUIDs(
-    const std::vector<std::string>& blob_uuids) {
-  DCHECK(transferred_blob_uuids_.empty());  // Should only be called once.
-  transferred_blob_uuids_ = blob_uuids;
-}
-
-void UIThreadExtensionFunction::WriteToConsole(
-    blink::mojom::ConsoleMessageLevel level,
-    const std::string& message) {
-  // Only the main frame handles dev tools messages.
-  WebContents::FromRenderFrameHost(render_frame_host_)
-      ->GetMainFrame()
-      ->AddMessageToConsole(level, message);
-}
-
-IOThreadExtensionFunction::IOThreadExtensionFunction()
-    : worker_thread_id_(extensions::kMainThreadId) {}
-
-IOThreadExtensionFunction::~IOThreadExtensionFunction() {
-}
-
-IOThreadExtensionFunction*
-IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
-  return this;
-}
-
-void IOThreadExtensionFunction::SetBadMessage() {
-  ExtensionFunction::SetBadMessage();
-  if (ipc_sender_) {
-    ReceivedBadMessage(
-        static_cast<content::BrowserMessageFilter*>(ipc_sender_.get()),
-        extensions::bad_message::EFD_BAD_MESSAGE, histogram_value());
-  }
-}
-
-void IOThreadExtensionFunction::Destruct() const {
-  BrowserThread::DeleteOnIOThread::Destruct(this);
-}
-
 ExtensionFunction::ScopedUserGestureForTests::ScopedUserGestureForTests() {
   UserGestureForTests::GetInstance()->IncrementCount();
 }
diff --git a/extensions/browser/extension_function.h b/extensions/browser/extension_function.h
index 6d19b806..139992f 100644
--- a/extensions/browser/extension_function.h
+++ b/extensions/browser/extension_function.h
@@ -30,10 +30,6 @@
 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-forward.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-forward.h"
 
-class ExtensionFunction;
-class UIThreadExtensionFunction;
-class IOThreadExtensionFunction;
-
 namespace base {
 class ListValue;
 class Value;
@@ -47,7 +43,6 @@
 
 namespace extensions {
 class ExtensionFunctionDispatcher;
-class IOThreadExtensionMessageFilter;
 class QuotaLimitHeuristic;
 }
 
@@ -88,19 +83,11 @@
     return extensions::functions::histogramvalue;                            \
   }
 
-// Traits that describe how ExtensionFunction should be deleted. This just calls
-// the virtual "Destruct" method on ExtensionFunction, allowing derived classes
-// to override the behavior.
-struct ExtensionFunctionDeleteTraits {
- public:
-  static void Destruct(const ExtensionFunction* x);
-};
-
 // Abstract base class for extension functions the ExtensionFunctionDispatcher
 // knows how to dispatch to.
-class ExtensionFunction
-    : public base::RefCountedThreadSafe<ExtensionFunction,
-                                        ExtensionFunctionDeleteTraits> {
+class ExtensionFunction : public base::RefCountedThreadSafe<
+                              ExtensionFunction,
+                              content::BrowserThread::DeleteOnUIThread> {
  public:
   enum ResponseType {
     // The function has succeeded.
@@ -118,9 +105,6 @@
 
   ExtensionFunction();
 
-  virtual UIThreadExtensionFunction* AsUIThreadExtensionFunction();
-  virtual IOThreadExtensionFunction* AsIOThreadExtensionFunction();
-
   // Returns true if the function has permission to run.
   //
   // This checks the Extension's permissions against the features declared in
@@ -320,6 +304,40 @@
 
   bool did_respond() const { return did_respond_; }
 
+  // Called when a message was received.
+  // Should return true if it processed the message.
+  virtual bool OnMessageReceived(const IPC::Message& message);
+
+  // Set the browser context which contains the extension that has originated
+  // this function call.
+  void set_browser_context(content::BrowserContext* context) {
+    context_ = context;
+  }
+  content::BrowserContext* browser_context() const { return context_; }
+
+  void SetRenderFrameHost(content::RenderFrameHost* render_frame_host);
+  content::RenderFrameHost* render_frame_host() const {
+    return render_frame_host_;
+  }
+
+  void set_dispatcher(
+      const base::WeakPtr<extensions::ExtensionFunctionDispatcher>&
+          dispatcher) {
+    dispatcher_ = dispatcher;
+  }
+  extensions::ExtensionFunctionDispatcher* dispatcher() const {
+    return dispatcher_.get();
+  }
+
+  void set_worker_thread_id(int worker_thread_id) {
+    worker_thread_id_ = worker_thread_id;
+  }
+  int worker_thread_id() const { return worker_thread_id_; }
+
+  // Returns the web contents associated with the sending |render_frame_host_|.
+  // This can be null.
+  content::WebContents* GetSenderWebContents();
+
   // Sets did_respond_ to true so that the function won't DCHECK if it never
   // sends a response. Typically, this shouldn't be used, even in testing. It's
   // only for when you want to test functionality that doesn't exercise the
@@ -419,25 +437,37 @@
 
   virtual ~ExtensionFunction();
 
-  // Helper method for ExtensionFunctionDeleteTraits. Deletes this object.
-  virtual void Destruct() const = 0;
-
   // Called after the response is sent, allowing the function to perform any
   // additional work or cleanup.
-  virtual void OnResponded() {}
+  virtual void OnResponded();
 
   // Return true if the argument to this function at |index| was provided and
   // is non-null.
   bool HasOptionalArgument(size_t index);
 
+  // Emits a message to the extension's devtools console.
+  void WriteToConsole(blink::mojom::ConsoleMessageLevel level,
+                      const std::string& message);
+
+  // Sets the Blob UUIDs whose ownership is being transferred to the renderer.
+  void SetTransferredBlobUUIDs(const std::vector<std::string>& blob_uuids);
+
   // The extension that called this function.
   scoped_refptr<const extensions::Extension> extension_;
 
   // The arguments to the API. Only non-null if argument were specified.
   std::unique_ptr<base::ListValue> args_;
 
+  // The BrowserContext of this function's extension.
+  // TODO(devlin): Grr... protected members. Move this to be private.
+  content::BrowserContext* context_ = nullptr;
+
  private:
+  friend struct content::BrowserThread::DeleteOnThread<
+      content::BrowserThread::UI>;
+  friend class base::DeleteHelper<ExtensionFunction>;
   friend class ResponseValueObject;
+  class RenderFrameHostTracker;
 
   // Call with true to indicate success, false to indicate failure. If this
   // failed, |error_| should be set.
@@ -458,133 +488,64 @@
   ResponseCallback response_callback_;
 
   // Id of this request, used to map the response back to the caller.
-  int request_id_;
+  int request_id_ = -1;
 
   // The id of the profile of this function's extension.
-  void* profile_id_;
+  void* profile_id_ = nullptr;
 
   // The name of this function.
-  const char* name_;
+  const char* name_ = nullptr;
 
   // The URL of the frame which is making this request
   GURL source_url_;
 
   // True if the js caller provides a callback function to receive the response
   // of this call.
-  bool has_callback_;
+  bool has_callback_ = false;
 
   // True if this callback should include information from incognito contexts
   // even if our profile_ is non-incognito. Note that in the case of a "split"
   // mode extension, this will always be false, and we will limit access to
   // data from within the same profile_ (either incognito or not).
-  bool include_incognito_information_;
+  bool include_incognito_information_ = false;
 
   // True if the call was made in response of user gesture.
-  bool user_gesture_;
+  bool user_gesture_ = false;
 
   // Any class that gets a malformed message should set this to true before
   // returning.  Usually we want to kill the message sending process.
-  bool bad_message_;
+  bool bad_message_ = false;
 
   // The sample value to record with the histogram API when the function
   // is invoked.
-  extensions::functions::HistogramValue histogram_value_;
+  extensions::functions::HistogramValue histogram_value_ =
+      extensions::functions::UNKNOWN;
 
   // The type of the JavaScript context where this call originated.
-  extensions::Feature::Context source_context_type_;
+  extensions::Feature::Context source_context_type_ =
+      extensions::Feature::UNSPECIFIED_CONTEXT;
 
   // The process ID of the page that triggered this function call, or -1
   // if unknown.
-  int source_process_id_;
+  int source_process_id_ = -1;
 
   // If this ExtensionFunction was called by an extension Service Worker, then
   // this contains the worker's version id.
-  int64_t service_worker_version_id_;
+  int64_t service_worker_version_id_ =
+      blink::mojom::kInvalidServiceWorkerVersionId;
 
   // The response type of the function, if the response has been sent.
   std::unique_ptr<ResponseType> response_type_;
 
   // Whether this function has responded.
   // TODO(devlin): Replace this with response_type_ != null.
-  bool did_respond_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionFunction);
-};
-
-// Extension functions that run on the UI thread. Most functions fall into
-// this category.
-class UIThreadExtensionFunction : public ExtensionFunction {
- public:
-  UIThreadExtensionFunction();
-
-  UIThreadExtensionFunction* AsUIThreadExtensionFunction() override;
-
-  bool PreRunValidation(std::string* error) override;
-  void SetBadMessage() final;
-
-  // Called when a message was received.
-  // Should return true if it processed the message.
-  virtual bool OnMessageReceived(const IPC::Message& message);
-
-  // Set the browser context which contains the extension that has originated
-  // this function call.
-  void set_browser_context(content::BrowserContext* context) {
-    context_ = context;
-  }
-  content::BrowserContext* browser_context() const { return context_; }
-
-  void SetRenderFrameHost(content::RenderFrameHost* render_frame_host);
-  content::RenderFrameHost* render_frame_host() const {
-    return render_frame_host_;
-  }
-
-  void set_dispatcher(const base::WeakPtr<
-      extensions::ExtensionFunctionDispatcher>& dispatcher) {
-    dispatcher_ = dispatcher;
-  }
-  extensions::ExtensionFunctionDispatcher* dispatcher() const {
-    return dispatcher_.get();
-  }
-
-  void set_worker_thread_id(int worker_thread_id) {
-    worker_thread_id_ = worker_thread_id;
-  }
-  int worker_thread_id() const { return worker_thread_id_; }
-
-  // Returns the web contents associated with the sending |render_frame_host_|.
-  // This can be null.
-  content::WebContents* GetSenderWebContents();
-
- protected:
-  // Emits a message to the extension's devtools console.
-  void WriteToConsole(blink::mojom::ConsoleMessageLevel level,
-                      const std::string& message);
-
-  friend struct content::BrowserThread::DeleteOnThread<
-      content::BrowserThread::UI>;
-  friend class base::DeleteHelper<UIThreadExtensionFunction>;
-
-  ~UIThreadExtensionFunction() override;
-
-  void OnResponded() override;
-
-  // Sets the Blob UUIDs whose ownership is being transferred to the renderer.
-  void SetTransferredBlobUUIDs(const std::vector<std::string>& blob_uuids);
-
-  // The BrowserContext of this function's extension.
-  // TODO(devlin): Grr... protected members. Move this to be private.
-  content::BrowserContext* context_;
-
- private:
-  class RenderFrameHostTracker;
-
-  void Destruct() const override;
+  bool did_respond_ = false;
 
   // The dispatcher that will service this extension function call.
   base::WeakPtr<extensions::ExtensionFunctionDispatcher> dispatcher_;
 
   // The RenderFrameHost we will send responses to.
-  content::RenderFrameHost* render_frame_host_;
+  content::RenderFrameHost* render_frame_host_ = nullptr;
 
   std::unique_ptr<RenderFrameHostTracker> tracker_;
 
@@ -593,63 +554,7 @@
 
   int worker_thread_id_ = -1;
 
-  DISALLOW_COPY_AND_ASSIGN(UIThreadExtensionFunction);
-};
-
-// Extension functions that run on the IO thread. This type of function avoids
-// a roundtrip to and from the UI thread (because communication with the
-// extension process happens on the IO thread). It's intended to be used when
-// performance is critical (e.g. the webRequest API which can block network
-// requests). Generally, UIThreadExtensionFunction is more appropriate and will
-// be easier to use and interface with the rest of the browser.
-// To use this, specify `"forIOThread": true` in the function's schema.
-// TODO(http://crbug.com/980774): Remove this as it is no longer used. Also
-// remove "forIOThread" support in JSON.
-class IOThreadExtensionFunction : public ExtensionFunction {
- public:
-  IOThreadExtensionFunction();
-
-  IOThreadExtensionFunction* AsIOThreadExtensionFunction() override;
-  void SetBadMessage() final;
-
-  void set_ipc_sender(
-      base::WeakPtr<extensions::IOThreadExtensionMessageFilter> ipc_sender) {
-    ipc_sender_ = ipc_sender;
-  }
-
-  base::WeakPtr<extensions::IOThreadExtensionMessageFilter> ipc_sender_weak()
-      const {
-    return ipc_sender_;
-  }
-
-  void set_worker_thread_id(int worker_thread_id) {
-    worker_thread_id_ = worker_thread_id;
-  }
-  int worker_thread_id() const { return worker_thread_id_; }
-
-  void set_extension_info_map(const extensions::InfoMap* extension_info_map) {
-    extension_info_map_ = extension_info_map;
-  }
-  const extensions::InfoMap* extension_info_map() const {
-    return extension_info_map_.get();
-  }
-
- protected:
-  friend struct content::BrowserThread::DeleteOnThread<
-      content::BrowserThread::IO>;
-  friend class base::DeleteHelper<IOThreadExtensionFunction>;
-
-  ~IOThreadExtensionFunction() override;
-
-  void Destruct() const override;
-
- private:
-  base::WeakPtr<extensions::IOThreadExtensionMessageFilter> ipc_sender_;
-  int worker_thread_id_;
-
-  scoped_refptr<const extensions::InfoMap> extension_info_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(IOThreadExtensionFunction);
+  DISALLOW_COPY_AND_ASSIGN(ExtensionFunction);
 };
 
 #endif  // EXTENSIONS_BROWSER_EXTENSION_FUNCTION_H_
diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc
index f63b7d3..15b13c88 100644
--- a/extensions/browser/extension_function_dispatcher.cc
+++ b/extensions/browser/extension_function_dispatcher.cc
@@ -67,16 +67,6 @@
          blink::mojom::kInvalidServiceWorkerVersionId;
 }
 
-// Separate copy of ExtensionAPI used for IO thread extension functions. We need
-// this because ExtensionAPI has mutable data. It should be possible to remove
-// this once all the extension APIs are updated to the feature system.
-struct Static {
-  Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {}
-  std::unique_ptr<ExtensionAPI> api;
-};
-base::LazyInstance<Static>::DestructorAtExit g_global_io_data =
-    LAZY_INSTANCE_INITIALIZER;
-
 void CommonResponseCallback(IPC::Sender* ipc_sender,
                             int routing_id,
                             int worker_thread_id,
@@ -104,23 +94,10 @@
   }
 }
 
-void IOThreadResponseCallback(
-    const base::WeakPtr<IOThreadExtensionMessageFilter>& ipc_sender,
-    int routing_id,
-    int worker_thread_id,
-    int request_id,
-    ExtensionFunction::ResponseType type,
-    const base::ListValue& results,
-    const std::string& error) {
-  if (!ipc_sender.get())
-    return;
-
-  CommonResponseCallback(ipc_sender.get(), routing_id, worker_thread_id,
-                         request_id, type, results, error);
-}
-
 }  // namespace
 
+// TODO(http://crbug.com/980774): Simplify this or change the name now that
+// IOThreadExtensionFunction is gone.
 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper
     : public content::WebContentsObserver {
  public:
@@ -273,109 +250,6 @@
   return GetAssociatedWebContents();
 }
 
-// static
-void ExtensionFunctionDispatcher::DoDispatchOnIOThread(
-    InfoMap* extension_info_map,
-    void* profile_id,
-    int render_process_id,
-    base::WeakPtr<IOThreadExtensionMessageFilter> ipc_sender,
-    const ExtensionHostMsg_Request_Params& params,
-    const ExtensionFunction::ResponseCallback& callback) {
-  const Extension* extension =
-      extension_info_map->extensions().GetByID(params.extension_id);
-
-  scoped_refptr<ExtensionFunction> function(
-      CreateExtensionFunction(params,
-                              extension,
-                              render_process_id,
-                              extension_info_map->process_map(),
-                              g_global_io_data.Get().api.get(),
-                              profile_id,
-                              callback));
-  if (!function.get())
-    return;
-
-  IOThreadExtensionFunction* function_io =
-      function->AsIOThreadExtensionFunction();
-  if (!function_io) {
-    NOTREACHED();
-    return;
-  }
-  function_io->set_ipc_sender(ipc_sender);
-  function_io->set_worker_thread_id(params.worker_thread_id);
-  function_io->set_service_worker_version_id(params.service_worker_version_id);
-  function_io->set_extension_info_map(extension_info_map);
-  if (extension) {
-    function->set_include_incognito_information(
-        extension_info_map->CanCrossIncognito(extension));
-  }
-
-  if (!CheckPermissions(function.get(), params, callback))
-    return;
-
-  if (!extension) {
-    // Skip all of the UMA, quota, event page, activity logging stuff if there
-    // isn't an extension, e.g. if the function call was from WebUI.
-    function->RunWithValidation()->Execute();
-    return;
-  }
-
-  QuotaService* quota = extension_info_map->GetQuotaService();
-  std::string violation_error = quota->Assess(extension->id(),
-                                              function.get(),
-                                              &params.arguments,
-                                              base::TimeTicks::Now());
-  if (violation_error.empty()) {
-    NotifyApiFunctionCalled(extension->id(), params.name, params.arguments,
-                            static_cast<content::BrowserContext*>(profile_id));
-    base::UmaHistogramSparse("Extensions.FunctionCalls",
-                             function->histogram_value());
-    base::ElapsedTimer timer;
-    function->RunWithValidation()->Execute();
-    // TODO(devlin): Once we have a baseline metric for how long functions take,
-    // we can create a handful of buckets and record the function name so that
-    // we can find what the fastest/slowest are.
-    // Note: Many functions execute finish asynchronously, so this time is not
-    // always a representation of total time taken. See also
-    // Extensions.Functions.TotalExecutionTime.
-    UMA_HISTOGRAM_TIMES("Extensions.Functions.SynchronousExecutionTime",
-                        timer.Elapsed());
-  } else {
-    function->OnQuotaExceeded(violation_error);
-  }
-}
-
-// static
-void ExtensionFunctionDispatcher::DispatchOnIOThread(
-    InfoMap* extension_info_map,
-    void* profile_id,
-    int render_process_id,
-    base::WeakPtr<IOThreadExtensionMessageFilter> ipc_sender,
-    int routing_id,
-    const ExtensionHostMsg_Request_Params& params) {
-  ExtensionFunction::ResponseCallback callback(
-      base::BindRepeating(&IOThreadResponseCallback, ipc_sender, routing_id,
-                          kMainThreadId, params.request_id));
-
-  DoDispatchOnIOThread(extension_info_map, profile_id, render_process_id,
-                       ipc_sender, params, callback);
-}
-
-// static
-void ExtensionFunctionDispatcher::DispatchOnIOThreadForServiceWorker(
-    InfoMap* extension_info_map,
-    void* profile_id,
-    int render_process_id,
-    base::WeakPtr<IOThreadExtensionMessageFilter> ipc_sender,
-    const ExtensionHostMsg_Request_Params& params) {
-  ExtensionFunction::ResponseCallback callback(base::BindRepeating(
-      &IOThreadResponseCallback, ipc_sender, MSG_ROUTING_NONE,
-      params.worker_thread_id, params.request_id));
-
-  DoDispatchOnIOThread(extension_info_map, profile_id, render_process_id,
-                       ipc_sender, params, callback);
-}
-
 ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
     content::BrowserContext* browser_context)
     : browser_context_(browser_context), delegate_(nullptr) {}
@@ -446,8 +320,6 @@
     content::RenderFrameHost* render_frame_host,
     int render_process_id,
     const ExtensionFunction::ResponseCallback& callback) {
-  // TODO(yzshen): There is some shared logic between this method and
-  // DispatchOnIOThread(). It is nice to deduplicate.
   ProcessMap* process_map = ProcessMap::Get(browser_context_);
   if (!process_map)
     return;
@@ -469,21 +341,14 @@
   if (!function.get())
     return;
 
-  UIThreadExtensionFunction* function_ui =
-      function->AsUIThreadExtensionFunction();
-  if (!function_ui) {
-    NOTREACHED();
-    return;
-  }
-  function_ui->set_worker_thread_id(params.worker_thread_id);
+  function->set_worker_thread_id(params.worker_thread_id);
   if (IsRequestFromServiceWorker(params)) {
-    function_ui->set_service_worker_version_id(
-        params.service_worker_version_id);
+    function->set_service_worker_version_id(params.service_worker_version_id);
   } else {
-    function_ui->SetRenderFrameHost(render_frame_host);
+    function->SetRenderFrameHost(render_frame_host);
   }
-  function_ui->set_dispatcher(AsWeakPtr());
-  function_ui->set_browser_context(browser_context_);
+  function->set_dispatcher(AsWeakPtr());
+  function->set_browser_context(browser_context_);
   if (extension &&
       ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
           extension, browser_context_)) {
@@ -556,11 +421,6 @@
   if (!IsRequestFromServiceWorker(params)) {
     // Increment ref count for non-service worker extension API. Ref count for
     // service worker extension API is handled separately on IO thread via IPC.
-
-    // We only adjust the keepalive count for UIThreadExtensionFunction for
-    // now, largely for simplicity's sake. This is OK because currently, only
-    // the webRequest API uses IOThreadExtensionFunction, and that API is not
-    // compatible with lazy background pages.
     process_manager->IncrementLazyKeepaliveCount(
         function->extension(), Activity::API_FUNCTION, function->name());
   }
diff --git a/extensions/browser/extension_function_dispatcher.h b/extensions/browser/extension_function_dispatcher.h
index 08f11f8e..92d3529 100644
--- a/extensions/browser/extension_function_dispatcher.h
+++ b/extensions/browser/extension_function_dispatcher.h
@@ -25,8 +25,6 @@
 
 class Extension;
 class ExtensionAPI;
-class InfoMap;
-class IOThreadExtensionMessageFilter;
 class ProcessMap;
 class WindowController;
 
@@ -70,25 +68,6 @@
     virtual ~Delegate() {}
   };
 
-  // Dispatches an IO-thread extension function. Only used for specific
-  // functions that must be handled on the IO-thread.
-  static void DispatchOnIOThread(
-      InfoMap* extension_info_map,
-      void* profile_id,
-      int render_process_id,
-      base::WeakPtr<IOThreadExtensionMessageFilter> ipc_sender,
-      int routing_id,
-      const ExtensionHostMsg_Request_Params& params);
-
-  // Dispatches an IO-thread extension function for a Service Worker. Only
-  // used for specific functions that must be handled on the IO-thread.
-  static void DispatchOnIOThreadForServiceWorker(
-      InfoMap* extension_info_map,
-      void* profile_id,
-      int render_process_id,
-      base::WeakPtr<IOThreadExtensionMessageFilter> ipc_sender,
-      const ExtensionHostMsg_Request_Params& params);
-
   // Public constructor. Callers must ensure that:
   // - This object outlives any RenderFrameHost's passed to created
   //   ExtensionFunctions.
@@ -137,14 +116,6 @@
   // |ui_thread_response_callback_wrappers_for_worker_|.
   struct WorkerResponseCallbackMapKey;
 
-  static void DoDispatchOnIOThread(
-      InfoMap* extension_info_map,
-      void* profile_id,
-      int render_process_id,
-      base::WeakPtr<IOThreadExtensionMessageFilter> ipc_sender,
-      const ExtensionHostMsg_Request_Params& params,
-      const ExtensionFunction::ResponseCallback& callback);
-
   // Helper to check whether an ExtensionFunction has the required permissions.
   // This should be called after the function is fully initialized.
   // If the check fails, |callback| is run with an access-denied error and false
diff --git a/extensions/browser/io_thread_extension_message_filter.cc b/extensions/browser/io_thread_extension_message_filter.cc
index 20ee5d02..02dce56 100644
--- a/extensions/browser/io_thread_extension_message_filter.cc
+++ b/extensions/browser/io_thread_extension_message_filter.cc
@@ -6,9 +6,6 @@
 
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
-#include "extensions/browser/extension_function_dispatcher.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/browser/info_map.h"
 #include "extensions/common/extension_messages.h"
 #include "ipc/ipc_message_macros.h"
 
@@ -16,13 +13,8 @@
 
 namespace extensions {
 
-IOThreadExtensionMessageFilter::IOThreadExtensionMessageFilter(
-    int render_process_id,
-    content::BrowserContext* context)
-    : BrowserMessageFilter(ExtensionMsgStart),
-      render_process_id_(render_process_id),
-      browser_context_id_(context),
-      extension_info_map_(ExtensionSystem::Get(context)->info_map()) {
+IOThreadExtensionMessageFilter::IOThreadExtensionMessageFilter()
+    : BrowserMessageFilter(ExtensionMsgStart) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
@@ -42,10 +34,6 @@
   IPC_BEGIN_MESSAGE_MAP(IOThreadExtensionMessageFilter, message)
   IPC_MESSAGE_HANDLER(ExtensionHostMsg_GenerateUniqueID,
                       OnExtensionGenerateUniqueID)
-  IPC_MESSAGE_HANDLER(ExtensionHostMsg_RequestForIOThread,
-                      OnExtensionRequestForIOThread)
-  IPC_MESSAGE_HANDLER(ExtensionHostMsg_RequestWorkerForIOThread,
-                      OnExtensionRequestWorkerForIOThread)
   IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -57,21 +45,4 @@
   *unique_id = ++next_unique_id;
 }
 
-void IOThreadExtensionMessageFilter::OnExtensionRequestForIOThread(
-    int routing_id,
-    const ExtensionHostMsg_Request_Params& params) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  ExtensionFunctionDispatcher::DispatchOnIOThread(
-      extension_info_map_.get(), browser_context_id_, render_process_id_,
-      weak_ptr_factory_.GetWeakPtr(), routing_id, params);
-}
-
-void IOThreadExtensionMessageFilter::OnExtensionRequestWorkerForIOThread(
-    const ExtensionHostMsg_Request_Params& params) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  ExtensionFunctionDispatcher::DispatchOnIOThreadForServiceWorker(
-      extension_info_map_.get(), browser_context_id_, render_process_id_,
-      weak_ptr_factory_.GetWeakPtr(), params);
-}
-
 }  // namespace extensions
diff --git a/extensions/browser/io_thread_extension_message_filter.h b/extensions/browser/io_thread_extension_message_filter.h
index 091dad9..4b67c55 100644
--- a/extensions/browser/io_thread_extension_message_filter.h
+++ b/extensions/browser/io_thread_extension_message_filter.h
@@ -5,30 +5,16 @@
 #ifndef EXTENSIONS_BROWSER_IO_THREAD_EXTENSION_MESSAGE_FILTER_H_
 #define EXTENSIONS_BROWSER_IO_THREAD_EXTENSION_MESSAGE_FILTER_H_
 
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
 #include "content/public/browser/browser_message_filter.h"
 
-struct ExtensionHostMsg_Request_Params;
-
-namespace content {
-class BrowserContext;
-}
-
 namespace extensions {
 
-class InfoMap;
-
 // This class filters out incoming extension-specific IPC messages from the
 // renderer process. It is created on the UI thread, but handles messages on the
 // IO thread and is destroyed there.
 class IOThreadExtensionMessageFilter : public content::BrowserMessageFilter {
  public:
-  IOThreadExtensionMessageFilter(int render_process_id,
-                                 content::BrowserContext* context);
-
-  int render_process_id() { return render_process_id_; }
+  IOThreadExtensionMessageFilter();
 
  private:
   friend class base::DeleteHelper<IOThreadExtensionMessageFilter>;
@@ -42,22 +28,6 @@
 
   // Message handlers on the IO thread.
   void OnExtensionGenerateUniqueID(int* unique_id);
-  void OnExtensionRequestForIOThread(
-      int routing_id,
-      const ExtensionHostMsg_Request_Params& params);
-  void OnExtensionRequestWorkerForIOThread(
-      const ExtensionHostMsg_Request_Params& params);
-
-  const int render_process_id_;
-
-  // The browser context as a void pointer, for use as an identifier on the IO
-  // thread.
-  void* browser_context_id_;
-
-  scoped_refptr<extensions::InfoMap> extension_info_map_;
-
-  // Weak pointers produced by this factory are bound to the IO thread.
-  base::WeakPtrFactory<IOThreadExtensionMessageFilter> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(IOThreadExtensionMessageFilter);
 };
diff --git a/extensions/browser/quota_service_unittest.cc b/extensions/browser/quota_service_unittest.cc
index c5a69012..95ac240d 100644
--- a/extensions/browser/quota_service_unittest.cc
+++ b/extensions/browser/quota_service_unittest.cc
@@ -61,7 +61,6 @@
  public:
   explicit MockFunction(const char* name) { set_name(name); }
 
-  void Destruct() const override { delete this; }
   ResponseAction Run() override { return RespondLater(); }
 
  protected:
diff --git a/extensions/common/extension_messages.h b/extensions/common/extension_messages.h
index 4467ebf..48ac3c93 100644
--- a/extensions/common/extension_messages.h
+++ b/extensions/common/extension_messages.h
@@ -738,20 +738,6 @@
 IPC_MESSAGE_ROUTED1(ExtensionHostMsg_Request,
                     ExtensionHostMsg_Request_Params)
 
-// A renderer sends this message when an extension process starts an API
-// request. The browser will always respond with a ExtensionMsg_Response.
-IPC_MESSAGE_CONTROL2(ExtensionHostMsg_RequestForIOThread,
-                     int /* routing_id */,
-                     ExtensionHostMsg_Request_Params)
-
-// A service worker thread sends this message when an extension service worker
-// starts an API request. The browser will always respond with a
-// ExtensionMsg_ResponseWorker. This message is for API requests that run on
-// the IO thread. It is defined here so it's handled by the same message
-// filter as ExtensionHostMsg_RequestForIOThread.
-IPC_MESSAGE_CONTROL1(ExtensionHostMsg_RequestWorkerForIOThread,
-                     ExtensionHostMsg_Request_Params)
-
 // Notify the browser that the given extension added a listener to an event.
 IPC_MESSAGE_CONTROL5(ExtensionHostMsg_AddListener,
                      std::string /* extension_id */,
diff --git a/extensions/docs/api_functions.md b/extensions/docs/api_functions.md
index 102eabc..f0ddfda2 100644
--- a/extensions/docs/api_functions.md
+++ b/extensions/docs/api_functions.md
@@ -90,7 +90,7 @@
 Next, we define the function in C++, starting with the header file.
 
 ```
-GizmoFrobulateFunction : public UIThreadExtensionFunction {
+GizmoFrobulateFunction : public ExtensionFunction {
  public:
   // This declares the extension function and initiates the mapping between the
   // string name to the C++ class as well as the histogram value.
diff --git a/extensions/renderer/bindings/api_binding.cc b/extensions/renderer/bindings/api_binding.cc
index 0f003be..ff82934f 100644
--- a/extensions/renderer/bindings/api_binding.cc
+++ b/extensions/renderer/bindings/api_binding.cc
@@ -105,18 +105,14 @@
 }  // namespace
 
 struct APIBinding::MethodData {
-  MethodData(std::string full_name,
-             const APISignature* signature,
-             binding::RequestThread thread)
-      : full_name(std::move(full_name)), signature(signature), thread(thread) {}
+  MethodData(std::string full_name, const APISignature* signature)
+      : full_name(std::move(full_name)), signature(signature) {}
 
   // The fully-qualified name of this api (e.g. runtime.sendMessage instead of
   // sendMessage).
   const std::string full_name;
   // The expected API signature.
   const APISignature* signature;
-  // Thread to invoke the method on.
-  const binding::RequestThread thread;
   // The callback used by the v8 function.
   APIBinding::HandlerCallback callback;
 };
@@ -234,15 +230,10 @@
 
       SignaturePair signatures = GetAPISignatureFromDictionary(func_dict);
 
-      bool for_io_thread = false;
-      func_dict->GetBoolean("forIOThread", &for_io_thread);
-
       std::string full_name =
           base::StringPrintf("%s.%s", api_name_.c_str(), name.c_str());
       methods_[name] = std::make_unique<MethodData>(
-          full_name, signatures.method_signature.get(),
-          for_io_thread ? binding::RequestThread::IO
-                        : binding::RequestThread::UI);
+          full_name, signatures.method_signature.get());
       type_refs->AddAPIMethodSignature(full_name,
                                        std::move(signatures.method_signature));
       if (signatures.callback_signature) {
@@ -417,7 +408,7 @@
     DCHECK(method.callback.is_null());
     method.callback =
         base::BindRepeating(&APIBinding::HandleCall, weak_factory_.GetWeakPtr(),
-                            method.full_name, method.signature, method.thread);
+                            method.full_name, method.signature);
 
     object_template->Set(
         gin::StringToSymbol(isolate, key_value.first),
@@ -593,7 +584,6 @@
 
 void APIBinding::HandleCall(const std::string& name,
                             const APISignature* signature,
-                            const binding::RequestThread thread,
                             gin::Arguments* arguments) {
   std::string error;
   v8::Isolate* isolate = arguments->isolate();
@@ -696,9 +686,9 @@
     return;
   }
 
-  request_handler_->StartRequest(
-      context, name, std::move(parse_result.arguments), parse_result.callback,
-      custom_callback, thread);
+  request_handler_->StartRequest(context, name,
+                                 std::move(parse_result.arguments),
+                                 parse_result.callback, custom_callback);
 }
 
 }  // namespace extensions
diff --git a/extensions/renderer/bindings/api_binding.h b/extensions/renderer/bindings/api_binding.h
index 1559f7f..e62af33 100644
--- a/extensions/renderer/bindings/api_binding.h
+++ b/extensions/renderer/bindings/api_binding.h
@@ -108,7 +108,6 @@
   // |thread| and matches the arguments against |signature|.
   void HandleCall(const std::string& name,
                   const APISignature* signature,
-                  const binding::RequestThread thread,
                   gin::Arguments* args);
 
   // The root name of the API, e.g. "tabs" for chrome.tabs.
diff --git a/extensions/renderer/bindings/api_binding_js_util.cc b/extensions/renderer/bindings/api_binding_js_util.cc
index 19b10b6..c44419f0 100644
--- a/extensions/renderer/bindings/api_binding_js_util.cc
+++ b/extensions/renderer/bindings/api_binding_js_util.cc
@@ -70,7 +70,6 @@
   const APISignature* signature = type_refs_->GetAPIMethodSignature(name);
   DCHECK(signature);
 
-  binding::RequestThread thread = binding::RequestThread::UI;
   v8::Local<v8::Function> custom_callback;
   if (!options.IsEmpty() && !options->IsUndefined() && !options->IsNull()) {
     if (!options->IsObject()) {
@@ -83,11 +82,8 @@
       return;
     }
     gin::Dictionary options_dict(isolate, options_obj);
-    // NOTE: We don't throw any errors here if forIOThread or customCallback are
-    // of invalid types. We could, if we wanted to be a bit more verbose.
-    bool for_io_thread = false;
-    if (options_dict.Get("forIOThread", &for_io_thread) && for_io_thread)
-      thread = binding::RequestThread::IO;
+    // NOTE: We don't throw any errors here if customCallback is of an invalid
+    // type. We could, if we wanted to be a bit more verbose.
     options_dict.Get("customCallback", &custom_callback);
   }
 
@@ -104,9 +100,9 @@
       signature->ConvertArgumentsIgnoringSchema(context, request_args);
   CHECK(parse_result.succeeded());
 
-  request_handler_->StartRequest(
-      context, name, std::move(parse_result.arguments), parse_result.callback,
-      custom_callback, thread);
+  request_handler_->StartRequest(context, name,
+                                 std::move(parse_result.arguments),
+                                 parse_result.callback, custom_callback);
 }
 
 void APIBindingJSUtil::RegisterEventArgumentMassager(
diff --git a/extensions/renderer/bindings/api_binding_js_util_unittest.cc b/extensions/renderer/bindings/api_binding_js_util_unittest.cc
index f456bda..9e8aafe 100644
--- a/extensions/renderer/bindings/api_binding_js_util_unittest.cc
+++ b/extensions/renderer/bindings/api_binding_js_util_unittest.cc
@@ -174,29 +174,16 @@
   ASSERT_TRUE(last_request());
   EXPECT_EQ("alpha.functionWithCallback", last_request()->method_name);
   EXPECT_EQ("[\"someString\"]", ValueToString(*last_request()->arguments));
-  EXPECT_EQ(binding::RequestThread::UI, last_request()->thread);
-  reset_last_request();
-
-  const char kSendRequestForIOThread[] =
-      "obj.sendRequest('alpha.functionWithCallback',\n"
-      "                ['someOtherString', function() {}],\n"
-      "                {__proto__: null, forIOThread: true});";
-  CallFunctionOnObject(context, v8_util, kSendRequestForIOThread);
-  ASSERT_TRUE(last_request());
-  EXPECT_EQ("alpha.functionWithCallback", last_request()->method_name);
-  EXPECT_EQ("[\"someOtherString\"]", ValueToString(*last_request()->arguments));
-  EXPECT_EQ(binding::RequestThread::IO, last_request()->thread);
   reset_last_request();
 
   const char kSendRequestForUIThread[] =
       "obj.sendRequest('alpha.functionWithCallback',\n"
       "                ['someOtherString', function() {}],\n"
-      "                {__proto__: null, forIOThread: false});";
+      "                {__proto__: null});";
   CallFunctionOnObject(context, v8_util, kSendRequestForUIThread);
   ASSERT_TRUE(last_request());
   EXPECT_EQ("alpha.functionWithCallback", last_request()->method_name);
   EXPECT_EQ("[\"someOtherString\"]", ValueToString(*last_request()->arguments));
-  EXPECT_EQ(binding::RequestThread::UI, last_request()->thread);
   reset_last_request();
 
   const char kSendRequestWithCustomCallback[] =
@@ -213,7 +200,6 @@
   ASSERT_TRUE(last_request());
   EXPECT_EQ("alpha.functionWithCallback", last_request()->method_name);
   EXPECT_EQ("[\"stringy\"]", ValueToString(*last_request()->arguments));
-  EXPECT_EQ(binding::RequestThread::UI, last_request()->thread);
   bindings_system()->CompleteRequest(last_request()->request_id,
                                      base::ListValue(), std::string());
   EXPECT_EQ("true", GetStringPropertyFromObject(context->Global(), context,
@@ -239,7 +225,6 @@
   ASSERT_TRUE(last_request());
   EXPECT_EQ("alpha.functionWithCallback", last_request()->method_name);
   EXPECT_EQ("[null,null]", ValueToString(*last_request()->arguments));
-  EXPECT_EQ(binding::RequestThread::UI, last_request()->thread);
   reset_last_request();
 }
 
diff --git a/extensions/renderer/bindings/api_binding_types.h b/extensions/renderer/bindings/api_binding_types.h
index 8461616..e00c185 100644
--- a/extensions/renderer/bindings/api_binding_types.h
+++ b/extensions/renderer/bindings/api_binding_types.h
@@ -44,12 +44,6 @@
   kLastListenerWithFilterForContextOwnerRemoved,
 };
 
-// The browser thread that the request should be sent to.
-enum class RequestThread {
-  UI,
-  IO,
-};
-
 // Whether promises are supported in a given API function.
 enum class PromiseSupport {
   kAllowed,
diff --git a/extensions/renderer/bindings/api_binding_unittest.cc b/extensions/renderer/bindings/api_binding_unittest.cc
index 933bc68..08edf038 100644
--- a/extensions/renderer/bindings/api_binding_unittest.cc
+++ b/extensions/renderer/bindings/api_binding_unittest.cc
@@ -367,50 +367,6 @@
               "Badness");
 }
 
-// Test that "forIOThread" property in a function schema is respected.
-TEST_F(APIBindingUnittest, IOThreadCalls) {
-  const char kFunctions[] =
-      "[{"
-      "  'name' : 'uiFunc1',"
-      "  'parameters' : []"
-      "}, {"
-      "  'name' : 'uiFunc2',"
-      "  'parameters' : [],"
-      "  'forIOThread' : false"
-      "}, {"
-      "  'name' : 'ioFunc',"
-      "  'parameters' : [],"
-      "  'forIOThread' : true"
-      "}]";
-  SetFunctions(kFunctions);
-  InitializeBinding();
-
-  v8::HandleScope handle_scope(isolate());
-  v8::Local<v8::Context> context = MainContext();
-  v8::Local<v8::Object> binding_object = binding()->CreateInstance(context);
-
-  struct {
-    const char* func_name;
-    binding::RequestThread thread;
-  } test_cases[] = {
-      {"uiFunc1", binding::RequestThread::UI},
-      {"uiFunc2", binding::RequestThread::UI},
-      {"ioFunc", binding::RequestThread::IO},
-  };
-  const char kFunctionCall[] = "(function(obj) { obj.%s(); })";
-  v8::Local<v8::Value> argv[] = {binding_object};
-
-  for (const auto& test_case : test_cases) {
-    SCOPED_TRACE(base::StringPrintf("Testing case-%s", test_case.func_name));
-    v8::Local<v8::Function> func = FunctionFromString(
-        context, base::StringPrintf(kFunctionCall, test_case.func_name));
-    RunFunction(func, context, base::size(argv), argv);
-    ASSERT_TRUE(last_request());
-    EXPECT_EQ(test_case.thread, last_request()->thread);
-    reset_last_request();
-  }
-}
-
 // Test that enum values are properly exposed on the binding object.
 TEST_F(APIBindingUnittest, EnumValues) {
   const char kTypes[] =
@@ -1507,10 +1463,10 @@
          v8::Local<v8::Context> context,
          std::vector<v8::Local<v8::Value>>* arguments,
          const APITypeReferenceMap& map) {
-        handler->StartRequest(
-            context, "test.handleAndSendRequest",
-            std::make_unique<base::ListValue>(), v8::Local<v8::Function>(),
-            v8::Local<v8::Function>(), binding::RequestThread::UI);
+        handler->StartRequest(context, "test.handleAndSendRequest",
+                              std::make_unique<base::ListValue>(),
+                              v8::Local<v8::Function>(),
+                              v8::Local<v8::Function>());
         return RequestResult(RequestResult::HANDLED);
       };
   hooks->AddHandler(
diff --git a/extensions/renderer/bindings/api_request_handler.cc b/extensions/renderer/bindings/api_request_handler.cc
index 9e50db0..cff35b2 100644
--- a/extensions/renderer/bindings/api_request_handler.cc
+++ b/extensions/renderer/bindings/api_request_handler.cc
@@ -247,8 +247,7 @@
                                     const std::string& method,
                                     std::unique_ptr<base::ListValue> arguments,
                                     v8::Local<v8::Function> callback,
-                                    v8::Local<v8::Function> custom_callback,
-                                    binding::RequestThread thread) {
+                                    v8::Local<v8::Function> custom_callback) {
   std::unique_ptr<AsyncResultHandler> async_handler;
   int request_id = GetNextRequestId();
   if (!custom_callback.IsEmpty() || !callback.IsEmpty()) {
@@ -285,7 +284,7 @@
         isolate, callback, std::move(callback_args));
   }
 
-  StartRequestImpl(context, request_id, method, std::move(arguments), thread,
+  StartRequestImpl(context, request_id, method, std::move(arguments),
                    std::move(async_handler));
   return request_id;
 }
@@ -294,14 +293,13 @@
 APIRequestHandler::StartPromiseBasedRequest(
     v8::Local<v8::Context> context,
     const std::string& method,
-    std::unique_ptr<base::ListValue> arguments,
-    binding::RequestThread thread) {
+    std::unique_ptr<base::ListValue> arguments) {
   v8::Isolate* isolate = context->GetIsolate();
   v8::Local<v8::Promise::Resolver> resolver =
       v8::Promise::Resolver::New(context).ToLocalChecked();
   auto async_handler = std::make_unique<AsyncResultHandler>(isolate, resolver);
   int request_id = GetNextRequestId();
-  StartRequestImpl(context, request_id, method, std::move(arguments), thread,
+  StartRequestImpl(context, request_id, method, std::move(arguments),
                    std::move(async_handler));
 
   return {request_id, resolver->GetPromise()};
@@ -382,7 +380,6 @@
     int request_id,
     const std::string& method,
     std::unique_ptr<base::ListValue> arguments,
-    binding::RequestThread thread,
     std::unique_ptr<AsyncResultHandler> async_handler) {
   auto request = std::make_unique<Request>();
   request->request_id = request_id;
@@ -403,7 +400,6 @@
       interaction_provider_->HasActiveInteraction(context);
   request->arguments = std::move(arguments);
   request->method_name = method;
-  request->thread = thread;
 
   last_sent_request_id_ = request_id;
   send_request_.Run(std::move(request), context);
diff --git a/extensions/renderer/bindings/api_request_handler.h b/extensions/renderer/bindings/api_request_handler.h
index 123fe92..5ebe753 100644
--- a/extensions/renderer/bindings/api_request_handler.h
+++ b/extensions/renderer/bindings/api_request_handler.h
@@ -40,7 +40,6 @@
     std::string method_name;
     bool has_callback = false;
     bool has_user_gesture = false;
-    binding::RequestThread thread = binding::RequestThread::UI;
     std::unique_ptr<base::ListValue> arguments;
 
    private:
@@ -64,16 +63,14 @@
                    const std::string& method,
                    std::unique_ptr<base::ListValue> arguments,
                    v8::Local<v8::Function> callback,
-                   v8::Local<v8::Function> custom_callback,
-                   binding::RequestThread thread);
+                   v8::Local<v8::Function> custom_callback);
 
   // Starts a request and returns a promise, which will be resolved or rejected
   // when the request is completed.
   std::pair<int, v8::Local<v8::Promise>> StartPromiseBasedRequest(
       v8::Local<v8::Context> context,
       const std::string& method,
-      std::unique_ptr<base::ListValue> arguments,
-      binding::RequestThread thread);
+      std::unique_ptr<base::ListValue> arguments);
 
   // Adds a pending request for the request handler to manage (and complete via
   // CompleteRequest). This is used by renderer-side implementations that
@@ -142,7 +139,6 @@
                         int request_id,
                         const std::string& method,
                         std::unique_ptr<base::ListValue> arguments,
-                        binding::RequestThread thread,
                         std::unique_ptr<AsyncResultHandler> async_handler);
 
   // Common implementation for completing a request.
diff --git a/extensions/renderer/bindings/api_request_handler_unittest.cc b/extensions/renderer/bindings/api_request_handler_unittest.cc
index b3672d41..8e647df6 100644
--- a/extensions/renderer/bindings/api_request_handler_unittest.cc
+++ b/extensions/renderer/bindings/api_request_handler_unittest.cc
@@ -94,7 +94,7 @@
 
   int request_id = request_handler->StartRequest(
       context, kMethod, std::make_unique<base::ListValue>(), function,
-      v8::Local<v8::Function>(), binding::RequestThread::UI);
+      v8::Local<v8::Function>());
   EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
               testing::UnorderedElementsAre(request_id));
 
@@ -113,8 +113,7 @@
 
   request_id = request_handler->StartRequest(
       context, kMethod, std::make_unique<base::ListValue>(),
-      v8::Local<v8::Function>(), v8::Local<v8::Function>(),
-      binding::RequestThread::UI);
+      v8::Local<v8::Function>(), v8::Local<v8::Function>());
   EXPECT_NE(-1, request_id);
   request_handler->CompleteRequest(request_id, base::ListValue(),
                                    std::string());
@@ -132,7 +131,7 @@
 
   int request_id = request_handler->StartRequest(
       context, kMethod, std::make_unique<base::ListValue>(), function,
-      v8::Local<v8::Function>(), binding::RequestThread::UI);
+      v8::Local<v8::Function>());
   EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
               testing::UnorderedElementsAre(request_id));
 
@@ -170,10 +169,10 @@
 
   int request_a = request_handler->StartRequest(
       context_a, kMethod, std::make_unique<base::ListValue>(), function_a,
-      v8::Local<v8::Function>(), binding::RequestThread::UI);
+      v8::Local<v8::Function>());
   int request_b = request_handler->StartRequest(
       context_b, kMethod, std::make_unique<base::ListValue>(), function_b,
-      v8::Local<v8::Function>(), binding::RequestThread::UI);
+      v8::Local<v8::Function>());
 
   EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
               testing::UnorderedElementsAre(request_a, request_b));
@@ -218,7 +217,7 @@
 
   int request_id = request_handler->StartRequest(
       context, "method", std::make_unique<base::ListValue>(), callback,
-      custom_callback, binding::RequestThread::UI);
+      custom_callback);
   EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
               testing::UnorderedElementsAre(request_id));
 
@@ -261,7 +260,7 @@
   v8::Local<v8::Function> empty_callback;
   int request_id = request_handler->StartRequest(
       context, "method", std::make_unique<base::ListValue>(), empty_callback,
-      custom_callback, binding::RequestThread::UI);
+      custom_callback);
   EXPECT_THAT(request_handler->GetPendingRequestIdsForTesting(),
               testing::UnorderedElementsAre(request_id));
 
@@ -306,7 +305,7 @@
   // Try first without a user gesture.
   int request_id = request_handler->StartRequest(
       context, kMethod, std::make_unique<base::ListValue>(), v8_callback,
-      v8::Local<v8::Function>(), binding::RequestThread::UI);
+      v8::Local<v8::Function>());
   request_handler->CompleteRequest(request_id, *ListValueFromString("[]"),
                                    std::string());
 
@@ -326,7 +325,7 @@
 
   request_id = request_handler->StartRequest(
       context, kMethod, std::make_unique<base::ListValue>(), v8_callback,
-      v8::Local<v8::Function>(), binding::RequestThread::UI);
+      v8::Local<v8::Function>());
   request_handler->CompleteRequest(request_id, *ListValueFromString("[]"),
                                    std::string());
   ASSERT_TRUE(ran_with_user_gesture);
@@ -336,39 +335,6 @@
   EXPECT_TRUE(interaction_provider()->HasActiveInteraction(context));
 }
 
-TEST_F(APIRequestHandlerTest, RequestThread) {
-  v8::HandleScope handle_scope(isolate());
-  v8::Local<v8::Context> context = MainContext();
-
-  base::Optional<binding::RequestThread> thread;
-  auto on_request = [](base::Optional<binding::RequestThread>* thread_out,
-                       std::unique_ptr<APIRequestHandler::Request> request,
-                       v8::Local<v8::Context> context) {
-    *thread_out = request->thread;
-  };
-
-  APIRequestHandler request_handler(
-      base::BindRepeating(on_request, &thread),
-      APILastError(APILastError::GetParent(), binding::AddConsoleError()),
-      nullptr, interaction_provider());
-
-  request_handler.StartRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
-      v8::Local<v8::Function>(), v8::Local<v8::Function>(),
-      binding::RequestThread::UI);
-  ASSERT_TRUE(thread);
-  EXPECT_EQ(binding::RequestThread::UI, *thread);
-  thread.reset();
-
-  request_handler.StartRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
-      v8::Local<v8::Function>(), v8::Local<v8::Function>(),
-      binding::RequestThread::IO);
-  ASSERT_TRUE(thread);
-  EXPECT_EQ(binding::RequestThread::IO, *thread);
-  thread.reset();
-}
-
 TEST_F(APIRequestHandlerTest, SettingLastError) {
   v8::HandleScope handle_scope(isolate());
   v8::Local<v8::Context> context = MainContext();
@@ -406,7 +372,7 @@
         FunctionFromString(context, kReportExposedLastError);
     int request_id = request_handler.StartRequest(
         context, kMethod, std::make_unique<base::ListValue>(), callback,
-        v8::Local<v8::Function>(), binding::RequestThread::UI);
+        v8::Local<v8::Function>());
     request_handler.CompleteRequest(request_id, base::ListValue(),
                                     std::string());
     EXPECT_FALSE(logged_error);
@@ -422,7 +388,7 @@
         FunctionFromString(context, kReportExposedLastError);
     int request_id = request_handler.StartRequest(
         context, kMethod, std::make_unique<base::ListValue>(), callback,
-        v8::Local<v8::Function>(), binding::RequestThread::UI);
+        v8::Local<v8::Function>());
     request_handler.CompleteRequest(request_id, base::ListValue(),
                                     "some error");
     EXPECT_FALSE(logged_error);
@@ -437,7 +403,7 @@
         FunctionFromString(context, "(function() {})");
     int request_id = request_handler.StartRequest(
         context, kMethod, std::make_unique<base::ListValue>(), callback,
-        v8::Local<v8::Function>(), binding::RequestThread::UI);
+        v8::Local<v8::Function>());
     request_handler.CompleteRequest(request_id, base::ListValue(),
                                     "some error");
     ASSERT_TRUE(logged_error);
@@ -452,7 +418,7 @@
         FunctionFromString(context, "(function() {})");
     int request_id = request_handler.StartRequest(
         context, kMethod, std::make_unique<base::ListValue>(),
-        v8::Local<v8::Function>(), custom_callback, binding::RequestThread::UI);
+        v8::Local<v8::Function>(), custom_callback);
     request_handler.CompleteRequest(request_id, base::ListValue(),
                                     "some error");
     ASSERT_TRUE(logged_error);
@@ -465,8 +431,7 @@
     // associated callback callback. The error should be logged.
     int request_id = request_handler.StartRequest(
         context, kMethod, std::make_unique<base::ListValue>(),
-        v8::Local<v8::Function>(), v8::Local<v8::Function>(),
-        binding::RequestThread::UI);
+        v8::Local<v8::Function>(), v8::Local<v8::Function>());
     request_handler.CompleteRequest(request_id, base::ListValue(),
                                     "some error");
     ASSERT_TRUE(logged_error);
@@ -566,8 +531,7 @@
   v8::Local<v8::Promise> promise;
   int request_id = -1;
   std::tie(request_id, promise) = request_handler->StartPromiseBasedRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
-      binding::RequestThread::UI);
+      context, kMethod, std::make_unique<base::ListValue>());
 
   EXPECT_NE(-1, request_id);
   ASSERT_FALSE(promise.IsEmpty());
@@ -596,8 +560,7 @@
   v8::Local<v8::Promise> promise;
   int request_id = -1;
   std::tie(request_id, promise) = request_handler->StartPromiseBasedRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
-      binding::RequestThread::UI);
+      context, kMethod, std::make_unique<base::ListValue>());
 
   EXPECT_NE(-1, request_id);
   ASSERT_FALSE(promise.IsEmpty());
diff --git a/extensions/renderer/bindings/declarative_event.cc b/extensions/renderer/bindings/declarative_event.cc
index b915e3c..e768b3fd 100644
--- a/extensions/renderer/bindings/declarative_event.cc
+++ b/extensions/renderer/bindings/declarative_event.cc
@@ -203,8 +203,7 @@
 
   request_handler_->StartRequest(
       context, request_name, std::move(parse_result.arguments),
-      parse_result.callback, v8::Local<v8::Function>(),
-      binding::RequestThread::UI);
+      parse_result.callback, v8::Local<v8::Function>());
 }
 
 }  // namespace extensions
diff --git a/extensions/renderer/chrome_setting.cc b/extensions/renderer/chrome_setting.cc
index d0fedca..c1aea81 100644
--- a/extensions/renderer/chrome_setting.cc
+++ b/extensions/renderer/chrome_setting.cc
@@ -176,8 +176,7 @@
   parse_result.arguments->Insert(0u, std::make_unique<base::Value>(pref_name_));
   request_handler_->StartRequest(
       context, full_name, std::move(parse_result.arguments),
-      parse_result.callback, v8::Local<v8::Function>(),
-      binding::RequestThread::UI);
+      parse_result.callback, v8::Local<v8::Function>());
 }
 
 }  // namespace extensions
diff --git a/extensions/renderer/content_setting.cc b/extensions/renderer/content_setting.cc
index 898f7950..461d2ce 100644
--- a/extensions/renderer/content_setting.cc
+++ b/extensions/renderer/content_setting.cc
@@ -197,10 +197,10 @@
   }
 
   parse_result.arguments->Insert(0u, std::make_unique<base::Value>(pref_name_));
-  request_handler_->StartRequest(
-      context, "contentSettings." + method_name,
-      std::move(parse_result.arguments), parse_result.callback,
-      v8::Local<v8::Function>(), binding::RequestThread::UI);
+  request_handler_->StartRequest(context, "contentSettings." + method_name,
+                                 std::move(parse_result.arguments),
+                                 parse_result.callback,
+                                 v8::Local<v8::Function>());
 }
 
 }  // namespace extensions
diff --git a/extensions/renderer/ipc_message_sender.cc b/extensions/renderer/ipc_message_sender.cc
index d8938d6b..658e4dfd 100644
--- a/extensions/renderer/ipc_message_sender.cc
+++ b/extensions/renderer/ipc_message_sender.cc
@@ -60,23 +60,14 @@
   MainThreadIPCMessageSender() : render_thread_(content::RenderThread::Get()) {}
   ~MainThreadIPCMessageSender() override {}
 
-  void SendRequestIPC(ScriptContext* context,
-                      std::unique_ptr<ExtensionHostMsg_Request_Params> params,
-                      binding::RequestThread thread) override {
+  void SendRequestIPC(
+      ScriptContext* context,
+      std::unique_ptr<ExtensionHostMsg_Request_Params> params) override {
     content::RenderFrame* frame = context->GetRenderFrame();
     if (!frame)
       return;
 
-    switch (thread) {
-      case binding::RequestThread::UI:
-        frame->Send(
-            new ExtensionHostMsg_Request(frame->GetRoutingID(), *params));
-        break;
-      case binding::RequestThread::IO:
-        frame->Send(new ExtensionHostMsg_RequestForIOThread(
-            frame->GetRoutingID(), *params));
-        break;
-    }
+    frame->Send(new ExtensionHostMsg_Request(frame->GetRoutingID(), *params));
   }
 
   void SendOnRequestResponseReceivedIPC(int request_id) override {}
@@ -225,9 +216,9 @@
         service_worker_version_id_(service_worker_version_id) {}
   ~WorkerThreadIPCMessageSender() override {}
 
-  void SendRequestIPC(ScriptContext* context,
-                      std::unique_ptr<ExtensionHostMsg_Request_Params> params,
-                      binding::RequestThread thread) override {
+  void SendRequestIPC(
+      ScriptContext* context,
+      std::unique_ptr<ExtensionHostMsg_Request_Params> params) override {
     DCHECK(!context->GetRenderFrame());
     DCHECK(context->IsForServiceWorker());
     DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
@@ -243,16 +234,7 @@
     // HandleWorkerResponse().
     dispatcher_->Send(new ExtensionHostMsg_IncrementServiceWorkerActivity(
         service_worker_version_id_, guid));
-
-    switch (thread) {
-      case binding::RequestThread::UI:
-        dispatcher_->Send(new ExtensionHostMsg_RequestWorker(*params));
-        break;
-      case binding::RequestThread::IO:
-        dispatcher_->Send(
-            new ExtensionHostMsg_RequestWorkerForIOThread(*params));
-        break;
-    }
+    dispatcher_->Send(new ExtensionHostMsg_RequestWorker(*params));
   }
 
   void SendOnRequestResponseReceivedIPC(int request_id) override {
diff --git a/extensions/renderer/ipc_message_sender.h b/extensions/renderer/ipc_message_sender.h
index 1dcf822..690c9e3 100644
--- a/extensions/renderer/ipc_message_sender.h
+++ b/extensions/renderer/ipc_message_sender.h
@@ -34,8 +34,7 @@
   // Sends a request message to the browser.
   virtual void SendRequestIPC(
       ScriptContext* context,
-      std::unique_ptr<ExtensionHostMsg_Request_Params> params,
-      binding::RequestThread thread) = 0;
+      std::unique_ptr<ExtensionHostMsg_Request_Params> params) = 0;
 
   // Handles sending any additional messages required after receiving a response
   // to a request.
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc
index 83a5649..208be25 100644
--- a/extensions/renderer/native_extension_bindings_system.cc
+++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -847,8 +847,7 @@
   params->service_worker_version_id =
       blink::mojom::kInvalidServiceWorkerVersionId;
 
-  ipc_message_sender_->SendRequestIPC(script_context, std::move(params),
-                                      request->thread);
+  ipc_message_sender_->SendRequestIPC(script_context, std::move(params));
 }
 
 void NativeExtensionBindingsSystem::OnEventListenerChanged(
diff --git a/extensions/renderer/native_extension_bindings_system_test_base.cc b/extensions/renderer/native_extension_bindings_system_test_base.cc
index 40a4047..16e2b50d 100644
--- a/extensions/renderer/native_extension_bindings_system_test_base.cc
+++ b/extensions/renderer/native_extension_bindings_system_test_base.cc
@@ -22,8 +22,7 @@
 TestIPCMessageSender::~TestIPCMessageSender() {}
 void TestIPCMessageSender::SendRequestIPC(
     ScriptContext* context,
-    std::unique_ptr<ExtensionHostMsg_Request_Params> params,
-    binding::RequestThread thread) {
+    std::unique_ptr<ExtensionHostMsg_Request_Params> params) {
   last_params_ = std::move(params);
 }
 
diff --git a/extensions/renderer/native_extension_bindings_system_test_base.h b/extensions/renderer/native_extension_bindings_system_test_base.h
index aa76ea9..29d096b7 100644
--- a/extensions/renderer/native_extension_bindings_system_test_base.h
+++ b/extensions/renderer/native_extension_bindings_system_test_base.h
@@ -47,9 +47,9 @@
   ~TestIPCMessageSender() override;
 
   // IPCMessageSender:
-  void SendRequestIPC(ScriptContext* context,
-                      std::unique_ptr<ExtensionHostMsg_Request_Params> params,
-                      binding::RequestThread thread) override;
+  void SendRequestIPC(
+      ScriptContext* context,
+      std::unique_ptr<ExtensionHostMsg_Request_Params> params) override;
   void SendOnRequestResponseReceivedIPC(int request_id) override {}
   // The event listener methods are less of a pain to mock (since they don't
   // have complex parameters like ExtensionHostMsg_Request_Params).
diff --git a/extensions/renderer/storage_area.cc b/extensions/renderer/storage_area.cc
index 80f89b3..7c60bf1 100644
--- a/extensions/renderer/storage_area.cc
+++ b/extensions/renderer/storage_area.cc
@@ -247,8 +247,7 @@
   parse_result.arguments->Insert(0u, std::make_unique<base::Value>(name_));
   request_handler_->StartRequest(
       context, full_method_name, std::move(parse_result.arguments),
-      parse_result.callback, v8::Local<v8::Function>(),
-      binding::RequestThread::UI);
+      parse_result.callback, v8::Local<v8::Function>());
 }
 
 v8::Local<v8::Value> StorageArea::GetOnChangedEvent(
diff --git a/extensions/shell/browser/api/file_system/shell_file_system_delegate.cc b/extensions/shell/browser/api/file_system/shell_file_system_delegate.cc
index 58035a35..95ea2d7 100644
--- a/extensions/shell/browser/api/file_system/shell_file_system_delegate.cc
+++ b/extensions/shell/browser/api/file_system/shell_file_system_delegate.cc
@@ -22,7 +22,7 @@
 }
 
 bool ShellFileSystemDelegate::ShowSelectFileDialog(
-    scoped_refptr<UIThreadExtensionFunction> extension_function,
+    scoped_refptr<ExtensionFunction> extension_function,
     ui::SelectFileDialog::Type type,
     const base::FilePath& default_path,
     const ui::SelectFileDialog::FileTypeInfo* file_types,
diff --git a/extensions/shell/browser/api/file_system/shell_file_system_delegate.h b/extensions/shell/browser/api/file_system/shell_file_system_delegate.h
index df41e02..b58ec590 100644
--- a/extensions/shell/browser/api/file_system/shell_file_system_delegate.h
+++ b/extensions/shell/browser/api/file_system/shell_file_system_delegate.h
@@ -17,7 +17,7 @@
   // FileSystemDelegate:
   base::FilePath GetDefaultDirectory() override;
   bool ShowSelectFileDialog(
-      scoped_refptr<UIThreadExtensionFunction> extension_function,
+      scoped_refptr<ExtensionFunction> extension_function,
       ui::SelectFileDialog::Type type,
       const base::FilePath& default_path,
       const ui::SelectFileDialog::FileTypeInfo* file_types,
diff --git a/extensions/shell/browser/api/identity/identity_api.h b/extensions/shell/browser/api/identity/identity_api.h
index 049908b8..27ce43f0 100644
--- a/extensions/shell/browser/api/identity/identity_api.h
+++ b/extensions/shell/browser/api/identity/identity_api.h
@@ -12,7 +12,7 @@
 namespace shell {
 
 // Stub. See the IDL file for documentation.
-class IdentityRemoveCachedAuthTokenFunction : public UIThreadExtensionFunction {
+class IdentityRemoveCachedAuthTokenFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("identity.removeCachedAuthToken", UNKNOWN)
 
diff --git a/extensions/shell/browser/shell_content_browser_client.cc b/extensions/shell/browser/shell_content_browser_client.cc
index 52f58cc6..125d1111 100644
--- a/extensions/shell/browser/shell_content_browser_client.cc
+++ b/extensions/shell/browser/shell_content_browser_client.cc
@@ -112,8 +112,7 @@
   BrowserContext* browser_context = browser_main_parts_->browser_context();
   host->AddFilter(
       new ExtensionMessageFilter(render_process_id, browser_context));
-  host->AddFilter(
-      new IOThreadExtensionMessageFilter(render_process_id, browser_context));
+  host->AddFilter(new IOThreadExtensionMessageFilter());
   host->AddFilter(
       new ExtensionsGuestViewMessageFilter(
           render_process_id, browser_context));
diff --git a/fuchsia/BUILD.gn b/fuchsia/BUILD.gn
index ecc9681..79d48b5 100644
--- a/fuchsia/BUILD.gn
+++ b/fuchsia/BUILD.gn
@@ -13,6 +13,7 @@
   sources = [
     "fidl/cast/api_bindings.fidl",
     "fidl/cast/application_config.fidl",
+    "fidl/cast/application_controller.fidl",
     "fidl/cast/queryable_data.fidl",
   ]
 
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn
index e6badcc..4c0d86b 100644
--- a/fuchsia/engine/BUILD.gn
+++ b/fuchsia/engine/BUILD.gn
@@ -131,8 +131,6 @@
     "browser/web_engine_remote_debugging.h",
     "browser/web_engine_screen.cc",
     "browser/web_engine_screen.h",
-    "browser/web_engine_url_request_context_getter.cc",
-    "browser/web_engine_url_request_context_getter.h",
     "common.cc",
     "common.h",
     "context_provider_impl.cc",
diff --git a/fuchsia/engine/browser/web_engine_browser_context.cc b/fuchsia/engine/browser/web_engine_browser_context.cc
index df15f6c..c381d9c 100644
--- a/fuchsia/engine/browser/web_engine_browser_context.cc
+++ b/fuchsia/engine/browser/web_engine_browser_context.cc
@@ -19,9 +19,7 @@
 #include "content/public/browser/resource_context.h"
 #include "fuchsia/engine/browser/web_engine_net_log.h"
 #include "fuchsia/engine/browser/web_engine_permission_manager.h"
-#include "fuchsia/engine/browser/web_engine_url_request_context_getter.h"
 #include "fuchsia/engine/common.h"
-#include "net/url_request/url_request_context.h"
 #include "services/network/public/cpp/network_switches.h"
 
 class WebEngineBrowserContext::ResourceContext
@@ -144,21 +142,3 @@
 WebEngineBrowserContext::GetBrowsingDataRemoverDelegate() {
   return nullptr;
 }
-
-net::URLRequestContextGetter* WebEngineBrowserContext::CreateRequestContext(
-    content::ProtocolHandlerMap* protocol_handlers,
-    content::URLRequestInterceptorScopedVector request_interceptors) {
-  DCHECK(!url_request_getter_);
-  url_request_getter_ = new WebEngineURLRequestContextGetter(
-      base::CreateSingleThreadTaskRunnerWithTraits(
-          {content::BrowserThread::IO}),
-      net_log_.get(), std::move(*protocol_handlers),
-      std::move(request_interceptors), data_dir_path_);
-  return url_request_getter_.get();
-}
-
-net::URLRequestContextGetter*
-WebEngineBrowserContext::CreateMediaRequestContext() {
-  DCHECK(url_request_getter_.get());
-  return url_request_getter_.get();
-}
diff --git a/fuchsia/engine/browser/web_engine_browser_context.h b/fuchsia/engine/browser/web_engine_browser_context.h
index 914f7de2..c508858c 100644
--- a/fuchsia/engine/browser/web_engine_browser_context.h
+++ b/fuchsia/engine/browser/web_engine_browser_context.h
@@ -14,7 +14,6 @@
 
 class WebEngineNetLog;
 class WebEnginePermissionManager;
-class WebEngineURLRequestContextGetter;
 
 class WebEngineBrowserContext : public content::BrowserContext {
  public:
@@ -42,10 +41,6 @@
   content::BackgroundSyncController* GetBackgroundSyncController() override;
   content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
       override;
-  net::URLRequestContextGetter* CreateRequestContext(
-      content::ProtocolHandlerMap* protocol_handlers,
-      content::URLRequestInterceptorScopedVector request_interceptors) override;
-  net::URLRequestContextGetter* CreateMediaRequestContext() override;
 
  private:
   // Contains URLRequestContextGetter required for resource loading.
@@ -54,7 +49,6 @@
   base::FilePath data_dir_path_;
 
   std::unique_ptr<WebEngineNetLog> net_log_;
-  scoped_refptr<WebEngineURLRequestContextGetter> url_request_getter_;
   std::unique_ptr<SimpleFactoryKey> simple_factory_key_;
   std::unique_ptr<ResourceContext> resource_context_;
   std::unique_ptr<WebEnginePermissionManager> permission_manager_;
diff --git a/fuchsia/engine/browser/web_engine_url_request_context_getter.cc b/fuchsia/engine/browser/web_engine_url_request_context_getter.cc
deleted file mode 100644
index 91a97a6..0000000
--- a/fuchsia/engine/browser/web_engine_url_request_context_getter.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "fuchsia/engine/browser/web_engine_url_request_context_getter.h"
-
-#include <utility>
-
-#include "base/single_thread_task_runner.h"
-#include "content/public/browser/cookie_store_factory.h"
-#include "net/cookies/cookie_store.h"
-#include "net/proxy_resolution/proxy_config_service.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_builder.h"
-
-WebEngineURLRequestContextGetter::WebEngineURLRequestContextGetter(
-    scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
-    net::NetLog* net_log,
-    content::ProtocolHandlerMap protocol_handlers,
-    content::URLRequestInterceptorScopedVector request_interceptors,
-    base::FilePath data_dir_path)
-    : network_task_runner_(std::move(network_task_runner)),
-      net_log_(net_log),
-      protocol_handlers_(std::move(protocol_handlers)),
-      request_interceptors_(std::move(request_interceptors)),
-      data_dir_path_(data_dir_path) {}
-
-WebEngineURLRequestContextGetter::~WebEngineURLRequestContextGetter() = default;
-
-net::URLRequestContext*
-WebEngineURLRequestContextGetter::GetURLRequestContext() {
-  if (!url_request_context_) {
-    net::URLRequestContextBuilder builder;
-    builder.set_net_log(net_log_);
-    builder.set_data_enabled(true);
-
-    for (auto& protocol_handler : protocol_handlers_) {
-      builder.SetProtocolHandler(protocol_handler.first,
-                                 std::move(protocol_handler.second));
-    }
-    protocol_handlers_.clear();
-
-    builder.SetInterceptors(std::move(request_interceptors_));
-
-    if (data_dir_path_.empty()) {
-      // Set up an in-memory (ephemeral) CookieStore.
-      builder.SetCookieStore(
-          content::CreateCookieStore(content::CookieStoreConfig(), nullptr));
-    } else {
-      // Set up a persistent CookieStore under |data_dir_path|.
-      content::CookieStoreConfig cookie_config(
-          data_dir_path_.Append(FILE_PATH_LITERAL("Cookies")), false, false,
-          NULL);
-
-      // Fuchsia protects the local data at rest so there is no need to encrypt
-      // cookie store.
-      builder.SetCookieStore(
-          content::CreateCookieStore(cookie_config, nullptr));
-    }
-
-    url_request_context_ = builder.Build();
-  }
-  return url_request_context_.get();
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-WebEngineURLRequestContextGetter::GetNetworkTaskRunner() const {
-  return network_task_runner_;
-}
diff --git a/fuchsia/engine/browser/web_engine_url_request_context_getter.h b/fuchsia/engine/browser/web_engine_url_request_context_getter.h
deleted file mode 100644
index 9d501cdc..0000000
--- a/fuchsia/engine/browser/web_engine_url_request_context_getter.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_URL_REQUEST_CONTEXT_GETTER_H_
-#define FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_URL_REQUEST_CONTEXT_GETTER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "content/public/browser/browser_context.h"
-#include "net/url_request/url_request_context_getter.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}  // namespace base
-
-namespace net {
-class NetLog;
-class ProxyConfigService;
-}  // namespace net
-
-class WebEngineURLRequestContextGetter : public net::URLRequestContextGetter {
- public:
-  WebEngineURLRequestContextGetter(
-      scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
-      net::NetLog* net_log,
-      content::ProtocolHandlerMap protocol_handlers,
-      content::URLRequestInterceptorScopedVector request_interceptors,
-      base::FilePath data_dir_path);
-
-  // net::URLRequestContextGetter overrides.
-  net::URLRequestContext* GetURLRequestContext() override;
-  scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
-      const override;
-
- protected:
-  ~WebEngineURLRequestContextGetter() override;
-
- private:
-  scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
-  net::NetLog* net_log_;
-  std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
-  std::unique_ptr<net::URLRequestContext> url_request_context_;
-
-  content::ProtocolHandlerMap protocol_handlers_;
-  content::URLRequestInterceptorScopedVector request_interceptors_;
-  base::FilePath data_dir_path_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebEngineURLRequestContextGetter);
-};
-
-#endif  // FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_URL_REQUEST_CONTEXT_GETTER_H_
diff --git a/fuchsia/fidl/cast/application_controller.fidl b/fuchsia/fidl/cast/application_controller.fidl
new file mode 100644
index 0000000..17bf031
--- /dev/null
+++ b/fuchsia/fidl/cast/application_controller.fidl
@@ -0,0 +1,19 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library chromium.cast;
+
+[Discoverable]
+protocol ApplicationControllerReceiver {
+  /// Used by the Agent to receive a controller from the Cast Runner.
+  /// Can only be called at most one time for the lifetime of the Component.
+  SetApplicationController(ApplicationController controller);
+};
+
+/// Allows clients to access and modify certain aspects of the Cast receiver
+/// application runtime.
+protocol ApplicationController {
+  /// Enables or disables touch event processing.
+  SetTouchInputEnabled(bool enable);
+};
diff --git a/headless/lib/browser/headless_browser_context_impl.cc b/headless/lib/browser/headless_browser_context_impl.cc
index 1faeeeb..3f20abd 100644
--- a/headless/lib/browser/headless_browser_context_impl.cc
+++ b/headless/lib/browser/headless_browser_context_impl.cc
@@ -227,19 +227,6 @@
   return nullptr;
 }
 
-net::URLRequestContextGetter* HeadlessBrowserContextImpl::CreateRequestContext(
-    content::ProtocolHandlerMap* protocol_handlers,
-    content::URLRequestInterceptorScopedVector request_interceptors) {
-  NOTREACHED();
-  return nullptr;
-}
-
-net::URLRequestContextGetter*
-HeadlessBrowserContextImpl::CreateMediaRequestContext() {
-  NOTREACHED();
-  return nullptr;
-}
-
 HeadlessWebContents* HeadlessBrowserContextImpl::CreateWebContents(
     HeadlessWebContents::Builder* builder) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -311,13 +298,6 @@
 HeadlessBrowserContext::Builder::Builder(Builder&&) = default;
 
 HeadlessBrowserContext::Builder&
-HeadlessBrowserContext::Builder::SetProtocolHandlers(
-    ProtocolHandlerMap protocol_handlers) {
-  options_->protocol_handlers_ = std::move(protocol_handlers);
-  return *this;
-}
-
-HeadlessBrowserContext::Builder&
 HeadlessBrowserContext::Builder::SetProductNameAndVersion(
     const std::string& product_name_and_version) {
   options_->product_name_and_version_ = product_name_and_version;
diff --git a/headless/lib/browser/headless_browser_context_impl.h b/headless/lib/browser/headless_browser_context_impl.h
index 45cae12..891a7e3f 100644
--- a/headless/lib/browser/headless_browser_context_impl.h
+++ b/headless/lib/browser/headless_browser_context_impl.h
@@ -76,10 +76,6 @@
   content::BackgroundSyncController* GetBackgroundSyncController() override;
   content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
       override;
-  net::URLRequestContextGetter* CreateRequestContext(
-      content::ProtocolHandlerMap* protocol_handlers,
-      content::URLRequestInterceptorScopedVector request_interceptors) override;
-  net::URLRequestContextGetter* CreateMediaRequestContext() override;
 
   HeadlessWebContents* CreateWebContents(HeadlessWebContents::Builder* builder);
   // Register web contents which were created not through Headless API
diff --git a/headless/lib/browser/headless_browser_context_options.cc b/headless/lib/browser/headless_browser_context_options.cc
index 4b5f961..48cb678 100644
--- a/headless/lib/browser/headless_browser_context_options.cc
+++ b/headless/lib/browser/headless_browser_context_options.cc
@@ -77,15 +77,6 @@
       browser_options_->override_web_preferences_callback);
 }
 
-const ProtocolHandlerMap& HeadlessBrowserContextOptions::protocol_handlers()
-    const {
-  return protocol_handlers_;
-}
-
-ProtocolHandlerMap HeadlessBrowserContextOptions::TakeProtocolHandlers() {
-  return std::move(protocol_handlers_);
-}
-
 gfx::FontRenderParams::Hinting
 HeadlessBrowserContextOptions::font_render_hinting() const {
   return ReturnOverriddenValue(font_render_hinting_,
diff --git a/headless/lib/browser/headless_browser_context_options.h b/headless/lib/browser/headless_browser_context_options.h
index 5ed0cf2..c5ef99c 100644
--- a/headless/lib/browser/headless_browser_context_options.h
+++ b/headless/lib/browser/headless_browser_context_options.h
@@ -48,12 +48,6 @@
   // See HeadlessBrowser::Options::font_render_hinting.
   gfx::FontRenderParams::Hinting font_render_hinting() const;
 
-  // Custom network protocol handlers. These can be used to override URL
-  // fetching for different network schemes.
-  const ProtocolHandlerMap& protocol_handlers() const;
-  // Since ProtocolHandlerMap is move-only, this method takes ownership of them.
-  ProtocolHandlerMap TakeProtocolHandlers();
-
   // Callback that is invoked to override WebPreferences for RenderViews
   // created within this HeadlessBrowserContext.
   base::RepeatingCallback<void(WebPreferences*)>
@@ -78,8 +72,6 @@
   base::Optional<base::RepeatingCallback<void(WebPreferences*)>>
       override_web_preferences_callback_;
 
-  ProtocolHandlerMap protocol_handlers_;
-
   base::Optional<gfx::FontRenderParams::Hinting> font_render_hinting_;
 
   DISALLOW_COPY_AND_ASSIGN(HeadlessBrowserContextOptions);
diff --git a/headless/public/headless_browser_context.h b/headless/public/headless_browser_context.h
index 66961f11..22fa9db 100644
--- a/headless/public/headless_browser_context.h
+++ b/headless/public/headless_browser_context.h
@@ -31,8 +31,6 @@
 // Builder::SetOverrideWebPreferencesCallback().
 using content::WebPreferences;
 
-using content::ProtocolHandlerMap;
-
 // Represents an isolated session with a unique cache, cookies, and other
 // profile/session related data.
 // When browser context is deleted, all associated web contents are closed.
@@ -77,10 +75,6 @@
   Builder(Builder&&);
   ~Builder();
 
-  // Set custom network protocol handlers. These can be used to override URL
-  // fetching for different network schemes.
-  Builder& SetProtocolHandlers(ProtocolHandlerMap protocol_handlers);
-
   // By default if you add mojo bindings, http and https are disabled because
   // its almost certinly unsafe for arbitary sites on the internet to have
   // access to these bindings.  If you know what you're doing it may be OK to
diff --git a/headless/test/test_network_interceptor.cc b/headless/test/test_network_interceptor.cc
index 0d60a0de..213deaf806 100644
--- a/headless/test/test_network_interceptor.cc
+++ b/headless/test/test_network_interceptor.cc
@@ -40,7 +40,6 @@
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
 
-  void ProceedWithResponse() override { DCHECK(false); }
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
diff --git a/ios/OWNERS b/ios/OWNERS
index 839f864..b7f9aac 100644
--- a/ios/OWNERS
+++ b/ios/OWNERS
@@ -14,3 +14,4 @@
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
+# COMPONENT: UI>Browser>Mobile
diff --git a/ios/chrome/browser/autofill/form_input_egtest.mm b/ios/chrome/browser/autofill/form_input_egtest.mm
index e71c7fc..a50389ab1 100644
--- a/ios/chrome/browser/autofill/form_input_egtest.mm
+++ b/ios/chrome/browser/autofill/form_input_egtest.mm
@@ -27,6 +27,8 @@
 #error "This file requires ARC support."
 #endif
 
+using chrome_test_util::WebViewMatcher;
+
 namespace {
 
 const char kFormElementId1[] = "username";
@@ -99,9 +101,7 @@
       forConfigKey:kGREYConfigKeySynchronizationEnabled];
 
   // Brings up the keyboard by tapping on one of the form's field.
-  [[EarlGrey
-      selectElementWithMatcher:web::WebViewInWebState(
-                                   chrome_test_util::GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:web::WebViewTapElement(
                         chrome_test_util::GetCurrentWebState(),
                         [ElementSelector
diff --git a/ios/chrome/browser/component_updater/BUILD.gn b/ios/chrome/browser/component_updater/BUILD.gn
index e811b5f..b3a2fa3 100644
--- a/ios/chrome/browser/component_updater/BUILD.gn
+++ b/ios/chrome/browser/component_updater/BUILD.gn
@@ -10,6 +10,8 @@
   deps = [
     "//base",
     "//components/component_updater",
+    "//components/services/patch:in_process",
+    "//components/services/patch/public/mojom",
     "//components/services/unzip:in_process",
     "//components/services/unzip/public/mojom",
     "//components/update_client",
@@ -18,6 +20,5 @@
     "//ios/chrome/browser/google",
     "//ios/chrome/common",
     "//ios/web",
-    "//services/service_manager/public/cpp",
   ]
 }
diff --git a/ios/chrome/browser/component_updater/ios_component_updater_configurator.cc b/ios/chrome/browser/component_updater/ios_component_updater_configurator.cc
index 91f0eab..5ca721e 100644
--- a/ios/chrome/browser/component_updater/ios_component_updater_configurator.cc
+++ b/ios/chrome/browser/component_updater/ios_component_updater_configurator.cc
@@ -14,6 +14,7 @@
 #include "base/version.h"
 #include "components/component_updater/component_updater_command_line_config_policy.h"
 #include "components/component_updater/configurator_impl.h"
+#include "components/services/patch/in_process_file_patcher.h"
 #include "components/services/unzip/in_process_unzipper.h"
 #include "components/update_client/activity_data_service.h"
 #include "components/update_client/net/network_chromium.h"
@@ -26,9 +27,7 @@
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/google/google_brand.h"
 #include "ios/chrome/common/channel_info.h"
-#include "ios/web/public/service/service_manager_connection.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 namespace component_updater {
 
@@ -171,7 +170,7 @@
 IOSConfigurator::GetPatcherFactory() {
   if (!patch_factory_) {
     patch_factory_ = base::MakeRefCounted<update_client::PatchChromiumFactory>(
-        web::ServiceManagerConnection::Get()->GetConnector()->Clone());
+        base::BindRepeating(&patch::LaunchInProcessFilePatcher));
   }
   return patch_factory_;
 }
diff --git a/ios/chrome/browser/context_menu/context_menu_egtest.mm b/ios/chrome/browser/context_menu/context_menu_egtest.mm
index db58b7e..510c2636 100644
--- a/ios/chrome/browser/context_menu/context_menu_egtest.mm
+++ b/ios/chrome/browser/context_menu/context_menu_egtest.mm
@@ -39,6 +39,7 @@
 using chrome_test_util::OmniboxText;
 using chrome_test_util::OpenLinkInNewTabButton;
 using chrome_test_util::SystemSelectionCalloutCopyButton;
+using chrome_test_util::WebViewMatcher;
 
 namespace {
 // Directory containing the |kLogoPagePath| and |kLogoPageImageSourcePath|
@@ -124,9 +125,7 @@
 
 // Long press on |element_id| to trigger context menu.
 void LongPressElement(const char* element_id) {
-  id<GREYMatcher> web_view_matcher =
-      web::WebViewInWebState(chrome_test_util::GetCurrentWebState());
-  [[EarlGrey selectElementWithMatcher:web_view_matcher]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:chrome_test_util::LongPressElementForContextMenu(
                         [ElementSelector selectorWithElementID:element_id],
                         true /* menu should appear */)];
@@ -163,6 +162,13 @@
 
 @implementation ContextMenuTestCase
 
+// TODO(crbug.com/976259) Disable broken context menu tests on Xcode 11 beta 5.
++ (NSArray*)testInvocations {
+  if (@available(iOS 13, *))
+    return @[];
+  return [super testInvocations];
+}
+
 + (void)setUp {
   [super setUp];
   [ChromeEarlGrey setContentSettings:CONTENT_SETTING_ALLOW];
@@ -257,9 +263,7 @@
       CGRectGetMidX([chrome_test_util::GetActiveViewController() view].bounds),
       topInset + 20.0);
 
-  id<GREYMatcher> web_view_matcher =
-      web::WebViewInWebState(chrome_test_util::GetCurrentWebState());
-  [[EarlGrey selectElementWithMatcher:web_view_matcher]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:grey_longPressAtPointWithDuration(
                         point, kGREYLongPressDefaultDuration)];
 
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
index 189580f1..be5fdd7 100644
--- a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
+++ b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
@@ -43,6 +43,8 @@
 using chrome_test_util::SettingsDoneButton;
 using chrome_test_util::SettingsMenuButton;
 using chrome_test_util::SettingsMenuPrivacyButton;
+using chrome_test_util::WebViewMatcher;
+
 using tab_usage_recorder_test_util::OpenNewIncognitoTabUsingUIAndEvictMainTabs;
 using tab_usage_recorder_test_util::SwitchToNormalMode;
 
@@ -691,9 +693,7 @@
   NewMainTabWithURL(initialURL, "link");
 
   int numberOfTabs = [ChromeEarlGrey mainTabCount];
-  id<GREYMatcher> webViewMatcher =
-      web::WebViewInWebState(chrome_test_util::GetCurrentWebState());
-  [[EarlGrey selectElementWithMatcher:webViewMatcher]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:chrome_test_util::LongPressElementForContextMenu(
                         [ElementSelector selectorWithElementID:"link"],
                         true /* menu should appear */)];
diff --git a/ios/chrome/browser/snapshots/BUILD.gn b/ios/chrome/browser/snapshots/BUILD.gn
index 42045a9..676edde68 100644
--- a/ios/chrome/browser/snapshots/BUILD.gn
+++ b/ios/chrome/browser/snapshots/BUILD.gn
@@ -4,7 +4,6 @@
 
 source_set("snapshots") {
   public = [
-    "lru_cache.h",
     "snapshot_cache.h",
     "snapshot_cache_factory.h",
     "snapshot_cache_internal.h",
@@ -12,17 +11,18 @@
     "snapshot_cache_tab_model_list_observer.h",
     "snapshot_cache_web_state_list_observer.h",
     "snapshot_generator_delegate.h",
+    "snapshot_lru_cache.h",
     "snapshot_tab_helper.h",
     "snapshots_util.h",
   ]
   sources = [
-    "lru_cache.mm",
     "snapshot_cache.mm",
     "snapshot_cache_factory.mm",
     "snapshot_cache_tab_model_list_observer.mm",
     "snapshot_cache_web_state_list_observer.mm",
     "snapshot_generator.h",
     "snapshot_generator.mm",
+    "snapshot_lru_cache.mm",
     "snapshot_tab_helper.mm",
     "snapshots_util.mm",
   ]
@@ -68,8 +68,8 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
-    "lru_cache_unittest.mm",
     "snapshot_cache_unittest.mm",
+    "snapshot_lru_cache_unittest.mm",
     "snapshot_tab_helper_unittest.mm",
     "snapshots_util_unittest.mm",
   ]
diff --git a/ios/chrome/browser/snapshots/snapshot_cache.mm b/ios/chrome/browser/snapshots/snapshot_cache.mm
index bea97d50..be67f57 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache.mm
+++ b/ios/chrome/browser/snapshots/snapshot_cache.mm
@@ -23,8 +23,8 @@
 #include "base/task/post_task.h"
 #include "base/task_runner_util.h"
 #include "base/threading/scoped_blocking_call.h"
-#import "ios/chrome/browser/snapshots/lru_cache.h"
 #import "ios/chrome/browser/snapshots/snapshot_cache_observer.h"
+#import "ios/chrome/browser/snapshots/snapshot_lru_cache.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 
@@ -229,7 +229,7 @@
 @implementation SnapshotCache {
   // Cache to hold color snapshots in memory. n.b. Color snapshots are not
   // kept in memory on tablets.
-  LRUCache* lruCache_;
+  SnapshotLRUCache* lruCache_;
 
   // Temporary dictionary to hold grey snapshots for tablet side swipe. This
   // will be nil before -createGreyCache is called and after -removeGreyCache
@@ -279,7 +279,8 @@
                         snapshotsScale:(ImageScale)snapshotsScale {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequenceChecker_);
   if ((self = [super init])) {
-    lruCache_ = [[LRUCache alloc] initWithCacheSize:kLRUCacheMaxCapacity];
+    lruCache_ =
+        [[SnapshotLRUCache alloc] initWithCacheSize:kLRUCacheMaxCapacity];
     cacheDirectory_ = cacheDirectory;
     snapshotsScale_ = snapshotsScale;
 
@@ -349,7 +350,7 @@
   const base::FilePath cacheDirectory = cacheDirectory_;
   const ImageScale snapshotsScale = snapshotsScale_;
 
-  __weak LRUCache* weakLRUCache = lruCache_;
+  __weak SnapshotLRUCache* weakLRUCache = lruCache_;
   base::PostTaskAndReplyWithResult(
       taskRunner_.get(), FROM_HERE,
       base::BindOnce(^base::scoped_nsobject<UIImage>() {
diff --git a/ios/chrome/browser/snapshots/lru_cache.h b/ios/chrome/browser/snapshots/snapshot_lru_cache.h
similarity index 89%
rename from ios/chrome/browser/snapshots/lru_cache.h
rename to ios/chrome/browser/snapshots/snapshot_lru_cache.h
index dcc4c81..adf4f35 100644
--- a/ios/chrome/browser/snapshots/lru_cache.h
+++ b/ios/chrome/browser/snapshots/snapshot_lru_cache.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_SNAPSHOTS_LRU_CACHE_H_
-#define IOS_CHROME_BROWSER_SNAPSHOTS_LRU_CACHE_H_
+#ifndef IOS_CHROME_BROWSER_SNAPSHOTS_SNAPSHOT_LRU_CACHE_H_
+#define IOS_CHROME_BROWSER_SNAPSHOTS_SNAPSHOT_LRU_CACHE_H_
 
 #import <Foundation/Foundation.h>
 
 // This class implements a cache with a limited size. Once the cache reach its
 // size limit, it will start to evict items in a Least Recently Used order
 // (where the term "used" is determined in terms of query to the cache).
-@interface LRUCache : NSObject
+@interface SnapshotLRUCache : NSObject
 
 // The maximum amount of items that the cache can hold before starting to
 // evict. The value 0 is used to signify that the cache can hold an unlimited
@@ -50,4 +50,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_SNAPSHOTS_LRU_CACHE_H_
+#endif  // IOS_CHROME_BROWSER_SNAPSHOTS_SNAPSHOT_LRU_CACHE_H_
diff --git a/ios/chrome/browser/snapshots/lru_cache.mm b/ios/chrome/browser/snapshots/snapshot_lru_cache.mm
similarity index 95%
rename from ios/chrome/browser/snapshots/lru_cache.mm
rename to ios/chrome/browser/snapshots/snapshot_lru_cache.mm
index e899269..ed7db809 100644
--- a/ios/chrome/browser/snapshots/lru_cache.mm
+++ b/ios/chrome/browser/snapshots/snapshot_lru_cache.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/snapshots/lru_cache.h"
+#import "ios/chrome/browser/snapshots/snapshot_lru_cache.h"
 
 #include <stddef.h>
 
@@ -41,7 +41,7 @@
 
 }  // namespace
 
-@implementation LRUCache {
+@implementation SnapshotLRUCache {
   std::unique_ptr<NSObjectMRUCache> _cache;
 }
 
diff --git a/ios/chrome/browser/snapshots/lru_cache_unittest.mm b/ios/chrome/browser/snapshots/snapshot_lru_cache_unittest.mm
similarity index 85%
rename from ios/chrome/browser/snapshots/lru_cache_unittest.mm
rename to ios/chrome/browser/snapshots/snapshot_lru_cache_unittest.mm
index 70987da..d5e768b6 100644
--- a/ios/chrome/browser/snapshots/lru_cache_unittest.mm
+++ b/ios/chrome/browser/snapshots/snapshot_lru_cache_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/snapshots/lru_cache.h"
+#import "ios/chrome/browser/snapshots/snapshot_lru_cache.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -12,10 +12,10 @@
 
 namespace {
 
-using LRUCacheTest = PlatformTest;
+using SnapshotLRUCacheTest = PlatformTest;
 
-TEST_F(LRUCacheTest, Basic) {
-  LRUCache* cache = [[LRUCache alloc] initWithCacheSize:3];
+TEST_F(SnapshotLRUCacheTest, Basic) {
+  SnapshotLRUCache* cache = [[SnapshotLRUCache alloc] initWithCacheSize:3];
 
   NSString* value1 = @"Value 1";
   NSString* value2 = @"Value 2";
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm
index 3fadde7..05fa198 100644
--- a/ios/chrome/browser/translate/translate_egtest.mm
+++ b/ios/chrome/browser/translate/translate_egtest.mm
@@ -62,6 +62,7 @@
 using chrome_test_util::ButtonWithAccessibilityLabelId;
 using chrome_test_util::CloseButton;
 using chrome_test_util::ToolsMenuView;
+using chrome_test_util::WebStateScrollViewMatcher;
 
 namespace {
 
@@ -757,9 +758,7 @@
   [self assertTranslateInfobarIsVisible];
 
   // Scroll down to enter the fullscreen mode.
-  [[EarlGrey
-      selectElementWithMatcher:web::WebViewScrollView(
-                                   chrome_test_util::GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebStateScrollViewMatcher()]
       performAction:grey_swipeFastInDirection(kGREYDirectionUp)];
 
   // Expect the translate infobar to be hidden.
@@ -767,9 +766,7 @@
       assertWithMatcher:grey_notVisible()];
 
   // Scroll up to exit the fullscreen mode.
-  [[EarlGrey
-      selectElementWithMatcher:web::WebViewScrollView(
-                                   chrome_test_util::GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebStateScrollViewMatcher()]
       performAction:grey_swipeFastInDirection(kGREYDirectionDown)];
 
   [self assertTranslateInfobarIsVisible];
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
index 677a748f..0d26b3d9 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
@@ -25,6 +25,8 @@
 #error "This file requires ARC support."
 #endif
 
+using chrome_test_util::WebViewMatcher;
+
 namespace {
 
 const std::string kFormElementID1 = "username";
@@ -60,9 +62,7 @@
 
 // Helper to tap a web element.
 void TapOnWebElementWithID(const std::string& elementID) {
-  [[EarlGrey
-      selectElementWithMatcher:web::WebViewInWebState(
-                                   chrome_test_util::GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:web::WebViewTapElement(
                         chrome_test_util::GetCurrentWebState(),
                         [ElementSelector selectorWithElementID:elementID])];
diff --git a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
index 5cbd139..6417a97 100644
--- a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
+++ b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
@@ -43,6 +43,8 @@
 using chrome_test_util::ButtonWithAccessibilityLabel;
 using chrome_test_util::OKButton;
 using chrome_test_util::SettingsDoneButton;
+using chrome_test_util::WebViewMatcher;
+
 using base::test::ios::kWaitForJSCompletionTimeout;
 using base::test::ios::kWaitForUIElementTimeout;
 using base::test::ios::WaitUntilConditionOrTimeout;
@@ -582,10 +584,7 @@
 
   // TODO(crbug.com/712358): Use method LongPressElementAndTapOnButton once
   // it is moved out of context_menu_egtests.mm and into a shared location.
-  id<GREYMatcher> webViewMatcher =
-      web::WebViewInWebState(chrome_test_util::GetCurrentWebState());
-
-  [[EarlGrey selectElementWithMatcher:webViewMatcher]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:chrome_test_util::LongPressElementForContextMenu(
                         [ElementSelector selectorWithElementID:kLinkID],
                         true /* menu should appear */)];
diff --git a/ios/chrome/browser/ui/download/download_manager_egtest.mm b/ios/chrome/browser/ui/download/download_manager_egtest.mm
index 98f2faf..c6bde17c 100644
--- a/ios/chrome/browser/ui/download/download_manager_egtest.mm
+++ b/ios/chrome/browser/ui/download/download_manager_egtest.mm
@@ -28,9 +28,8 @@
 #endif
 
 using chrome_test_util::ButtonWithAccessibilityLabelId;
-using chrome_test_util::GetCurrentWebState;
 using chrome_test_util::OpenLinkInNewTabButton;
-using web::WebViewInWebState;
+using chrome_test_util::WebViewMatcher;
 
 namespace {
 
@@ -181,7 +180,7 @@
   [ChromeEarlGrey waitForWebStateContainingText:"Download"];
 
   // Open context menu for download link.
-  [[EarlGrey selectElementWithMatcher:WebViewInWebState(GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:chrome_test_util::LongPressElementForContextMenu(
                         [ElementSelector selectorWithElementID:"download"],
                         /*menu_should_appear=*/true)];
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
index 026a44df..e53da1b 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
@@ -36,6 +36,8 @@
 using base::test::ios::kWaitForJSCompletionTimeout;
 using base::test::ios::WaitUntilConditionOrTimeout;
 
+using chrome_test_util::WebStateScrollViewMatcher;
+
 namespace {
 
 // The page height of test pages. This must be big enough to triger fullscreen.
@@ -109,9 +111,7 @@
         chrome_test_util::GetCurrentWebState()->GetView().safeAreaInsets.top;
   }
   DCHECK_LT(yOffset, 0);
-  [[EarlGrey
-      selectElementWithMatcher:web::WebViewScrollView(
-                                   chrome_test_util::GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebStateScrollViewMatcher()]
       assertWithMatcher:grey_scrollViewContentOffset(CGPointMake(0, yOffset))];
 }
 
diff --git a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm
index c931e6a2..d8c0442 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm
@@ -41,6 +41,8 @@
 
 using chrome_test_util::BackButton;
 using chrome_test_util::ForwardButton;
+using chrome_test_util::WebStateScrollViewMatcher;
+using chrome_test_util::WebViewMatcher;
 
 const char kPageURL[] = "/test-page.html";
 const char kPageURL2[] = "/test-page-2.html";
@@ -602,9 +604,7 @@
       assertWithMatcher:positionMatcher];
 
   // Scroll down
-  [[EarlGrey
-      selectElementWithMatcher:web::WebViewScrollView(
-                                   chrome_test_util::GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebStateScrollViewMatcher()]
       performAction:grey_swipeFastInDirection(kGREYDirectionUp)];
 
   // Check that the button is visible.
@@ -664,9 +664,7 @@
       assertWithMatcher:grey_not(grey_enabled())];
 
   // Open a page in a new incognito tab to have the focus.
-  [[EarlGrey
-      selectElementWithMatcher:web::WebViewInWebState(
-                                   chrome_test_util::GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:chrome_test_util::LongPressElementForContextMenu(
                         [ElementSelector selectorWithElementID:kLinkID],
                         true /* menu should appear */)];
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index 8b55acf..bcc0491 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -95,7 +95,6 @@
     "page_placeholder_tab_helper_unittest.mm",
     "repost_form_tab_helper_unittest.mm",
     "sad_tab_tab_helper_unittest.mm",
-    "services_unittest.mm",
     "tab_id_tab_helper_unittest.mm",
     "web_navigation_util_unittest.mm",
     "web_state_delegate_tab_helper_unittest.mm",
@@ -110,7 +109,6 @@
     "//base",
     "//base/test:test_support",
     "//components/search_engines",
-    "//components/services/patch/public/mojom",
     "//components/strings:components_strings_grit",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state:test_support",
@@ -127,7 +125,6 @@
     "//ios/web/public/test/http_server",
     "//net:test_support",
     "//services/network:test_support",
-    "//services/service_manager/public/cpp",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/ocmock",
@@ -230,9 +227,6 @@
     "//components/payments/core",
     "//components/prefs",
     "//components/resources",
-    "//components/services/patch:lib",
-    "//components/services/patch/public/cpp:manifest",
-    "//components/services/patch/public/mojom",
     "//components/strings",
     "//components/version_info",
     "//ios/chrome/app/resources:ios_resources",
@@ -256,6 +250,7 @@
     "//net",
     "//services/identity/public/cpp:manifest",
     "//services/identity/public/mojom",
+    "//services/service_manager/public/cpp",
     "//ui/base",
     "//ui/gfx",
     "//url",
diff --git a/ios/chrome/browser/web/chrome_overlay_manifests.cc b/ios/chrome/browser/web/chrome_overlay_manifests.cc
index 10f6d03..3d3a9f7 100644
--- a/ios/chrome/browser/web/chrome_overlay_manifests.cc
+++ b/ios/chrome/browser/web/chrome_overlay_manifests.cc
@@ -5,8 +5,6 @@
 #include "ios/chrome/browser/web/chrome_overlay_manifests.h"
 
 #include "base/no_destructor.h"
-#include "components/services/patch/public/cpp/manifest.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
 #include "services/identity/public/cpp/manifest.h"
 #include "services/identity/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/manifest_builder.h"
@@ -15,18 +13,8 @@
   static base::NoDestructor<service_manager::Manifest> manifest{
       service_manager::ManifestBuilder()
           .RequireCapability(identity::mojom::kServiceName, "identity_accessor")
-          .RequireCapability(patch::mojom::kServiceName, "patch_file")
           .PackageService(identity::GetManifest())
           .Build()};
 
   return *manifest;
 }
-
-const service_manager::Manifest& GetChromeWebPackagedServicesOverlayManifest() {
-  static base::NoDestructor<service_manager::Manifest> manifest{
-      service_manager::ManifestBuilder()
-          .PackageService(patch::GetManifest())
-          .Build()};
-
-  return *manifest;
-}
diff --git a/ios/chrome/browser/web/chrome_overlay_manifests.h b/ios/chrome/browser/web/chrome_overlay_manifests.h
index f43b3bbb..06bc713 100644
--- a/ios/chrome/browser/web/chrome_overlay_manifests.h
+++ b/ios/chrome/browser/web/chrome_overlay_manifests.h
@@ -12,9 +12,4 @@
 // web_browser service instances.
 const service_manager::Manifest& GetChromeWebBrowserOverlayManifest();
 
-// Returns the manifest Chrome amends to the web_packaged_services service
-// manifest. This allows Chrome to extend the set of in-process services
-// packaged by the browser.
-const service_manager::Manifest& GetChromeWebPackagedServicesOverlayManifest();
-
 #endif  // IOS_CHROME_BROWSER_WEB_CHROME_OVERLAY_MANIFESTS_H_
diff --git a/ios/chrome/browser/web/chrome_web_client.h b/ios/chrome/browser/web/chrome_web_client.h
index 93d830f..9194f10 100644
--- a/ios/chrome/browser/web/chrome_web_client.h
+++ b/ios/chrome/browser/web/chrome_web_client.h
@@ -37,7 +37,6 @@
   bool IsDataResourceGzipped(int resource_id) const override;
   base::Optional<service_manager::Manifest> GetServiceManifestOverlay(
       base::StringPiece name) override;
-  std::vector<service_manager::Manifest> GetExtraServiceManifests() override;
   void GetAdditionalWebUISchemes(
       std::vector<std::string>* additional_schemes) override;
   void PostBrowserURLRewriterCreation(
@@ -59,9 +58,6 @@
                         bool is_post,
                         bool is_off_the_record,
                         NSString** error_html) override;
-  std::unique_ptr<service_manager::Service> HandleServiceRequest(
-      const std::string& service_name,
-      service_manager::mojom::ServiceRequest request) override;
   UIView* GetWindowedContainer() override;
 
  private:
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm
index 1e957e7..3c40171 100644
--- a/ios/chrome/browser/web/chrome_web_client.mm
+++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -10,8 +10,6 @@
 #include "base/mac/bundle_locations.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/dom_distiller/core/url_constants.h"
-#include "components/services/patch/patch_service.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/version_info/version_info.h"
 #include "ios/chrome/browser/application_context.h"
@@ -160,11 +158,6 @@
   return base::nullopt;
 }
 
-std::vector<service_manager::Manifest>
-ChromeWebClient::GetExtraServiceManifests() {
-  return GetChromeWebPackagedServicesOverlayManifest().packaged_services;
-}
-
 void ChromeWebClient::GetAdditionalWebUISchemes(
     std::vector<std::string>* additional_schemes) {
   additional_schemes->push_back(dom_distiller::kDomDistillerScheme);
@@ -237,17 +230,6 @@
   *error_html = GetErrorPage(url, error, is_post, is_off_the_record);
 }
 
-std::unique_ptr<service_manager::Service> ChromeWebClient::HandleServiceRequest(
-    const std::string& service_name,
-    service_manager::mojom::ServiceRequest request) {
-  if (service_name == patch::mojom::kServiceName) {
-    // The Patch service is used by the component updater.
-    return std::make_unique<patch::PatchService>(std::move(request));
-  }
-
-  return nullptr;
-}
-
 UIView* ChromeWebClient::GetWindowedContainer() {
   if (!windowed_container_) {
     windowed_container_ = [[WindowedContainerView alloc] init];
diff --git a/ios/chrome/browser/web/forms_egtest.mm b/ios/chrome/browser/web/forms_egtest.mm
index 948b190b..fead00b7 100644
--- a/ios/chrome/browser/web/forms_egtest.mm
+++ b/ios/chrome/browser/web/forms_egtest.mm
@@ -35,6 +35,8 @@
 
 using chrome_test_util::ButtonWithAccessibilityLabelId;
 using chrome_test_util::OmniboxText;
+using chrome_test_util::WebViewMatcher;
+
 using testing::ElementToDismissAlert;
 
 namespace {
@@ -618,7 +620,7 @@
              @"Web view did not become interactable.");
 
   web::WebState* currentWebState = chrome_test_util::GetCurrentWebState();
-  [[EarlGrey selectElementWithMatcher:web::WebViewInWebState(currentWebState)]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:web::WebViewTapElement(
                         currentWebState,
                         [ElementSelector selectorWithElementID:ID])];
diff --git a/ios/chrome/browser/web/services_unittest.mm b/ios/chrome/browser/web/services_unittest.mm
deleted file mode 100644
index 405baad..0000000
--- a/ios/chrome/browser/web/services_unittest.mm
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/macros.h"
-#include "base/test/bind_test_util.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
-#include "components/services/patch/public/mojom/file_patcher.mojom.h"
-#include "ios/chrome/browser/web/chrome_web_client.h"
-#include "ios/web/public/service/service_manager_connection.h"
-#include "ios/web/public/test/scoped_testing_web_client.h"
-#include "ios/web/public/test/test_service_manager_context.h"
-#include "ios/web/public/test/test_web_thread_bundle.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-template <typename T>
-class ServicesTest : public PlatformTest {
- public:
-  ServicesTest() : web_client_(std::make_unique<ChromeWebClient>()) {}
-  ~ServicesTest() override = default;
-
- protected:
-  service_manager::Connector* connector() {
-    return web::ServiceManagerConnection::Get()->GetConnector();
-  }
-
- private:
-  web::ScopedTestingWebClient web_client_;
-  web::TestWebThreadBundle thread_bundle_;
-  web::TestServiceManagerContext service_manager_context_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServicesTest);
-};
-
-struct FilePatchConfig {
-  static std::string ServiceName() { return patch::mojom::kServiceName; }
-
-  using Interface = patch::mojom::FilePatcher;
-};
-
-}  // namespace
-
-using ServicesTestConfig = ::testing::Types<FilePatchConfig>;
-TYPED_TEST_SUITE(ServicesTest, ServicesTestConfig);
-
-// Tests that services provided by Chrome reachable from browser code.
-TYPED_TEST(ServicesTest, CanConnectToService) {
-  mojo::InterfacePtr<typename TypeParam::Interface> service;
-  this->connector()->BindInterface(TypeParam::ServiceName(),
-                                   mojo::MakeRequest(&service));
-
-  // If the service is present, the interface will be connected and
-  // FlushForTesting will complete without an error on the interface. Conversely
-  // if there is a problem connecting to the service, we will always hit the
-  // error handler before FlushForTesting returns.
-  bool encountered_error = false;
-  service.set_connection_error_handler(
-      base::BindLambdaForTesting([&] { encountered_error = true; }));
-  service.FlushForTesting();
-  EXPECT_FALSE(encountered_error);
-}
diff --git a/ios/chrome/browser/web/tab_order_egtest.mm b/ios/chrome/browser/web/tab_order_egtest.mm
index 0c9f3eb..57c643c08 100644
--- a/ios/chrome/browser/web/tab_order_egtest.mm
+++ b/ios/chrome/browser/web/tab_order_egtest.mm
@@ -20,6 +20,8 @@
 
 using chrome_test_util::GetCurrentWebState;
 using chrome_test_util::OpenLinkInNewTabButton;
+using chrome_test_util::WebViewMatcher;
+
 using web::WebViewInWebState;
 
 namespace {
@@ -95,7 +97,7 @@
                   @"Unexpected number of tabs");
 
   // New child WebState should be inserted BEFORE |childWebState1|.
-  [[EarlGrey selectElementWithMatcher:WebViewInWebState(GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:chrome_test_util::LongPressElementForContextMenu(
                         [ElementSelector selectorWithElementID:kLinkSelectorID],
                         true /* menu should appear */)];
@@ -107,7 +109,7 @@
                      @"Unexpected next web state");
 
   // New child WebState should be inserted AFTER |childWebState3|.
-  [[EarlGrey selectElementWithMatcher:WebViewInWebState(GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:chrome_test_util::LongPressElementForContextMenu(
                         [ElementSelector selectorWithElementID:kLinkSelectorID],
                         true /* menu should appear */)];
diff --git a/ios/chrome/browser/web/window_open_by_dom_egtest.mm b/ios/chrome/browser/web/window_open_by_dom_egtest.mm
index 53e93ec..afc54e0 100644
--- a/ios/chrome/browser/web/window_open_by_dom_egtest.mm
+++ b/ios/chrome/browser/web/window_open_by_dom_egtest.mm
@@ -30,8 +30,9 @@
 
 using chrome_test_util::GetCurrentWebState;
 using chrome_test_util::OmniboxText;
+using chrome_test_util::WebViewMatcher;
+
 using web::test::HttpServer;
-using web::WebViewInWebState;
 
 namespace {
 // URL of the file-based page supporting these tests.
@@ -85,7 +86,7 @@
 - (void)testLinkWithBlankTargetSessionStorage {
   [ChromeEarlGrey executeJavaScript:@"sessionStorage.setItem('key', 'value');"];
   const char ID[] = "webScenarioWindowOpenSameURLWithBlankTarget";
-  [[EarlGrey selectElementWithMatcher:WebViewInWebState(GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:web::WebViewTapElement(
                         GetCurrentWebState(),
                         [ElementSelector selectorWithElementID:ID])];
@@ -101,7 +102,7 @@
 // Tests tapping a link with target="_blank".
 - (void)testLinkWithBlankTarget {
   const char ID[] = "webScenarioWindowOpenRegularLink";
-  [[EarlGrey selectElementWithMatcher:WebViewInWebState(GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:web::WebViewTapElement(
                         GetCurrentWebState(),
                         [ElementSelector selectorWithElementID:ID])];
@@ -111,7 +112,7 @@
 // Tests opening a window with URL that ends with /..;
 - (void)testWindowOpenWithSpecialURL {
   const char ID[] = "webScenarioWindowOpenWithSpecialURL";
-  [[EarlGrey selectElementWithMatcher:WebViewInWebState(GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:web::WebViewTapElement(
                         GetCurrentWebState(),
                         [ElementSelector selectorWithElementID:ID])];
@@ -149,7 +150,7 @@
 - (void)testLinkWithBlankTargetMultipleTimes {
   const char ID[] = "webScenarioWindowOpenRegularLinkMultipleTimes";
   web::WebState* test_page_web_state = GetCurrentWebState();
-  id<GREYMatcher> test_page_matcher = WebViewInWebState(test_page_web_state);
+  id<GREYMatcher> test_page_matcher = WebViewMatcher();
   id<GREYAction> link_tap = web::WebViewTapElement(
       test_page_web_state, [ElementSelector selectorWithElementID:ID]);
   [[EarlGrey selectElementWithMatcher:test_page_matcher]
@@ -214,7 +215,7 @@
 // second delay.
 - (void)testLinkWithBlankTargetWithDelayedClose {
   const char ID[] = "webScenarioWindowOpenWithDelayedClose";
-  [[EarlGrey selectElementWithMatcher:WebViewInWebState(GetCurrentWebState())]
+  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
       performAction:web::WebViewTapElement(
                         GetCurrentWebState(),
                         [ElementSelector selectorWithElementID:ID])];
diff --git a/ios/testing/OWNERS b/ios/testing/OWNERS
new file mode 100644
index 0000000..c770a15
--- /dev/null
+++ b/ios/testing/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Test>iOS
diff --git a/ios/third_party/OWNERS b/ios/third_party/OWNERS
new file mode 100644
index 0000000..9ff3529
--- /dev/null
+++ b/ios/third_party/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: UI>Browser>Mobile
diff --git a/ios/web/init/web_main_loop.mm b/ios/web/init/web_main_loop.mm
index 984b229..c0f0322 100644
--- a/ios/web/init/web_main_loop.mm
+++ b/ios/web/init/web_main_loop.mm
@@ -21,6 +21,7 @@
 #include "base/task/single_thread_task_executor.h"
 #include "base/task/thread_pool/thread_pool.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
 #import "ios/web/net/cookie_notification_bridge.h"
 #include "ios/web/public/init/ios_global_state.h"
 #include "ios/web/public/init/web_main_parts.h"
diff --git a/ios/web/public/web_client.h b/ios/web/public/web_client.h
index 6d7989d..57bb049 100644
--- a/ios/web/public/web_client.h
+++ b/ios/web/public/web_client.h
@@ -19,7 +19,6 @@
 #include "ios/web/common/user_agent.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "services/service_manager/public/cpp/manifest.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
 #include "ui/base/layout.h"
 #include "url/url_util.h"
 
@@ -36,10 +35,6 @@
 class SSLInfo;
 }
 
-namespace service_manager {
-class Service;
-}
-
 namespace web {
 
 class BrowserState;
@@ -141,11 +136,6 @@
   virtual NSString* GetDocumentStartScriptForMainFrame(
       BrowserState* browser_state) const;
 
-  // Handles an incoming service request from the Service Manager.
-  virtual std::unique_ptr<service_manager::Service> HandleServiceRequest(
-      const std::string& service_name,
-      service_manager::mojom::ServiceRequest request);
-
   // Allows the embedder to augment service manifests for existing services.
   // Specifically, the sets of exposed and required capabilities, interface
   // filter capabilities (deprecated), and packaged services will be taken from
@@ -156,12 +146,6 @@
   virtual base::Optional<service_manager::Manifest> GetServiceManifestOverlay(
       base::StringPiece name);
 
-  // Allows the embedder to provide manifests for additional services available
-  // at runtime. Any extra manifests returned by this method should have
-  // corresponding logic to actually run the service on-demand in
-  // |HandleServiceRequest()|.
-  virtual std::vector<service_manager::Manifest> GetExtraServiceManifests();
-
   // Allows the embedder to bind an interface request for a WebState-scoped
   // interface that originated from the main frame of |web_state|. Called if
   // |web_state| could not bind the request for |interface_name| itself.
diff --git a/ios/web/service/service_manager_context.h b/ios/web/service/service_manager_context.h
index bd8ba3b..e70704b2 100644
--- a/ios/web/service/service_manager_context.h
+++ b/ios/web/service/service_manager_context.h
@@ -9,11 +9,6 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "services/service_manager/public/cpp/identity.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
 
 namespace web {
 
@@ -27,15 +22,7 @@
  private:
   class InProcessServiceManagerContext;
 
-  void RunService(
-      const service_manager::Identity& identity,
-      mojo::PendingReceiver<service_manager::mojom::Service> receiver);
-  void OnServiceQuit(service_manager::Service* service);
-
   scoped_refptr<InProcessServiceManagerContext> in_process_context_;
-  std::map<service_manager::Service*, std::unique_ptr<service_manager::Service>>
-      running_services_;
-  base::WeakPtrFactory<ServiceManagerContext> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(ServiceManagerContext);
 };
diff --git a/ios/web/service/service_manager_context.mm b/ios/web/service/service_manager_context.mm
index d639e2c..aaa5694 100644
--- a/ios/web/service/service_manager_context.mm
+++ b/ios/web/service/service_manager_context.mm
@@ -165,9 +165,6 @@
 ServiceManagerContext::ServiceManagerContext() {
   std::vector<service_manager::Manifest> manifests = {GetWebSystemManifest(),
                                                       GetWebBrowserManifest()};
-  for (auto& manifest : GetWebClient()->GetExtraServiceManifests())
-    manifests.push_back(std::move(manifest));
-
   mojo::PendingRemote<service_manager::mojom::Service> system_remote;
   ServiceManagerConnection::Set(ServiceManagerConnection::Create(
       system_remote.InitWithNewPipeAndPassReceiver(),
@@ -175,10 +172,8 @@
   auto* system_connection = ServiceManagerConnection::Get();
 
   in_process_context_ = base::MakeRefCounted<InProcessServiceManagerContext>();
-  in_process_context_->Start(
-      std::move(system_remote), std::move(manifests),
-      base::BindRepeating(&ServiceManagerContext::RunService,
-                          weak_ptr_factory_.GetWeakPtr()));
+  in_process_context_->Start(std::move(system_remote), std::move(manifests),
+                             base::DoNothing());
   system_connection->Start();
 }
 
@@ -193,26 +188,4 @@
     ServiceManagerConnection::Destroy();
 }
 
-void ServiceManagerContext::RunService(
-    const service_manager::Identity& identity,
-    mojo::PendingReceiver<service_manager::mojom::Service> receiver) {
-  std::unique_ptr<service_manager::Service> service =
-      GetWebClient()->HandleServiceRequest(identity.name(),
-                                           std::move(receiver));
-  if (!service) {
-    LOG(ERROR) << "Ignoring unhandled request for service: " << identity.name();
-    return;
-  }
-
-  auto* raw_service = service.get();
-  service->set_termination_closure(
-      base::BindOnce(&ServiceManagerContext::OnServiceQuit,
-                     base::Unretained(this), raw_service));
-  running_services_.emplace(raw_service, std::move(service));
-}
-
-void ServiceManagerContext::OnServiceQuit(service_manager::Service* service) {
-  running_services_.erase(service);
-}
-
 }  // namespace web
diff --git a/ios/web/shell/test/context_menu_egtest.mm b/ios/web/shell/test/context_menu_egtest.mm
index 8d4811d..9b60ebb5 100644
--- a/ios/web/shell/test/context_menu_egtest.mm
+++ b/ios/web/shell/test/context_menu_egtest.mm
@@ -38,6 +38,13 @@
 
 @implementation ContextMenuTestCase
 
+// TODO(crbug.com/976259) Disable broken context menu tests on Xcode 11 beta 5.
++ (NSArray*)testInvocations {
+  if (@available(iOS 13, *))
+    return @[];
+  return [super testInvocations];
+}
+
 - (void)setUp {
   [super setUp];
 
diff --git a/ios/web/web_client.mm b/ios/web/web_client.mm
index 7f03982..5e01909 100644
--- a/ios/web/web_client.mm
+++ b/ios/web/web_client.mm
@@ -8,7 +8,6 @@
 
 #include "ios/web/common/features.h"
 #include "ios/web/public/init/web_main_parts.h"
-#include "services/service_manager/public/cpp/service.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -81,21 +80,11 @@
   return @"";
 }
 
-std::unique_ptr<service_manager::Service> WebClient::HandleServiceRequest(
-    const std::string& service_name,
-    service_manager::mojom::ServiceRequest request) {
-  return nullptr;
-}
-
 base::Optional<service_manager::Manifest> WebClient::GetServiceManifestOverlay(
     base::StringPiece name) {
   return base::nullopt;
 }
 
-std::vector<service_manager::Manifest> WebClient::GetExtraServiceManifests() {
-  return {};
-}
-
 void WebClient::AllowCertificateError(
     WebState* web_state,
     int cert_error,
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index f7fea81..2babbb7 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -383,7 +383,7 @@
     public_deps += [ "//media/base/win:d3d11" ]
   }
 
-  if (is_chromecast) {
+  if (is_chromecast || is_fuchsia) {
     sources += [ "demuxer_memory_limit_low.cc" ]
   } else if (is_android) {
     sources += [ "demuxer_memory_limit_android.cc" ]
diff --git a/media/capture/mojom/video_capture_types_for_blink.typemap b/media/capture/mojom/video_capture_types_for_blink.typemap
new file mode 100644
index 0000000..b3c6c36
--- /dev/null
+++ b/media/capture/mojom/video_capture_types_for_blink.typemap
@@ -0,0 +1,32 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//media/capture/mojom/video_capture_types.mojom"
+
+public_headers = [
+  "//media/capture/video_capture_types.h",
+  "//media/capture/video/video_capture_device_descriptor.h",
+  "//media/capture/video/video_capture_device_info.h",
+]
+
+traits_headers = [ "//media/capture/mojom/video_capture_types_mojom_traits.h" ]
+
+deps = [
+  "//media",
+  "//media/capture:capture_base",
+]
+
+type_mappings = [
+  "media.mojom.ResolutionChangePolicy=media::ResolutionChangePolicy",
+  "media.mojom.PowerLineFrequency=media::PowerLineFrequency",
+  "media.mojom.VideoCapturePixelFormat=media::VideoPixelFormat",
+  "media.mojom.VideoCaptureBufferType=media::VideoCaptureBufferType",
+  "media.mojom.VideoCaptureError=media::VideoCaptureError",
+  "media.mojom.VideoCaptureFrameDropReason=media::VideoCaptureFrameDropReason",
+  "media.mojom.VideoCaptureFormat=media::VideoCaptureFormat",
+  "media.mojom.VideoCaptureParams=media::VideoCaptureParams",
+  "media.mojom.VideoCaptureDeviceDescriptor=media::VideoCaptureDeviceDescriptor",
+  "media.mojom.VideoCaptureDeviceInfo=media::VideoCaptureDeviceInfo",
+  "media.mojom.VideoFacingMode=media::VideoFacingMode",
+]
diff --git a/media/gpu/v4l2/v4l2_mjpeg_decode_accelerator.cc b/media/gpu/v4l2/v4l2_mjpeg_decode_accelerator.cc
index 7262689..6f9e7c7 100644
--- a/media/gpu/v4l2/v4l2_mjpeg_decode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_mjpeg_decode_accelerator.cc
@@ -256,6 +256,13 @@
             << ", size=" << bitstream_buffer.size();
   DCHECK(io_task_runner_->BelongsToCurrentThread());
 
+  if (video_frame->HasDmaBufs()) {
+    VLOGF(1) << "Decoding to dmabuf-backed video frame is not supported, id: "
+             << bitstream_buffer.id();
+    PostNotifyError(bitstream_buffer.id(), INVALID_ARGUMENT);
+    return;
+  }
+
   if (bitstream_buffer.id() < 0) {
     VLOGF(1) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
     PostNotifyError(bitstream_buffer.id(), INVALID_ARGUMENT);
diff --git a/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc b/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc
index bb7bd98e..16766ba 100644
--- a/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc
@@ -7,42 +7,63 @@
 #include <stddef.h>
 #include <va/va.h>
 
+#include <array>
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
 #include "base/containers/span.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
+#include "gpu/ipc/common/gpu_memory_buffer_impl.h"
+#include "gpu/ipc/common/gpu_memory_buffer_support.h"
 #include "media/base/bitstream_buffer.h"
 #include "media/base/unaligned_shared_memory.h"
 #include "media/base/video_frame.h"
+#include "media/base/video_frame_layout.h"
 #include "media/base/video_types.h"
+#include "media/gpu/format_utils.h"
+#include "media/gpu/linux/platform_video_frame_utils.h"
 #include "media/gpu/macros.h"
 #include "media/gpu/vaapi/va_surface.h"
 #include "media/gpu/vaapi/vaapi_image_decoder.h"
 #include "media/gpu/vaapi/vaapi_utils.h"
 #include "media/gpu/vaapi/vaapi_wrapper.h"
 #include "third_party/libyuv/include/libyuv.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/linux/native_pixmap_dmabuf.h"
+#include "ui/gfx/native_pixmap.h"
 
 namespace media {
 
 namespace {
 
+constexpr uint32_t kInvalidVaFourcc = 0u;
+
 // UMA errors that the VaapiMjpegDecodeAccelerator class reports.
-enum VAJDADecoderFailure {
+enum VAJDAFailure {
   VAAPI_ERROR = 0,
-  VAJDA_DECODER_FAILURES_MAX,
+  VAJDA_FAILURES_MAX,
 };
 
-static void ReportToVAJDADecoderFailureUMA(VAJDADecoderFailure failure) {
+static void ReportToVAJDADecoderFailureUMA(VAJDAFailure failure) {
   UMA_HISTOGRAM_ENUMERATION("Media.VAJDA.DecoderFailure", failure,
-                            VAJDA_DECODER_FAILURES_MAX + 1);
+                            VAJDA_FAILURES_MAX + 1);
+}
+
+static void ReportToVAJDAVppFailureUMA(VAJDAFailure failure) {
+  UMA_HISTOGRAM_ENUMERATION("Media.VAJDA.VppFailure", failure,
+                            VAJDA_FAILURES_MAX + 1);
 }
 
 static void ReportToVAJDAResponseToClientUMA(
@@ -72,6 +93,8 @@
   size_t min_size = 0;
   if (image->format.fourcc == VA_FOURCC_I420) {
     min_size = VideoFrame::AllocationSize(PIXEL_FORMAT_I420, dimensions);
+  } else if (image->format.fourcc == VA_FOURCC_NV12) {
+    min_size = VideoFrame::AllocationSize(PIXEL_FORMAT_NV12, dimensions);
   } else if (image->format.fourcc == VA_FOURCC_YUY2 ||
              image->format.fourcc == VA_FOURCC('Y', 'U', 'Y', 'V')) {
     min_size = VideoFrame::AllocationSize(PIXEL_FORMAT_YUY2, dimensions);
@@ -81,6 +104,33 @@
   return base::strict_cast<size_t>(image->data_size) >= min_size;
 }
 
+static uint32_t VideoPixelFormatToVAFourCC(VideoPixelFormat format) {
+  switch (format) {
+    case PIXEL_FORMAT_I420:
+      return VA_FOURCC_I420;
+    case PIXEL_FORMAT_YV12:
+      return VA_FOURCC_YV12;
+    case PIXEL_FORMAT_NV12:
+      return VA_FOURCC_NV12;
+    case PIXEL_FORMAT_NV21:
+      return VA_FOURCC_NV21;
+    case PIXEL_FORMAT_UYVY:
+      return VA_FOURCC_UYVY;
+    case PIXEL_FORMAT_YUY2:
+      return VA_FOURCC_YUY2;
+    case PIXEL_FORMAT_ARGB:
+      return VA_FOURCC_ARGB;
+    case PIXEL_FORMAT_XRGB:
+      return VA_FOURCC_XRGB;
+    case PIXEL_FORMAT_ABGR:
+      return VA_FOURCC_ABGR;
+    case PIXEL_FORMAT_XBGR:
+      return VA_FOURCC_XBGR;
+    default:
+      return kInvalidVaFourcc;
+  }
+}
+
 }  // namespace
 
 void VaapiMjpegDecodeAccelerator::NotifyError(int32_t bitstream_buffer_id,
@@ -136,6 +186,16 @@
     return false;
   }
 
+  vpp_vaapi_wrapper_ = VaapiWrapper::Create(
+      VaapiWrapper::kVideoProcess, VAProfileNone,
+      base::BindRepeating(&ReportToVAJDAVppFailureUMA, VAAPI_ERROR));
+  if (!vpp_vaapi_wrapper_) {
+    VLOGF(1) << "Failed initializing VAAPI for VPP";
+    return false;
+  }
+
+  gpu_memory_buffer_support_ = std::make_unique<gpu::GpuMemoryBufferSupport>();
+
   if (!decoder_thread_.Start()) {
     VLOGF(1) << "Failed to start decoding thread.";
     return false;
@@ -145,14 +205,13 @@
   return true;
 }
 
-bool VaapiMjpegDecodeAccelerator::OutputPictureOnTaskRunner(
+bool VaapiMjpegDecodeAccelerator::OutputPictureLibYuvOnTaskRunner(
     std::unique_ptr<ScopedVAImage> scoped_image,
     int32_t input_buffer_id,
     scoped_refptr<VideoFrame> video_frame) {
   DCHECK(decoder_task_runner_->BelongsToCurrentThread());
 
-  TRACE_EVENT1("jpeg", "VaapiMjpegDecodeAccelerator::OutputPictureOnTaskRunner",
-               "input_buffer_id", input_buffer_id);
+  TRACE_EVENT1("jpeg", __func__, "input_buffer_id", input_buffer_id);
 
   DCHECK(scoped_image);
   const VAImage* image = scoped_image->image();
@@ -170,55 +229,133 @@
     return false;
   }
 
-  // Copy image content from VAImage to VideoFrame. If the image is not in the
-  // I420 format we'll have to convert it.
-  auto* mem = static_cast<uint8_t*>(scoped_image->va_buffer()->data());
-  DCHECK_GE(base::strict_cast<int>(image->width),
-            video_frame->coded_size().width());
-  DCHECK_GE(base::strict_cast<int>(image->height),
-            video_frame->coded_size().height());
+  // The decoded image size is aligned up to JPEG MCU size, so it may be larger
+  // than |video_frame|'s visible size.
+  if (base::strict_cast<int>(image->width) < visible_size.width() ||
+      base::strict_cast<int>(image->height) < visible_size.height()) {
+    VLOGF(1) << "Decoded image size is smaller than output frame size";
+    return false;
+  }
   DCHECK(VerifyDataSize(image));
-  uint8_t* dst_y = video_frame->data(VideoFrame::kYPlane);
-  uint8_t* dst_u = video_frame->data(VideoFrame::kUPlane);
-  uint8_t* dst_v = video_frame->data(VideoFrame::kVPlane);
-  size_t dst_y_stride = video_frame->stride(VideoFrame::kYPlane);
-  size_t dst_u_stride = video_frame->stride(VideoFrame::kUPlane);
-  size_t dst_v_stride = video_frame->stride(VideoFrame::kVPlane);
+
+  // Extract source pointers and strides.
+  auto* const mem =
+      static_cast<const uint8_t*>(scoped_image->va_buffer()->data());
+  std::array<const uint8_t*, VideoFrame::kMaxPlanes> src_ptrs{};
+  std::array<int, VideoFrame::kMaxPlanes> src_strides{};
+  for (uint32_t i = 0; i < image->num_planes; i++) {
+    src_ptrs[i] = mem + image->offsets[i];
+    if (!base::CheckedNumeric<uint32_t>(image->pitches[i])
+             .AssignIfValid(&src_strides[i])) {
+      VLOGF(1) << "Can't extract the strides";
+      return false;
+    }
+  }
+
+  // Extract destination pointers and strides.
+  std::array<uint8_t*, VideoFrame::kMaxPlanes> dst_ptrs{};
+  std::array<int, VideoFrame::kMaxPlanes> dst_strides{};
+  base::ScopedClosureRunner buffer_unmapper;
+  if (video_frame->HasDmaBufs()) {
+    // Dmabuf-backed frame needs to be mapped for SW access.
+    DCHECK(gpu_memory_buffer_support_);
+    base::Optional<gfx::BufferFormat> gfx_format =
+        VideoPixelFormatToGfxBufferFormat(video_frame->format());
+    if (!gfx_format) {
+      VLOGF(1) << "Unsupported format: " << video_frame->format();
+      return false;
+    }
+    std::unique_ptr<gpu::GpuMemoryBufferImpl> gmb =
+        gpu_memory_buffer_support_->CreateGpuMemoryBufferImplFromHandle(
+            CreateGpuMemoryBufferHandle(video_frame.get()),
+            video_frame->coded_size(), *gfx_format,
+            gfx::BufferUsage::SCANOUT_CPU_READ_WRITE, base::DoNothing());
+    if (!gmb) {
+      VLOGF(1) << "Failed to create GPU memory buffer";
+      return false;
+    }
+    if (!gmb->Map()) {
+      VLOGF(1) << "Failed to map GPU memory buffer";
+      return false;
+    }
+    for (size_t i = 0; i < video_frame->layout().num_planes(); i++) {
+      dst_ptrs[i] = static_cast<uint8_t*>(gmb->memory(i));
+      dst_strides[i] = gmb->stride(i);
+    }
+    buffer_unmapper.ReplaceClosure(
+        base::BindOnce(&gpu::GpuMemoryBufferImpl::Unmap, std::move(gmb)));
+  } else {
+    for (size_t i = 0; i < video_frame->layout().num_planes(); i++) {
+      dst_ptrs[i] = video_frame->visible_data(i);
+      dst_strides[i] = video_frame->stride(i);
+    }
+  }
 
   switch (image->format.fourcc) {
-    case VA_FOURCC_I420: {
+    case VA_FOURCC_I420:
       DCHECK_EQ(image->num_planes, 3u);
-      const uint8_t* src_y = mem + image->offsets[0];
-      const uint8_t* src_u = mem + image->offsets[1];
-      const uint8_t* src_v = mem + image->offsets[2];
-      const size_t src_y_stride = image->pitches[0];
-      const size_t src_u_stride = image->pitches[1];
-      const size_t src_v_stride = image->pitches[2];
-      if (libyuv::I420Copy(src_y, src_y_stride, src_u, src_u_stride, src_v,
-                           src_v_stride, dst_y, dst_y_stride, dst_u,
-                           dst_u_stride, dst_v, dst_v_stride,
-                           visible_size.width(), visible_size.height())) {
-        VLOGF(1) << "I420Copy failed";
-        return false;
+      switch (video_frame->format()) {
+        case PIXEL_FORMAT_I420:
+          DCHECK_EQ(video_frame->layout().num_planes(), 3u);
+          if (libyuv::I420Copy(src_ptrs[0], src_strides[0], src_ptrs[1],
+                               src_strides[1], src_ptrs[2], src_strides[2],
+                               dst_ptrs[0], dst_strides[0], dst_ptrs[1],
+                               dst_strides[1], dst_ptrs[2], dst_strides[2],
+                               visible_size.width(), visible_size.height())) {
+            VLOGF(1) << "I420Copy failed";
+            return false;
+          }
+          break;
+        case PIXEL_FORMAT_NV12:
+          DCHECK_EQ(video_frame->layout().num_planes(), 2u);
+          if (libyuv::I420ToNV12(src_ptrs[0], src_strides[0], src_ptrs[1],
+                                 src_strides[1], src_ptrs[2], src_strides[2],
+                                 dst_ptrs[0], dst_strides[0], dst_ptrs[1],
+                                 dst_strides[1], visible_size.width(),
+                                 visible_size.height())) {
+            VLOGF(1) << "I420ToNV12 failed";
+            return false;
+          }
+          break;
+        default:
+          VLOGF(1) << "Can't convert image from I420 to "
+                   << video_frame->format();
+          return false;
       }
       break;
-    }
     case VA_FOURCC_YUY2:
-    case VA_FOURCC('Y', 'U', 'Y', 'V'): {
+    case VA_FOURCC('Y', 'U', 'Y', 'V'):
       DCHECK_EQ(image->num_planes, 1u);
-      const uint8_t* src_yuy2 = mem + image->offsets[0];
-      const size_t src_yuy2_stride = image->pitches[0];
-      if (libyuv::YUY2ToI420(src_yuy2, src_yuy2_stride, dst_y, dst_y_stride,
-                             dst_u, dst_u_stride, dst_v, dst_v_stride,
-                             visible_size.width(), visible_size.height())) {
-        VLOGF(1) << "YUY2ToI420 failed";
-        return false;
+      switch (video_frame->format()) {
+        case PIXEL_FORMAT_I420:
+          DCHECK_EQ(video_frame->layout().num_planes(), 3u);
+          if (libyuv::YUY2ToI420(src_ptrs[0], src_strides[0], dst_ptrs[0],
+                                 dst_strides[0], dst_ptrs[1], dst_strides[1],
+                                 dst_ptrs[2], dst_strides[2],
+                                 visible_size.width(), visible_size.height())) {
+            VLOGF(1) << "YUY2ToI420 failed";
+            return false;
+          }
+          break;
+        case PIXEL_FORMAT_NV12:
+          DCHECK_EQ(video_frame->layout().num_planes(), 2u);
+          if (libyuv::YUY2ToNV12(src_ptrs[0], src_strides[0], dst_ptrs[0],
+                                 dst_strides[0], dst_ptrs[1], dst_strides[1],
+                                 visible_size.width(), visible_size.height())) {
+            VLOGF(1) << "YUY2ToNV12 failed";
+            return false;
+          }
+          break;
+        default:
+          VLOGF(1) << "Can't convert image from YUYV to "
+                   << video_frame->format();
+          return false;
       }
       break;
-    }
     default:
-      VLOGF(1) << "Can't convert image to I420: unsupported format "
-               << FourccToString(image->format.fourcc);
+      VLOGF(1) << "Can't convert image from "
+               << FourccToString(image->format.fourcc) << " to "
+               << video_frame->format();
       return false;
   }
 
@@ -230,6 +367,71 @@
   return true;
 }
 
+bool VaapiMjpegDecodeAccelerator::OutputPictureVppOnTaskRunner(
+    const ScopedVASurface* surface,
+    int32_t input_buffer_id,
+    scoped_refptr<VideoFrame> video_frame) {
+  DCHECK(decoder_task_runner_->BelongsToCurrentThread());
+  DCHECK(surface);
+
+  TRACE_EVENT1("jpeg", __func__, "input_buffer_id", input_buffer_id);
+
+  // Bind a VA surface to |video_frame|.
+  scoped_refptr<gfx::NativePixmap> pixmap =
+      CreateNativePixmapDmaBuf(video_frame.get());
+  if (!pixmap) {
+    VLOGF(1) << "Cannot create native pixmap for output buffer";
+    return false;
+  }
+  scoped_refptr<VASurface> output_surface =
+      vpp_vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap);
+  if (!output_surface) {
+    VLOGF(1) << "Cannot create VA surface for output buffer";
+    return false;
+  }
+
+  // Use VPP to blit the visible size region within |surface| into
+  // |output_surface|. BlitSurface() does scaling not cropping when source and
+  // destination sizes don't match, so we manipulate the sizes of surfaces to
+  // effectively do the cropping.
+  const gfx::Size& blit_size = video_frame->visible_rect().size();
+  if (surface->size().width() < blit_size.width() ||
+      surface->size().height() < blit_size.height()) {
+    VLOGF(1) << "Decoded surface size is smaller than target size";
+    return false;
+  }
+  scoped_refptr<VASurface> src_surface = base::MakeRefCounted<VASurface>(
+      surface->id(), blit_size, surface->format(),
+      base::DoNothing() /* release_cb */);
+  scoped_refptr<VASurface> dst_surface = base::MakeRefCounted<VASurface>(
+      output_surface->id(), blit_size, output_surface->format(),
+      base::DoNothing() /* release_cb */);
+
+  // We should call vaSyncSurface() when passing surface between contexts. See:
+  // https://lists.01.org/pipermail/intel-vaapi-media/2019-June/000131.html
+  if (!vpp_vaapi_wrapper_->SyncSurface(src_surface->id())) {
+    VLOGF(1) << "Cannot sync VPP input surface";
+    return false;
+  }
+  if (!vpp_vaapi_wrapper_->BlitSurface(src_surface, dst_surface)) {
+    VLOGF(1) << "Cannot convert decoded image into output buffer";
+    return false;
+  }
+
+  // Sync target surface since the buffer is returning to client.
+  if (!vpp_vaapi_wrapper_->SyncSurface(dst_surface->id())) {
+    VLOGF(1) << "Cannot sync VPP output surface";
+    return false;
+  }
+
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&VaapiMjpegDecodeAccelerator::VideoFrameReady,
+                     weak_this_factory_.GetWeakPtr(), input_buffer_id));
+
+  return true;
+}
+
 void VaapiMjpegDecodeAccelerator::DecodeTask(
     int32_t bitstream_buffer_id,
     std::unique_ptr<UnalignedSharedMemory> shm,
@@ -238,22 +440,56 @@
   DCHECK(decoder_task_runner_->BelongsToCurrentThread());
   TRACE_EVENT0("jpeg", "DecodeTask");
 
+  // TODO(andrescj): validate that the video frame's visible size is the same as
+  // the parsed JPEG's visible size when it is returned from Decode(), and
+  // remove the size checks in OutputPicture*().
   VaapiImageDecodeStatus status = decoder_.Decode(
       base::make_span(static_cast<const uint8_t*>(shm->memory()), shm->size()));
   if (status != VaapiImageDecodeStatus::kSuccess) {
     NotifyError(bitstream_buffer_id, VaapiJpegDecodeStatusToError(status));
     return;
   }
+  const ScopedVASurface* surface = decoder_.GetScopedVASurface();
+  DCHECK(surface);
+  DCHECK(surface->IsValid());
+
+  // For DMA-buf backed |video_frame|, we will import it as a VA surface and use
+  // VPP to convert the decoded |surface| into it, if the formats and sizes are
+  // supported.
+  const uint32_t video_frame_va_fourcc =
+      VideoPixelFormatToVAFourCC(video_frame->format());
+  if (video_frame_va_fourcc == kInvalidVaFourcc) {
+    VLOGF(1) << "Unsupported video frame format: " << video_frame->format();
+    NotifyError(bitstream_buffer_id, PLATFORM_FAILURE);
+    return;
+  }
+  // TODO(kamesan): move HasDmaBufs() to DCHECK when we deprecate
+  // shared-memory-backed video frame.
+  if (video_frame->HasDmaBufs() &&
+      VaapiWrapper::IsVppResolutionAllowed(surface->size()) &&
+      VaapiWrapper::IsVppSupportedForJpegDecodedSurfaceToFourCC(
+          surface->format(), video_frame_va_fourcc)) {
+    if (!OutputPictureVppOnTaskRunner(surface, bitstream_buffer_id,
+                                      std::move(video_frame))) {
+      VLOGF(1) << "Output picture using VPP failed";
+      NotifyError(bitstream_buffer_id, PLATFORM_FAILURE);
+    }
+    return;
+  }
+
+  // Fallback to do conversion by libyuv. This happens when:
+  // 1. |video_frame| is backed by shared memory.
+  // 2. VPP doesn't support the format conversion. This is intended for AMD
+  //    VAAPI driver whose VPP only supports converting decoded 4:2:0 JPEGs.
   std::unique_ptr<ScopedVAImage> image =
-      decoder_.GetImage(VA_FOURCC_I420 /* preferred_image_fourcc */, &status);
+      decoder_.GetImage(video_frame_va_fourcc, &status);
   if (status != VaapiImageDecodeStatus::kSuccess) {
     NotifyError(bitstream_buffer_id, VaapiJpegDecodeStatusToError(status));
     return;
   }
-
-  if (!OutputPictureOnTaskRunner(std::move(image), bitstream_buffer_id,
-                                 std::move(video_frame))) {
-    VLOGF(1) << "Output picture failed";
+  if (!OutputPictureLibYuvOnTaskRunner(std::move(image), bitstream_buffer_id,
+                                       std::move(video_frame))) {
+    VLOGF(1) << "Output picture using libyuv failed";
     NotifyError(bitstream_buffer_id, PLATFORM_FAILURE);
   }
 }
@@ -267,17 +503,24 @@
   DVLOGF(4) << "Mapping new input buffer id: " << bitstream_buffer.id()
             << " size: " << bitstream_buffer.size();
 
-  // UnalignedSharedMemory will take over the |bitstream_buffer.handle()|.
-  auto shm = std::make_unique<UnalignedSharedMemory>(
-      bitstream_buffer.TakeRegion(), bitstream_buffer.size(),
-      false /* read_only */);
-
   if (bitstream_buffer.id() < 0) {
     VLOGF(1) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
     NotifyError(bitstream_buffer.id(), INVALID_ARGUMENT);
     return;
   }
 
+  if ((video_frame->visible_rect().width() & 1) ||
+      (video_frame->visible_rect().height() & 1)) {
+    VLOGF(1) << "Video frame visible size has odd dimension";
+    NotifyError(bitstream_buffer.id(), PLATFORM_FAILURE);
+    return;
+  }
+
+  // UnalignedSharedMemory will take over the |bitstream_buffer.handle()|.
+  auto shm = std::make_unique<UnalignedSharedMemory>(
+      bitstream_buffer.TakeRegion(), bitstream_buffer.size(),
+      false /* read_only */);
+
   if (!shm->MapAt(bitstream_buffer.offset(), bitstream_buffer.size())) {
     VLOGF(1) << "Failed to map input buffer";
     NotifyError(bitstream_buffer.id(), UNREADABLE_INPUT);
diff --git a/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.h b/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.h
index c32ceb5..ff507816 100644
--- a/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.h
+++ b/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.h
@@ -21,11 +21,16 @@
 class SingleThreadTaskRunner;
 }
 
+namespace gpu {
+class GpuMemoryBufferSupport;
+}
+
 namespace media {
 
 class BitstreamBuffer;
 class ScopedVAImage;
 class UnalignedSharedMemory;
+class VaapiWrapper;
 class VideoFrame;
 
 // Class to provide MJPEG decode acceleration for Intel systems with hardware
@@ -65,11 +70,18 @@
                   std::unique_ptr<UnalignedSharedMemory> shm,
                   scoped_refptr<VideoFrame> video_frame);
 
-  // Puts contents of |image| into given |video_frame| and passes the
-  // |input_buffer_id| of the resulting picture to client for output.
-  bool OutputPictureOnTaskRunner(std::unique_ptr<ScopedVAImage> image,
-                                 int32_t input_buffer_id,
-                                 scoped_refptr<VideoFrame> video_frame);
+  // Puts contents of |surface| into given |video_frame| using VA-API Video
+  // Processing Pipeline (VPP), and passes the |input_buffer_id| of the
+  // resulting picture to client for output.
+  bool OutputPictureVppOnTaskRunner(const ScopedVASurface* surface,
+                                    int32_t input_buffer_id,
+                                    scoped_refptr<VideoFrame> video_frame);
+
+  // Puts contents of |image| into given |video_frame| using libyuv, and passes
+  // the |input_buffer_id| of the resulting picture to client for output.
+  bool OutputPictureLibYuvOnTaskRunner(std::unique_ptr<ScopedVAImage> image,
+                                       int32_t input_buffer_id,
+                                       scoped_refptr<VideoFrame> video_frame);
 
   // ChildThread's task runner.
   const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
@@ -82,8 +94,14 @@
 
   VaapiJpegDecoder decoder_;
 
-  // Comes after |decoder_| to ensure its destructor is executed before
-  // |decoder_| is destroyed.
+  // VaapiWrapper for VPP context. This is used to convert decoded data into
+  // client buffer.
+  scoped_refptr<VaapiWrapper> vpp_vaapi_wrapper_;
+
+  // For creating GpuMemoryBuffer from client DMA buffer that can be mapped for
+  // software access.
+  std::unique_ptr<gpu::GpuMemoryBufferSupport> gpu_memory_buffer_support_;
+
   base::Thread decoder_thread_;
   // Use this to post tasks to |decoder_thread_| instead of
   // |decoder_thread_.task_runner()| because the latter will be NULL once
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index 13122494..f50d5cc 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -467,11 +467,10 @@
                                VAProfile profile,
                                std::vector<VAConfigAttrib>* required_attribs) {
   va_lock->AssertAcquired();
-  // No attribute for kVideoProcess.
-  if (mode == VaapiWrapper::kVideoProcess)
-    return true;
 
-  // VAConfigAttribRTFormat is common to both encode and decode |mode|s.
+  // Choose a suitable VAConfigAttribRTFormat for every |mode|. For video
+  // processing, the supported surface attribs may vary according to which RT
+  // format is set.
   if (profile == VAProfileVP9Profile2 || profile == VAProfileVP9Profile3) {
     required_attribs->push_back(
         {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420_10BPP});
@@ -519,6 +518,7 @@
     VAProfile va_profile;
     gfx::Size min_resolution;
     gfx::Size max_resolution;
+    std::vector<uint32_t> pixel_formats;
     VaapiWrapper::InternalFormats supported_internal_formats;
   };
   static const VASupportedProfiles& Get();
@@ -641,9 +641,6 @@
 std::vector<VASupportedProfiles::ProfileInfo>
 VASupportedProfiles::GetSupportedProfileInfosForCodecModeInternal(
     VaapiWrapper::CodecMode mode) const {
-  if (mode == VaapiWrapper::kVideoProcess)
-    return {ProfileInfo{VAProfileNone, gfx::Size()}};
-
   std::vector<ProfileInfo> supported_profile_infos;
   std::vector<VAProfile> va_profiles;
   if (!GetSupportedVAProfiles(&va_profiles))
@@ -665,7 +662,7 @@
     if (IsBlackListedDriver(va_vendor_string, mode, va_profile))
       continue;
 
-    ProfileInfo profile_info;
+    ProfileInfo profile_info{};
     if (!FillProfileInfo_Locked(va_profile, entrypoint, required_attribs,
                                 &profile_info)) {
       LOG(ERROR) << "FillProfileInfo_Locked failed for va_profile "
@@ -805,6 +802,12 @@
     } else if (attrib.type == VASurfaceAttribMinHeight) {
       profile_info->min_resolution.set_height(
           base::strict_cast<int>(attrib.value.value.i));
+    } else if (attrib.type == VASurfaceAttribPixelFormat) {
+      // According to va.h, VASurfaceAttribPixelFormat is meaningful as input to
+      // vaQuerySurfaceAttributes(). However, per the implementation of
+      // i965_QuerySurfaceAttributes(), our usage here should enumerate all the
+      // formats.
+      profile_info->pixel_formats.push_back(attrib.value.value.i);
     }
   }
   if (profile_info->max_resolution.IsEmpty()) {
@@ -1248,6 +1251,45 @@
 }
 
 // static
+bool VaapiWrapper::IsVppResolutionAllowed(const gfx::Size& size) {
+  VASupportedProfiles::ProfileInfo profile_info;
+  if (!VASupportedProfiles::Get().IsProfileSupported(
+          kVideoProcess, VAProfileNone, &profile_info)) {
+    return false;
+  }
+  return gfx::Rect(profile_info.min_resolution.width(),
+                   profile_info.min_resolution.height(),
+                   profile_info.max_resolution.width(),
+                   profile_info.max_resolution.height())
+      .Contains(size.width(), size.height());
+}
+
+// static
+bool VaapiWrapper::IsVppSupportedForJpegDecodedSurfaceToFourCC(
+    unsigned int rt_format,
+    uint32_t fourcc) {
+  if (!IsDecodingSupportedForInternalFormat(VAProfileJPEGBaseline, rt_format))
+    return false;
+
+  VASupportedProfiles::ProfileInfo profile_info;
+  if (!VASupportedProfiles::Get().IsProfileSupported(
+          kVideoProcess, VAProfileNone, &profile_info)) {
+    return false;
+  }
+
+  // Workaround: for Mesa VAAPI driver, VPP only supports internal surface
+  // format for 4:2:0 JPEG image.
+  if (base::StartsWith(VADisplayState::Get()->va_vendor_string(),
+                       kMesaGalliumDriverPrefix,
+                       base::CompareCase::SENSITIVE) &&
+      rt_format != VA_RT_FORMAT_YUV420) {
+    return false;
+  }
+
+  return base::Contains(profile_info.pixel_formats, fourcc);
+}
+
+// static
 bool VaapiWrapper::IsJpegEncodeSupported() {
   return VASupportedProfiles::Get().IsProfileSupported(kEncode,
                                                        VAProfileJPEGBaseline);
@@ -1513,6 +1555,16 @@
   return exported_pixmap;
 }
 
+bool VaapiWrapper::SyncSurface(VASurfaceID va_surface_id) {
+  DCHECK_NE(va_surface_id, VA_INVALID_ID);
+
+  base::AutoLock auto_lock(*va_lock_);
+
+  VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
+  VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
+  return true;
+}
+
 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
                                 size_t size,
                                 const void* buffer) {
diff --git a/media/gpu/vaapi/vaapi_wrapper.h b/media/gpu/vaapi/vaapi_wrapper.h
index c41e709..5c35b20d 100644
--- a/media/gpu/vaapi/vaapi_wrapper.h
+++ b/media/gpu/vaapi/vaapi_wrapper.h
@@ -164,6 +164,17 @@
                                                uint32_t preferred_fourcc,
                                                uint32_t* suitable_fourcc);
 
+  // Checks the surface size is allowed for VPP. Returns true if the size is
+  // supported, false otherwise.
+  static bool IsVppResolutionAllowed(const gfx::Size& size);
+
+  // Returns true if VPP supports the format conversion from a JPEG decoded
+  // internal surface to a FOURCC. |rt_format| corresponds to the JPEG's
+  // subsampling format. |fourcc| is the output surface's FOURCC.
+  static bool IsVppSupportedForJpegDecodedSurfaceToFourCC(
+      unsigned int rt_format,
+      uint32_t fourcc);
+
   // Return true when JPEG encode is supported.
   static bool IsJpegEncodeSupported();
 
@@ -243,6 +254,10 @@
   std::unique_ptr<NativePixmapAndSizeInfo> ExportVASurfaceAsNativePixmapDmaBuf(
       const ScopedVASurface& va_surface);
 
+  // Synchronize the VASurface explicitly. This is useful when sharing a surface
+  // between contexts.
+  bool SyncSurface(VASurfaceID va_surface_id);
+
   // Submit parameters or slice data of |va_buffer_type|, copying them from
   // |buffer| of size |size|, into HW codec. The data in |buffer| is no
   // longer needed and can be freed after this method returns.
diff --git a/net/data/ssl/blacklist/3ae699d94e8febdacb86d4f90d40903333478e65e0655c432451197e33fa07f2.pem b/net/data/ssl/blocklist/3ae699d94e8febdacb86d4f90d40903333478e65e0655c432451197e33fa07f2.pem
similarity index 100%
rename from net/data/ssl/blacklist/3ae699d94e8febdacb86d4f90d40903333478e65e0655c432451197e33fa07f2.pem
rename to net/data/ssl/blocklist/3ae699d94e8febdacb86d4f90d40903333478e65e0655c432451197e33fa07f2.pem
diff --git a/net/data/ssl/blacklist/a25a19546819d048000ef9c6577c4bcd8d2155b1e4346a4599d6c8b79799d4a1.pem b/net/data/ssl/blocklist/a25a19546819d048000ef9c6577c4bcd8d2155b1e4346a4599d6c8b79799d4a1.pem
similarity index 100%
rename from net/data/ssl/blacklist/a25a19546819d048000ef9c6577c4bcd8d2155b1e4346a4599d6c8b79799d4a1.pem
rename to net/data/ssl/blocklist/a25a19546819d048000ef9c6577c4bcd8d2155b1e4346a4599d6c8b79799d4a1.pem
diff --git a/net/data/ssl/blacklist/d8888f4a84f74c974dffb573a1bf5bbbacd1713b905096f8eb015062bf396c4d.pem b/net/data/ssl/blocklist/d8888f4a84f74c974dffb573a1bf5bbbacd1713b905096f8eb015062bf396c4d.pem
similarity index 100%
rename from net/data/ssl/blacklist/d8888f4a84f74c974dffb573a1bf5bbbacd1713b905096f8eb015062bf396c4d.pem
rename to net/data/ssl/blocklist/d8888f4a84f74c974dffb573a1bf5bbbacd1713b905096f8eb015062bf396c4d.pem
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn
index b78243b..7908815 100644
--- a/pdf/BUILD.gn
+++ b/pdf/BUILD.gn
@@ -114,6 +114,13 @@
         "pdfium/pdfium_unsupported_features.cc",
         "pdfium/pdfium_unsupported_features.h",
       ]
+
+      if (is_linux) {
+        sources += [
+          "pdfium/pdfium_font_linux.cc",
+          "pdfium/pdfium_font_linux.h",
+        ]
+      }
     }
   }
 
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 73aeda1..fb7cd00b 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -16,8 +16,6 @@
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
-#include "base/i18n/encoding_detection.h"
-#include "base/i18n/icu_string_conversions.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
@@ -40,7 +38,6 @@
 #include "pdf/url_loader_wrapper_impl.h"
 #include "ppapi/cpp/instance.h"
 #include "ppapi/cpp/private/pdf.h"
-#include "ppapi/cpp/trusted/browser_font_trusted.h"
 #include "ppapi/cpp/var_dictionary.h"
 #include "printing/units.h"
 #include "third_party/pdfium/public/cpp/fpdf_scopers.h"
@@ -50,11 +47,14 @@
 #include "third_party/pdfium/public/fpdf_ext.h"
 #include "third_party/pdfium/public/fpdf_ppo.h"
 #include "third_party/pdfium/public/fpdf_searchex.h"
-#include "third_party/pdfium/public/fpdf_sysfontinfo.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/gfx/geometry/rect.h"
 #include "v8/include/v8.h"
 
+#if defined(OS_LINUX)
+#include "pdf/pdfium/pdfium_font_linux.h"
+#endif
+
 using printing::ConvertUnit;
 using printing::ConvertUnitDouble;
 using printing::kPointsPerInch;
@@ -138,180 +138,6 @@
 constexpr base::TimeDelta kMaxInitialProgressivePaintTime =
     base::TimeDelta::FromMilliseconds(250);
 
-#if defined(OS_LINUX)
-
-PP_Instance g_last_instance_id;
-
-// TODO(npm): Move font stuff to another file to reduce the size of this one
-PP_BrowserFont_Trusted_Weight WeightToBrowserFontTrustedWeight(int weight) {
-  static_assert(PP_BROWSERFONT_TRUSTED_WEIGHT_100 == 0,
-                "PP_BrowserFont_Trusted_Weight min");
-  static_assert(PP_BROWSERFONT_TRUSTED_WEIGHT_900 == 8,
-                "PP_BrowserFont_Trusted_Weight max");
-  constexpr int kMinimumWeight = 100;
-  constexpr int kMaximumWeight = 900;
-  int normalized_weight =
-      std::min(std::max(weight, kMinimumWeight), kMaximumWeight);
-  normalized_weight = (normalized_weight / 100) - 1;
-  return static_cast<PP_BrowserFont_Trusted_Weight>(normalized_weight);
-}
-
-// This list is for CPWL_FontMap::GetDefaultFontByCharset().
-// We pretend to have these font natively and let the browser (or underlying
-// fontconfig) to pick the proper font on the system.
-void EnumFonts(FPDF_SYSFONTINFO* sysfontinfo, void* mapper) {
-  FPDF_AddInstalledFont(mapper, "Arial", FXFONT_DEFAULT_CHARSET);
-
-  const FPDF_CharsetFontMap* font_map = FPDF_GetDefaultTTFMap();
-  for (; font_map->charset != -1; ++font_map) {
-    FPDF_AddInstalledFont(mapper, font_map->fontname, font_map->charset);
-  }
-}
-
-void* MapFont(FPDF_SYSFONTINFO*,
-              int weight,
-              int italic,
-              int charset,
-              int pitch_family,
-              const char* face,
-              int* exact) {
-  // Do not attempt to map fonts if pepper is not initialized (for privet local
-  // printing).
-  // TODO(noamsml): Real font substitution (http://crbug.com/391978)
-  if (!pp::Module::Get())
-    return nullptr;
-
-  pp::BrowserFontDescription description;
-
-  // Pretend the system does not have the Symbol font to force a fallback to
-  // the built in Symbol font in CFX_FontMapper::FindSubstFont().
-  if (strcmp(face, "Symbol") == 0)
-    return nullptr;
-
-  if (pitch_family & FXFONT_FF_FIXEDPITCH) {
-    description.set_family(PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE);
-  } else if (pitch_family & FXFONT_FF_ROMAN) {
-    description.set_family(PP_BROWSERFONT_TRUSTED_FAMILY_SERIF);
-  }
-
-  static const struct {
-    const char* pdf_name;
-    const char* face;
-    bool bold;
-    bool italic;
-  } kPdfFontSubstitutions[] = {
-      {"Courier", "Courier New", false, false},
-      {"Courier-Bold", "Courier New", true, false},
-      {"Courier-BoldOblique", "Courier New", true, true},
-      {"Courier-Oblique", "Courier New", false, true},
-      {"Helvetica", "Arial", false, false},
-      {"Helvetica-Bold", "Arial", true, false},
-      {"Helvetica-BoldOblique", "Arial", true, true},
-      {"Helvetica-Oblique", "Arial", false, true},
-      {"Times-Roman", "Times New Roman", false, false},
-      {"Times-Bold", "Times New Roman", true, false},
-      {"Times-BoldItalic", "Times New Roman", true, true},
-      {"Times-Italic", "Times New Roman", false, true},
-
-      // MS P?(Mincho|Gothic) are the most notable fonts in Japanese PDF files
-      // without embedding the glyphs. Sometimes the font names are encoded
-      // in Japanese Windows's locale (CP932/Shift_JIS) without space.
-      // Most Linux systems don't have the exact font, but for outsourcing
-      // fontconfig to find substitutable font in the system, we pass ASCII
-      // font names to it.
-      {"MS-PGothic", "MS PGothic", false, false},
-      {"MS-Gothic", "MS Gothic", false, false},
-      {"MS-PMincho", "MS PMincho", false, false},
-      {"MS-Mincho", "MS Mincho", false, false},
-      // MS PGothic in Shift_JIS encoding.
-      {"\x82\x6C\x82\x72\x82\x6F\x83\x53\x83\x56\x83\x62\x83\x4E", "MS PGothic",
-       false, false},
-      // MS Gothic in Shift_JIS encoding.
-      {"\x82\x6C\x82\x72\x83\x53\x83\x56\x83\x62\x83\x4E", "MS Gothic", false,
-       false},
-      // MS PMincho in Shift_JIS encoding.
-      {"\x82\x6C\x82\x72\x82\x6F\x96\xBE\x92\xA9", "MS PMincho", false, false},
-      // MS Mincho in Shift_JIS encoding.
-      {"\x82\x6C\x82\x72\x96\xBE\x92\xA9", "MS Mincho", false, false},
-  };
-
-  // Similar logic exists in PDFium's CFX_FolderFontInfo::FindFont().
-  if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH))
-    face = "Courier New";
-
-  // Map from the standard PDF fonts to TrueType font names.
-  size_t i;
-  for (i = 0; i < base::size(kPdfFontSubstitutions); ++i) {
-    if (strcmp(face, kPdfFontSubstitutions[i].pdf_name) == 0) {
-      description.set_face(kPdfFontSubstitutions[i].face);
-      if (kPdfFontSubstitutions[i].bold)
-        description.set_weight(PP_BROWSERFONT_TRUSTED_WEIGHT_BOLD);
-      if (kPdfFontSubstitutions[i].italic)
-        description.set_italic(true);
-      break;
-    }
-  }
-
-  if (i == base::size(kPdfFontSubstitutions)) {
-    // Convert to UTF-8 before calling set_face().
-    std::string face_utf8;
-    if (base::IsStringUTF8(face)) {
-      face_utf8 = face;
-    } else {
-      std::string encoding;
-      if (base::DetectEncoding(face, &encoding)) {
-        // ConvertToUtf8AndNormalize() clears |face_utf8| on failure.
-        base::ConvertToUtf8AndNormalize(face, encoding, &face_utf8);
-      }
-    }
-
-    if (face_utf8.empty())
-      return nullptr;
-
-    description.set_face(face_utf8);
-    description.set_weight(WeightToBrowserFontTrustedWeight(weight));
-    description.set_italic(italic > 0);
-  }
-
-  if (!pp::PDF::IsAvailable()) {
-    NOTREACHED();
-    return nullptr;
-  }
-
-  PP_Resource font_resource = pp::PDF::GetFontFileWithFallback(
-      pp::InstanceHandle(g_last_instance_id),
-      &description.pp_font_description(),
-      static_cast<PP_PrivateFontCharset>(charset));
-  long res_id = font_resource;
-  return reinterpret_cast<void*>(res_id);
-}
-
-unsigned long GetFontData(FPDF_SYSFONTINFO*,
-                          void* font_id,
-                          unsigned int table,
-                          unsigned char* buffer,
-                          unsigned long buf_size) {
-  if (!pp::PDF::IsAvailable()) {
-    NOTREACHED();
-    return 0;
-  }
-
-  uint32_t size = buf_size;
-  long res_id = reinterpret_cast<long>(font_id);
-  if (!pp::PDF::GetFontTableForPrivateFontFile(res_id, table, buffer, &size))
-    return 0;
-  return size;
-}
-
-void DeleteFont(FPDF_SYSFONTINFO*, void* font_id) {
-  long res_id = reinterpret_cast<long>(font_id);
-  pp::Module::Get()->core()->ReleaseResource(res_id);
-}
-
-FPDF_SYSFONTINFO g_font_info = {1,           0, EnumFonts, MapFont,   0,
-                                GetFontData, 0, 0,         DeleteFont};
-#endif  // defined(OS_LINUX)
-
 PDFiumEngine::CreateDocumentLoaderFunction
     g_create_document_loader_for_testing = nullptr;
 
@@ -561,8 +387,7 @@
   FPDF_InitLibraryWithConfig(&config);
 
 #if defined(OS_LINUX)
-  // Font loading doesn't work in the renderer sandbox in Linux.
-  FPDF_SetSystemFontInfo(&g_font_info);
+  InitializeLinuxFontMapper();
 #endif
 
   InitializeUnsupportedFeaturesHandler();
@@ -595,9 +420,7 @@
 
 #if defined(OS_LINUX)
   // PreviewModeClient does not know its pp::Instance.
-  pp::Instance* instance = client_->GetPluginInstance();
-  if (instance)
-    g_last_instance_id = instance->pp_instance();
+  SetLastInstance(client_->GetPluginInstance());
 #endif
 }
 
@@ -1046,7 +869,7 @@
   KillFormFocus();
 
 #if defined(OS_LINUX)
-  g_last_instance_id = client_->GetPluginInstance()->pp_instance();
+  SetLastInstance(client_->GetPluginInstance());
 #endif
 
   return ConvertPdfToBufferDev(
@@ -2900,7 +2723,7 @@
 
   last_progressive_start_time_ = base::Time::Now();
 #if defined(OS_LINUX)
-  g_last_instance_id = client_->GetPluginInstance()->pp_instance();
+  SetLastInstance(client_->GetPluginInstance());
 #endif
 
   int page_index = progressive_paints_[progressive_index].page_index();
@@ -3373,7 +3196,7 @@
   }
   most_visible_page_ = index;
 #if defined(OS_LINUX)
-  g_last_instance_id = client_->GetPluginInstance()->pp_instance();
+  SetLastInstance(client_->GetPluginInstance());
 #endif
   if (most_visible_page_ != -1 && called_do_document_action_) {
     FPDF_PAGE new_page = pages_[most_visible_page_]->GetPage();
diff --git a/pdf/pdfium/pdfium_font_linux.cc b/pdf/pdfium/pdfium_font_linux.cc
new file mode 100644
index 0000000..c8d8578
--- /dev/null
+++ b/pdf/pdfium/pdfium_font_linux.cc
@@ -0,0 +1,206 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "pdf/pdfium/pdfium_font_linux.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/i18n/encoding_detection.h"
+#include "base/i18n/icu_string_conversions.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/private/pdf.h"
+#include "ppapi/cpp/trusted/browser_font_trusted.h"
+#include "third_party/pdfium/public/fpdf_sysfontinfo.h"
+
+namespace chrome_pdf {
+
+namespace {
+
+PP_Instance g_last_instance_id;
+
+PP_BrowserFont_Trusted_Weight WeightToBrowserFontTrustedWeight(int weight) {
+  static_assert(PP_BROWSERFONT_TRUSTED_WEIGHT_100 == 0,
+                "PP_BrowserFont_Trusted_Weight min");
+  static_assert(PP_BROWSERFONT_TRUSTED_WEIGHT_900 == 8,
+                "PP_BrowserFont_Trusted_Weight max");
+  constexpr int kMinimumWeight = 100;
+  constexpr int kMaximumWeight = 900;
+  int normalized_weight =
+      std::min(std::max(weight, kMinimumWeight), kMaximumWeight);
+  normalized_weight = (normalized_weight / 100) - 1;
+  return static_cast<PP_BrowserFont_Trusted_Weight>(normalized_weight);
+}
+
+// This list is for CPWL_FontMap::GetDefaultFontByCharset().
+// We pretend to have these font natively and let the browser (or underlying
+// fontconfig) pick the proper font on the system.
+void EnumFonts(FPDF_SYSFONTINFO* sysfontinfo, void* mapper) {
+  FPDF_AddInstalledFont(mapper, "Arial", FXFONT_DEFAULT_CHARSET);
+
+  const FPDF_CharsetFontMap* font_map = FPDF_GetDefaultTTFMap();
+  for (; font_map->charset != -1; ++font_map) {
+    FPDF_AddInstalledFont(mapper, font_map->fontname, font_map->charset);
+  }
+}
+
+void* MapFont(FPDF_SYSFONTINFO*,
+              int weight,
+              int italic,
+              int charset,
+              int pitch_family,
+              const char* face,
+              int* exact) {
+  // Do not attempt to map fonts if PPAPI is not initialized (for Privet local
+  // printing).
+  // TODO(noamsml): Real font substitution (http://crbug.com/391978)
+  if (!pp::Module::Get())
+    return nullptr;
+
+  pp::BrowserFontDescription description;
+
+  // Pretend the system does not have the Symbol font to force a fallback to
+  // the built in Symbol font in CFX_FontMapper::FindSubstFont().
+  if (strcmp(face, "Symbol") == 0)
+    return nullptr;
+
+  if (pitch_family & FXFONT_FF_FIXEDPITCH) {
+    description.set_family(PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE);
+  } else if (pitch_family & FXFONT_FF_ROMAN) {
+    description.set_family(PP_BROWSERFONT_TRUSTED_FAMILY_SERIF);
+  }
+
+  static const struct {
+    const char* pdf_name;
+    const char* face;
+    bool bold;
+    bool italic;
+  } kPdfFontSubstitutions[] = {
+      {"Courier", "Courier New", false, false},
+      {"Courier-Bold", "Courier New", true, false},
+      {"Courier-BoldOblique", "Courier New", true, true},
+      {"Courier-Oblique", "Courier New", false, true},
+      {"Helvetica", "Arial", false, false},
+      {"Helvetica-Bold", "Arial", true, false},
+      {"Helvetica-BoldOblique", "Arial", true, true},
+      {"Helvetica-Oblique", "Arial", false, true},
+      {"Times-Roman", "Times New Roman", false, false},
+      {"Times-Bold", "Times New Roman", true, false},
+      {"Times-BoldItalic", "Times New Roman", true, true},
+      {"Times-Italic", "Times New Roman", false, true},
+
+      // MS P?(Mincho|Gothic) are the most notable fonts in Japanese PDF files
+      // without embedding the glyphs. Sometimes the font names are encoded
+      // in Japanese Windows's locale (CP932/Shift_JIS) without space.
+      // Most Linux systems don't have the exact font, but for outsourcing
+      // fontconfig to find substitutable font in the system, we pass ASCII
+      // font names to it.
+      {"MS-PGothic", "MS PGothic", false, false},
+      {"MS-Gothic", "MS Gothic", false, false},
+      {"MS-PMincho", "MS PMincho", false, false},
+      {"MS-Mincho", "MS Mincho", false, false},
+      // MS PGothic in Shift_JIS encoding.
+      {"\x82\x6C\x82\x72\x82\x6F\x83\x53\x83\x56\x83\x62\x83\x4E", "MS PGothic",
+       false, false},
+      // MS Gothic in Shift_JIS encoding.
+      {"\x82\x6C\x82\x72\x83\x53\x83\x56\x83\x62\x83\x4E", "MS Gothic", false,
+       false},
+      // MS PMincho in Shift_JIS encoding.
+      {"\x82\x6C\x82\x72\x82\x6F\x96\xBE\x92\xA9", "MS PMincho", false, false},
+      // MS Mincho in Shift_JIS encoding.
+      {"\x82\x6C\x82\x72\x96\xBE\x92\xA9", "MS Mincho", false, false},
+  };
+
+  // Similar logic exists in PDFium's CFX_FolderFontInfo::FindFont().
+  if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH))
+    face = "Courier New";
+
+  // Map from the standard PDF fonts to TrueType font names.
+  size_t i;
+  for (i = 0; i < base::size(kPdfFontSubstitutions); ++i) {
+    if (strcmp(face, kPdfFontSubstitutions[i].pdf_name) == 0) {
+      description.set_face(kPdfFontSubstitutions[i].face);
+      if (kPdfFontSubstitutions[i].bold)
+        description.set_weight(PP_BROWSERFONT_TRUSTED_WEIGHT_BOLD);
+      if (kPdfFontSubstitutions[i].italic)
+        description.set_italic(true);
+      break;
+    }
+  }
+
+  if (i == base::size(kPdfFontSubstitutions)) {
+    // Convert to UTF-8 before calling set_face().
+    std::string face_utf8;
+    if (base::IsStringUTF8(face)) {
+      face_utf8 = face;
+    } else {
+      std::string encoding;
+      if (base::DetectEncoding(face, &encoding)) {
+        // ConvertToUtf8AndNormalize() clears |face_utf8| on failure.
+        base::ConvertToUtf8AndNormalize(face, encoding, &face_utf8);
+      }
+    }
+
+    if (face_utf8.empty())
+      return nullptr;
+
+    description.set_face(face_utf8);
+    description.set_weight(WeightToBrowserFontTrustedWeight(weight));
+    description.set_italic(italic > 0);
+  }
+
+  if (!pp::PDF::IsAvailable()) {
+    NOTREACHED();
+    return nullptr;
+  }
+
+  PP_Resource font_resource = pp::PDF::GetFontFileWithFallback(
+      pp::InstanceHandle(g_last_instance_id),
+      &description.pp_font_description(),
+      static_cast<PP_PrivateFontCharset>(charset));
+  long res_id = font_resource;
+  return reinterpret_cast<void*>(res_id);
+}
+
+unsigned long GetFontData(FPDF_SYSFONTINFO*,
+                          void* font_id,
+                          unsigned int table,
+                          unsigned char* buffer,
+                          unsigned long buf_size) {
+  if (!pp::PDF::IsAvailable()) {
+    NOTREACHED();
+    return 0;
+  }
+
+  uint32_t size = buf_size;
+  long res_id = reinterpret_cast<long>(font_id);
+  if (!pp::PDF::GetFontTableForPrivateFontFile(res_id, table, buffer, &size))
+    return 0;
+  return size;
+}
+
+void DeleteFont(FPDF_SYSFONTINFO*, void* font_id) {
+  long res_id = reinterpret_cast<long>(font_id);
+  pp::Module::Get()->core()->ReleaseResource(res_id);
+}
+
+FPDF_SYSFONTINFO g_font_info = {1,           0, EnumFonts, MapFont,   0,
+                                GetFontData, 0, 0,         DeleteFont};
+
+}  // namespace
+
+void InitializeLinuxFontMapper() {
+  FPDF_SetSystemFontInfo(&g_font_info);
+}
+
+void SetLastInstance(pp::Instance* last_instance) {
+  if (last_instance)
+    g_last_instance_id = last_instance->pp_instance();
+}
+
+}  // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_font_linux.h b/pdf/pdfium/pdfium_font_linux.h
new file mode 100644
index 0000000..4caa791
--- /dev/null
+++ b/pdf/pdfium/pdfium_font_linux.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PDF_PDFIUM_PDFIUM_FONT_LINUX_H_
+#define PDF_PDFIUM_PDFIUM_FONT_LINUX_H_
+
+namespace pp {
+class Instance;
+}
+
+namespace chrome_pdf {
+
+// Initializes a Linux-specific font mapper that proxies font requests via
+// PPAPI. This is necessary because font loading does not work in the sandbox on
+// Linux.
+void InitializeLinuxFontMapper();
+
+// Keeps track of the most recently used plugin instance. This is a no-op of
+// |last_instance| is null.
+void SetLastInstance(pp::Instance* last_instance);
+
+}  // namespace chrome_pdf
+
+#endif  // PDF_PDFIUM_PDFIUM_FONT_LINUX_H_
diff --git a/ppapi/proxy/ppb_buffer_proxy.cc b/ppapi/proxy/ppb_buffer_proxy.cc
index 5f597637c..d2fc43922 100644
--- a/ppapi/proxy/ppb_buffer_proxy.cc
+++ b/ppapi/proxy/ppb_buffer_proxy.cc
@@ -23,13 +23,10 @@
 namespace proxy {
 
 Buffer::Buffer(const HostResource& resource,
-               const base::SharedMemoryHandle& shm_handle,
-               uint32_t size)
+               base::UnsafeSharedMemoryRegion shm_region)
     : Resource(OBJECT_IS_PROXY, resource),
-      shm_(shm_handle, false),
-      size_(size),
-      map_count_(0) {
-}
+      shm_(std::move(shm_region)),
+      map_count_(0) {}
 
 Buffer::~Buffer() {
   Unmap();
@@ -40,7 +37,7 @@
 }
 
 PP_Bool Buffer::Describe(uint32_t* size_in_bytes) {
-  *size_in_bytes = size_;
+  *size_in_bytes = shm_.GetSize();
   return PP_TRUE;
 }
 
@@ -50,16 +47,16 @@
 
 void* Buffer::Map() {
   if (map_count_++ == 0)
-    shm_.Map(size_);
-  return shm_.memory();
+    mapping_ = shm_.Map();
+  return mapping_.memory();
 }
 
 void Buffer::Unmap() {
   if (--map_count_ == 0)
-    shm_.Unmap();
+    mapping_ = {};
 }
 
-int32_t Buffer::GetSharedMemory(base::SharedMemory** out_handle) {
+int32_t Buffer::GetSharedMemory(base::UnsafeSharedMemoryRegion** out_handle) {
   NOTREACHED();
   return PP_ERROR_NOTSUPPORTED;
 }
@@ -83,18 +80,18 @@
   dispatcher->Send(new PpapiHostMsg_PPBBuffer_Create(
       API_ID_PPB_BUFFER, instance, size, &result, &shm_handle));
   if (result.is_null() || !shm_handle.IsHandleValid() ||
-      !shm_handle.is_shmem())
+      !shm_handle.is_shmem_region())
     return 0;
 
-  return AddProxyResource(result, shm_handle.shmem(), size);
+  return AddProxyResource(result, base::UnsafeSharedMemoryRegion::Deserialize(
+                                      shm_handle.TakeSharedMemoryRegion()));
 }
 
 // static
 PP_Resource PPB_Buffer_Proxy::AddProxyResource(
     const HostResource& resource,
-    base::SharedMemoryHandle shm_handle,
-    uint32_t size) {
-  return (new Buffer(resource, shm_handle, size))->GetReference();
+    base::UnsafeSharedMemoryRegion shm_region) {
+  return (new Buffer(resource, std::move(shm_region)))->GetReference();
 }
 
 bool PPB_Buffer_Proxy::OnMessageReceived(const IPC::Message& msg) {
@@ -113,7 +110,7 @@
     HostResource* result_resource,
     ppapi::proxy::SerializedHandle* result_shm_handle) {
   // Overwritten below on success.
-  result_shm_handle->set_null_shmem();
+  result_shm_handle->set_null_shmem_region();
   HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
   if (!dispatcher)
     return;
@@ -132,14 +129,14 @@
       local_buffer_resource, false);
   if (trusted_buffer.failed())
     return;
-  base::SharedMemory* local_shm;
+  base::UnsafeSharedMemoryRegion* local_shm;
   if (trusted_buffer.object()->GetSharedMemory(&local_shm) != PP_OK)
     return;
 
   result_resource->SetHostResource(instance, local_buffer_resource);
 
-  result_shm_handle->set_shmem(
-      dispatcher->ShareSharedMemoryHandleWithRemote(local_shm->handle()), size);
+  result_shm_handle->set_unsafe_shmem_region(
+      dispatcher->ShareUnsafeSharedMemoryRegionWithRemote(*local_shm));
 }
 
 }  // namespace proxy
diff --git a/ppapi/proxy/ppb_buffer_proxy.h b/ppapi/proxy/ppb_buffer_proxy.h
index b36750a2..f79497e 100644
--- a/ppapi/proxy/ppb_buffer_proxy.h
+++ b/ppapi/proxy/ppb_buffer_proxy.h
@@ -8,7 +8,8 @@
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "base/memory/shared_memory.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "base/memory/unsafe_shared_memory_region.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/proxy/interface_proxy.h"
 #include "ppapi/shared_impl/resource.h"
@@ -25,8 +26,7 @@
 class Buffer : public thunk::PPB_Buffer_API, public Resource {
  public:
   Buffer(const HostResource& resource,
-         const base::SharedMemoryHandle& shm_handle,
-         uint32_t size);
+         base::UnsafeSharedMemoryRegion shm_handle);
   ~Buffer() override;
 
   // Resource overrides.
@@ -39,11 +39,11 @@
   void Unmap() override;
 
   // Trusted
-  int32_t GetSharedMemory(base::SharedMemory** shm) override;
+  int32_t GetSharedMemory(base::UnsafeSharedMemoryRegion** shm) override;
 
  private:
-  base::SharedMemory shm_;
-  uint32_t size_;
+  base::UnsafeSharedMemoryRegion shm_;
+  base::WritableSharedMemoryMapping mapping_;
   int map_count_;
 
   DISALLOW_COPY_AND_ASSIGN(Buffer);
@@ -56,9 +56,9 @@
 
   static PP_Resource CreateProxyResource(PP_Instance instance,
                                          uint32_t size);
-  static PP_Resource AddProxyResource(const HostResource& resource,
-                                      base::SharedMemoryHandle shm_handle,
-                                      uint32_t size);
+  static PP_Resource AddProxyResource(
+      const HostResource& resource,
+      base::UnsafeSharedMemoryRegion shm_region);
 
   // InterfaceProxy implementation.
   bool OnMessageReceived(const IPC::Message& msg) override;
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.cc b/ppapi/proxy/ppb_graphics_3d_proxy.cc
index e6570939..e7387d5 100644
--- a/ppapi/proxy/ppb_graphics_3d_proxy.cc
+++ b/ppapi/proxy/ppb_graphics_3d_proxy.cc
@@ -294,7 +294,7 @@
     gpu::Capabilities* capabilities,
     SerializedHandle* shared_state,
     gpu::CommandBufferId* command_buffer_id) {
-  shared_state->set_null_shmem();
+  shared_state->set_null_shmem_region();
 
   thunk::EnterResourceCreation enter(instance);
 
diff --git a/ppapi/proxy/serialized_handle.h b/ppapi/proxy/serialized_handle.h
index 8829678..24a18b5f 100644
--- a/ppapi/proxy/serialized_handle.h
+++ b/ppapi/proxy/serialized_handle.h
@@ -124,6 +124,10 @@
     shm_handle_ = base::SharedMemoryHandle();
     size_ = 0;
   }
+  void set_unsafe_shmem_region(base::UnsafeSharedMemoryRegion region) {
+    set_shmem_region(base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
+        std::move(region)));
+  }
   void set_socket(const IPC::PlatformFileForTransit& socket) {
     type_ = SOCKET;
     descriptor_ = socket;
diff --git a/ppapi/proxy/video_capture_resource.cc b/ppapi/proxy/video_capture_resource.cc
index b5628653..7e586fa 100644
--- a/ppapi/proxy/video_capture_resource.cc
+++ b/ppapi/proxy/video_capture_resource.cc
@@ -149,9 +149,14 @@
   if (!ppp_video_capture_impl_)
     return;
 
-  std::vector<base::SharedMemoryHandle> handles;
-  params.TakeAllSharedMemoryHandles(&handles);
-  CHECK(handles.size() == buffers.size());
+  std::vector<base::UnsafeSharedMemoryRegion> regions;
+  for (size_t i = 0; i < params.handles().size(); ++i) {
+    base::UnsafeSharedMemoryRegion region;
+    params.TakeUnsafeSharedMemoryRegionAtIndex(i, &region);
+    DCHECK_EQ(buffer_size, region.GetSize());
+    regions.push_back(std::move(region));
+  }
+  CHECK(regions.size() == buffers.size());
 
   PluginResourceTracker* tracker =
       PluginGlobals::Get()->plugin_resource_tracker();
@@ -160,7 +165,7 @@
     // We assume that the browser created a new set of resources.
     DCHECK(!tracker->PluginResourceForHostResource(buffers[i]));
     resources[i] = ppapi::proxy::PPB_Buffer_Proxy::AddProxyResource(
-        buffers[i], handles[i], buffer_size);
+        buffers[i], std::move(regions[i]));
   }
 
   buffer_in_use_ = std::vector<bool>(buffers.size());
diff --git a/ppapi/thunk/ppb_buffer_api.h b/ppapi/thunk/ppb_buffer_api.h
index 924b178..ab82d418 100644
--- a/ppapi/thunk/ppb_buffer_api.h
+++ b/ppapi/thunk/ppb_buffer_api.h
@@ -10,7 +10,7 @@
 #include "ppapi/thunk/ppapi_thunk_export.h"
 
 namespace base {
-class SharedMemory;
+class UnsafeSharedMemoryRegion;
 }  // namespace base
 
 namespace ppapi {
@@ -26,7 +26,7 @@
   virtual void Unmap() = 0;
 
   // Trusted API
-  virtual int32_t GetSharedMemory(base::SharedMemory** shm) = 0;
+  virtual int32_t GetSharedMemory(base::UnsafeSharedMemoryRegion** shm) = 0;
 };
 
 }  // namespace thunk
diff --git a/remoting/protocol/host_control_dispatcher.cc b/remoting/protocol/host_control_dispatcher.cc
index 067fb829..9aa060f 100644
--- a/remoting/protocol/host_control_dispatcher.cc
+++ b/remoting/protocol/host_control_dispatcher.cc
@@ -18,12 +18,6 @@
 namespace remoting {
 namespace protocol {
 
-namespace {
-// It seems Chrome currently only properly supports receiving messages up to
-// 64KiB.
-constexpr int kMaxSafeMessageSizeInBytes = 64 * 1024;
-}  // namespace
-
 HostControlDispatcher::HostControlDispatcher()
     : ChannelDispatcherBase(kControlChannelName) {}
 HostControlDispatcher::~HostControlDispatcher() = default;
@@ -58,9 +52,12 @@
 void HostControlDispatcher::InjectClipboardEvent(const ClipboardEvent& event) {
   ControlMessage message;
   message.mutable_clipboard_event()->CopyFrom(event);
-  if (message.ByteSizeLong() > kMaxSafeMessageSizeInBytes) {
+  std::size_t message_size = message.ByteSizeLong();
+  if (message_size > max_message_size_) {
     // Better to drop the event than drop the connection, which can happen if
     // the browser receives a message larger than it can handle.
+    LOG(WARNING) << "Clipboard message dropped because message size "
+                 << message_size << " is larger than " << max_message_size_;
     return;
   }
   message_pipe()->Send(&message, base::Closure());
diff --git a/remoting/protocol/host_control_dispatcher.h b/remoting/protocol/host_control_dispatcher.h
index dcf6597..62a6f136e 100644
--- a/remoting/protocol/host_control_dispatcher.h
+++ b/remoting/protocol/host_control_dispatcher.h
@@ -5,6 +5,8 @@
 #ifndef REMOTING_PROTOCOL_HOST_CONTROL_DISPATCHER_H_
 #define REMOTING_PROTOCOL_HOST_CONTROL_DISPATCHER_H_
 
+#include <cstddef>
+
 #include "base/macros.h"
 #include "remoting/protocol/channel_dispatcher_base.h"
 #include "remoting/protocol/client_stub.h"
@@ -48,11 +50,23 @@
   // message. |host_stub| must outlive this object.
   void set_host_stub(HostStub* host_stub) { host_stub_ = host_stub; }
 
+  // Sets the maximum size of outgoing messages, which defaults to 64KiB. This
+  // is used to ensure we don't try to send any clipboard messages that the
+  // client can't receive. Clipboard updates that are larger than the maximum
+  // message size will be dropped.
+  void set_max_message_size(std::size_t max_message_size) {
+    LOG(INFO) << "Setting maximum message size to " << max_message_size;
+    max_message_size_ = max_message_size;
+  }
+
  private:
   void OnIncomingMessage(std::unique_ptr<CompoundBuffer> buffer) override;
 
   ClipboardStub* clipboard_stub_ = nullptr;
   HostStub* host_stub_ = nullptr;
+  // 64 KiB is the default message size expected to be supported in absence of
+  // a higher value negotiated via SDP.
+  std::size_t max_message_size_ = 64 * 1024;
 
   DISALLOW_COPY_AND_ASSIGN(HostControlDispatcher);
 };
diff --git a/remoting/protocol/webrtc_connection_to_client.cc b/remoting/protocol/webrtc_connection_to_client.cc
index 5252940..48fb7b9 100644
--- a/remoting/protocol/webrtc_connection_to_client.cc
+++ b/remoting/protocol/webrtc_connection_to_client.cc
@@ -26,6 +26,7 @@
 #include "remoting/protocol/webrtc_video_stream.h"
 #include "third_party/webrtc/api/media_stream_interface.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
+#include "third_party/webrtc/api/sctp_transport_interface.h"
 
 namespace remoting {
 namespace protocol {
@@ -179,6 +180,14 @@
 
 void WebrtcConnectionToClient::OnWebrtcTransportConnected() {
   DCHECK(thread_checker_.CalledOnValidThread());
+  auto sctp_transport = transport_->peer_connection()->GetSctpTransport();
+  if (sctp_transport) {
+    absl::optional<double> max_message_size =
+        sctp_transport->Information().MaxMessageSize();
+    if (max_message_size && *max_message_size > 0) {
+      control_dispatcher_->set_max_message_size(*max_message_size);
+    }
+  }
 }
 
 void WebrtcConnectionToClient::OnWebrtcTransportError(ErrorCode error) {
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index befe48b..ae313f5 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -223,10 +223,6 @@
   network_loader_->FollowRedirect(removed_headers, modified_headers, new_url);
 }
 
-void CorsURLLoader::ProceedWithResponse() {
-  NOTREACHED();
-}
-
 void CorsURLLoader::SetPriority(net::RequestPriority priority,
                                 int32_t intra_priority_value) {
   if (network_loader_)
diff --git a/services/network/cors/cors_url_loader.h b/services/network/cors/cors_url_loader.h
index 535b7fa3..816a6f1 100644
--- a/services/network/cors/cors_url_loader.h
+++ b/services/network/cors/cors_url_loader.h
@@ -60,7 +60,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/services/network/public/cpp/simple_url_loader_unittest.cc b/services/network/public/cpp/simple_url_loader_unittest.cc
index 64494c3b..a1d008a 100644
--- a/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -1910,7 +1910,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override {}
-  void ProceedWithResponse() override {}
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {
     NOTREACHED();
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom
index 03e054e..d47cfe2 100644
--- a/services/network/public/mojom/url_loader.mojom
+++ b/services/network/public/mojom/url_loader.mojom
@@ -423,14 +423,6 @@
                  network.mojom.HttpRequestHeaders modified_headers,
                  url.mojom.Url? new_url);
 
-  // Resumes loading the response body if the URLLoader paused the request upon
-  // receiving the final response headers.
-  // The URLLoader pauses the request when kURLLoadOptionPauseOnResponseStarted
-  // is used.
-  // TODO(arthursonzogni): This is a temporary feature. Remove this as soon as
-  // the InterceptingResourceHandler is removed. See https://crbug.com/791049.
-  ProceedWithResponse();
-
   // Sets the request priority.
   // |intra_priority_value| is a lesser priority which is used to prioritize
   // requests within a given priority level. If -1 is passed, the existing
diff --git a/services/network/public/mojom/url_loader_factory.mojom b/services/network/public/mojom/url_loader_factory.mojom
index 4f36d942..19db323 100644
--- a/services/network/public/mojom/url_loader_factory.mojom
+++ b/services/network/public/mojom/url_loader_factory.mojom
@@ -17,18 +17,13 @@
 // Sends the net::SSLInfo struct in OnComplete when the connection had a major
 // certificate error.
 const uint32 kURLLoadOptionSendSSLInfoForCertificateError = 8;
-// Pause the request upon receiving the final response header. The request can
-// be resumed by using URLLoader::ProceedWithResponse.
-// TODO(arthursonzogni): This is a temporary feature. Remove this as soon as
-// the InterceptingResourceHandler is removed. See https://crbug.com/791049.
-const uint32 kURLLoadOptionPauseOnResponseStarted = 16;
 // Uses the header client set in URLLoaderFactoryParams for this request.
-const uint32 kURLLoadOptionUseHeaderClient = 32;
+const uint32 kURLLoadOptionUseHeaderClient = 16;
 // Disallow the request from sending cookies. Disallow the response from writing
 // cookies.
-const uint32 kURLLoadOptionBlockAllCookies = 64;
+const uint32 kURLLoadOptionBlockAllCookies = 32;
 // Similar to |kURLLoadOptionBlockAllCookies|, but only for third party cookies.
-const uint32 kURLLoadOptionBlockThirdPartyCookies = 128;
+const uint32 kURLLoadOptionBlockThirdPartyCookies = 64;
 
 interface URLLoaderFactory {
   // Creates a URLLoader and starts loading with the given |request|. |client|'s
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 8fd2f07..d066761f 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -729,10 +729,6 @@
   new_redirect_url_.reset();
 }
 
-void URLLoader::ProceedWithResponse() {
-  NOTREACHED();
-}
-
 void URLLoader::SetPriority(net::RequestPriority priority,
                             int32_t intra_priority_value) {
   if (url_request_ && resource_scheduler_client_) {
diff --git a/services/network/url_loader.h b/services/network/url_loader.h
index 9e54588..394e3300 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -81,7 +81,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn b/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn
index 1a65586..813ea0e 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn
@@ -45,3 +45,14 @@
     "//services/service_manager/public/cpp",
   ]
 }
+
+source_set("browser") {
+  sources = [
+    "browser_metrics.cc",
+    "browser_metrics.h",
+  ]
+
+  deps = [
+    "//base",
+  ]
+}
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.cc
new file mode 100644
index 0000000..7fe4475
--- /dev/null
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.cc
@@ -0,0 +1,63 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h"
+
+#include <cmath>
+
+#include "base/rand_util.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+
+namespace memory_instrumentation {
+namespace {
+
+const char kAudioServiceHistogramName[] = "AudioService";
+const char kBrowserHistogramName[] = "Browser";
+const char kExtensionHistogramName[] = "Extension";
+const char kGpuHistogramName[] = "Gpu";
+const char kNetworkServiceHistogramName[] = "NetworkService";
+const char kRendererHistogramName[] = "Renderer";
+const char kUtilityHistogramName[] = "Utility";
+
+}  // namespace
+
+const char kMemoryHistogramPrefix[] = "Memory.";
+
+const char* HistogramProcessTypeToString(HistogramProcessType type) {
+  switch (type) {
+    case HistogramProcessType::kAudioService:
+      return kAudioServiceHistogramName;
+    case HistogramProcessType::kBrowser:
+      return kBrowserHistogramName;
+    case HistogramProcessType::kExtension:
+      return kExtensionHistogramName;
+    case HistogramProcessType::kGpu:
+      return kGpuHistogramName;
+    case HistogramProcessType::kNetworkService:
+      return kNetworkServiceHistogramName;
+    case HistogramProcessType::kRenderer:
+      return kRendererHistogramName;
+    case HistogramProcessType::kUtility:
+      return kUtilityHistogramName;
+  }
+}
+
+std::string GetPrivateFootprintHistogramName(HistogramProcessType type) {
+  return std::string(kMemoryHistogramPrefix) +
+         HistogramProcessTypeToString(type) + ".PrivateMemoryFootprint";
+}
+
+base::TimeDelta GetDelayForNextMemoryLog() {
+#if defined(OS_ANDROID)
+  base::TimeDelta mean_time = base::TimeDelta::FromMinutes(5);
+#else
+  base::TimeDelta mean_time = base::TimeDelta::FromMinutes(30);
+#endif
+  // Compute the actual delay before sampling using a Poisson process.
+  double uniform = base::RandDouble();
+  return -std::log(uniform) * mean_time;
+}
+
+}  // namespace memory_instrumentation
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h b/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h
new file mode 100644
index 0000000..5ed4e1ac
--- /dev/null
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/browser_metrics.h
@@ -0,0 +1,48 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_BROWSER_METRICS_H_
+#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_BROWSER_METRICS_H_
+
+#include <string>
+
+#include "base/metrics/histogram_functions.h"
+
+// Macro used for logging memory related metrics in mb.
+#define MEMORY_METRICS_HISTOGRAM_MB(name, value) \
+  base::UmaHistogramCustomCounts(name, value, 1, 64000, 100)
+
+namespace base {
+class TimeDelta;
+}
+
+namespace memory_instrumentation {
+
+// Prefix for memory related histograms.
+extern const char kMemoryHistogramPrefix[];
+
+// Types of processes uses by chrome.
+enum class HistogramProcessType {
+  kAudioService,
+  kBrowser,
+  kExtension,
+  kGpu,
+  kNetworkService,
+  kRenderer,
+  kUtility,
+};
+
+// Returns a string used in histograms for the process of |type|.
+const char* HistogramProcessTypeToString(HistogramProcessType type);
+
+// Returns the memory footprint histogram name for the process of the specified
+// type.
+std::string GetPrivateFootprintHistogramName(HistogramProcessType type);
+
+// Returns the delay used in logging memory related metrics.
+base::TimeDelta GetDelayForNextMemoryLog();
+
+}  // namespace memory_instrumentation
+
+#endif  // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_BROWSER_METRICS_H_
diff --git a/services/shape_detection/face_detection_impl_mac_unittest.mm b/services/shape_detection/face_detection_impl_mac_unittest.mm
index fafefcf..19c4d62 100644
--- a/services/shape_detection/face_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/face_detection_impl_mac_unittest.mm
@@ -55,8 +55,6 @@
     base::Callback<std::unique_ptr<mojom::FaceDetection>(
         shape_detection::mojom::FaceDetectorOptionsPtr)>;
 
-}  // anonymous namespace
-
 struct TestParams {
   bool fast_mode;
   int image_width;
@@ -66,21 +64,44 @@
   size_t num_landmarks;
   size_t num_mouth_points;
   FaceDetectorFactory factory;
-} kTestParams[] = {
-    {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
-     base::Bind(&CreateFaceDetectorImplMac)},
-    {true, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
-     base::Bind(&CreateFaceDetectorImplMac)},
-    {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 4, 10,
-     base::Bind(&CreateFaceDetectorImplMacVision)},
-    {false, 240, 240, "services/test/data/the_beatles.jpg", 3, 3, 1,
-     base::Bind(&CreateFaceDetectorImplMac)},
-    {true, 240, 240, "services/test/data/the_beatles.jpg", 3, 3, 1,
-     base::Bind(&CreateFaceDetectorImplMac)},
-    {false, 240, 240, "services/test/data/the_beatles.jpg", 4, 4, 10,
-     base::Bind(&CreateFaceDetectorImplMacVision)},
 };
 
+std::vector<TestParams> GetTestParams() {
+  if (@available(macOS 10.14, *)) {
+    return {
+        {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
+         base::Bind(&CreateFaceDetectorImplMac)},
+        {true, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
+         base::Bind(&CreateFaceDetectorImplMac)},
+        {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 4, 10,
+         base::Bind(&CreateFaceDetectorImplMacVision)},
+        {false, 240, 240, "services/test/data/the_beatles.jpg", 4, 3, 1,
+         base::Bind(&CreateFaceDetectorImplMac)},
+        {true, 240, 240, "services/test/data/the_beatles.jpg", 4, 3, 1,
+         base::Bind(&CreateFaceDetectorImplMac)},
+        {false, 240, 240, "services/test/data/the_beatles.jpg", 4, 4, 10,
+         base::Bind(&CreateFaceDetectorImplMacVision)},
+    };
+  } else {
+    return {
+        {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
+         base::Bind(&CreateFaceDetectorImplMac)},
+        {true, 120, 120, "services/test/data/mona_lisa.jpg", 1, 3, 1,
+         base::Bind(&CreateFaceDetectorImplMac)},
+        {false, 120, 120, "services/test/data/mona_lisa.jpg", 1, 4, 10,
+         base::Bind(&CreateFaceDetectorImplMacVision)},
+        {false, 240, 240, "services/test/data/the_beatles.jpg", 3, 3, 1,
+         base::Bind(&CreateFaceDetectorImplMac)},
+        {true, 240, 240, "services/test/data/the_beatles.jpg", 3, 3, 1,
+         base::Bind(&CreateFaceDetectorImplMac)},
+        {false, 240, 240, "services/test/data/the_beatles.jpg", 4, 4, 10,
+         base::Bind(&CreateFaceDetectorImplMacVision)},
+    };
+  }
+}
+
+}  // anonymous namespace
+
 class FaceDetectionImplMacTest : public TestWithParam<struct TestParams> {
  public:
   ~FaceDetectionImplMacTest() override {}
@@ -177,6 +198,6 @@
   run_loop.Run();
 }
 
-INSTANTIATE_TEST_SUITE_P(, FaceDetectionImplMacTest, ValuesIn(kTestParams));
+INSTANTIATE_TEST_SUITE_P(, FaceDetectionImplMacTest, ValuesIn(GetTestParams()));
 
 }  // shape_detection namespace
diff --git a/services/viz/public/cpp/compositing/frame_timing_details_mojom_traits.h b/services/viz/public/cpp/compositing/frame_timing_details_mojom_traits.h
index 24274a7..0e5d94f 100644
--- a/services/viz/public/cpp/compositing/frame_timing_details_mojom_traits.h
+++ b/services/viz/public/cpp/compositing/frame_timing_details_mojom_traits.h
@@ -20,9 +20,22 @@
     return frame_timing_details.presentation_feedback;
   }
 
+  static base::TimeTicks received_compositor_frame_timestamp(
+      const viz::FrameTimingDetails& frame_timing_details) {
+    return frame_timing_details.received_compositor_frame_timestamp;
+  }
+
+  static base::TimeTicks draw_start_timestamp(
+      const viz::FrameTimingDetails& frame_timing_details) {
+    return frame_timing_details.draw_start_timestamp;
+  }
+
   static bool Read(viz::mojom::FrameTimingDetailsDataView data,
                    viz::FrameTimingDetails* out) {
-    return data.ReadPresentationFeedback(&out->presentation_feedback);
+    return data.ReadPresentationFeedback(&out->presentation_feedback) &&
+           data.ReadReceivedCompositorFrameTimestamp(
+               &out->received_compositor_frame_timestamp) &&
+           data.ReadDrawStartTimestamp(&out->draw_start_timestamp);
   }
 };
 
diff --git a/services/viz/public/mojom/compositing/frame_timing_details.mojom b/services/viz/public/mojom/compositing/frame_timing_details.mojom
index 909b552..881f2746 100644
--- a/services/viz/public/mojom/compositing/frame_timing_details.mojom
+++ b/services/viz/public/mojom/compositing/frame_timing_details.mojom
@@ -4,9 +4,12 @@
 
 module viz.mojom;
 
+import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/mojom/presentation_feedback.mojom";
 
 // viz::FrameTimingDetails
 struct FrameTimingDetails {
   gfx.mojom.PresentationFeedback presentation_feedback;
+  mojo_base.mojom.TimeTicks received_compositor_frame_timestamp;
+  mojo_base.mojom.TimeTicks draw_start_timestamp;
 };
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn
index 4298143..d5ed4000 100644
--- a/storage/browser/BUILD.gn
+++ b/storage/browser/BUILD.gn
@@ -53,8 +53,6 @@
     "blob/shareable_blob_data_item.h",
     "blob/shareable_file_reference.cc",
     "blob/shareable_file_reference.h",
-    "blob/upload_blob_element_reader.cc",
-    "blob/upload_blob_element_reader.h",
     "blob/view_blob_internals_job.cc",
     "blob/view_blob_internals_job.h",
     "database/database_quota_client.cc",
diff --git a/storage/browser/blob/blob_url_loader.h b/storage/browser/blob/blob_url_loader.h
index 7c528d7..8e9474f 100644
--- a/storage/browser/blob/blob_url_loader.h
+++ b/storage/browser/blob/blob_url_loader.h
@@ -43,7 +43,6 @@
   void FollowRedirect(const std::vector<std::string>& removed_headers,
                       const net::HttpRequestHeaders& modified_request_headers,
                       const base::Optional<GURL>& new_url) override;
-  void ProceedWithResponse() override {}
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override {}
   void PauseReadingBodyFromNet() override {}
diff --git a/storage/browser/blob/upload_blob_element_reader.cc b/storage/browser/blob/upload_blob_element_reader.cc
deleted file mode 100644
index 502f87c..0000000
--- a/storage/browser/blob/upload_blob_element_reader.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "storage/browser/blob/upload_blob_element_reader.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/single_thread_task_runner.h"
-#include "net/base/net_errors.h"
-#include "storage/browser/blob/blob_data_handle.h"
-#include "storage/browser/blob/blob_reader.h"
-
-namespace storage {
-
-UploadBlobElementReader::UploadBlobElementReader(
-    std::unique_ptr<BlobDataHandle> handle)
-    : handle_(std::move(handle)) {}
-
-UploadBlobElementReader::~UploadBlobElementReader() = default;
-
-int UploadBlobElementReader::Init(net::CompletionOnceCallback callback) {
-  reader_ = handle_->CreateReader();
-  BlobReader::Status status = reader_->CalculateSize(std::move(callback));
-  switch (status) {
-    case BlobReader::Status::NET_ERROR:
-      return reader_->net_error();
-    case BlobReader::Status::IO_PENDING:
-      return net::ERR_IO_PENDING;
-    case BlobReader::Status::DONE:
-      return net::OK;
-  }
-  NOTREACHED();
-  return net::ERR_FAILED;
-}
-
-uint64_t UploadBlobElementReader::GetContentLength() const {
-  return reader_->total_size();
-}
-
-uint64_t UploadBlobElementReader::BytesRemaining() const {
-  return reader_->remaining_bytes();
-}
-
-bool UploadBlobElementReader::IsInMemory() const {
-  return reader_->IsInMemory();
-}
-
-int UploadBlobElementReader::Read(net::IOBuffer* buf,
-                                  int buf_length,
-                                  net::CompletionOnceCallback callback) {
-  int length = 0;
-  BlobReader::Status status =
-      reader_->Read(buf, buf_length, &length, std::move(callback));
-  switch (status) {
-    case BlobReader::Status::NET_ERROR:
-      return reader_->net_error();
-    case BlobReader::Status::IO_PENDING:
-      return net::ERR_IO_PENDING;
-    case BlobReader::Status::DONE:
-      return length;
-  }
-  NOTREACHED();
-  return net::ERR_FAILED;
-}
-
-const std::string& UploadBlobElementReader::uuid() const {
-  return handle_->uuid();
-}
-
-}  // namespace storage
diff --git a/storage/browser/blob/upload_blob_element_reader.h b/storage/browser/blob/upload_blob_element_reader.h
deleted file mode 100644
index 11ca8198..0000000
--- a/storage/browser/blob/upload_blob_element_reader.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef STORAGE_BROWSER_BLOB_UPLOAD_BLOB_ELEMENT_READER_H_
-#define STORAGE_BROWSER_BLOB_UPLOAD_BLOB_ELEMENT_READER_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "net/base/completion_once_callback.h"
-#include "net/base/upload_element_reader.h"
-
-namespace net {
-class IOBuffer;
-}
-
-namespace storage {
-class BlobDataHandle;
-class BlobReader;
-
-// This class is a wrapper around the BlobReader to make it conform
-// to the net::UploadElementReader interface, and it also holds around the
-// handle to the blob so it stays in memory while we read it.
-class COMPONENT_EXPORT(STORAGE_BROWSER) UploadBlobElementReader
-    : public net::UploadElementReader {
- public:
-  explicit UploadBlobElementReader(std::unique_ptr<BlobDataHandle> handle);
-  ~UploadBlobElementReader() override;
-
-  int Init(net::CompletionOnceCallback callback) override;
-
-  uint64_t GetContentLength() const override;
-
-  uint64_t BytesRemaining() const override;
-
-  bool IsInMemory() const override;
-
-  int Read(net::IOBuffer* buf,
-           int buf_length,
-           net::CompletionOnceCallback callback) override;
-
-  const std::string& uuid() const;
-
- private:
-  std::unique_ptr<BlobDataHandle> handle_;
-  std::unique_ptr<BlobReader> reader_;
-
-  DISALLOW_COPY_AND_ASSIGN(UploadBlobElementReader);
-};
-
-}  // namespace storage
-#endif  // STORAGE_BROWSER_BLOB_UPLOAD_BLOB_ELEMENT_READER_H_
diff --git a/storage/browser/blob/view_blob_internals_job.cc b/storage/browser/blob/view_blob_internals_job.cc
index c80b9327..91b390f3 100644
--- a/storage/browser/blob/view_blob_internals_job.cc
+++ b/storage/browser/blob/view_blob_internals_job.cc
@@ -23,7 +23,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/base/escape.h"
 #include "net/base/net_errors.h"
-#include "net/url_request/url_request.h"
 #include "storage/browser/blob/blob_data_item.h"
 #include "storage/browser/blob/blob_entry.h"
 #include "storage/browser/blob/blob_storage_context.h"
@@ -142,55 +141,6 @@
 
 namespace storage {
 
-ViewBlobInternalsJob::ViewBlobInternalsJob(
-    net::URLRequest* request,
-    net::NetworkDelegate* network_delegate,
-    BlobStorageContext* blob_storage_context)
-    : net::URLRequestSimpleJob(request, network_delegate),
-      blob_storage_context_(blob_storage_context),
-      weak_factory_(this) {
-}
-
-ViewBlobInternalsJob::~ViewBlobInternalsJob() = default;
-
-void ViewBlobInternalsJob::Start() {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&ViewBlobInternalsJob::StartAsync,
-                                weak_factory_.GetWeakPtr()));
-}
-
-bool ViewBlobInternalsJob::IsRedirectResponse(
-    GURL* location,
-    int* http_status_code,
-    bool* insecure_scheme_was_upgraded) {
-  if (request_->url().has_query()) {
-    // Strip the query parameters.
-    GURL::Replacements replacements;
-    replacements.ClearQuery();
-    *insecure_scheme_was_upgraded = false;
-    *location = request_->url().ReplaceComponents(replacements);
-    *http_status_code = 307;
-    return true;
-  }
-  return false;
-}
-
-void ViewBlobInternalsJob::Kill() {
-  net::URLRequestSimpleJob::Kill();
-  weak_factory_.InvalidateWeakPtrs();
-}
-
-int ViewBlobInternalsJob::GetData(std::string* mime_type,
-                                  std::string* charset,
-                                  std::string* data,
-                                  net::CompletionOnceCallback callback) const {
-  mime_type->assign("text/html");
-  charset->assign("UTF-8");
-
-  *data = GenerateHTML(blob_storage_context_);
-  return net::OK;
-}
-
 std::string ViewBlobInternalsJob::GenerateHTML(
     BlobStorageContext* blob_storage_context) {
   std::string out;
diff --git a/storage/browser/blob/view_blob_internals_job.h b/storage/browser/blob/view_blob_internals_job.h
index 9080d25..4e651f78 100644
--- a/storage/browser/blob/view_blob_internals_job.h
+++ b/storage/browser/blob/view_blob_internals_job.h
@@ -10,12 +10,6 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "net/base/completion_once_callback.h"
-#include "net/url_request/url_request_simple_job.h"
-
-namespace net {
-class URLRequest;
-}  // namespace net
 
 namespace storage {
 
@@ -24,37 +18,17 @@
 
 // A job subclass that implements a protocol to inspect the internal
 // state of blob registry.
-class COMPONENT_EXPORT(STORAGE_BROWSER) ViewBlobInternalsJob
-    : public net::URLRequestSimpleJob {
+class COMPONENT_EXPORT(STORAGE_BROWSER) ViewBlobInternalsJob {
  public:
-  ViewBlobInternalsJob(net::URLRequest* request,
-                       net::NetworkDelegate* network_delegate,
-                       BlobStorageContext* blob_storage_context);
-
-  void Start() override;
-  int GetData(std::string* mime_type,
-              std::string* charset,
-              std::string* data,
-              net::CompletionOnceCallback callback) const override;
-  bool IsRedirectResponse(GURL* location,
-                          int* http_status_code,
-                          bool* insecure_scheme_was_upgraded) override;
-  void Kill() override;
-
   static std::string GenerateHTML(BlobStorageContext* blob_storage_context);
 
  private:
-  ~ViewBlobInternalsJob() override;
-
   static void GenerateHTMLForBlobData(const BlobEntry& blob_data,
                                       const std::string& content_type,
                                       const std::string& content_disposition,
                                       size_t refcount,
                                       std::string* out);
 
-  BlobStorageContext* blob_storage_context_;
-  base::WeakPtrFactory<ViewBlobInternalsJob> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(ViewBlobInternalsJob);
 };
 
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 2b5d7bd..88492a2d 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -986,9 +986,6 @@
         "test": "components_browsertests"
       },
       {
-        "args": [
-          "--gtest_filter=-CrashAnalyzerTest.StackTraceCollection"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 17eb3763..975b6e3 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -382,12 +382,6 @@
           'shards': 5,
         },
       },
-      'linux-chromeos-google-rel': {
-        # TODO(crbug.com/980748): Remove this filter.
-        'args': [
-          '--gtest_filter=-CrashAnalyzerTest.StackTraceCollection',
-        ],
-      },
     },
   },
   'content_browsertests': {
diff --git a/third_party/blink/public/blink_resources.grd b/third_party/blink/public/blink_resources.grd
index 119dda39..e3a4d6efc 100644
--- a/third_party/blink/public/blink_resources.grd
+++ b/third_party/blink/public/blink_resources.grd
@@ -48,6 +48,7 @@
         <include name="IDR_PICKER_COMMON_JS" file="../renderer/core/html/forms/resources/pickerCommon.js" type="BINDATA" compress="gzip"/>
         <include name="IDR_PICKER_COMMON_CSS" file="../renderer/core/html/forms/resources/pickerCommon.css" type="BINDATA" compress="gzip"/>
         <include name="IDR_CALENDAR_PICKER_CSS" file="../renderer/core/html/forms/resources/calendarPicker.css" type="BINDATA" compress="gzip"/>
+        <include name="IDR_CALENDAR_PICKER_REFRESH_CSS" file="../renderer/core/html/forms/resources/calendar_picker_refresh.css" type="BINDATA" compress="gzip"/>
         <include name="IDR_CALENDAR_PICKER_JS" file="../renderer/core/html/forms/resources/calendarPicker.js" type="BINDATA" compress="gzip"/>
         <include name="IDR_PICKER_BUTTON_CSS" file="../renderer/core/html/forms/resources/pickerButton.css" type="BINDATA" compress="gzip"/>
         <include name="IDR_SUGGESTION_PICKER_CSS" file="../renderer/core/html/forms/resources/suggestionPicker.css" type="BINDATA" compress="gzip"/>
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index 049aac2b..5721233 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -162,6 +162,10 @@
 
   // Used to switch the current platform only for testing.
   // You should not pass in a Platform object that is not fully instantiated.
+  //
+  // NOTE: Instead of calling this directly, us a ScopedTestingPlatformSupport
+  // which will restore the previous platform on exit, preventing tests from
+  // clobbering each other.
   static void SetCurrentPlatformForTesting(Platform*);
 
   // This sets up a minimally viable implementation of blink::Thread without
diff --git a/third_party/blink/public/platform/web_url_loader_factory.h b/third_party/blink/public/platform/web_url_loader_factory.h
index bf73e20..72ca2e3 100644
--- a/third_party/blink/public/platform/web_url_loader_factory.h
+++ b/third_party/blink/public/platform/web_url_loader_factory.h
@@ -28,6 +28,14 @@
       std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>) = 0;
 };
 
+// A test version of the above factory interface, which supports cloning the
+// factory.
+class WebURLLoaderFactoryForTest : public WebURLLoaderFactory {
+ public:
+  // Clones this factory.
+  virtual std::unique_ptr<WebURLLoaderFactoryForTest> Clone() = 0;
+};
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_URL_LOADER_FACTORY_H_
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
index c16d7e1..e5f3f97 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
@@ -75,7 +75,6 @@
       const ComputedStyle&,
       const SVGComputedStyle&,
       const LayoutObject*,
-      const Node*,
       bool allow_visited_style) const override {
     // Directional properties are resolved by CSSDirectionAwareResolver
     // before calling CSSValueFromComputedStyleInternal.
diff --git a/third_party/blink/renderer/core/animation/BUILD.gn b/third_party/blink/renderer/core/animation/BUILD.gn
index 72b16e6..83c7a61 100644
--- a/third_party/blink/renderer/core/animation/BUILD.gn
+++ b/third_party/blink/renderer/core/animation/BUILD.gn
@@ -35,6 +35,8 @@
     "css/compositor_keyframe_value.h",
     "css/compositor_keyframe_value_factory.cc",
     "css/compositor_keyframe_value_factory.h",
+    "css/css_animation.cc",
+    "css/css_animation.h",
     "css/css_animation_data.cc",
     "css/css_animation_data.h",
     "css/css_animation_update.cc",
diff --git a/third_party/blink/renderer/core/animation/animation.h b/third_party/blink/renderer/core/animation/animation.h
index 81d8973d4..adbf1e5 100644
--- a/third_party/blink/renderer/core/animation/animation.h
+++ b/third_party/blink/renderer/core/animation/animation.h
@@ -63,12 +63,12 @@
 class PaintArtifactCompositor;
 class TreeScope;
 
-class CORE_EXPORT Animation final : public EventTargetWithInlineData,
-                                    public ActiveScriptWrappable<Animation>,
-                                    public ContextLifecycleObserver,
-                                    public CompositorAnimationDelegate,
-                                    public CompositorAnimationClient,
-                                    public AnimationEffectOwner {
+class CORE_EXPORT Animation : public EventTargetWithInlineData,
+                              public ActiveScriptWrappable<Animation>,
+                              public ContextLifecycleObserver,
+                              public CompositorAnimationDelegate,
+                              public CompositorAnimationClient,
+                              public AnimationEffectOwner {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(Animation);
 
diff --git a/third_party/blink/renderer/core/animation/css/css_animation.cc b/third_party/blink/renderer/core/animation/css/css_animation.cc
new file mode 100644
index 0000000..b5bde1f
--- /dev/null
+++ b/third_party/blink/renderer/core/animation/css/css_animation.cc
@@ -0,0 +1,40 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/animation/css/css_animation.h"
+
+namespace blink {
+
+CSSAnimation* CSSAnimation::Create(AnimationEffect* effect,
+                                   AnimationTimeline* timeline,
+                                   String animation_name,
+                                   ExceptionState& exception_state) {
+  DCHECK(timeline);
+  if (!timeline->IsDocumentTimeline()) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kNotSupportedError,
+        "Invalid timeline. CSSAnimation requires a DocumentTimeline");
+    return nullptr;
+  }
+  DCHECK(timeline->IsDocumentTimeline());
+
+  return MakeGarbageCollected<CSSAnimation>(
+      timeline->GetDocument()->ContextDocument(), timeline, effect,
+      animation_name);
+}
+
+CSSAnimation::CSSAnimation(ExecutionContext* execution_context,
+                           AnimationTimeline* timeline,
+                           AnimationEffect* content,
+                           String animation_name)
+    : Animation(execution_context, timeline, content),
+      animation_name_(animation_name) {
+  setId(animation_name);
+}
+
+String CSSAnimation::animationName() {
+  return animation_name_;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/animation/css/css_animation.h b/third_party/blink/renderer/core/animation/css/css_animation.h
new file mode 100644
index 0000000..2b01fee
--- /dev/null
+++ b/third_party/blink/renderer/core/animation/css/css_animation.h
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATION_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/core/animation/animation.h"
+#include "third_party/blink/renderer/core/core_export.h"
+
+namespace blink {
+
+class CORE_EXPORT CSSAnimation : public Animation {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static CSSAnimation* Create(AnimationEffect*,
+                              AnimationTimeline*,
+                              String animation_name,
+                              ExceptionState& = ASSERT_NO_EXCEPTION);
+
+  CSSAnimation(ExecutionContext*,
+               AnimationTimeline*,
+               AnimationEffect*,
+               String animation_name);
+
+  String animationName();
+
+ private:
+  String animation_name_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATION_H_
diff --git a/third_party/blink/renderer/core/animation/css/css_animation.idl b/third_party/blink/renderer/core/animation/css/css_animation.idl
new file mode 100644
index 0000000..89d5dd7
--- /dev/null
+++ b/third_party/blink/renderer/core/animation/css/css_animation.idl
@@ -0,0 +1,10 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://drafts.csswg.org/css-animations-2/#the-CSSAnimation-interface
+
+[Exposed=Window, RuntimeEnabled=WebAnimationsAPI]
+interface CSSAnimation : Animation {
+  readonly attribute CSSOMString animationName;
+};
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc
index 5c17beb..e68db18 100644
--- a/third_party/blink/renderer/core/animation/css/css_animations.cc
+++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/core/animation/animation.h"
 #include "third_party/blink/renderer/core/animation/compositor_animations.h"
 #include "third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.h"
+#include "third_party/blink/renderer/core/animation/css/css_animation.h"
 #include "third_party/blink/renderer/core/animation/css_interpolation_types_map.h"
 #include "third_party/blink/renderer/core/animation/document_timeline.h"
 #include "third_party/blink/renderer/core/animation/element_animations.h"
@@ -537,8 +538,10 @@
     auto* effect = MakeGarbageCollected<KeyframeEffect>(
         element, inert_animation->Model(), inert_animation->SpecifiedTiming(),
         KeyframeEffect::kDefaultPriority, event_delegate);
-    Animation* animation = element->GetDocument().Timeline().Play(effect);
-    animation->setId(entry.name);
+
+    CSSAnimation* animation = CSSAnimation::Create(
+        effect, &(element->GetDocument().Timeline()), entry.name);
+    animation->play();
     if (inert_animation->Paused())
       animation->pause();
     animation->Update(kTimingUpdateOnDemand);
diff --git a/third_party/blink/renderer/core/core_idl_files.gni b/third_party/blink/renderer/core/core_idl_files.gni
index 6bac5c6..11eb39e 100644
--- a/third_party/blink/renderer/core/core_idl_files.gni
+++ b/third_party/blink/renderer/core/core_idl_files.gni
@@ -42,6 +42,7 @@
                     "animation/animation.idl",
                     "animation/animation_effect.idl",
                     "animation/animation_timeline.idl",
+                    "animation/css/css_animation.idl",
                     "animation/document_timeline.idl",
                     "animation/keyframe_effect.idl",
                     "animation/scroll_timeline.idl",
diff --git a/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc b/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc
index 58c4a15..c18d609 100644
--- a/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc
+++ b/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc
@@ -39,8 +39,7 @@
     const PropertyRegistry* registry) {
   CustomProperty custom_property(custom_property_name, registry);
   return custom_property.CSSValueFromComputedStyle(
-      style, nullptr /* layout_object */, nullptr /* styled_node */,
-      false /* allow_visited_style */);
+      style, nullptr /* layout_object */, false /* allow_visited_style */);
 }
 
 HeapHashMap<AtomicString, Member<const CSSValue>>
diff --git a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
index 9b5dbb5..b97ae352 100644
--- a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
+++ b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
@@ -411,7 +411,7 @@
     return nullptr;
 
   const CSSValue* value = property_class.CSSValueFromComputedStyle(
-      *style, layout_object, styled_node, allow_visited_style_);
+      *style, layout_object, allow_visited_style_);
   if (value)
     return value;
 
diff --git a/third_party/blink/renderer/core/css/css_paint_value.cc b/third_party/blink/renderer/core/css/css_paint_value.cc
index a4c875a..04c17830 100644
--- a/third_party/blink/renderer/core/css/css_paint_value.cc
+++ b/third_party/blink/renderer/core/css/css_paint_value.cc
@@ -98,8 +98,7 @@
           generator_->CustomInvalidationProperties();
       float zoom = layout_object.StyleRef().EffectiveZoom();
       auto style_data = PaintWorkletStylePropertyMap::BuildCrossThreadData(
-          document, style, layout_object.GetNode(), native_properties,
-          custom_properties);
+          document, style, native_properties, custom_properties);
       paint_off_thread_ = style_data.has_value();
       if (paint_off_thread_) {
         Vector<std::unique_ptr<CrossThreadStyleValue>>
diff --git a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc
index 2d11b32..8ae6921e 100644
--- a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc
+++ b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc
@@ -245,7 +245,6 @@
     default:
       return CSSProperty::Get(property_id)
           .CSSValueFromComputedStyle(*style, nullptr /* layout_object */,
-                                     StyledNode(),
                                      false /* allow_visited_style */);
   }
 }
@@ -257,8 +256,7 @@
     return nullptr;
   CSSPropertyRef ref(property_name, node_->GetDocument());
   return ref.GetProperty().CSSValueFromComputedStyle(
-      *style, nullptr /* layout_object */, StyledNode(),
-      false /* allow_visited_style */);
+      *style, nullptr /* layout_object */, false /* allow_visited_style */);
 }
 
 void ComputedStylePropertyMap::ForEachProperty(
@@ -275,7 +273,7 @@
     DCHECK(property);
     DCHECK(!property->IDEquals(CSSPropertyID::kVariable));
     const CSSValue* value = property->CSSValueFromComputedStyle(
-        *style, nullptr /* layout_object */, StyledNode(), false);
+        *style, nullptr /* layout_object */, false);
     if (value)
       values.emplace_back(CSSPropertyName(property->PropertyID()), value);
   }
@@ -306,7 +304,7 @@
   }
 
   if (const CSSValue* value = property.CSSValueFromComputedStyle(
-          *style, nullptr /* layout_object */, StyledNode(), false)) {
+          *style, nullptr /* layout_object */, false)) {
     return value->CssText();
   }
 
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
index a90eb46..cab36ec3 100644
--- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
+++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
@@ -55,7 +55,6 @@
 };
 
 bool BuildNativeValues(const ComputedStyle& style,
-                       Node* styled_node,
                        const Vector<CSSPropertyID>& native_properties,
                        PaintWorkletStylePropertyMap::CrossThreadData& data) {
   DCHECK(IsMainThread());
@@ -68,7 +67,7 @@
     std::unique_ptr<CrossThreadStyleValue> value =
         CSSProperty::Get(property_id)
             .CrossThreadStyleValueFromComputedStyle(
-                style, /* layout_object */ nullptr, styled_node,
+                style, /* layout_object */ nullptr,
                 /* allow_visited_style */ false);
     if (value->GetType() == CrossThreadStyleValue::StyleValueType::kUnknownType)
       return false;
@@ -82,7 +81,6 @@
 
 bool BuildCustomValues(const Document& document,
                        const ComputedStyle& style,
-                       Node* styled_node,
                        const Vector<AtomicString>& custom_properties,
                        PaintWorkletStylePropertyMap::CrossThreadData& data) {
   DCHECK(IsMainThread());
@@ -90,7 +88,7 @@
     CSSPropertyRef ref(property_name, document);
     std::unique_ptr<CrossThreadStyleValue> value =
         ref.GetProperty().CrossThreadStyleValueFromComputedStyle(
-            style, /* layout_object */ nullptr, styled_node,
+            style, /* layout_object */ nullptr,
             /* allow_visited_style */ false);
     if (value->GetType() == CrossThreadStyleValue::StyleValueType::kUnknownType)
       return false;
@@ -110,16 +108,15 @@
 PaintWorkletStylePropertyMap::BuildCrossThreadData(
     const Document& document,
     const ComputedStyle& style,
-    Node* styled_node,
     const Vector<CSSPropertyID>& native_properties,
     const Vector<AtomicString>& custom_properties) {
   DCHECK(IsMainThread());
   PaintWorkletStylePropertyMap::CrossThreadData data;
   data.ReserveCapacityForSize(native_properties.size() +
                               custom_properties.size());
-  if (!BuildNativeValues(style, styled_node, native_properties, data))
+  if (!BuildNativeValues(style, native_properties, data))
     return base::nullopt;
-  if (!BuildCustomValues(document, style, styled_node, custom_properties, data))
+  if (!BuildCustomValues(document, style, custom_properties, data))
     return base::nullopt;
   return data;
 }
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h
index f769583..aac4903 100644
--- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h
+++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h
@@ -34,7 +34,6 @@
   static base::Optional<CrossThreadData> BuildCrossThreadData(
       const Document&,
       const ComputedStyle&,
-      Node* styled_node,
       const Vector<CSSPropertyID>& native_properties,
       const Vector<AtomicString>& custom_properties);
 
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
index e52f5a40..0400274 100644
--- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
+++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
@@ -147,7 +147,7 @@
 
   Vector<std::unique_ptr<CrossThreadStyleValue>> input_arguments;
   auto data = PaintWorkletStylePropertyMap::BuildCrossThreadData(
-      GetDocument(), node->ComputedStyleRef(), node, native_properties,
+      GetDocument(), node->ComputedStyleRef(), native_properties,
       custom_properties);
 
   EXPECT_TRUE(data.has_value());
@@ -186,7 +186,7 @@
 
   Vector<std::unique_ptr<CrossThreadStyleValue>> input_arguments;
   auto data1 = PaintWorkletStylePropertyMap::BuildCrossThreadData(
-      GetDocument(), node->ComputedStyleRef(), node, native_properties1,
+      GetDocument(), node->ComputedStyleRef(), native_properties1,
       custom_properties1);
 
   EXPECT_FALSE(data1.has_value());
@@ -196,7 +196,7 @@
   Vector<AtomicString> custom_properties2;
 
   auto data2 = PaintWorkletStylePropertyMap::BuildCrossThreadData(
-      GetDocument(), node->ComputedStyleRef(), node, native_properties2,
+      GetDocument(), node->ComputedStyleRef(), native_properties2,
       custom_properties2);
 
   EXPECT_FALSE(data2.has_value());
diff --git a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc
index c0f6f0f..0351536 100644
--- a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc
+++ b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc
@@ -18,10 +18,9 @@
 PrepopulatedComputedStylePropertyMap::PrepopulatedComputedStylePropertyMap(
     const Document& document,
     const ComputedStyle& style,
-    const Node* styled_node,
     const Vector<CSSPropertyID>& native_properties,
     const Vector<AtomicString>& custom_properties)
-    : StylePropertyMapReadOnlyMainThread(), styled_node_(styled_node) {
+    : StylePropertyMapReadOnlyMainThread() {
   // NOTE: This may over-reserve as shorthand properties will get dropped from
   // being in the map.
   native_values_.ReserveCapacityForSize(native_properties.size());
@@ -61,11 +60,10 @@
 void PrepopulatedComputedStylePropertyMap::UpdateNativeProperty(
     const ComputedStyle& style,
     CSSPropertyID property_id) {
-  native_values_.Set(property_id,
-                     CSSProperty::Get(property_id)
-                         .CSSValueFromComputedStyle(
-                             style, /* layout_object */ nullptr, styled_node_,
-                             /* allow_visited_style */ false));
+  native_values_.Set(property_id, CSSProperty::Get(property_id)
+                                      .CSSValueFromComputedStyle(
+                                          style, /* layout_object */ nullptr,
+                                          /* allow_visited_style */ false));
 }
 
 void PrepopulatedComputedStylePropertyMap::UpdateCustomProperty(
@@ -74,7 +72,7 @@
     const AtomicString& property_name) {
   CSSPropertyRef ref(property_name, document);
   const CSSValue* value = ref.GetProperty().CSSValueFromComputedStyle(
-      style, /* layout_object */ nullptr, styled_node_,
+      style, /* layout_object */ nullptr,
       /* allow_visited_style */ false);
   if (!value)
     value = CSSUnparsedValue::Create()->ToCSSValue();
@@ -124,7 +122,6 @@
 }
 
 void PrepopulatedComputedStylePropertyMap::Trace(blink::Visitor* visitor) {
-  visitor->Trace(styled_node_);
   visitor->Trace(native_values_);
   visitor->Trace(custom_values_);
   StylePropertyMapReadOnlyMainThread::Trace(visitor);
diff --git a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
index 1ff3f4d..5d821bd 100644
--- a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
+++ b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
@@ -31,7 +31,6 @@
   PrepopulatedComputedStylePropertyMap(
       const Document&,
       const ComputedStyle&,
-      const Node* styled_node,
       const Vector<CSSPropertyID>& native_properties,
       const Vector<AtomicString>& custom_properties);
 
@@ -54,7 +53,6 @@
                             const ComputedStyle&,
                             const AtomicString& property_name);
 
-  Member<const Node> styled_node_;
   HeapHashMap<CSSPropertyID, Member<const CSSValue>> native_values_;
   HeapHashMap<AtomicString, Member<const CSSValue>> custom_values_;
 
diff --git a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map_test.cc
index 75382e5..72cb0bf 100644
--- a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map_test.cc
+++ b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map_test.cc
@@ -28,7 +28,7 @@
     Element* node = GetDocument().getElementById("target");
     return CSSProperty::Get(property_id)
         .CSSValueFromComputedStyle(node->ComputedStyleRef(),
-                                   nullptr /* layout_object */, node,
+                                   nullptr /* layout_object */,
                                    false /* allow_visited_style */);
   }
 
@@ -58,7 +58,7 @@
 
   PrepopulatedComputedStylePropertyMap* map =
       MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>(
-          GetDocument(), node->ComputedStyleRef(), node, native_properties,
+          GetDocument(), node->ComputedStyleRef(), native_properties,
           empty_custom_properties);
 
   DummyExceptionStateForTesting exception_state;
@@ -94,8 +94,8 @@
 
   PrepopulatedComputedStylePropertyMap* map =
       MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>(
-          GetDocument(), node->ComputedStyleRef(), node,
-          empty_native_properties, custom_properties);
+          GetDocument(), node->ComputedStyleRef(), empty_native_properties,
+          custom_properties);
 
   DummyExceptionStateForTesting exception_state;
 
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
index 90c3634d..6da0605 100644
--- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -67,7 +67,6 @@
 
 CSSValue* ComputedStyleUtils::ValueForOffset(const ComputedStyle& style,
                                              const LayoutObject* layout_object,
-                                             const Node* styled_node,
                                              bool allow_visited_style) {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   if (RuntimeEnabledFeatures::CSSOffsetPositionAnchorEnabled()) {
@@ -84,7 +83,7 @@
                                             &GetCSSPropertyOffsetRotate()};
   for (const CSSProperty* longhand : longhands) {
     const CSSValue* value = longhand->CSSValueFromComputedStyle(
-        style, layout_object, styled_node, allow_visited_style);
+        style, layout_object, allow_visited_style);
     DCHECK(value);
     list->Append(*value);
   }
@@ -219,7 +218,6 @@
 const CSSValueList* ComputedStyleUtils::ValuesForBackgroundShorthand(
     const ComputedStyle& style,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) {
   CSSValueList* result = CSSValueList::CreateCommaSeparated();
   const FillLayer* curr_layer = &style.BackgroundLayers();
@@ -229,7 +227,7 @@
     if (!curr_layer->Next()) {  // color only for final layer
       const CSSValue* value =
           GetCSSPropertyBackgroundColor().CSSValueFromComputedStyle(
-              style, layout_object, styled_node, allow_visited_style);
+              style, layout_object, allow_visited_style);
       DCHECK(value);
       before_slash->Append(*value);
     }
@@ -508,15 +506,9 @@
 }
 
 CSSValue* ComputedStyleUtils::MinWidthOrMinHeightAuto(
-    const Node* styled_node,
     const ComputedStyle& style) {
-  LayoutObject* layout_object =
-      styled_node ? styled_node->GetLayoutObject() : nullptr;
-  if (layout_object && layout_object->IsBox() &&
-      (ToLayoutBox(layout_object)->IsFlexItemIncludingNG() ||
-       ToLayoutBox(layout_object)->IsGridItem())) {
+  if (style.IsFlexOrGridOrCustomItem() && !style.IsEnsuredInDisplayNone())
     return CSSIdentifierValue::Create(CSSValueID::kAuto);
-  }
   return ZoomAdjustedPixelValue(0, style);
 }
 
@@ -2204,13 +2196,12 @@
     const StylePropertyShorthand& shorthand,
     const ComputedStyle& style,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   for (unsigned i = 0; i < shorthand.length(); ++i) {
     const CSSValue* value =
         shorthand.properties()[i]->CSSValueFromComputedStyle(
-            style, layout_object, styled_node, allow_visited_style);
+            style, layout_object, allow_visited_style);
     DCHECK(value);
     list->Append(*value);
   }
@@ -2221,13 +2212,12 @@
     const StylePropertyShorthand& shorthand,
     const ComputedStyle& style,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) {
   CSSValueList* list = CSSValueList::CreateSlashSeparated();
   for (unsigned i = 0; i < shorthand.length(); ++i) {
     const CSSValue* value =
         shorthand.properties()[i]->CSSValueFromComputedStyle(
-            style, layout_object, styled_node, allow_visited_style);
+            style, layout_object, allow_visited_style);
     DCHECK(value);
     list->Append(*value);
   }
@@ -2238,22 +2228,21 @@
     const StylePropertyShorthand& shorthand,
     const ComputedStyle& style,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   // Assume the properties are in the usual order top, right, bottom, left.
   const CSSValue* top_value =
-      shorthand.properties()[0]->CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+      shorthand.properties()[0]->CSSValueFromComputedStyle(style, layout_object,
+                                                           allow_visited_style);
   const CSSValue* right_value =
-      shorthand.properties()[1]->CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+      shorthand.properties()[1]->CSSValueFromComputedStyle(style, layout_object,
+                                                           allow_visited_style);
   const CSSValue* bottom_value =
-      shorthand.properties()[2]->CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+      shorthand.properties()[2]->CSSValueFromComputedStyle(style, layout_object,
+                                                           allow_visited_style);
   const CSSValue* left_value =
-      shorthand.properties()[3]->CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+      shorthand.properties()[3]->CSSValueFromComputedStyle(style, layout_object,
+                                                           allow_visited_style);
 
   // All 4 properties must be specified.
   if (!top_value || !right_value || !bottom_value || !left_value)
@@ -2278,14 +2267,13 @@
     const StylePropertyShorthand& shorthand,
     const ComputedStyle& style,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) {
   const CSSValue* start_value =
-      shorthand.properties()[0]->CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+      shorthand.properties()[0]->CSSValueFromComputedStyle(style, layout_object,
+                                                           allow_visited_style);
   const CSSValue* end_value =
-      shorthand.properties()[1]->CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+      shorthand.properties()[1]->CSSValueFromComputedStyle(style, layout_object,
+                                                           allow_visited_style);
   // Both properties must be specified.
   if (!start_value || !end_value)
     return nullptr;
@@ -2299,14 +2287,13 @@
     const StylePropertyShorthand& shorthand,
     const ComputedStyle& style,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) {
   const CSSValue* align_value =
-      shorthand.properties()[0]->CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+      shorthand.properties()[0]->CSSValueFromComputedStyle(style, layout_object,
+                                                           allow_visited_style);
   const CSSValue* justify_value =
-      shorthand.properties()[1]->CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+      shorthand.properties()[1]->CSSValueFromComputedStyle(style, layout_object,
+                                                           allow_visited_style);
 
   return MakeGarbageCollected<CSSValuePair>(align_value, justify_value,
                                             CSSValuePair::kDropIdenticalValues);
@@ -2325,7 +2312,6 @@
 CSSValue* ComputedStyleUtils::ValuesForFontVariantProperty(
     const ComputedStyle& style,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) {
   enum VariantShorthandCases {
     kAllNormal,
@@ -2337,7 +2323,7 @@
   for (unsigned i = 0; i < shorthand.length(); ++i) {
     const CSSValue* value =
         shorthand.properties()[i]->CSSValueFromComputedStyle(
-            style, layout_object, styled_node, allow_visited_style);
+            style, layout_object, allow_visited_style);
 
     auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
     if (shorthand_case == kAllNormal && identifier_value &&
@@ -2362,7 +2348,7 @@
       for (unsigned i = 0; i < shorthand.length(); ++i) {
         const CSSValue* value =
             shorthand.properties()[i]->CSSValueFromComputedStyle(
-                style, layout_object, styled_node, allow_visited_style);
+                style, layout_object, allow_visited_style);
         DCHECK(value);
         auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
         if (identifier_value &&
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.h b/third_party/blink/renderer/core/css/properties/computed_style_utils.h
index eac5b3cf..d28094a 100644
--- a/third_party/blink/renderer/core/css/properties/computed_style_utils.h
+++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.h
@@ -58,7 +58,6 @@
   static const CSSValueList* ValuesForBackgroundShorthand(
       const ComputedStyle&,
       const LayoutObject*,
-      const Node*,
       bool allow_visited_style);
   static const CSSValue* BackgroundRepeatOrWebkitMaskRepeat(const FillLayer*);
   static const CSSValue* BackgroundPositionOrWebkitMaskPosition(
@@ -85,9 +84,8 @@
 
   static CSSValue* ValueForOffset(const ComputedStyle&,
                                   const LayoutObject*,
-                                  const Node*,
                                   bool allow_visited_style);
-  static CSSValue* MinWidthOrMinHeightAuto(const Node*, const ComputedStyle&);
+  static CSSValue* MinWidthOrMinHeightAuto(const ComputedStyle&);
   static CSSValue* ValueForPositionOffset(const ComputedStyle&,
                                           const CSSProperty&,
                                           const LayoutObject*);
@@ -179,32 +177,26 @@
   static CSSValueList* ValuesForShorthandProperty(const StylePropertyShorthand&,
                                                   const ComputedStyle&,
                                                   const LayoutObject*,
-                                                  const Node*,
                                                   bool allow_visited_style);
   static CSSValueList* ValuesForGridShorthand(const StylePropertyShorthand&,
                                               const ComputedStyle&,
                                               const LayoutObject*,
-                                              const Node*,
                                               bool allow_visited_style);
   static CSSValueList* ValuesForSidesShorthand(const StylePropertyShorthand&,
                                                const ComputedStyle&,
                                                const LayoutObject*,
-                                               const Node*,
                                                bool allow_visited_style);
   static CSSValuePair* ValuesForInlineBlockShorthand(
       const StylePropertyShorthand&,
       const ComputedStyle&,
       const LayoutObject*,
-      const Node*,
       bool allow_visited_style);
   static CSSValuePair* ValuesForPlaceShorthand(const StylePropertyShorthand&,
                                                const ComputedStyle&,
                                                const LayoutObject*,
-                                               const Node*,
                                                bool allow_visited_style);
   static CSSValue* ValuesForFontVariantProperty(const ComputedStyle&,
                                                 const LayoutObject*,
-                                                const Node*,
                                                 bool allow_visited_style);
   static CSSValue* ScrollCustomizationFlagsToCSSValue(
       scroll_customization::ScrollDirection);
diff --git a/third_party/blink/renderer/core/css/properties/css_property.cc b/third_party/blink/renderer/core/css/properties/css_property.cc
index 53d8572a..0c0540f 100644
--- a/third_party/blink/renderer/core/css/properties/css_property.cc
+++ b/third_party/blink/renderer/core/css/properties/css_property.cc
@@ -28,10 +28,9 @@
 CSSProperty::CrossThreadStyleValueFromComputedStyle(
     const ComputedStyle& computed_style,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   const CSSValue* css_value = CSSValueFromComputedStyle(
-      computed_style, layout_object, styled_node, allow_visited_style);
+      computed_style, layout_object, allow_visited_style);
   if (!css_value)
     return std::make_unique<CrossThreadUnsupportedValue>("");
   CSSStyleValue* style_value =
@@ -45,13 +44,12 @@
 const CSSValue* CSSProperty::CSSValueFromComputedStyle(
     const ComputedStyle& style,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   const SVGComputedStyle& svg_style = style.SvgStyle();
   const CSSProperty& resolved_property =
       ResolveDirectionAwareProperty(style.Direction(), style.GetWritingMode());
   return resolved_property.CSSValueFromComputedStyleInternal(
-      style, svg_style, layout_object, styled_node, allow_visited_style);
+      style, svg_style, layout_object, allow_visited_style);
 }
 
 void CSSProperty::FilterWebExposedCSSPropertiesIntoVector(
diff --git a/third_party/blink/renderer/core/css/properties/css_property.h b/third_party/blink/renderer/core/css/properties/css_property.h
index acc3dcd..9b6005c 100644
--- a/third_party/blink/renderer/core/css/properties/css_property.h
+++ b/third_party/blink/renderer/core/css/properties/css_property.h
@@ -66,20 +66,15 @@
       const ComputedStyle&,
       const SVGComputedStyle&,
       const LayoutObject*,
-      const Node*,
       bool allow_visited_style) const {
     return nullptr;
   }
-  // TODO: Resolve computed auto alignment in applyProperty/ComputedStyle and
-  // remove this const Node parameter.
   const CSSValue* CSSValueFromComputedStyle(const ComputedStyle&,
                                             const LayoutObject*,
-                                            const Node*,
                                             bool allow_visited_style) const;
   virtual std::unique_ptr<CrossThreadStyleValue>
   CrossThreadStyleValueFromComputedStyle(const ComputedStyle& computed_style,
                                          const LayoutObject* layout_object,
-                                         const Node* styled_node,
                                          bool allow_visited_style) const;
   virtual const CSSProperty& ResolveDirectionAwareProperty(TextDirection,
                                                            WritingMode) const {
diff --git a/third_party/blink/renderer/core/css/properties/css_property_methods.json5 b/third_party/blink/renderer/core/css/properties/css_property_methods.json5
index b666b54..b3b0095 100644
--- a/third_party/blink/renderer/core/css/properties/css_property_methods.json5
+++ b/third_party/blink/renderer/core/css/properties/css_property_methods.json5
@@ -32,7 +32,7 @@
     {
       name: "CSSValueFromComputedStyleInternal",
       return_type: "const CSSValue*",
-      parameters: "(const ComputedStyle&, const SVGComputedStyle&, const LayoutObject*, const Node*, bool allow_visited_style)",
+      parameters: "(const ComputedStyle&, const SVGComputedStyle&, const LayoutObject*, bool allow_visited_style)",
     },
     {
       name: "ColorIncludingFallback",
diff --git a/third_party/blink/renderer/core/css/properties/css_property_test.cc b/third_party/blink/renderer/core/css/properties/css_property_test.cc
index 80cbc05c..a281633 100644
--- a/third_party/blink/renderer/core/css/properties/css_property_test.cc
+++ b/third_party/blink/renderer/core/css/properties/css_property_test.cc
@@ -64,7 +64,7 @@
 
     // Get any value compatible with 'property'. The initial value will do.
     const CSSValue* initial_value = property.CSSValueFromComputedStyle(
-        *initial_style, nullptr /* layout_object */, nullptr /* node */,
+        *initial_style, nullptr /* layout_object */,
         false /* allow_visited_style */);
     ASSERT_TRUE(initial_value);
     String css_text = initial_value->CssText();
diff --git a/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc b/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc
index 554dcc5..28138d9 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/custom_property.cc
@@ -154,7 +154,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (registration_) {
     const CSSValue* value = style.GetVariableValue(name_, IsInherited());
diff --git a/third_party/blink/renderer/core/css/properties/longhands/custom_property.h b/third_party/blink/renderer/core/css/properties/longhands/custom_property.h
index a5f80df..87b813e 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/custom_property.h
+++ b/third_party/blink/renderer/core/css/properties/longhands/custom_property.h
@@ -45,7 +45,6 @@
       const ComputedStyle&,
       const SVGComputedStyle&,
       const LayoutObject*,
-      const Node* styled_node,
       bool allow_visited_style) const override;
 
   bool IsRegistered() const { return registration_; }
diff --git a/third_party/blink/renderer/core/css/properties/longhands/custom_property_test.cc b/third_party/blink/renderer/core/css/properties/longhands/custom_property_test.cc
index 24cc6ba..7c8868f 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/custom_property_test.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/custom_property_test.cc
@@ -32,7 +32,7 @@
   const CSSValue* GetComputedValue(const CustomProperty& property) {
     Element* node = GetDocument().getElementById("target");
     return property.CSSValueFromComputedStyle(node->ComputedStyleRef(),
-                                              nullptr /* layout_object */, node,
+                                              nullptr /* layout_object */,
                                               false /* allow_visited_style */);
   }
 
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index a5ae0660..23cedc2 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -72,7 +72,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::
       ValueForContentPositionAndDistributionWithOverflowAlignment(
@@ -95,7 +94,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForItemPositionWithOverflowAlignment(
       style.AlignItems());
@@ -113,7 +111,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForItemPositionWithOverflowAlignment(
       style.AlignSelf());
@@ -122,7 +119,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.AlignmentBaseline());
 }
@@ -139,7 +135,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForAnimationDelay(style.Animations());
 }
@@ -167,7 +162,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const CSSAnimationData* animation_data = style.Animations();
@@ -200,7 +194,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForAnimationDuration(style.Animations());
 }
@@ -228,7 +221,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const CSSAnimationData* animation_data = style.Animations();
@@ -261,7 +253,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const CSSAnimationData* animation_data = style.Animations();
@@ -299,7 +290,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const CSSAnimationData* animation_data = style.Animations();
@@ -334,7 +324,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const CSSAnimationData* animation_data = style.Animations();
@@ -367,7 +356,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForAnimationTimingFunction(
       style.Animations());
@@ -390,7 +378,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFilter(style, style.BackdropFilter());
 }
@@ -398,7 +385,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(
       (style.BackfaceVisibility() == EBackfaceVisibility::kHidden)
@@ -418,7 +404,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   for (const FillLayer* curr_layer = &style.BackgroundLayers(); curr_layer;
@@ -439,7 +424,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   for (const FillLayer* curr_layer = &style.BackgroundLayers(); curr_layer;
@@ -460,7 +444,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const FillLayer* curr_layer = &style.BackgroundLayers();
@@ -490,7 +473,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (allow_visited_style) {
     return cssvalue::CSSColorValue::Create(
@@ -513,7 +495,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const FillLayer& fill_layer = style.BackgroundLayers();
   return ComputedStyleUtils::BackgroundImageOrWebkitMaskImage(fill_layer);
@@ -531,7 +512,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const FillLayer* curr_layer = &style.BackgroundLayers();
@@ -556,7 +536,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const FillLayer* curr_layer = &style.BackgroundLayers();
   return ComputedStyleUtils::BackgroundPositionXOrWebkitMaskPositionX(
@@ -577,7 +556,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const FillLayer* curr_layer = &style.BackgroundLayers();
   return ComputedStyleUtils::BackgroundPositionYOrWebkitMaskPositionY(
@@ -596,7 +574,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const FillLayer& fill_layer = style.BackgroundLayers();
   return ComputedStyleUtils::BackgroundImageOrWebkitMaskSize(style, fill_layer);
@@ -618,7 +595,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   switch (svg_style.BaselineShift()) {
     case BS_SUPER:
@@ -733,7 +709,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return allow_visited_style ? cssvalue::CSSColorValue::Create(
                                    style.VisitedDependentColor(*this).Rgb())
@@ -752,7 +727,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return &ComputedStyleUtils::ValueForBorderRadiusCorner(
       style.BorderBottomLeftRadius(), style);
@@ -769,7 +743,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return &ComputedStyleUtils::ValueForBorderRadiusCorner(
       style.BorderBottomRightRadius(), style);
@@ -778,7 +751,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BorderBottomStyle());
 }
@@ -794,7 +766,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.BorderBottomWidth(), style);
 }
@@ -803,7 +774,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.BorderCollapse() == EBorderCollapse::kCollapse)
     return CSSIdentifierValue::Create(CSSValueID::kCollapse);
@@ -821,7 +791,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImageQuad(
       style.BorderImage().Outset(), style);
@@ -847,7 +816,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImageRepeat(style.BorderImage());
 }
@@ -870,7 +838,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImageSlice(style.BorderImage());
 }
@@ -898,7 +865,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.BorderImageSource())
     return style.BorderImageSource()->ComputedCSSValue();
@@ -928,7 +894,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImageQuad(
       style.BorderImage().BorderSlices(), style);
@@ -995,7 +960,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return allow_visited_style ? cssvalue::CSSColorValue::Create(
                                    style.VisitedDependentColor(*this).Rgb())
@@ -1007,7 +971,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BorderLeftStyle());
 }
@@ -1023,7 +986,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.BorderLeftWidth(), style);
 }
@@ -1048,7 +1010,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return allow_visited_style ? cssvalue::CSSColorValue::Create(
                                    style.VisitedDependentColor(*this).Rgb())
@@ -1060,7 +1021,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BorderRightStyle());
 }
@@ -1076,7 +1036,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.BorderRightWidth(), style);
 }
@@ -1101,7 +1060,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return allow_visited_style
              ? cssvalue::CSSColorValue::Create(
@@ -1121,7 +1079,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return &ComputedStyleUtils::ValueForBorderRadiusCorner(
       style.BorderTopLeftRadius(), style);
@@ -1138,7 +1095,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return &ComputedStyleUtils::ValueForBorderRadiusCorner(
       style.BorderTopRightRadius(), style);
@@ -1148,7 +1104,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BorderTopStyle());
 }
@@ -1164,7 +1119,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.BorderTopWidth(), style);
 }
@@ -1187,7 +1141,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForPositionOffset(style, *this,
                                                     layout_object);
@@ -1205,7 +1158,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForShadowList(style.BoxShadow(), style, true);
 }
@@ -1214,7 +1166,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.BoxSizing() == EBoxSizing::kContentBox)
     return CSSIdentifierValue::Create(CSSValueID::kContentBox);
@@ -1225,7 +1176,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BreakAfter());
 }
@@ -1234,7 +1184,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BreakBefore());
 }
@@ -1243,7 +1192,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BreakInside());
 }
@@ -1252,7 +1200,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.BufferedRendering());
 }
@@ -1261,7 +1208,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.CaptionSide());
 }
@@ -1291,7 +1237,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   blink::Color color;
   if (allow_visited_style)
@@ -1321,7 +1266,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.Clear());
 }
@@ -1377,7 +1321,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.HasAutoClip())
     return CSSIdentifierValue::Create(CSSValueID::kAuto);
@@ -1408,7 +1351,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (ClipPathOperation* operation = style.ClipPath()) {
     if (operation->GetType() == ClipPathOperation::SHAPE) {
@@ -1427,7 +1369,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.ClipRule());
 }
@@ -1450,7 +1391,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return cssvalue::CSSColorValue::Create(
       allow_visited_style ? style.VisitedDependentColor(*this).Rgb()
@@ -1491,7 +1431,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.ColorInterpolation());
 }
@@ -1500,7 +1439,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.ColorInterpolationFilters());
 }
@@ -1509,7 +1447,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.ColorRendering());
 }
@@ -1566,7 +1503,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.ColorScheme().IsEmpty())
     return CSSIdentifierValue::Create(CSSValueID::kNormal);
@@ -1632,7 +1568,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.HasAutoColumnCount())
     return CSSIdentifierValue::Create(CSSValueID::kAuto);
@@ -1644,7 +1579,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetColumnFill());
 }
@@ -1660,7 +1594,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool) const {
   return ComputedStyleUtils::ValueForGapLength(style.ColumnGap(), style);
 }
@@ -1683,7 +1616,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return allow_visited_style ? cssvalue::CSSColorValue::Create(
                                    style.VisitedDependentColor(*this).Rgb())
@@ -1695,7 +1627,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.ColumnRuleStyle());
 }
@@ -1713,7 +1644,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.ColumnRuleWidth(), style);
 }
@@ -1730,7 +1660,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(static_cast<unsigned>(style.GetColumnSpan())
                                         ? CSSValueID::kAll
@@ -1748,7 +1677,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.HasAutoColumnWidth())
     return CSSIdentifierValue::Create(CSSValueID::kAuto);
@@ -1805,7 +1733,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (!style.Contain())
     return CSSIdentifierValue::Create(CSSValueID::kNone);
@@ -1946,7 +1873,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForContentData(style);
 }
@@ -2063,7 +1989,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForCounterDirectives(style, true);
 }
@@ -2082,7 +2007,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForCounterDirectives(style, false);
 }
@@ -2150,7 +2074,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = nullptr;
   CursorList* cursors = style.Cursors();
@@ -2216,7 +2139,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(svg_style.Cx(),
                                                              style);
@@ -2233,7 +2155,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(svg_style.Cy(),
                                                              style);
@@ -2249,7 +2170,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (const StylePath* style_path = svg_style.D())
     return style_path->ComputedCSSValue();
@@ -2260,7 +2180,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.Direction());
 }
@@ -2306,7 +2225,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.IsDisplayLayoutCustomBox()) {
     return MakeGarbageCollected<cssvalue::CSSLayoutFunctionValue>(
@@ -2353,7 +2271,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.DominantBaseline());
 }
@@ -2362,7 +2279,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.EmptyCells());
 }
@@ -2377,7 +2293,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::AdjustSVGPaintForCurrentColor(
       svg_style.FillPaint(), style.GetColor());
@@ -2394,7 +2309,6 @@
     const ComputedStyle&,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(svg_style.FillOpacity(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -2404,7 +2318,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.FillRule());
 }
@@ -2419,7 +2332,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFilter(style, style.Filter());
 }
@@ -2439,7 +2351,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(style.FlexBasis(),
                                                              style);
@@ -2449,7 +2360,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.FlexDirection());
 }
@@ -2465,7 +2375,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.FlexGrow(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -2483,7 +2392,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.FlexShrink(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -2493,7 +2401,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.FlexWrap());
 }
@@ -2502,7 +2409,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.HasOutOfFlowPosition())
     return CSSIdentifierValue::Create(CSSValueID::kNone);
@@ -2529,7 +2435,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::CurrentColorOrValidColor(style,
                                                       style.FloodColor());
@@ -2546,7 +2451,6 @@
     const ComputedStyle&,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(svg_style.FloodOpacity(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -2563,7 +2467,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFontFamily(style);
 }
@@ -2579,7 +2482,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const blink::FontFeatureSettings* feature_settings =
       style.GetFontDescription().FeatureSettings();
@@ -2599,7 +2501,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetFontDescription().GetKerning());
 }
@@ -2619,7 +2520,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.HasFontSizeAdjust()) {
     return CSSNumericLiteralValue::Create(style.FontSizeAdjust(),
@@ -2639,7 +2539,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFontSize(style);
 }
@@ -2655,7 +2554,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFontStretch(style);
 }
@@ -2671,7 +2569,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFontStyle(style);
 }
@@ -2690,7 +2587,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFontVariantCaps(style);
 }
@@ -2716,7 +2612,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFontVariantEastAsian(style);
 }
@@ -2743,7 +2638,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFontVariantLigatures(style);
 }
@@ -2769,7 +2663,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFontVariantNumeric(style);
 }
@@ -2826,7 +2719,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const blink::FontVariationSettings* variation_settings =
       style.GetFontDescription().VariationSettings();
@@ -2854,7 +2746,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFontWeight(style);
 }
@@ -2863,7 +2754,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.ForcedColorAdjust());
 }
@@ -2937,7 +2827,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForGridTrackSizeList(kForColumns, style);
 }
@@ -2970,7 +2859,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   switch (style.GetGridAutoFlow()) {
@@ -3012,7 +2900,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForGridTrackSizeList(kForRows, style);
 }
@@ -3028,7 +2915,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForGridPosition(style.GridColumnEnd());
 }
@@ -3044,7 +2930,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForGridPosition(style.GridColumnStart());
 }
@@ -3060,7 +2945,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForGridPosition(style.GridRowEnd());
 }
@@ -3076,7 +2960,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForGridPosition(style.GridRowStart());
 }
@@ -3111,7 +2994,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (!style.NamedGridAreaRowCount()) {
     DCHECK(!style.NamedGridAreaColumnCount());
@@ -3189,7 +3071,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForGridTrackList(kForColumns, layout_object,
                                                    style);
@@ -3212,7 +3093,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForGridTrackList(kForRows, layout_object,
                                                    style);
@@ -3234,7 +3114,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   if (ComputedStyleUtils::WidthOrHeightShouldReturnUsedValue(layout_object)) {
     return ZoomAdjustedPixelValue(
@@ -3248,7 +3127,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetHyphens());
 }
@@ -3273,7 +3151,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.RespectImageOrientation() == kRespectImageOrientation)
     return CSSIdentifierValue::Create(CSSValueID::kFromImage);
@@ -3285,7 +3162,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.ImageRendering());
 }
@@ -3590,7 +3466,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.Isolation());
 }
@@ -3612,7 +3487,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::
       ValueForContentPositionAndDistributionWithOverflowAlignment(
@@ -3657,7 +3531,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForItemPositionWithOverflowAlignment(
       style.JustifyItems().GetPosition() == ItemPosition::kAuto
@@ -3677,7 +3550,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForItemPositionWithOverflowAlignment(
       style.JustifySelf());
@@ -3701,7 +3573,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForPositionOffset(style, *this,
                                                     layout_object);
@@ -3718,7 +3589,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (!style.LetterSpacing())
     return CSSIdentifierValue::Create(CSSValueID::kNormal);
@@ -3745,7 +3615,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::CurrentColorOrValidColor(style,
                                                       style.LightingColor());
@@ -3755,7 +3624,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetLineBreak());
 }
@@ -3771,7 +3639,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForLineHeight(style);
 }
@@ -3788,7 +3655,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.LineHeightStep(), style);
 }
@@ -3804,7 +3670,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.ListStyleImage())
     return style.ListStyleImage()->ComputedCSSValue();
@@ -3821,7 +3686,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.ListStylePosition());
 }
@@ -3830,7 +3694,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.ListStyleType());
 }
@@ -3872,7 +3735,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   const Length& margin_bottom = style.MarginBottom();
   if (margin_bottom.IsFixed() || !layout_object || !layout_object->IsBox()) {
@@ -3920,7 +3782,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   const Length& margin_left = style.MarginLeft();
   if (margin_left.IsFixed() || !layout_object || !layout_object->IsBox()) {
@@ -3950,7 +3811,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   const Length& margin_right = style.MarginRight();
   if (margin_right.IsFixed() || !layout_object || !layout_object->IsBox()) {
@@ -3994,7 +3854,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   const Length& margin_top = style.MarginTop();
   if (margin_top.IsFixed() || !layout_object || !layout_object->IsBox()) {
@@ -4017,7 +3876,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForSVGResource(svg_style.MarkerEndResource());
 }
@@ -4035,7 +3893,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForSVGResource(svg_style.MarkerMidResource());
 }
@@ -4053,7 +3910,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForSVGResource(
       svg_style.MarkerStartResource());
@@ -4071,7 +3927,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForSVGResource(svg_style.MaskerResource());
 }
@@ -4099,7 +3954,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   for (const FillLayer* curr_layer = &style.MaskLayers(); curr_layer;
@@ -4112,7 +3966,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.MaskType());
 }
@@ -4136,7 +3989,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const Length& max_height = style.MaxHeight();
   if (max_height.IsMaxSizeNone())
@@ -4162,7 +4014,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const Length& max_width = style.MaxWidth();
   if (max_width.IsMaxSizeNone())
@@ -4188,11 +4039,10 @@
 const CSSValue* MinHeight::CSSValueFromComputedStyleInternal(
     const ComputedStyle& style,
     const SVGComputedStyle&,
-    const LayoutObject*,
-    const Node* styled_node,
+    const LayoutObject* layout_object,
     bool allow_visited_style) const {
   if (style.MinHeight().IsAuto())
-    return ComputedStyleUtils::MinWidthOrMinHeightAuto(styled_node, style);
+    return ComputedStyleUtils::MinWidthOrMinHeightAuto(style);
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(style.MinHeight(),
                                                              style);
 }
@@ -4214,11 +4064,10 @@
 const CSSValue* MinWidth::CSSValueFromComputedStyleInternal(
     const ComputedStyle& style,
     const SVGComputedStyle&,
-    const LayoutObject*,
-    const Node* styled_node,
+    const LayoutObject* layout_object,
     bool allow_visited_style) const {
   if (style.MinWidth().IsAuto())
-    return ComputedStyleUtils::MinWidthOrMinHeightAuto(styled_node, style);
+    return ComputedStyleUtils::MinWidthOrMinHeightAuto(style);
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(style.MinWidth(),
                                                              style);
 }
@@ -4227,7 +4076,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetBlendMode());
 }
@@ -4236,7 +4084,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetObjectFit());
 }
@@ -4254,7 +4101,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return MakeGarbageCollected<CSSValuePair>(
       ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
@@ -4280,7 +4126,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForPosition(style.OffsetAnchor(), style);
 }
@@ -4297,7 +4142,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
       style.OffsetDistance(), style);
@@ -4314,7 +4158,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (const BasicShape* style_motion_path = style.OffsetPath())
     return ValueForBasicShape(style, style_motion_path);
@@ -4342,7 +4185,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForPosition(style.OffsetPosition(), style);
 }
@@ -4357,7 +4199,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   if (style.OffsetRotate().type == OffsetRotationType::kAuto)
@@ -4377,7 +4218,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.Opacity(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -4393,7 +4233,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.Order(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -4409,7 +4248,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.Orphans(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -4436,7 +4274,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return allow_visited_style ? cssvalue::CSSColorValue::Create(
                                    style.VisitedDependentColor(*this).Rgb())
@@ -4456,7 +4293,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.OutlineOffset(), style);
 }
@@ -4465,7 +4301,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.OutlineStyleIsAuto())
     return CSSIdentifierValue::Create(CSSValueID::kAuto);
@@ -4505,7 +4340,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.OutlineWidth(), style);
 }
@@ -4514,7 +4348,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.OverflowAnchor());
 }
@@ -4523,7 +4356,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.OverflowWrap());
 }
@@ -4532,7 +4364,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.OverflowX());
 }
@@ -4541,7 +4372,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.OverflowY());
 }
@@ -4550,7 +4380,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.OverscrollBehaviorX());
 }
@@ -4559,7 +4388,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.OverscrollBehaviorY());
 }
@@ -4601,7 +4429,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   const Length& padding_bottom = style.PaddingBottom();
   if (padding_bottom.IsFixed() || !layout_object || !layout_object->IsBox()) {
@@ -4649,7 +4476,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   const Length& padding_left = style.PaddingLeft();
   if (padding_left.IsFixed() || !layout_object || !layout_object->IsBox()) {
@@ -4679,7 +4505,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   const Length& padding_right = style.PaddingRight();
   if (padding_right.IsFixed() || !layout_object || !layout_object->IsBox()) {
@@ -4709,7 +4534,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   const Length& padding_top = style.PaddingTop();
   if (padding_top.IsFixed() || !layout_object || !layout_object->IsBox()) {
@@ -4785,7 +4609,6 @@
     const ComputedStyle&,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const EPaintOrder paint_order = svg_style.PaintOrder();
   if (paint_order == kPaintOrderNormal)
@@ -4846,7 +4669,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (!style.HasPerspective())
     return CSSIdentifierValue::Create(CSSValueID::kNone);
@@ -4871,7 +4693,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   if (layout_object) {
     LayoutRect box;
@@ -4900,7 +4721,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.PointerEvents());
 }
@@ -4909,7 +4729,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetPosition());
 }
@@ -4941,7 +4760,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (!style.Quotes()) {
     // TODO(ramya.v): We should return the quote values that we're actually
@@ -4972,7 +4790,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(svg_style.R(),
                                                              style);
@@ -4982,7 +4799,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.Resize());
 }
@@ -5022,7 +4838,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForPositionOffset(style, *this,
                                                     layout_object);
@@ -5063,7 +4878,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (!style.Rotate())
     return CSSIdentifierValue::Create(CSSValueID::kNone);
@@ -5093,7 +4907,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool) const {
   return ComputedStyleUtils::ValueForGapLength(style.RowGap(), style);
 }
@@ -5111,7 +4924,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(svg_style.Rx(),
                                                              style);
@@ -5130,7 +4942,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(svg_style.Ry(),
                                                              style);
@@ -5174,7 +4985,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   ScaleTransformOperation* scale = style.Scale();
   if (!scale)
@@ -5202,7 +5012,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetScrollBehavior());
 }
@@ -5258,7 +5067,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ScrollCustomizationFlagsToCSSValue(
       style.ScrollCustomization());
@@ -5292,7 +5100,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.ScrollMarginBottom(), style);
 }
@@ -5325,7 +5132,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.ScrollMarginLeft(), style);
 }
@@ -5342,7 +5148,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.ScrollMarginRight(), style);
 }
@@ -5359,7 +5164,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.ScrollMarginTop(), style);
 }
@@ -5395,7 +5199,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
       style.ScrollPaddingBottom(), style);
@@ -5432,7 +5235,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
       style.ScrollPaddingLeft(), style);
@@ -5451,7 +5253,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
       style.ScrollPaddingRight(), style);
@@ -5470,7 +5271,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
       style.ScrollPaddingTop(), style);
@@ -5502,7 +5302,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForScrollSnapAlign(style.GetScrollSnapAlign(),
                                                      style);
@@ -5512,7 +5311,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.ScrollSnapStop());
 }
@@ -5546,7 +5344,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForScrollSnapType(style.GetScrollSnapType(),
                                                     style);
@@ -5563,7 +5360,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.ShapeImageThreshold(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -5581,7 +5377,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSValue::Create(style.ShapeMargin(), style.EffectiveZoom());
 }
@@ -5613,7 +5408,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForShape(style, style.ShapeOutside());
 }
@@ -5622,7 +5416,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.ShapeRendering());
 }
@@ -5771,7 +5564,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.Speak());
 }
@@ -5796,7 +5588,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::CurrentColorOrValidColor(style, style.StopColor());
 }
@@ -5812,7 +5603,6 @@
     const ComputedStyle&,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(svg_style.StopOpacity(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -5828,7 +5618,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::AdjustSVGPaintForCurrentColor(
       svg_style.StrokePaint(), style.GetColor());
@@ -5860,7 +5649,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::StrokeDashArrayToCSSValueList(
       *svg_style.StrokeDashArray(), style);
@@ -5879,7 +5667,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
       style.StrokeDashOffset(), style);
@@ -5889,7 +5676,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.CapStyle());
 }
@@ -5898,7 +5684,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.JoinStyle());
 }
@@ -5915,7 +5700,6 @@
     const ComputedStyle&,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(svg_style.StrokeMiterLimit(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -5932,7 +5716,6 @@
     const ComputedStyle&,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(svg_style.StrokeOpacity(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -5951,7 +5734,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const Length& length = svg_style.StrokeWidth().length();
   if (length.IsFixed()) {
@@ -5976,7 +5758,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(
       style.GetTabSize().GetPixelSize(1.0),
@@ -5988,7 +5769,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.TableLayout());
 }
@@ -5997,7 +5777,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetTextAlign());
 }
@@ -6033,7 +5812,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.TextAlignLast());
 }
@@ -6042,7 +5820,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.TextAnchor());
 }
@@ -6051,7 +5828,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.TextCombine());
 }
@@ -6075,7 +5851,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::CurrentColorOrValidColor(
       style, style.TextDecorationColor());
@@ -6092,7 +5867,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::RenderTextDecorationFlagsToCSSValue(
       style.GetTextDecoration());
@@ -6102,7 +5876,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForTextDecorationSkipInk(
       style.TextDecorationSkipInk());
@@ -6112,7 +5885,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForTextDecorationStyle(
       style.TextDecorationStyle());
@@ -6169,7 +5941,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   list->Append(*ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
@@ -6230,7 +6001,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetTextJustify());
 }
@@ -6239,7 +6009,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetTextOrientation());
 }
@@ -6254,7 +6023,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.TextOverflow() != ETextOverflow::kClip)
     return CSSIdentifierValue::Create(CSSValueID::kEllipsis);
@@ -6265,7 +6033,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetFontDescription().TextRendering());
 }
@@ -6282,7 +6049,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForShadowList(style.TextShadow(), style,
                                                 false);
@@ -6304,7 +6070,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.GetTextSizeAdjust().IsAuto())
     return CSSIdentifierValue::Create(CSSValueID::kAuto);
@@ -6317,7 +6082,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.TextTransform());
 }
@@ -6354,7 +6118,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   auto text_underline_position = style.TextUnderlinePosition();
   if (text_underline_position == kTextUnderlinePositionAuto)
@@ -6395,7 +6158,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForPositionOffset(style, *this,
                                                     layout_object);
@@ -6461,7 +6223,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::TouchActionFlagsToCSSValue(style.GetTouchAction());
 }
@@ -6470,7 +6231,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.TransformBox());
 }
@@ -6492,7 +6252,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ComputedTransform(layout_object, style);
 }
@@ -6529,7 +6288,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   if (layout_object) {
@@ -6555,7 +6313,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(
       (style.TransformStyle3D() == ETransformStyle3D::kPreserve3d)
@@ -6575,7 +6332,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForAnimationDelay(style.Transitions());
 }
@@ -6600,7 +6356,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForAnimationDuration(style.Transitions());
 }
@@ -6628,7 +6383,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForTransitionProperty(style.Transitions());
 }
@@ -6651,7 +6405,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForAnimationTimingFunction(
       style.Transitions());
@@ -6705,7 +6458,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   if (!style.Translate())
     return CSSIdentifierValue::Create(CSSValueID::kNone);
@@ -6729,7 +6481,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetUnicodeBidi());
 }
@@ -6738,7 +6489,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.UserSelect());
 }
@@ -6747,7 +6497,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(svg_style.VectorEffect());
 }
@@ -6770,7 +6519,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   switch (style.VerticalAlign()) {
     case EVerticalAlign::kBaseline:
@@ -6824,7 +6572,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.Visibility());
 }
@@ -6833,7 +6580,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.DraggableRegionMode() == EDraggableRegionMode::kNone)
     return CSSIdentifierValue::Create(CSSValueID::kNone);
@@ -6861,7 +6607,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.Appearance());
 }
@@ -6879,7 +6624,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.HorizontalBorderSpacing(), style);
 }
@@ -6895,7 +6639,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImage(style.BorderImage(), style);
 }
@@ -6920,7 +6663,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.VerticalBorderSpacing(), style);
 }
@@ -6929,7 +6671,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BoxAlign());
 }
@@ -6938,7 +6679,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.BoxDecorationBreak() == EBoxDecorationBreak::kSlice)
     return CSSIdentifierValue::Create(CSSValueID::kSlice);
@@ -6949,7 +6689,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BoxDirection());
 }
@@ -6965,7 +6704,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.BoxFlex(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -6982,7 +6720,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.BoxOrdinalGroup(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -6992,7 +6729,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BoxOrient());
 }
@@ -7001,7 +6737,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.BoxPack());
 }
@@ -7051,7 +6786,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForReflection(style.BoxReflect(), style);
 }
@@ -7069,7 +6803,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetFontDescription().FontSmoothing());
 }
@@ -7087,7 +6820,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.Highlight() == g_null_atom)
     return CSSIdentifierValue::Create(CSSValueID::kNone);
@@ -7107,7 +6839,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.HyphenationString().IsNull())
     return CSSIdentifierValue::Create(CSSValueID::kAuto);
@@ -7118,7 +6849,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetLineBreak());
 }
@@ -7135,7 +6865,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (!style.HasLineClamp())
     return CSSIdentifierValue::Create(CSSValueID::kNone);
@@ -7156,7 +6885,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.Locale().IsNull())
     return CSSIdentifierValue::Create(CSSValueID::kAuto);
@@ -7178,7 +6906,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.MarginAfterCollapse());
 }
@@ -7187,7 +6914,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.MarginBeforeCollapse());
 }
@@ -7196,7 +6922,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.MarginAfterCollapse());
 }
@@ -7205,7 +6930,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.MarginBeforeCollapse());
 }
@@ -7221,7 +6945,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImageQuad(
       style.MaskBoxImage().Outset(), style);
@@ -7238,7 +6961,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImageRepeat(style.MaskBoxImage());
 }
@@ -7255,7 +6977,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImageSlice(style.MaskBoxImage());
 }
@@ -7271,7 +6992,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.MaskBoxImageSource())
     return style.MaskBoxImageSource()->ComputedCSSValue();
@@ -7295,7 +7015,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImageQuad(
       style.MaskBoxImage().BorderSlices(), style);
@@ -7314,7 +7033,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const FillLayer* curr_layer = &style.MaskLayers();
@@ -7337,7 +7055,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const FillLayer* curr_layer = &style.MaskLayers();
@@ -7358,7 +7075,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const FillLayer& fill_layer = style.MaskLayers();
   return ComputedStyleUtils::BackgroundImageOrWebkitMaskImage(fill_layer);
@@ -7377,7 +7093,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateCommaSeparated();
   const FillLayer* curr_layer = &style.MaskLayers();
@@ -7402,7 +7117,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const FillLayer* curr_layer = &style.MaskLayers();
   return ComputedStyleUtils::BackgroundPositionXOrWebkitMaskPositionX(
@@ -7423,7 +7137,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const FillLayer* curr_layer = &style.MaskLayers();
   return ComputedStyleUtils::BackgroundPositionYOrWebkitMaskPositionY(
@@ -7442,7 +7155,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const FillLayer& fill_layer = style.MaskLayers();
   return ComputedStyleUtils::BackgroundImageOrWebkitMaskSize(style, fill_layer);
@@ -7470,7 +7182,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.PrintColorAdjust());
 }
@@ -7479,7 +7190,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.RtlOrdering() == EOrder::kVisual
                                         ? CSSValueID::kVisual
@@ -7490,7 +7200,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetRubyPosition());
 }
@@ -7515,7 +7224,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::CurrentColorOrValidColor(
       style, style.TapHighlightColor());
@@ -7525,7 +7233,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.TextCombine() == ETextCombine::kAll)
     return CSSIdentifierValue::Create(CSSValueID::kHorizontal);
@@ -7544,7 +7251,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::RenderTextDecorationFlagsToCSSValue(
       style.TextDecorationsInEffect());
@@ -7568,7 +7274,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::CurrentColorOrValidColor(
       style, style.TextEmphasisColor());
@@ -7628,7 +7333,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   switch (style.GetTextEmphasisPosition()) {
@@ -7691,7 +7395,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   switch (style.GetTextEmphasisMark()) {
     case TextEmphasisMark::kNone:
@@ -7796,7 +7499,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::CurrentColorOrValidColor(style,
                                                       style.TextFillColor());
@@ -7806,7 +7508,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.GetTextOrientation() == ETextOrientation::kMixed)
     return CSSIdentifierValue::Create(CSSValueID::kVerticalRight);
@@ -7823,7 +7524,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.TextSecurity());
 }
@@ -7846,7 +7546,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::CurrentColorOrValidColor(style,
                                                       style.TextStrokeColor());
@@ -7865,7 +7564,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.TextStrokeWidth(), style);
 }
@@ -7900,7 +7598,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.UserDrag());
 }
@@ -7909,7 +7606,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.UserModify());
 }
@@ -7918,7 +7614,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetWritingMode());
 }
@@ -7933,7 +7628,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.WhiteSpace());
 }
@@ -7948,7 +7642,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.Widows(),
                                         CSSPrimitiveValue::UnitType::kNumber);
@@ -7970,7 +7663,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node*,
     bool allow_visited_style) const {
   if (ComputedStyleUtils::WidthOrHeightShouldReturnUsedValue(layout_object)) {
     return ZoomAdjustedPixelValue(
@@ -8041,7 +7733,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForWillChange(
       style.WillChangeProperties(), style.WillChangeContents(),
@@ -8102,7 +7793,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.WordBreak());
 }
@@ -8118,7 +7808,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ZoomAdjustedPixelValue(style.WordSpacing(), style);
 }
@@ -8127,7 +7816,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSIdentifierValue::Create(style.GetWritingMode());
 }
@@ -8149,7 +7837,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(svg_style.X(),
                                                              style);
@@ -8166,7 +7853,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle& svg_style,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ZoomAdjustedPixelValueForLength(svg_style.Y(),
                                                              style);
@@ -8184,7 +7870,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   if (style.HasAutoZIndex() || !style.IsStackingContext())
     return CSSIdentifierValue::Create(CSSValueID::kAuto);
@@ -8223,7 +7908,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return CSSNumericLiteralValue::Create(style.Zoom(),
                                         CSSPrimitiveValue::UnitType::kNumber);
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
index e60f650..8dd364f 100644
--- a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
@@ -105,7 +105,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const CSSAnimationData* animation_data = style.Animations();
   if (animation_data) {
@@ -172,10 +171,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
-  return ComputedStyleUtils::ValuesForBackgroundShorthand(
-      style, layout_object, styled_node, allow_visited_style);
+  return ComputedStyleUtils::ValuesForBackgroundShorthand(style, layout_object,
+                                                          allow_visited_style);
 }
 
 bool BackgroundPosition::ParseShorthand(
@@ -211,7 +209,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::BackgroundPositionOrWebkitMaskPosition(
       *this, style, &style.BackgroundLayers());
@@ -251,7 +248,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::BackgroundRepeatOrWebkitMaskRepeat(
       &style.BackgroundLayers());
@@ -271,11 +267,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      borderBlockColorShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderBlockColorShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderBlock::ParseShorthand(
@@ -307,14 +301,13 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   const CSSValue* value_start =
       GetCSSPropertyBorderBlockStart().CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+          style, layout_object, allow_visited_style);
   const CSSValue* value_end =
       GetCSSPropertyBorderBlockEnd().CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+          style, layout_object, allow_visited_style);
   if (!DataEquivalent(value_start, value_end)) {
     return nullptr;
   }
@@ -355,11 +348,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      borderBlockStyleShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderBlockStyleShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderBlockWidth::ParseShorthand(
@@ -376,11 +367,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      borderBlockWidthShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderBlockWidthShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderBottom::ParseShorthand(
@@ -397,11 +386,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      borderBottomShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderBottomShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderColor::ParseShorthand(
@@ -418,11 +405,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForSidesShorthand(
-      borderColorShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderColorShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool Border::ParseShorthand(
@@ -457,16 +442,15 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   const CSSValue* value = GetCSSPropertyBorderTop().CSSValueFromComputedStyle(
-      style, layout_object, styled_node, allow_visited_style);
+      style, layout_object, allow_visited_style);
   static const CSSProperty* kProperties[3] = {&GetCSSPropertyBorderRight(),
                                               &GetCSSPropertyBorderBottom(),
                                               &GetCSSPropertyBorderLeft()};
   for (size_t i = 0; i < base::size(kProperties); ++i) {
     const CSSValue* value_for_side = kProperties[i]->CSSValueFromComputedStyle(
-        style, layout_object, styled_node, allow_visited_style);
+        style, layout_object, allow_visited_style);
     if (!DataEquivalent(value, value_for_side)) {
       return nullptr;
     }
@@ -533,7 +517,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImage(style.BorderImage(), style);
 }
@@ -552,11 +535,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      borderInlineColorShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderInlineColorShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderInline::ParseShorthand(
@@ -588,14 +569,13 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   const CSSValue* value_start =
       GetCSSPropertyBorderInlineStart().CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+          style, layout_object, allow_visited_style);
   const CSSValue* value_end =
       GetCSSPropertyBorderInlineEnd().CSSValueFromComputedStyle(
-          style, layout_object, styled_node, allow_visited_style);
+          style, layout_object, allow_visited_style);
   if (!DataEquivalent(value_start, value_end)) {
     return nullptr;
   }
@@ -636,11 +616,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      borderInlineStyleShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderInlineStyleShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderInlineWidth::ParseShorthand(
@@ -657,11 +635,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      borderInlineWidthShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderInlineWidthShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderLeft::ParseShorthand(
@@ -678,11 +654,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      borderLeftShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderLeftShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderRadius::ParseShorthand(
@@ -734,7 +708,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForBorderRadiusShorthand(style);
 }
@@ -753,11 +726,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      borderRightShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderRightShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderSpacing::ParseShorthand(
@@ -796,7 +767,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   list->Append(*ZoomAdjustedPixelValue(style.HorizontalBorderSpacing(), style));
@@ -818,11 +788,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForSidesShorthand(
-      borderStyleShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderStyleShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderTop::ParseShorthand(
@@ -839,11 +807,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      borderTopShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderTopShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool BorderWidth::ParseShorthand(
@@ -860,11 +826,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForSidesShorthand(
-      borderWidthShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      borderWidthShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool ColumnRule::ParseShorthand(
@@ -881,11 +845,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      columnRuleShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      columnRuleShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool Columns::ParseShorthand(
@@ -922,11 +884,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      columnsShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      columnsShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool Flex::ParseShorthand(bool important,
@@ -1014,10 +974,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      flexShorthand(), style, layout_object, styled_node, allow_visited_style);
+      flexShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool FlexFlow::ParseShorthand(
@@ -1034,11 +993,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      flexFlowShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      flexFlowShorthand(), style, layout_object, allow_visited_style);
 }
 namespace {
 
@@ -1275,7 +1232,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForFont(style);
 }
@@ -1385,10 +1341,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
-  return ComputedStyleUtils::ValuesForFontVariantProperty(
-      style, layout_object, styled_node, allow_visited_style);
+  return ComputedStyleUtils::ValuesForFontVariantProperty(style, layout_object,
+                                                          allow_visited_style);
 }
 
 bool Gap::ParseShorthand(bool important,
@@ -1418,10 +1373,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      gapShorthand(), style, layout_object, styled_node, allow_visited_style);
+      gapShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool GridArea::ParseShorthand(
@@ -1497,11 +1451,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
-  return ComputedStyleUtils::ValuesForGridShorthand(gridAreaShorthand(), style,
-                                                    layout_object, styled_node,
-                                                    allow_visited_style);
+  return ComputedStyleUtils::ValuesForGridShorthand(
+      gridAreaShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool GridColumn::ParseShorthand(
@@ -1539,11 +1491,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForGridShorthand(
-      gridColumnShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      gridColumnShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool GridColumnGap::ParseShorthand(
@@ -1567,11 +1517,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      gridColumnGapShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      gridColumnGapShorthand(), style, layout_object, allow_visited_style);
 }
 
 namespace {
@@ -1762,10 +1710,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForGridShorthand(
-      gridShorthand(), style, layout_object, styled_node, allow_visited_style);
+      gridShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool GridGap::ParseShorthand(
@@ -1796,11 +1743,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      gridGapShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      gridGapShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool GridRow::ParseShorthand(
@@ -1838,11 +1783,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
-  return ComputedStyleUtils::ValuesForGridShorthand(gridRowShorthand(), style,
-                                                    layout_object, styled_node,
-                                                    allow_visited_style);
+  return ComputedStyleUtils::ValuesForGridShorthand(
+      gridRowShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool GridRowGap::ParseShorthand(
@@ -1866,11 +1809,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      gridRowGapShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      gridRowGapShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool GridTemplate::ParseShorthand(
@@ -1919,11 +1860,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForGridShorthand(
-      gridTemplateShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      gridTemplateShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool InsetBlock::ParseShorthand(
@@ -1940,11 +1879,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      insetBlockShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      insetBlockShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool Inset::ParseShorthand(
@@ -1961,10 +1898,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForSidesShorthand(
-      insetShorthand(), style, layout_object, styled_node, allow_visited_style);
+      insetShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool InsetInline::ParseShorthand(
@@ -1981,11 +1917,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      insetInlineShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      insetInlineShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool ListStyle::ParseShorthand(
@@ -2080,11 +2014,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      listStyleShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      listStyleShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool MarginBlock::ParseShorthand(
@@ -2101,11 +2033,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      marginBlockShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      marginBlockShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool Margin::ParseShorthand(
@@ -2130,11 +2060,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
-  return ComputedStyleUtils::ValuesForSidesShorthand(marginShorthand(), style,
-                                                     layout_object, styled_node,
-                                                     allow_visited_style);
+  return ComputedStyleUtils::ValuesForSidesShorthand(
+      marginShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool MarginInline::ParseShorthand(
@@ -2151,11 +2079,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      marginInlineShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      marginInlineShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool Marker::ParseShorthand(
@@ -2302,9 +2228,8 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
-  return ComputedStyleUtils::ValueForOffset(style, layout_object, styled_node,
+  return ComputedStyleUtils::ValueForOffset(style, layout_object,
                                             allow_visited_style);
 }
 
@@ -2322,11 +2247,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      outlineShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      outlineShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool Overflow::ParseShorthand(
@@ -2343,7 +2266,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   list->Append(*CSSIdentifierValue::Create(style.OverflowX()));
@@ -2367,7 +2289,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   list->Append(*CSSIdentifierValue::Create(style.OverscrollBehaviorX()));
@@ -2391,11 +2312,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      paddingBlockShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      paddingBlockShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool Padding::ParseShorthand(
@@ -2420,11 +2339,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
-  return ComputedStyleUtils::ValuesForSidesShorthand(paddingShorthand(), style,
-                                                     layout_object, styled_node,
-                                                     allow_visited_style);
+  return ComputedStyleUtils::ValuesForSidesShorthand(
+      paddingShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool PaddingInline::ParseShorthand(
@@ -2441,11 +2358,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      paddingInlineShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      paddingInlineShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool PageBreakAfter::ParseShorthand(
@@ -2472,7 +2387,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForPageBreakBetween(style.BreakAfter());
 }
@@ -2501,7 +2415,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForPageBreakBetween(style.BreakBefore());
 }
@@ -2529,7 +2442,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForPageBreakInside(style.BreakInside());
 }
@@ -2589,11 +2501,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForPlaceShorthand(
-      placeContentShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      placeContentShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool PlaceItems::ParseShorthand(
@@ -2641,11 +2551,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForPlaceShorthand(
-      placeItemsShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      placeItemsShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool PlaceSelf::ParseShorthand(
@@ -2692,11 +2600,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForPlaceShorthand(
-      placeSelfShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      placeSelfShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool ScrollMarginBlock::ParseShorthand(
@@ -2713,11 +2619,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      scrollMarginBlockShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      scrollMarginBlockShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool ScrollMargin::ParseShorthand(
@@ -2734,11 +2638,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForSidesShorthand(
-      scrollMarginShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      scrollMarginShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool ScrollMarginInline::ParseShorthand(
@@ -2755,11 +2657,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      scrollMarginInlineShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      scrollMarginInlineShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool ScrollPaddingBlock::ParseShorthand(
@@ -2776,11 +2676,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      scrollPaddingBlockShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      scrollPaddingBlockShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool ScrollPadding::ParseShorthand(
@@ -2797,11 +2695,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForSidesShorthand(
-      scrollPaddingShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      scrollPaddingShorthand(), style, layout_object, allow_visited_style);
 }
 
 bool ScrollPaddingInline::ParseShorthand(
@@ -2818,10 +2714,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForInlineBlockShorthand(
-      scrollPaddingInlineShorthand(), style, layout_object, styled_node,
+      scrollPaddingInlineShorthand(), style, layout_object,
       allow_visited_style);
 }
 
@@ -2839,11 +2734,9 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject* layout_object,
-    const Node* styled_node,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValuesForShorthandProperty(
-      textDecorationShorthand(), style, layout_object, styled_node,
-      allow_visited_style);
+      textDecorationShorthand(), style, layout_object, allow_visited_style);
 }
 
 namespace {
@@ -2909,7 +2802,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   const CSSTransitionData* transition_data = style.Transitions();
   if (transition_data) {
@@ -2969,7 +2861,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForWebkitColumnBreakBetween(
       style.BreakAfter());
@@ -2998,7 +2889,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForWebkitColumnBreakBetween(
       style.BreakBefore());
@@ -3027,7 +2917,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForWebkitColumnBreakInside(
       style.BreakInside());
@@ -3128,7 +3017,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::ValueForNinePieceImage(style.MaskBoxImage(),
                                                     style);
@@ -3177,7 +3065,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::BackgroundPositionOrWebkitMaskPosition(
       *this, style, &style.MaskLayers());
@@ -3217,7 +3104,6 @@
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
-    const Node*,
     bool allow_visited_style) const {
   return ComputedStyleUtils::BackgroundRepeatOrWebkitMaskRepeat(
       &style.MaskLayers());
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index 0916cf8..77d89f3 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -356,8 +356,11 @@
   // Blockify the children of flex, grid or LayoutCustom containers.
   if (layout_parent_style.BlockifiesChildren()) {
     style.SetIsInBlockifyingDisplay();
-    if (style.Display() != EDisplay::kContents)
+    if (style.Display() != EDisplay::kContents) {
       style.SetDisplay(EquivalentBlockDisplay(style.Display()));
+      if (!style.HasOutOfFlowPosition())
+        style.SetIsFlexOrGridOrCustomItem();
+    }
   }
 
   if (style.Display() == EDisplay::kBlock && !style.IsFloating())
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
index af7d9d24..5d9a62db 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -140,7 +140,7 @@
     const LayoutObject* layout_object = nullptr;
     bool allow_visited_style = false;
     const CSSValue* value = ref.GetProperty().CSSValueFromComputedStyle(
-        *state_.Style(), layout_object, Body(), allow_visited_style);
+        *state_.Style(), layout_object, allow_visited_style);
     return value ? value->CssText() : g_null_atom;
   }
 
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index e645ba9..03330bf 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -2335,6 +2335,41 @@
   font_builder.CreateFontForDocument(selector, document_style);
 }
 
+#define PROPAGATE_FROM(source, getter, setter, initial) \
+  PROPAGATE_VALUE(source ? source->getter() : initial, getter, setter);
+
+#define PROPAGATE_VALUE(value, getter, setter)     \
+  if ((new_viewport_style->getter()) != (value)) { \
+    new_viewport_style->setter(value);             \
+    changed = true;                                \
+  }
+
+bool PropagateScrollSnapStyleToViewport(
+    Document& document,
+    const ComputedStyle* document_element_style,
+    scoped_refptr<ComputedStyle> new_viewport_style) {
+  bool changed = false;
+  // We only propagate the properties related to snap container since viewport
+  // defining element cannot be a snap area.
+  PROPAGATE_FROM(document_element_style, GetScrollSnapType, SetScrollSnapType,
+                 cc::ScrollSnapType());
+  PROPAGATE_FROM(document_element_style, ScrollPaddingTop, SetScrollPaddingTop,
+                 Length());
+  PROPAGATE_FROM(document_element_style, ScrollPaddingRight,
+                 SetScrollPaddingRight, Length());
+  PROPAGATE_FROM(document_element_style, ScrollPaddingBottom,
+                 SetScrollPaddingBottom, Length());
+  PROPAGATE_FROM(document_element_style, ScrollPaddingLeft,
+                 SetScrollPaddingLeft, Length());
+
+  if (changed) {
+    document.GetSnapCoordinator()->SnapContainerDidChange(
+        *document.GetLayoutView(), false /* is_removed */);
+  }
+
+  return changed;
+}
+
 void Document::PropagateStyleToViewport() {
   DCHECK(InStyleRecalc());
   HTMLElement* body = this->body();
@@ -2352,15 +2387,6 @@
       ComputedStyle::Clone(viewport_style);
   bool changed = false;
 
-#define PROPAGATE_FROM(source, getter, setter, initial) \
-  PROPAGATE_VALUE(source ? source->getter() : initial, getter, setter);
-
-#define PROPAGATE_VALUE(value, getter, setter)     \
-  if ((new_viewport_style->getter()) != (value)) { \
-    new_viewport_style->setter(value);             \
-    changed = true;                                \
-  }
-
   // Writing mode and direction
   {
     const ComputedStyle* direction_style =
@@ -2440,23 +2466,9 @@
       }
     }
 
-    // TODO(954423, 952711): scroll-snap-* and overscroll-behavior (and most
-    // likely overflow-anchor) should be propagated from the document element
-    // and not the viewport defining element.
-
-    // We only propagate the properties related to snap container since viewport
-    // defining element cannot be a snap area.
-    PROPAGATE_FROM(overflow_style, GetScrollSnapType, SetScrollSnapType,
-                   cc::ScrollSnapType());
-    PROPAGATE_FROM(overflow_style, ScrollPaddingTop, SetScrollPaddingTop,
-                   Length());
-    PROPAGATE_FROM(overflow_style, ScrollPaddingRight, SetScrollPaddingRight,
-                   Length());
-    PROPAGATE_FROM(overflow_style, ScrollPaddingBottom, SetScrollPaddingBottom,
-                   Length());
-    PROPAGATE_FROM(overflow_style, ScrollPaddingLeft, SetScrollPaddingLeft,
-                   Length());
-
+    // TODO(954423, 952711): overscroll-behavior (and most likely
+    // overflow-anchor) should be propagated from documet element and not the
+    // viewport defining element.
     PROPAGATE_FROM(overflow_style, OverscrollBehaviorX, SetOverscrollBehaviorX,
                    EOverscrollBehavior::kAuto);
     PROPAGATE_FROM(overflow_style, OverscrollBehaviorY, SetOverscrollBehaviorY,
@@ -2533,6 +2545,9 @@
                    false);
   }
 
+  changed |= PropagateScrollSnapStyleToViewport(*this, document_element_style,
+                                                new_viewport_style);
+
   if (changed) {
     new_viewport_style->UpdateFontOrientation();
     GetLayoutView()->SetStyle(new_viewport_style);
@@ -2548,10 +2563,9 @@
         scrollable_area->VerticalScrollbar()->StyleChanged();
     }
   }
-
+}
 #undef PROPAGATE_VALUE
 #undef PROPAGATE_FROM
-}
 
 #if DCHECK_IS_ON()
 static void AssertLayoutTreeUpdated(Node& root) {
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc
index 3238df8..323bd90 100644
--- a/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -44,21 +44,13 @@
 
 enum Milestone {
   kUnknown,
-  kM60,
   kM61,
   kM62,
-  kM63,
   kM64,
   kM65,
-  kM66,
-  kM67,
-  kM68,
-  kM69,
   kM70,
   kM71,
   kM72,
-  kM73,
-  kM74,
   kM75,
   kM76,
   kM77,
@@ -75,36 +67,20 @@
   switch (milestone) {
     case kUnknown:
       return "";
-    case kM60:
-      return "M60, around August 2017";
     case kM61:
       return "M61, around September 2017";
     case kM62:
       return "M62, around October 2017";
-    case kM63:
-      return "M63, around December 2017";
     case kM64:
       return "M64, around January 2018";
     case kM65:
       return "M65, around March 2018";
-    case kM66:
-      return "M66, around April 2018";
-    case kM67:
-      return "M67, around May 2018";
-    case kM68:
-      return "M68, around July 2018";
-    case kM69:
-      return "M69, around September 2018";
     case kM70:
       return "M70, around October 2018";
     case kM71:
       return "M71, around December 2018";
     case kM72:
       return "M72, around January 2019";
-    case kM73:
-      return "M73, around March 2019";
-    case kM74:
-      return "M74, around April 2019";
     case kM75:
       return "M75, around June 2019";
     case kM76:
@@ -132,36 +108,20 @@
   switch (milestone) {
     case kUnknown:
       return 0;
-    case kM60:
-      return 1500955200000;  // July 25, 2017.
     case kM61:
       return 1504584000000;  // September 5, 2017.
     case kM62:
       return 1508212800000;  // October 17, 2017.
-    case kM63:
-      return 1512450000000;  // December 5, 2017.
     case kM64:
       return 1516683600000;  // January 23, 2018.
     case kM65:
       return 1520312400000;  // March 6, 2018.
-    case kM66:
-      return 1523937600000;  // April 17, 2018.
-    case kM67:
-      return 1527566400000;  // May 29, 2018.
-    case kM68:
-      return 1532404800000;  // July 24, 2018.
-    case kM69:
-      return 1536033600000;  // September 4, 2018.
     case kM70:
       return 1539662400000;  // October 16, 2018.
     case kM71:
       return 1543899600000;  // December 4, 2018.
     case kM72:
       return 1548734400000;  // January 29, 2019.
-    case kM73:
-      return 1552363200000;  // March 12, 2019.
-    case kM74:
-      return 1555992000000;  // April 23, 2019.
     case kM75:
       return 1559620800000;  // June 4, 2019.
     case kM76:
diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc
index 06e790f..2eb0735 100644
--- a/third_party/blink/renderer/core/frame/location.cc
+++ b/third_party/blink/renderer/core/frame/location.cc
@@ -201,7 +201,10 @@
   if (hash[0] == '#')
     new_fragment_identifier = hash.Substring(1);
   url.SetFragmentIdentifier(new_fragment_identifier);
-  if (old_fragment_identifier == url.FragmentIdentifier())
+  // Note that by parsing the URL and *then* comparing fragments, we are
+  // comparing fragments post-canonicalization, and so this handles the
+  // cases where fragment identifiers are ignored or invalid.
+  if (EqualIgnoringNullity(old_fragment_identifier, url.FragmentIdentifier()))
     return;
   SetLocation(url.GetString(), IncumbentDOMWindow(isolate),
               EnteredDOMWindow(isolate), &exception_state);
diff --git a/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc b/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc
index 8b37c16..e9dfcdc7a 100644
--- a/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc
+++ b/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc
@@ -121,9 +121,15 @@
 
   AddString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data);
   data->Append(Platform::Current()->GetDataResource("pickerCommon.css"));
-  data->Append(Platform::Current()->GetDataResource("pickerButton.css"));
+  if (!RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
+    data->Append(Platform::Current()->GetDataResource("pickerButton.css"));
+  }
   data->Append(Platform::Current()->GetDataResource("suggestionPicker.css"));
   data->Append(Platform::Current()->GetDataResource("calendarPicker.css"));
+  if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
+    data->Append(
+        Platform::Current()->GetDataResource("calendar_picker_refresh.css"));
+  }
   AddString(
       "</style></head><body><div id=main>Loading...</div><script>\n"
       "window.dialogArguments = {\n",
@@ -169,6 +175,8 @@
   AddProperty("dayLabels", locale_->WeekDayShortLabels(), data);
   AddProperty("isLocaleRTL", locale_->IsRTL(), data);
   AddProperty("isRTL", parameters_->is_anchor_element_rtl, data);
+  AddProperty("isFormControlsRefreshEnabled",
+              RuntimeEnabledFeatures::FormControlsRefreshEnabled(), data);
   AddProperty("mode", parameters_->type.GetString(), data);
   if (parameters_->suggestions.size()) {
     Vector<String> suggestion_values;
diff --git a/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js b/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
index 85fafbf..2eaf4bce 100644
--- a/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
+++ b/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
@@ -46,6 +46,7 @@
     dayLabels: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
     shortMonthLabels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
     isLocaleRTL: false,
+    isFormControlsRefreshEnabled: false,
     mode: 'date',
     weekLabel: 'Week',
     anchorRectInScreen: new Rectangle(0, 0, 0, 0),
@@ -2914,7 +2915,7 @@
    * @type {!MonthPopupButton}
    */
   this.monthPopupButton = new MonthPopupButton(
-      this.calendarPicker.calendarTableView.width() - CalendarTableView.BorderWidth * 2 -
+      this.calendarPicker.calendarTableView.width() - CalendarTableView.GetBorderWidth() * 2 -
       CalendarNavigationButton.Width * 3 - CalendarNavigationButton.LeftMargin * 2);
   this.monthPopupButton.attachTo(titleElement);
 
@@ -2928,19 +2929,21 @@
   this._previousMonthButton.on(CalendarNavigationButton.EventTypeRepeatingButtonClick, this.onNavigationButtonClick);
   this._previousMonthButton.element.setAttribute('aria-label', global.params.axShowPreviousMonth);
 
-  /**
-   * @type {!CalendarNavigationButton}
-   * @const
-   */
-  this._todayButton = new CalendarNavigationButton();
-  this._todayButton.attachTo(this);
-  this._todayButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onNavigationButtonClick);
-  this._todayButton.element.classList.add(CalendarHeaderView.ClassNameTodayButton);
-  var monthContainingToday = Month.createFromToday();
-  this._todayButton.setDisabled(
-      monthContainingToday < this.calendarPicker.minimumMonth ||
-      monthContainingToday > this.calendarPicker.maximumMonth);
-  this._todayButton.element.setAttribute('aria-label', global.params.todayLabel);
+  if (!global.params.isFormControlsRefreshEnabled) {
+    /**
+     * @type {!CalendarNavigationButton}
+     * @const
+     */
+    this._todayButton = new CalendarNavigationButton();
+    this._todayButton.attachTo(this);
+    this._todayButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onNavigationButtonClick);
+    this._todayButton.element.classList.add(CalendarHeaderView.GetClassNameTodayButton());
+    var monthContainingToday = Month.createFromToday();
+    this._todayButton.setDisabled(
+        monthContainingToday < this.calendarPicker.minimumMonth ||
+        monthContainingToday > this.calendarPicker.maximumMonth);
+    this._todayButton.element.setAttribute('aria-label', global.params.todayLabel);
+  }
 
   /**
    * @type {!CalendarNavigationButton}
@@ -2953,11 +2956,11 @@
   this._nextMonthButton.element.setAttribute('aria-label', global.params.axShowNextMonth);
 
   if (global.params.isLocaleRTL) {
-    this._nextMonthButton.element.innerHTML = CalendarHeaderView._BackwardTriangle;
-    this._previousMonthButton.element.innerHTML = CalendarHeaderView._ForwardTriangle;
+    this._nextMonthButton.element.innerHTML = CalendarHeaderView.GetBackwardTriangle();
+    this._previousMonthButton.element.innerHTML = CalendarHeaderView.GetForwardTriangle();
   } else {
-    this._nextMonthButton.element.innerHTML = CalendarHeaderView._ForwardTriangle;
-    this._previousMonthButton.element.innerHTML = CalendarHeaderView._BackwardTriangle;
+    this._nextMonthButton.element.innerHTML = CalendarHeaderView.GetForwardTriangle();
+    this._previousMonthButton.element.innerHTML = CalendarHeaderView.GetBackwardTriangle();
   }
 }
 
@@ -2967,11 +2970,38 @@
 CalendarHeaderView.BottomMargin = 10;
 CalendarHeaderView._ForwardTriangle =
     '<svg width=\'4\' height=\'7\'><polygon points=\'0,7 0,0, 4,3.5\' style=\'fill:#6e6e6e;\' /></svg>';
+CalendarHeaderView._ForwardTriangleRefresh =
+    '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\
+    <path d=\"M15.3516 8.60156L8 15.9531L0.648438 8.60156L1.35156 7.89844L7.5 14.0469V0H8.5V14.0469L14.6484 7.89844L15.3516 8.60156Z\" fill=\"#101010\"/>\
+    </svg>'
+CalendarHeaderView.GetForwardTriangle = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return CalendarHeaderView._ForwardTriangleRefresh;
+  }
+  return CalendarHeaderView._ForwardTriangle;
+}
 CalendarHeaderView._BackwardTriangle =
     '<svg width=\'4\' height=\'7\'><polygon points=\'0,3.5 4,7 4,0\' style=\'fill:#6e6e6e;\' /></svg>';
+CalendarHeaderView._BackwardTriangleRefresh =
+    '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\
+    <path d=\"M14.6484 8.10156L8.5 1.95312V16H7.5V1.95312L1.35156 8.10156L0.648438 7.39844L8 0.046875L15.3516 7.39844L14.6484 8.10156Z\" fill=\"#101010\"/>\
+    </svg>'
+CalendarHeaderView.GetBackwardTriangle = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return CalendarHeaderView._BackwardTriangleRefresh;
+  }
+  return CalendarHeaderView._BackwardTriangle;
+}
 CalendarHeaderView.ClassNameCalendarHeaderView = 'calendar-header-view';
 CalendarHeaderView.ClassNameCalendarTitle = 'calendar-title';
 CalendarHeaderView.ClassNameTodayButton = 'today-button';
+CalendarHeaderView.ClassNameTodayButtonRefresh = 'today-button-refresh';
+CalendarHeaderView.GetClassNameTodayButton = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return CalendarHeaderView.ClassNameTodayButtonRefresh;
+  }
+  return CalendarHeaderView.ClassNameTodayButton;
+}
 
 CalendarHeaderView.prototype.onCurrentMonthChanged = function() {
   this.monthPopupButton.setCurrentMonth(this.calendarPicker.currentMonth());
@@ -2997,15 +3027,22 @@
  */
 CalendarHeaderView.prototype.setDisabled = function(disabled) {
   this.disabled = disabled;
+  if (global.params.isFormControlsRefreshEnabled) {
+    this._previousMonthButton.element.style.visibility = this.disabled ? 'hidden' : 'visible';
+    this._nextMonthButton.element.style.visibility = this.disabled ? 'hidden' : 'visible';
+  }
+
   this.monthPopupButton.element.disabled = this.disabled;
   this._previousMonthButton.setDisabled(
       this.disabled || this.calendarPicker.currentMonth() <= this.calendarPicker.minimumMonth);
   this._nextMonthButton.setDisabled(
       this.disabled || this.calendarPicker.currentMonth() >= this.calendarPicker.maximumMonth);
-  var monthContainingToday = Month.createFromToday();
-  this._todayButton.setDisabled(
-      this.disabled || monthContainingToday < this.calendarPicker.minimumMonth ||
-      monthContainingToday > this.calendarPicker.maximumMonth);
+  if (this._todayButton) {
+    var monthContainingToday = Month.createFromToday();
+    this._todayButton.setDisabled(
+        this.disabled || monthContainingToday < this.calendarPicker.minimumMonth ||
+        monthContainingToday > this.calendarPicker.maximumMonth);
+  }
 };
 
 /**
@@ -3015,9 +3052,9 @@
 function DayCell() {
   ListCell.call(this);
   this.element.classList.add(DayCell.ClassNameDayCell);
-  this.element.style.width = DayCell.Width + 'px';
-  this.element.style.height = DayCell.Height + 'px';
-  this.element.style.lineHeight = (DayCell.Height - DayCell.PaddingSize * 2) + 'px';
+  this.element.style.width = DayCell.GetWidth() + 'px';
+  this.element.style.height = DayCell.GetHeight() + 'px';
+  this.element.style.lineHeight = (DayCell.GetHeight() - DayCell.PaddingSize * 2) + 'px';
   this.element.setAttribute('role', 'gridcell');
   /**
    * @type {?Day}
@@ -3027,8 +3064,22 @@
 
 DayCell.prototype = Object.create(ListCell.prototype);
 
-DayCell.Width = 34;
-DayCell.Height = hasInaccuratePointingDevice() ? 34 : 20;
+DayCell._Width = 34;
+DayCell._WidthRefresh = 28;
+DayCell.GetWidth = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return DayCell._WidthRefresh;
+  }
+  return DayCell._Width;
+}
+DayCell._Height = hasInaccuratePointingDevice() ? 34 : 20;
+DayCell._HeightRefresh = 28;
+DayCell.GetHeight = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return DayCell._HeightRefresh;
+  }
+  return DayCell._Height;
+}
 DayCell.PaddingSize = 1;
 DayCell.ClassNameDayCell = 'day-cell';
 DayCell.ClassNameHighlighted = 'highlighted';
@@ -3120,8 +3171,8 @@
   ListCell.call(this);
   this.element.classList.add(WeekNumberCell.ClassNameWeekNumberCell);
   this.element.style.width = (WeekNumberCell.Width - WeekNumberCell.SeparatorWidth) + 'px';
-  this.element.style.height = WeekNumberCell.Height + 'px';
-  this.element.style.lineHeight = (WeekNumberCell.Height - WeekNumberCell.PaddingSize * 2) + 'px';
+  this.element.style.height = WeekNumberCell.GetHeight() + 'px';
+  this.element.style.lineHeight = (WeekNumberCell.GetHeight() - WeekNumberCell.PaddingSize * 2) + 'px';
   /**
    * @type {?Week}
    */
@@ -3131,7 +3182,14 @@
 WeekNumberCell.prototype = Object.create(ListCell.prototype);
 
 WeekNumberCell.Width = 48;
-WeekNumberCell.Height = DayCell.Height;
+WeekNumberCell._Height = DayCell._Height;
+WeekNumberCell._HeightRefresh = DayCell._HeightRefresh;
+WeekNumberCell.GetHeight = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return WeekNumberCell._HeightRefresh;
+  }
+  return WeekNumberCell._Height;
+}
 WeekNumberCell.SeparatorWidth = 1;
 WeekNumberCell.PaddingSize = 1;
 WeekNumberCell.ClassNameWeekNumberCell = 'week-number-cell';
@@ -3208,7 +3266,7 @@
   for (var i = 0; i < DaysPerWeek; ++i) {
     var weekDayNumber = (global.params.weekStartDay + i) % DaysPerWeek;
     var labelElement = createElement('div', 'week-day-label', global.params.dayLabels[weekDayNumber]);
-    labelElement.style.width = DayCell.Width + 'px';
+    labelElement.style.width = DayCell.GetWidth() + 'px';
     this.element.appendChild(labelElement);
     if (getLanguage() === 'ja') {
       if (weekDayNumber === 0)
@@ -3221,7 +3279,14 @@
 
 CalendarTableHeaderView.prototype = Object.create(View.prototype);
 
-CalendarTableHeaderView.Height = 25;
+CalendarTableHeaderView._Height = 25;
+CalendarTableHeaderView._HeightRefresh = 29;
+CalendarTableHeaderView.GetHeight = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return CalendarTableHeaderView._HeightRefresh;
+  }
+  return CalendarTableHeaderView._Height;
+}
 
 /**
  * @constructor
@@ -3230,7 +3295,7 @@
 function CalendarRowCell() {
   ListCell.call(this);
   this.element.classList.add(CalendarRowCell.ClassNameCalendarRowCell);
-  this.element.style.height = CalendarRowCell.Height + 'px';
+  this.element.style.height = CalendarRowCell.GetHeight() + 'px';
   this.element.setAttribute('role', 'row');
 
   /**
@@ -3250,7 +3315,14 @@
 
 CalendarRowCell.prototype = Object.create(ListCell.prototype);
 
-CalendarRowCell.Height = DayCell.Height;
+CalendarRowCell._Height = DayCell._Height;
+CalendarRowCell._HeightRefresh = DayCell._HeightRefresh;
+CalendarRowCell.GetHeight = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return CalendarRowCell._HeightRefresh;
+  }
+  return CalendarRowCell._Height;
+}
 CalendarRowCell.ClassNameCalendarRowCell = 'calendar-row-cell';
 
 CalendarRowCell._recycleBin = [];
@@ -3325,15 +3397,33 @@
   var headerView = new CalendarTableHeaderView(this.hasWeekNumberColumn);
   headerView.attachTo(this, this.scrollView);
 
+  if (global.params.isFormControlsRefreshEnabled) {
+    /**
+     * @type {!CalendarNavigationButton}
+     * @const
+     */
+    var todayButton = new CalendarNavigationButton();
+    todayButton.attachTo(this);
+    todayButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onTodayButtonClick);
+    todayButton.element.textContent = global.params.todayLabel;
+    todayButton.element.classList.add(CalendarHeaderView.GetClassNameTodayButton());
+    var monthContainingToday = Month.createFromToday();
+    todayButton.setDisabled(
+        monthContainingToday < this.calendarPicker.minimumMonth ||
+        monthContainingToday > this.calendarPicker.maximumMonth);
+    todayButton.element.setAttribute('aria-label', global.params.todayLabel);
+  }
+
+
   if (this.hasWeekNumberColumn) {
-    this.setWidth(DayCell.Width * DaysPerWeek + WeekNumberCell.Width);
+    this.setWidth(DayCell.GetWidth() * DaysPerWeek + WeekNumberCell.Width);
     /**
      * @type {?Array}
      * @const
      */
     this._weekNumberCells = [];
   } else {
-    this.setWidth(DayCell.Width * DaysPerWeek);
+    this.setWidth(DayCell.GetWidth() * DaysPerWeek);
   }
 
   /**
@@ -3354,7 +3444,22 @@
 
 CalendarTableView.prototype = Object.create(ListView.prototype);
 
-CalendarTableView.BorderWidth = 1;
+CalendarTableView._BorderWidth = 1;
+CalendarTableView._BorderWidthRefresh = 0;
+CalendarTableView.GetBorderWidth = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return CalendarTableView._BorderWidthRefresh;
+  }
+  return CalendarTableView._BorderWidth;
+}
+CalendarTableView._TodayButtonHeight = 0;
+CalendarTableView._TodayButtonHeightRefresh = 28;
+CalendarTableView.GetTodayButtonHeight = function() {
+  if (global.params.isFormControlsRefreshEnabled) {
+    return CalendarTableView._TodayButtonHeightRefresh;
+  }
+  return CalendarTableView._TodayButtonHeight;
+}
 CalendarTableView.ClassNameCalendarTableView = 'calendar-table-view';
 
 /**
@@ -3362,7 +3467,7 @@
  * @return {!number}
  */
 CalendarTableView.prototype.rowAtScrollOffset = function(scrollOffset) {
-  return Math.floor(scrollOffset / CalendarRowCell.Height);
+  return Math.floor(scrollOffset / CalendarRowCell.GetHeight());
 };
 
 /**
@@ -3370,7 +3475,7 @@
  * @return {!number}
  */
 CalendarTableView.prototype.scrollOffsetForRow = function(row) {
-  return row * CalendarRowCell.Height;
+  return row * CalendarRowCell.GetHeight();
 };
 
 /**
@@ -3392,6 +3497,10 @@
   this.calendarPicker.selectRangeContainingDay(dayCell.day);
 };
 
+CalendarTableView.prototype.onTodayButtonClick = function(sender) {
+  this.calendarPicker.selectRangeContainingDay(Day.createFromToday());
+}
+
 /**
  * @param {?Event} event
  */
@@ -3439,14 +3548,17 @@
  * @return {!number} Height in pixels.
  */
 CalendarTableView.prototype.height = function() {
-  return this.scrollView.height() + CalendarTableHeaderView.Height + CalendarTableView.BorderWidth * 2;
+  return this.scrollView.height() + CalendarTableHeaderView.GetHeight() + CalendarTableView.GetBorderWidth() * 2 + CalendarTableView.GetTodayButtonHeight();
 };
 
 /**
  * @param {!number} height Height in pixels.
  */
 CalendarTableView.prototype.setHeight = function(height) {
-  this.scrollView.setHeight(height - CalendarTableHeaderView.Height - CalendarTableView.BorderWidth * 2);
+  this.scrollView.setHeight(height - CalendarTableHeaderView.GetHeight() - CalendarTableView.GetBorderWidth() * 2 - CalendarTableView.GetTodayButtonHeight());
+  if (global.params.isFormControlsRefreshEnabled) {
+    this.element.style.height = height + 'px';
+  }
 };
 
 /**
@@ -3689,6 +3801,7 @@
 CalendarPicker.ClassNamePreparing = 'preparing';
 CalendarPicker.EventTypeCurrentMonthChanged = 'currentMonthChanged';
 CalendarPicker.commitDelayMs = 100;
+CalendarPicker.VisibleRowsRefresh = 6;
 
 /**
  * @param {!Event} event
@@ -3794,9 +3907,9 @@
 CalendarPicker.prototype.adjustHeight = function() {
   var rowForFirstDayInMonth = this.calendarTableView.columnAndRowForDay(this._currentMonth.firstDay()).row;
   var rowForLastDayInMonth = this.calendarTableView.columnAndRowForDay(this._currentMonth.lastDay()).row;
-  var numberOfRows = rowForLastDayInMonth - rowForFirstDayInMonth + 1;
+  var numberOfRows = global.params.isFormControlsRefreshEnabled ? CalendarPicker.VisibleRowsRefresh : rowForLastDayInMonth - rowForFirstDayInMonth + 1;
   var calendarTableViewHeight =
-      CalendarTableHeaderView.Height + numberOfRows * DayCell.Height + CalendarTableView.BorderWidth * 2;
+      CalendarTableHeaderView.GetHeight() + numberOfRows * DayCell.GetHeight() + CalendarTableView.GetBorderWidth() * 2 + CalendarTableView.GetTodayButtonHeight();
   var height = (this.monthPopupView.isVisible ? YearListView.Height : calendarTableViewHeight) +
       CalendarHeaderView.Height + CalendarHeaderView.BottomMargin + CalendarPicker.Padding * 2 +
       CalendarPicker.BorderWidth * 2;
@@ -3827,6 +3940,9 @@
  */
 CalendarPicker.prototype.lastVisibleDay = function() {
   var lastVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().lastDay()).row;
+  if (global.params.isFormControlsRefreshEnabled) {
+    lastVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().firstDay()).row + CalendarPicker.VisibleRowsRefresh - 1;
+  }
   var lastVisibleDay = this.calendarTableView.dayAtColumnAndRow(DaysPerWeek - 1, lastVisibleRow);
   if (!lastVisibleDay)
     lastVisibleDay = Day.Maximum;
@@ -4019,7 +4135,7 @@
  */
 CalendarPicker.prototype.width = function() {
   return this.calendarTableView.width() +
-      (CalendarTableView.BorderWidth + CalendarPicker.BorderWidth + CalendarPicker.Padding) * 2;
+      (CalendarTableView.GetBorderWidth() + CalendarPicker.BorderWidth + CalendarPicker.Padding) * 2;
 };
 
 /**
@@ -4039,7 +4155,7 @@
   resizeWindow(this.width(), this._height);
   this.calendarTableView.setHeight(
       this._height - CalendarHeaderView.Height - CalendarHeaderView.BottomMargin - CalendarPicker.Padding * 2 -
-      CalendarTableView.BorderWidth * 2);
+      CalendarPicker.BorderWidth * 2);
 };
 
 /**
diff --git a/third_party/blink/renderer/core/html/forms/resources/calendar_picker_refresh.css b/third_party/blink/renderer/core/html/forms/resources/calendar_picker_refresh.css
new file mode 100644
index 0000000..270321a
--- /dev/null
+++ b/third_party/blink/renderer/core/html/forms/resources/calendar_picker_refresh.css
@@ -0,0 +1,118 @@
+/* Copyright (C) 2019 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+body {
+  font: 12px "Segoe UI", system-ui, Roboto, Ubuntu, sans-serif;
+}
+
+.calendar-picker {
+  background-color: #ffffff;
+  border-radius: 2px;
+}
+
+.calendar-table-view {
+  border: 0;
+}
+
+.calendar-table-header-view {
+  background-color: #ffffff;
+  border: 0;
+  height: 29px;
+}
+
+.week-day-label {
+  line-height: 28px;
+}
+
+.calendar-navigation-button {
+  -webkit-align-self: center;
+  background-color: #ffffff;
+  border: 0;
+  color: #101010;
+  padding: 0;
+  text-align: center;
+  width: 28px;
+}
+
+.calendar-navigation-button svg {
+  padding-top: 4px;
+}
+
+.calendar-navigation-button:hover {
+  background-color: #F3F3F3;
+}
+
+.calendar-navigation-button:disabled {
+  color: #C5C5C5;
+}
+
+.calendar-title {
+  -webkit-align-self: flex-start;
+  flex: 1;
+  text-align: left;
+}
+
+.month-popup-button {
+  border-width: 0px !important;
+  font-weight: bold;
+  padding: 0;
+}
+
+.month-popup-button .disclosure-triangle {
+  margin: 0;
+  margin-inline-start: 4px;
+}
+
+.day-cell {
+  background-color: #ffffff;
+  border: 0;
+  border-radius: 2px;
+  color: #767676;
+  padding: 1px;
+  text-align: center;
+}
+
+.day-cell.current-month {
+  color: #101010;
+}
+
+.week-number-cell.highlighted,
+.day-cell.highlighted {
+  background-color: #F3F3F3;
+}
+
+.week-number-cell.selected,
+.day-cell.selected {
+  background-color: #D9EBF9;
+  font-weight: bold;
+}
+
+.week-number-cell.disabled,
+.day-cell.disabled {
+  background-color: #ffffff;
+  color: #C5C5C5;
+}
+
+.day-cell.highlighted.today,
+.day-cell.today {
+  background-color: #0078D4;
+  border: 0;
+  color: #FFFFFF;
+  font-weight: bold;
+}
+
+.today-button-refresh {
+  border: 0;
+  bottom: 12px;
+  color: #0078D4;
+  font-size: 12px;
+  height: 20px;
+  padding: 4px;
+  position: absolute;
+  right: 20px;
+  width: auto;
+}
+
+
diff --git a/third_party/blink/renderer/core/input/scroll_snap_test.cc b/third_party/blink/renderer/core/input/scroll_snap_test.cc
index b385e838..b9f78b1 100644
--- a/third_party/blink/renderer/core/input/scroll_snap_test.cc
+++ b/third_party/blink/renderer/core/input/scroll_snap_test.cc
@@ -211,9 +211,11 @@
   request.Complete(R"HTML(
     <!DOCTYPE html>
     <style>
+    html {
+      scroll-snap-type: both mandatory;
+    }
     body {
       overflow: scroll;
-      scroll-snap-type: both mandatory;
       height: 300px;
       width: 300px;
       margin: 0px;
diff --git a/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc b/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc
index fc4f4f10..9e920992 100644
--- a/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc
+++ b/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc
@@ -121,7 +121,7 @@
   StylePropertyMapReadOnly* style_map =
       MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>(
           layout_custom.GetDocument(), layout_custom.StyleRef(),
-          layout_custom.GetNode(), definition_->native_invalidation_properties_,
+          definition_->native_invalidation_properties_,
           definition_->custom_invalidation_properties_);
 
   ScriptValue return_value;
diff --git a/third_party/blink/renderer/core/layout/custom/custom_layout_child.cc b/third_party/blink/renderer/core/layout/custom/custom_layout_child.cc
index b34bd33d..b611ca1 100644
--- a/third_party/blink/renderer/core/layout/custom/custom_layout_child.cc
+++ b/third_party/blink/renderer/core/layout/custom/custom_layout_child.cc
@@ -18,7 +18,6 @@
       style_map_(MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>(
           box->GetDocument(),
           box->StyleRef(),
-          box->GetNode(),
           definition.ChildNativeInvalidationProperties(),
           definition.ChildCustomInvalidationProperties())) {}
 
diff --git a/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc b/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
index 02c528d..443254b 100644
--- a/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
@@ -50,18 +50,20 @@
   ASSERT_EQ(Window().scrollY(), content->OffsetTop());
 }
 
-TEST_F(ScrollIntoViewTest, ScrollPaddingOnBodyViewportDefining) {
+TEST_F(ScrollIntoViewTest, ScrollPaddingOnDocumentElWhenBodyDefinesViewport) {
   v8::HandleScope HandleScope(v8::Isolate::GetCurrent());
   WebView().MainFrameWidget()->Resize(WebSize(300, 300));
   SimRequest request("https://example.com/test.html", "text/html");
   LoadURL("https://example.com/test.html");
   request.Complete(R"HTML(
       <style>
+      html {
+        scroll-padding: 10px;
+      }
       body {
         margin: 0px;
         height: 300px;
         overflow: scroll;
-        scroll-padding: 10px;
       }
       </style>
       <div id='space' style='height: 1000px'></div>
@@ -79,7 +81,8 @@
   ASSERT_EQ(Window().scrollY(), target->OffsetTop() - 10);
 }
 
-TEST_F(ScrollIntoViewTest, ScrollPaddingOnHtmlViewportDefining) {
+TEST_F(ScrollIntoViewTest,
+       ScrollPaddingOnDocumentElWhenDocumentElDefinesViewport) {
   v8::HandleScope HandleScope(v8::Isolate::GetCurrent());
   WebView().MainFrameWidget()->Resize(WebSize(300, 300));
   SimRequest request("https://example.com/test.html", "text/html");
@@ -108,7 +111,7 @@
   ASSERT_EQ(Window().scrollY(), target->OffsetTop() - 10);
 }
 
-TEST_F(ScrollIntoViewTest, ScrollPaddingBodyOverflowHtmlViewportDefining) {
+TEST_F(ScrollIntoViewTest, ScrollPaddingOnBodyWhenDocumentElDefinesViewport) {
   v8::HandleScope HandleScope(v8::Isolate::GetCurrent());
   WebView().MainFrameWidget()->Resize(WebSize(300, 300));
   SimRequest request("https://example.com/test.html", "text/html");
diff --git a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
index 0ee31ee..4921e0b 100644
--- a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
+++ b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
@@ -31,15 +31,14 @@
   // https://drafts.csswg.org/css-scroll-snap/#snap-model
   // "Snap positions must only affect the nearest ancestor (on the element’s
   // containing block chain) scroll container".
-  Element* viewport_defining_element =
-      snap_area.GetDocument().ViewportDefiningElement();
+  Element* document_element = snap_area.GetDocument().documentElement();
   LayoutBox* box = snap_area.ContainingBlock();
   while (box && !box->HasOverflowClip() && !box->IsLayoutView() &&
-         box->GetNode() != viewport_defining_element)
+         box->GetNode() != document_element)
     box = box->ContainingBlock();
 
-  // If we reach to viewportDefiningElement then we dispatch to viewport
-  if (box && box->GetNode() == viewport_defining_element)
+  // If we reach to document element then we dispatch to viewport
+  if (box && box->GetNode() == document_element)
     return snap_area.GetDocument().GetLayoutView();
 
   return box;
@@ -52,11 +51,11 @@
     return;
   }
 
-  // Scroll snap properties have no effect on the viewport defining element
-  // instead they are propagated to (See Document::PropagateStyleToViewport) and
-  // handled by the LayoutView.
+  // Scroll snap properties have no effect on the document element instead they
+  // are propagated to (See Document::PropagateStyleToViewport) and handled by
+  // the LayoutView.
   if (snap_container.GetNode() ==
-      snap_container.GetDocument().ViewportDefiningElement())
+      snap_container.GetDocument().documentElement())
     return;
 
   bool is_scroll_container =
diff --git a/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
index 538f45ebf..6a943ec 100644
--- a/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
@@ -213,6 +213,38 @@
   EXPECT_EQ(1U, SizeOfSnapAreas(SnapContainer()));
 }
 
+TEST_F(SnapCoordinatorTest, ViewpoertScrollSnapStyleComesFromDocumentElement) {
+  SetHTML(R"HTML(
+    <style>
+    :root {
+      scroll-snap-type: both mandatory;
+    }
+    body {
+     scroll-snap-type: none;
+    }
+    </style>
+    <body>
+    </body>
+    )HTML");
+  UpdateAllLifecyclePhasesForTest();
+
+  Element* body = GetDocument().body();
+  EXPECT_EQ(body, GetDocument().ViewportDefiningElement());
+
+  SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
+  base::Optional<cc::SnapContainerData> viewport_data =
+      snap_coordinator->GetSnapContainerData(*GetDocument().GetLayoutView());
+  EXPECT_TRUE(viewport_data.has_value());
+  EXPECT_EQ(viewport_data.value().scroll_snap_type(),
+            cc::ScrollSnapType(false, cc::SnapAxis::kBoth,
+                               cc::SnapStrictness::kMandatory));
+
+  base::Optional<cc::SnapContainerData> body_data =
+      snap_coordinator->GetSnapContainerData(*body->GetLayoutBox());
+
+  EXPECT_FALSE(body_data.has_value());
+}
+
 TEST_F(SnapCoordinatorTest, LayoutViewCapturesWhenBodyElementViewportDefining) {
   SetHTML(R"HTML(
     <style>
@@ -327,6 +359,8 @@
   // should capture snap points defined on it as opposed to layout view.
   Element& body = *GetDocument().body();
   EXPECT_EQ(2U, SizeOfSnapAreas(body));
+  EXPECT_EQ(0U, SizeOfSnapAreas(*GetDocument().documentElement()));
+  EXPECT_EQ(0U, SizeOfSnapAreas(GetDocument()));
 }
 
 #define EXPECT_EQ_CONTAINER(expected, actual)                          \
@@ -416,9 +450,11 @@
 TEST_F(SnapCoordinatorTest, ScrolledSnapDataCalculationOnViewport) {
   SetHTML(R"HTML(
     <style>
+    :root {
+      scroll-snap-type: both mandatory;
+    }
     body {
       margin: 0px;
-      scroll-snap-type: both mandatory;
       overflow: scroll;
     }
     #container {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
index de12ac6e..f0f18f2 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -167,6 +167,21 @@
          !text_fragment.GetLayoutObject()->NextInPreOrder();
 }
 
+const LayoutObject* ListMarkerFromMarkerOrMarkerContent(
+    const LayoutObject* object) {
+  if (object->IsLayoutNGListMarkerIncludingInside())
+    return object;
+
+  // Check if this is a marker content.
+  if (object->IsAnonymous()) {
+    const LayoutObject* parent = object->Parent();
+    if (parent && parent->IsLayoutNGListMarkerIncludingInside())
+      return parent;
+  }
+
+  return nullptr;
+}
+
 }  // namespace
 
 NGPaintFragment::NGPaintFragment(
@@ -1152,11 +1167,14 @@
     return Parent()->NodeForHitTest();
 
   // When the fragment is a list marker, return the list item.
-  const LayoutObject* object = GetLayoutObject();
-  if (object && object->IsLayoutNGListMarker()) {
-    if (LayoutNGListItem* list_item = LayoutNGListItem::FromMarker(*object))
-      return list_item->GetNode();
-    return nullptr;
+  if (const LayoutObject* object = GetLayoutObject()) {
+    if (const LayoutObject* marker =
+            ListMarkerFromMarkerOrMarkerContent(object)) {
+      if (const LayoutNGListItem* list_item =
+              LayoutNGListItem::FromMarker(*marker))
+        return list_item->GetNode();
+      return nullptr;
+    }
   }
 
   for (const NGPaintFragment* runner = Parent(); runner;
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
index f43af5e..17884c7 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
@@ -1303,9 +1303,11 @@
   SetBodyInnerHTML(R"HTML(
     <!DOCTYPE html>
     <style>
+    html {
+      scroll-snap-type: both proximity;
+    }
     body {
       overflow: scroll;
-      scroll-snap-type: both proximity;
       height: 300px;
       width: 300px;
       margin: 0px;
@@ -1325,7 +1327,6 @@
       height: 200px;
       scroll-snap-align: start;
     }
-
     </style>
 
     <div id="container">
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/PRESUBMIT.py b/third_party/blink/renderer/core/script/resources/layered_api/PRESUBMIT.py
index 4364aaf..3dafa97 100644
--- a/third_party/blink/renderer/core/script/resources/layered_api/PRESUBMIT.py
+++ b/third_party/blink/renderer/core/script/resources/layered_api/PRESUBMIT.py
@@ -8,13 +8,8 @@
 
 def _CommonChecks(input_api, output_api):
   results = []
-  # TODO(tkent): {kv-storage,toast,virtual-scroller}/.eslintrc.js specify babel-eslint parser, which
-  # is not in third_party/node/node_modules/.
   mjs_files = input_api.AffectedFiles(
-      file_filter=lambda f: (f.LocalPath().endswith('.mjs') and
-                             not '/virtual-scroller/' in f.LocalPath() and
-                             not '/kv-storage/' in f.LocalPath() and
-                             not '/toast/' in f.LocalPath()),
+      file_filter=lambda f: f.LocalPath().endswith('.mjs'),
       include_deletes=False)
   if not mjs_files:
     return results
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/.eslintrc.js b/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/.eslintrc.js
index 8f9a676..822d372 100644
--- a/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/.eslintrc.js
+++ b/third_party/blink/renderer/core/script/resources/layered_api/elements/toast/.eslintrc.js
@@ -87,7 +87,9 @@
     'no-implicit-coercion': 'error',
     'no-implicit-globals': 'error',
     'no-implied-eval': 'error',
-    'no-invalid-this': 'error',
+    // no-invalid-this doesn't work well for private fields.
+    // https://github.com/babel/eslint-plugin-babel/issues/182
+    // 'no-invalid-this': 'error',
     'no-iterator': 'error',
     'no-labels': ['error', {allowLoop: true}],
     'no-lone-blocks': 'error',
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/.eslintrc.js b/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/.eslintrc.js
index 8f9a676..822d372 100644
--- a/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/.eslintrc.js
+++ b/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/.eslintrc.js
@@ -87,7 +87,9 @@
     'no-implicit-coercion': 'error',
     'no-implicit-globals': 'error',
     'no-implied-eval': 'error',
-    'no-invalid-this': 'error',
+    // no-invalid-this doesn't work well for private fields.
+    // https://github.com/babel/eslint-plugin-babel/issues/182
+    // 'no-invalid-this': 'error',
     'no-iterator': 'error',
     'no-labels': ['error', {allowLoop: true}],
     'no-lone-blocks': 'error',
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/index.mjs b/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/index.mjs
index 88ef25e8..7ba0db6 100644
--- a/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/index.mjs
+++ b/third_party/blink/renderer/core/script/resources/layered_api/kv-storage/index.mjs
@@ -89,6 +89,7 @@
 
   keys() {
     // Brand check: throw if there is no such private field.
+    // eslint-disable-next-line no-unused-expressions
     this.#databaseName;
 
     return createStorageAreaAsyncIterator(
@@ -100,6 +101,7 @@
 
   values() {
     // Brand check: throw if there is no such private field.
+    // eslint-disable-next-line no-unused-expressions
     this.#databaseName;
 
     return createStorageAreaAsyncIterator(
@@ -111,6 +113,7 @@
 
   entries() {
     // Brand check: throw if there is no such private field.
+    // eslint-disable-next-line no-unused-expressions
     this.#databaseName;
 
     return createStorageAreaAsyncIterator(
@@ -125,7 +128,7 @@
       this.#backingStoreObject = Object.freeze({
         database: this.#databaseName,
         store: DEFAULT_IDB_STORE_NAME,
-        version: 1
+        version: 1,
       });
     }
 
@@ -149,7 +152,7 @@
   entries: {enumerable: true},
   backingStore: {enumerable: true},
   [Symbol.asyncIterator]: {enumerable: false},
-  [Symbol.toStringTag]: {writable: false, enumerable: false}
+  [Symbol.toStringTag]: {writable: false, enumerable: false},
 });
 
 export default new StorageArea(DEFAULT_STORAGE_AREA_NAME);
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
index abc0621d..5b8ddb37 100644
--- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
+++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -983,5 +983,11 @@
       default_value: "false",
       custom_compare: true,
     },
+    {
+      name: "IsFlexOrGridOrCustomItem",
+      field_template: "monotonic_flag",
+      default_value: "false",
+      custom_compare: true,
+    },
   ],
 }
diff --git a/third_party/blink/renderer/devtools/front_end/data_grid/DataGrid.js b/third_party/blink/renderer/devtools/front_end/data_grid/DataGrid.js
index 76647c9..33af6eb 100644
--- a/third_party/blink/renderer/devtools/front_end/data_grid/DataGrid.js
+++ b/third_party/blink/renderer/devtools/front_end/data_grid/DataGrid.js
@@ -253,12 +253,16 @@
         dataColumn.style.width = column.width;
       }
       this._headerRow.appendChild(this._headerTableHeaders[columnId]);
-      this._topFillerRow.createChild('td', 'top-filler-td');
+      const topFillerRowCell = this._topFillerRow.createChild('th', 'top-filler-td');
+      topFillerRowCell.textContent = column.title;
+      topFillerRowCell.scope = 'col';
       this._bottomFillerRow.createChild('td', 'bottom-filler-td')[DataGrid.DataGrid._columnIdSymbol] = columnId;
     }
 
     this._headerRow.createChild('th', 'corner');
-    this._topFillerRow.createChild('td', 'corner').classList.add('top-filler-td');
+    const topFillerRowCornerCell = this._topFillerRow.createChild('th', 'corner');
+    topFillerRowCornerCell.classList.add('top-filler-td');
+    topFillerRowCornerCell.scope = 'col';
     this._bottomFillerRow.createChild('td', 'corner').classList.add('bottom-filler-td');
     this._headerTableColumnGroup.createChild('col', 'corner');
     this._dataTableColumnGroup.createChild('col', 'corner');
@@ -1625,7 +1629,6 @@
    */
   createCell(columnId) {
     const cell = this.createTD(columnId);
-
     const data = this.data[columnId];
     if (data instanceof Node)
       cell.appendChild(data);
diff --git a/third_party/blink/renderer/devtools/front_end/data_grid/dataGrid.css b/third_party/blink/renderer/devtools/front_end/data_grid/dataGrid.css
index 54dcf83..caf0972 100644
--- a/third_party/blink/renderer/devtools/front_end/data_grid/dataGrid.css
+++ b/third_party/blink/renderer/devtools/front_end/data_grid/dataGrid.css
@@ -173,6 +173,11 @@
     background-color: hsla(0, 0%, 90%, 1);
 }
 
+.data-grid .top-filler-td {
+    border-bottom: 0 none transparent;
+    line-height: 0;
+}
+
 .data-grid button {
     line-height: 18px;
     color: inherit;
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
index 54e1827..b0bd44a 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
@@ -320,10 +320,10 @@
   authenticator->Cancel();
 }
 
-void OnStoreComplete(std::unique_ptr<ScopedPromiseResolver> scoped_resolver,
-                     RequiredOriginType required_origin_type) {
+void OnStoreComplete(std::unique_ptr<ScopedPromiseResolver> scoped_resolver) {
   auto* resolver = scoped_resolver->Release();
-  AssertSecurityRequirementsBeforeResponse(resolver, required_origin_type);
+  AssertSecurityRequirementsBeforeResponse(
+      resolver, RequiredOriginType::kSecureAndSameWithAncestors);
   resolver->Resolve();
 }
 
@@ -616,13 +616,6 @@
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
 
-  auto required_origin_type =
-      credential->IsFederatedCredential() || credential->IsPasswordCredential()
-          ? RequiredOriginType::kSecureAndSameWithAncestors
-          : RequiredOriginType::kSecure;
-  if (!CheckSecurityRequirementsBeforeRequest(resolver, required_origin_type))
-    return promise;
-
   if (!(credential->IsFederatedCredential() ||
         credential->IsPasswordCredential())) {
     resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -631,8 +624,11 @@
     return promise;
   }
 
-  DCHECK(credential->IsFederatedCredential() ||
-         credential->IsPasswordCredential());
+  if (!CheckSecurityRequirementsBeforeRequest(
+          resolver, RequiredOriginType::kSecureAndSameWithAncestors)) {
+    return promise;
+  }
+
   const KURL& url =
       credential->IsFederatedCredential()
           ? static_cast<const FederatedCredential*>(credential)->iconURL()
@@ -647,9 +643,9 @@
       CredentialManagerProxy::From(script_state)->CredentialManager();
   credential_manager->Store(
       CredentialInfo::From(credential),
-      WTF::Bind(&OnStoreComplete,
-                WTF::Passed(std::make_unique<ScopedPromiseResolver>(resolver)),
-                required_origin_type));
+      WTF::Bind(
+          &OnStoreComplete,
+          WTF::Passed(std::make_unique<ScopedPromiseResolver>(resolver))));
 
   return promise;
 }
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
index 6c69827..557befd9 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
@@ -125,7 +125,6 @@
   StylePropertyMapReadOnly* style_map =
       MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>(
           layout_object.GetDocument(), layout_object.StyleRef(),
-          layout_object.GetNode(),
           paint_definition->NativeInvalidationProperties(),
           paint_definition->CustomInvalidationProperties());
   sk_sp<PaintRecord> paint_record = paint_definition->Paint(
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc
index 14dc4ec..61a159d 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc
@@ -132,7 +132,7 @@
   StylePropertyMapReadOnly* style_map =
       MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>(
           layout_object.GetDocument(), layout_object.StyleRef(),
-          layout_object.GetNode(), definition->NativeInvalidationProperties(),
+          definition->NativeInvalidationProperties(),
           definition->CustomInvalidationProperties());
   scoped_refptr<Image> image = PaintGeneratedImage::Create(
       definition->Paint(container_size, zoom, style_map, nullptr,
diff --git a/third_party/blink/renderer/modules/exported/web_ax_object.cc b/third_party/blink/renderer/modules/exported/web_ax_object.cc
index 3ebfbd5..4fb9d34 100644
--- a/third_party/blink/renderer/modules/exported/web_ax_object.cc
+++ b/third_party/blink/renderer/modules/exported/web_ax_object.cc
@@ -1240,7 +1240,7 @@
 
   return WebString(CSSProperty::Get(CSSPropertyID::kDisplay)
                        .CSSValueFromComputedStyle(
-                           *computed_style, /* layout_object */ nullptr, node,
+                           *computed_style, /* layout_object */ nullptr,
                            /* allow_visited_style */ false)
                        ->CssText());
 }
diff --git a/third_party/blink/renderer/modules/mediastream/input_device_info.cc b/third_party/blink/renderer/modules/mediastream/input_device_info.cc
index c770b3a..cf2b6e5 100644
--- a/third_party/blink/renderer/modules/mediastream/input_device_info.cc
+++ b/third_party/blink/renderer/modules/mediastream/input_device_info.cc
@@ -67,9 +67,9 @@
     float min_frame_rate = 1.0f;
     float max_frame_rate = min_frame_rate;
     for (const auto& format : video_input_capabilities->formats) {
-      max_width = std::max(max_width, format->frame_size.width);
-      max_height = std::max(max_height, format->frame_size.height);
-      max_frame_rate = std::max(max_frame_rate, format->frame_rate);
+      max_width = std::max(max_width, format.frame_size.width());
+      max_height = std::max(max_height, format.frame_size.height());
+      max_frame_rate = std::max(max_frame_rate, format.frame_rate);
     }
     platform_capabilities_.width = {1, max_width};
     platform_capabilities_.height = {1, max_height};
diff --git a/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc b/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc
index f9ff4995..f014dd3 100644
--- a/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc
+++ b/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc
@@ -9,8 +9,15 @@
 #include "third_party/blink/renderer/core/geometry/dom_point_init.h"
 #include "third_party/blink/renderer/core/geometry/dom_point_read_only.h"
 #include "third_party/blink/renderer/modules/xr/xr_utils.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
 
+namespace {
+bool IsWithinEpsilon(double a, double b) {
+  return std::abs(a - b) < std::numeric_limits<double>::epsilon();
+}
+}  // namespace
+
 namespace blink {
 
 // makes a deep copy of transformationMatrix
@@ -59,7 +66,24 @@
 }
 
 XRRigidTransform* XRRigidTransform::Create(DOMPointInit* position,
-                                           DOMPointInit* orientation) {
+                                           DOMPointInit* orientation,
+                                           ExceptionState& exception_state) {
+  if (position && !IsWithinEpsilon(1.0, position->w())) {
+    exception_state.ThrowTypeError("W component of position must be 1.0");
+    return nullptr;
+  }
+
+  if (orientation) {
+    if (IsWithinEpsilon(orientation->x(), 0.0) &&
+        IsWithinEpsilon(orientation->y(), 0.0) &&
+        IsWithinEpsilon(orientation->z(), 0.0) &&
+        IsWithinEpsilon(orientation->w(), 0.0)) {
+      exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                        "Orientation's length cannot be 0");
+      return nullptr;
+    }
+  }
+
   return MakeGarbageCollected<XRRigidTransform>(position, orientation);
 }
 
diff --git a/third_party/blink/renderer/modules/xr/xr_rigid_transform.h b/third_party/blink/renderer/modules/xr/xr_rigid_transform.h
index 2863528..c395827 100644
--- a/third_party/blink/renderer/modules/xr/xr_rigid_transform.h
+++ b/third_party/blink/renderer/modules/xr/xr_rigid_transform.h
@@ -16,6 +16,7 @@
 
 class DOMPointInit;
 class DOMPointReadOnly;
+class ExceptionState;
 class TransformationMatrix;
 
 // MODULES_EXPORT is required for unit tests using XRRigidTransform (currently
@@ -26,7 +27,9 @@
  public:
   explicit XRRigidTransform(const TransformationMatrix&);
   XRRigidTransform(DOMPointInit*, DOMPointInit*);
-  static XRRigidTransform* Create(DOMPointInit*, DOMPointInit*);
+  static XRRigidTransform* Create(DOMPointInit*,
+                                  DOMPointInit*,
+                                  ExceptionState&);
 
   ~XRRigidTransform() override = default;
 
diff --git a/third_party/blink/renderer/modules/xr/xr_rigid_transform.idl b/third_party/blink/renderer/modules/xr/xr_rigid_transform.idl
index f76a795d1..1faea2b 100644
--- a/third_party/blink/renderer/modules/xr/xr_rigid_transform.idl
+++ b/third_party/blink/renderer/modules/xr/xr_rigid_transform.idl
@@ -8,7 +8,8 @@
     SecureContext,
     Exposed=Window,
     RuntimeEnabled=WebXR,
-    Constructor(optional DOMPointInit position, optional DOMPointInit orientation)
+    Constructor(optional DOMPointInit position, optional DOMPointInit orientation),
+    RaisesException=Constructor
 ] interface XRRigidTransform {
   [SameObject] readonly attribute DOMPointReadOnly position;
   [SameObject] readonly attribute DOMPointReadOnly orientation;
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 32f59c5..9644e43 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1424,6 +1424,7 @@
     "//device/vr/public/mojom:mojom_blink",
     "//gin",
     "//media",
+    "//media/capture/mojom:video_capture",
     "//mojo/public/cpp/base",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/bindings:wtf_support",
diff --git a/third_party/blink/renderer/platform/mojo/BUILD.gn b/third_party/blink/renderer/platform/mojo/BUILD.gn
index 5d356fa..d245432 100644
--- a/third_party/blink/renderer/platform/mojo/BUILD.gn
+++ b/third_party/blink/renderer/platform/mojo/BUILD.gn
@@ -8,7 +8,6 @@
     "geometry_struct_traits.h",
   ]
   public_deps = [
-    "//media/capture/mojom:video_capture",
     "//third_party/blink/public:blink_headers",
     "//ui/gfx/geometry",
     "//ui/gfx/geometry/mojom:mojom_blink_headers",
diff --git a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
index 1fed0f27..0925c08 100644
--- a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
+++ b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 typemaps = [
+  "//media/capture/mojom/video_capture_types_for_blink.typemap",
   "//ui/gfx/mojom/transform.typemap",
   "//services/network/public/cpp/http_request_headers.typemap",
   "//third_party/blink/renderer/core/messaging/blink_cloneable_message.typemap",
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support.h b/third_party/blink/renderer/platform/testing/testing_platform_support.h
index bd09d84..ce28683f 100644
--- a/third_party/blink/renderer/platform/testing/testing_platform_support.h
+++ b/third_party/blink/renderer/platform/testing/testing_platform_support.h
@@ -144,6 +144,9 @@
   const T* operator->() const { return testing_platform_support_.get(); }
   T* operator->() { return testing_platform_support_.get(); }
 
+  const T& operator*() const { return *testing_platform_support_; }
+  T& operator*() { return *testing_platform_support_; }
+
   T* GetTestingPlatformSupport() { return testing_platform_support_.get(); }
 
  private:
diff --git a/third_party/blink/renderer/platform/text/locale_icu.cc b/third_party/blink/renderer/platform/text/locale_icu.cc
index 1550e54..514931f 100644
--- a/third_party/blink/renderer/platform/text/locale_icu.cc
+++ b/third_party/blink/renderer/platform/text/locale_icu.cc
@@ -38,6 +38,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/date_math.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -248,8 +249,13 @@
                                          UCAL_FIRST_DAY_OF_WEEK) -
                        UCAL_SUNDAY;
 
-  week_day_short_labels_ = CreateLabelVector(
-      short_date_format_, UDAT_SHORT_WEEKDAYS, UCAL_SUNDAY, 7);
+  if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
+    week_day_short_labels_ = CreateLabelVector(
+        short_date_format_, UDAT_NARROW_WEEKDAYS, UCAL_SUNDAY, 7);
+  } else {
+    week_day_short_labels_ = CreateLabelVector(
+        short_date_format_, UDAT_SHORT_WEEKDAYS, UCAL_SUNDAY, 7);
+  }
   if (!week_day_short_labels_)
     week_day_short_labels_ = CreateFallbackWeekDayShortLabels();
 }
diff --git a/third_party/blink/renderer/platform/text/locale_mac.mm b/third_party/blink/renderer/platform/text/locale_mac.mm
index 4e50935..5f721423 100644
--- a/third_party/blink/renderer/platform/text/locale_mac.mm
+++ b/third_party/blink/renderer/platform/text/locale_mac.mm
@@ -37,6 +37,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "third_party/blink/renderer/platform/language.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/web_test_support.h"
 #include "third_party/blink/renderer/platform/wtf/date_math.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -135,7 +136,9 @@
   if (!week_day_short_labels_.IsEmpty())
     return week_day_short_labels_;
   week_day_short_labels_.ReserveCapacity(7);
-  NSArray* array = [ShortDateFormatter() shortWeekdaySymbols];
+  NSArray* array = RuntimeEnabledFeatures::FormControlsRefreshEnabled()
+                       ? [ShortDateFormatter() veryShortWeekdaySymbols]
+                       : [ShortDateFormatter() shortWeekdaySymbols];
   if ([array count] == 7) {
     for (unsigned i = 0; i < 7; ++i)
       week_day_short_labels_.push_back(String([array objectAtIndex:i]));
diff --git a/third_party/blink/renderer/platform/text/locale_win.cc b/third_party/blink/renderer/platform/text/locale_win.cc
index e94e41e..2464478 100644
--- a/third_party/blink/renderer/platform/text/locale_win.cc
+++ b/third_party/blink/renderer/platform/text/locale_win.cc
@@ -36,6 +36,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "third_party/blink/renderer/platform/language.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/text/date_components.h"
 #include "third_party/blink/renderer/platform/text/date_time_format.h"
 #include "third_party/blink/renderer/platform/web_test_support.h"
@@ -295,9 +296,19 @@
                             LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
                             LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
                             LOCALE_SABBREVDAYNAME6};
+  const LCTYPE kTypesRefresh[7] = {
+      LOCALE_SSHORTESTDAYNAME7,  // Sunday
+      LOCALE_SSHORTESTDAYNAME1,  // Monday
+      LOCALE_SSHORTESTDAYNAME2, LOCALE_SSHORTESTDAYNAME3,
+      LOCALE_SSHORTESTDAYNAME4, LOCALE_SSHORTESTDAYNAME5,
+      LOCALE_SSHORTESTDAYNAME6};
   week_day_short_labels_.ReserveCapacity(base::size(kTypes));
   for (unsigned i = 0; i < base::size(kTypes); ++i) {
-    week_day_short_labels_.push_back(GetLocaleInfoString(kTypes[i]));
+    if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
+      week_day_short_labels_.push_back(GetLocaleInfoString(kTypesRefresh[i]));
+    } else {
+      week_day_short_labels_.push_back(GetLocaleInfoString(kTypes[i]));
+    }
     if (week_day_short_labels_.back().IsEmpty()) {
       week_day_short_labels_.Shrink(0);
       week_day_short_labels_.ReserveCapacity(base::size(WTF::kWeekdayName));
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index d4810f0..dc00985 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2146,6 +2146,7 @@
 crbug.com/753671 external/wpt/css/css-content/quotes-022.html [ Failure ]
 crbug.com/753671 external/wpt/css/css-content/quotes-025.html [ Failure ]
 crbug.com/753671 external/wpt/css/css-content/quotes-033.html [ Failure ]
+crbug.com/989123 external/wpt/css/css-typed-om/the-stylepropertymap/computed/get-auto-min-size.html [ Failure ]
 
 # ====== Style team owned tests to here ======
 
@@ -2223,6 +2224,7 @@
 crbug.com/791529 virtual/cascade/external/wpt/css/css-variables/variable-transitions-transition-property-variable-before-value.html [ Skip ]
 crbug.com/791529 virtual/cascade/external/wpt/css/css-variables/variable-transitions-value-before-transition-property-variable.html [ Skip ]
 crbug.com/552085 virtual/cascade/external/wpt/css/css-cascade/important-prop.html [ Failure ]
+crbug.com/989123 virtual/cascade/external/wpt/css/css-typed-om/the-stylepropertymap/computed/get-auto-min-size.html [ Failure ]
 
 # This is for some reason WontFix'd in the main expectations (see NeverFixTests).
 # That seems wrong, as we should support 'revert' eventually.
@@ -3320,8 +3322,6 @@
 crbug.com/626703 [ Win7 ] external/wpt/pointerevents/extension/pointerevent_touch-action-pan-right-css_touch.html [ Timeout ]
 crbug.com/626703 [ Mac10.11 ] external/wpt/shape-detection/detection-security-test.https.html [ Timeout ]
 crbug.com/626703 [ Mac10.11 ] external/wpt/shape-detection/shapedetection-cross-origin.sub.https.html [ Timeout ]
-crbug.com/626703 [ Mac10.13 ] external/wpt/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/mediastreamaudiosourcenode-routing.html [ Timeout ]
-crbug.com/626703 [ Retina ] external/wpt/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/mediastreamaudiosourcenode-routing.html [ Timeout ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size.html [ Failure ]
 crbug.com/626703 external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-offer.html [ Timeout ]
 crbug.com/626703 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-offer.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index 7c7fe24..de50a5f 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -11665,6 +11665,18 @@
      {}
     ]
    ],
+   "css/CSS2/floats/zero-available-space-float-positioning.html": [
+    [
+     "css/CSS2/floats/zero-available-space-float-positioning.html",
+     [
+      [
+       "/css/reference/ref-filled-green-100px-square-only.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/CSS2/floats/zero-width-floats-positioning.html": [
     [
      "css/CSS2/floats/zero-width-floats-positioning.html",
@@ -140617,9 +140629,6 @@
    "css/css-scroll-snap/parsing/scroll-padding-valid-expected.txt": [
     []
    ],
-   "css/css-scroll-snap/scroll-snap-type-on-root-element-expected.txt": [
-    []
-   ],
    "css/css-scroll-snap/scroll-target-001-ref.html": [
     []
    ],
@@ -161695,6 +161704,9 @@
    "interfaces/media-capabilities.idl": [
     []
    ],
+   "interfaces/media-playback-quality.idl": [
+    []
+   ],
    "interfaces/media-source.idl": [
     []
    ],
@@ -162289,9 +162301,6 @@
    "mathml/relations/css-styling/mathvariant-tailed-ref.html": [
     []
    ],
-   "mathml/relations/css-styling/padding-border-margin/helper.js": [
-    []
-   ],
    "mathml/relations/css-styling/padding-border-margin/padding-border-margin-001-ref.html": [
     []
    ],
@@ -162349,6 +162358,9 @@
    "mathml/relations/text-and-math/use-typo-metrics-1-ref.html": [
     []
    ],
+   "mathml/support/box-comparison.js": [
+    []
+   ],
    "mathml/support/feature-detection.js": [
     []
    ],
@@ -162424,6 +162436,9 @@
    "media-capabilities/idlharness.any.worker-expected.txt": [
     []
    ],
+   "media-playback-quality/META.yml": [
+    []
+   ],
    "media-source/META.yml": [
     []
    ],
@@ -174316,9 +174331,6 @@
    "webaudio/resources/stereopanner-testing.js": [
     []
    ],
-   "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel-expected.txt": [
-    []
-   ],
    "webaudio/the-audio-api/the-audiobuffersourcenode-interface/resources/audiobuffersource-multi-channels-expected.wav": [
     []
    ],
@@ -176683,9 +176695,6 @@
    "webxr/resources/webxr_util.js": [
     []
    ],
-   "webxr/xrRigidTransform_constructor.https-expected.txt": [
-    []
-   ],
    "webxr/xrWebGLLayer_framebuffer.https-expected.txt": [
     []
    ],
@@ -250341,6 +250350,12 @@
      {}
     ]
    ],
+   "mathml/relations/css-styling/width-height-001.html": [
+    [
+     "mathml/relations/css-styling/width-height-001.html",
+     {}
+    ]
+   ],
    "mathml/relations/css-styling/writing-mode/writing-mode-001.html": [
     [
      "mathml/relations/css-styling/writing-mode/writing-mode-001.html",
@@ -250439,6 +250454,23 @@
      }
     ]
    ],
+   "media-playback-quality/idlharness.window.js": [
+    [
+     "media-playback-quality/idlharness.window.html",
+     {
+      "script_metadata": [
+       [
+        "script",
+        "/resources/WebIDLParser.js"
+       ],
+       [
+        "script",
+        "/resources/idlharness.js"
+       ]
+      ]
+     }
+    ]
+   ],
    "media-source/SourceBuffer-abort-readyState.html": [
     [
      "media-source/SourceBuffer-abort-readyState.html",
@@ -330534,6 +330566,10 @@
    "21235d550dc83532be86788294bcc891a81c4caa",
    "reftest"
   ],
+  "css/CSS2/floats/zero-available-space-float-positioning.html": [
+   "62ace6daa036929b46a8e9c1cc516fda403b7131",
+   "reftest"
+  ],
   "css/CSS2/floats/zero-space-between-floats-001.html": [
    "a7796011b0191e18ac24dee8ac94d2e878752201",
    "testharness"
@@ -371818,10 +371854,6 @@
    "89b4edaf135be41ebb2e548076498a2c5f9afdf8",
    "testharness"
   ],
-  "css/css-scroll-snap/scroll-snap-type-on-root-element-expected.txt": [
-   "fd0d526cbd200ef04e7219a0b0e130967d6cdfe3",
-   "support"
-  ],
   "css/css-scroll-snap/scroll-snap-type-on-root-element.html": [
    "eaa94176547481429d0ebdbe296fc5752e31bfb2",
    "testharness"
@@ -442150,6 +442182,10 @@
    "e66309187f467045c44f9083a51f0d610bcc7019",
    "support"
   ],
+  "interfaces/media-playback-quality.idl": [
+   "12b2c74e6183af66ec5bfae1897b7c46f276bdac",
+   "support"
+  ],
   "interfaces/media-source.idl": [
    "1d3c02d847ea66e6bc5a8c0f520d6c7b9ad9e1d6",
    "support"
@@ -443855,31 +443891,27 @@
    "reftest"
   ],
   "mathml/relations/css-styling/padding-border-margin/border-001.html": [
-   "83eb924d82389008846adaca6eae35b450849a6f",
+   "784491cf2e1bf60ea7c9edc951b9252d903d592f",
    "testharness"
   ],
   "mathml/relations/css-styling/padding-border-margin/border-002.html": [
-   "cbf3efe096697bf543b4326a3467ae3b18501a58",
+   "85a3dc2e2ac5797fea9a311cde82854eb80b33f2",
    "testharness"
   ],
-  "mathml/relations/css-styling/padding-border-margin/helper.js": [
-   "c7b4b0a1b49dc0bada186df03e0f79432462ed12",
-   "support"
-  ],
   "mathml/relations/css-styling/padding-border-margin/margin-001.html": [
-   "c674d4c829e414067e02384ef06d38a44ba96e4f",
+   "67146882319b40398caa461a3ce86501bee19557",
    "testharness"
   ],
   "mathml/relations/css-styling/padding-border-margin/margin-002.html": [
-   "78e99c42cca58a60d8adf13f99dd95dc0db84462",
+   "87583b584a34faf3cf7cd54551f74ebf09009618",
    "testharness"
   ],
   "mathml/relations/css-styling/padding-border-margin/padding-001.html": [
-   "f195d4794030dcb0ee3770a446301466a7950a7e",
+   "afcd930452655f2265cf5929c28200e0668a3cc4",
    "testharness"
   ],
   "mathml/relations/css-styling/padding-border-margin/padding-002.html": [
-   "073faa1aeb3e7d25415a2827c77a911d40fbee5b",
+   "c634e4076e066686bb7bd5dd77e36716020f82c3",
    "testharness"
   ],
   "mathml/relations/css-styling/padding-border-margin/padding-border-margin-001-ref.html": [
@@ -443922,6 +443954,10 @@
    "8173b9cd2ef9162d6596c412d559abdb409d7267",
    "reftest"
   ],
+  "mathml/relations/css-styling/width-height-001.html": [
+   "8d52f48a2d95acd1c103a00694915331cbcfccb1",
+   "testharness"
+  ],
   "mathml/relations/css-styling/writing-mode/writing-mode-001.html": [
    "01a93eb15f0af1b4fc7455e5b208898cca6e88e3",
    "testharness"
@@ -444050,6 +444086,10 @@
    "4e92a846461b65d150cef9a9444de27abf40a26d",
    "reftest"
   ],
+  "mathml/support/box-comparison.js": [
+   "b1e91cdd99ad197bd1302353dcedf71b74c0edb3",
+   "support"
+  ],
   "mathml/support/feature-detection.js": [
    "50ca926d25ea810177068a5f5de29f39749db7e6",
    "support"
@@ -444170,6 +444210,14 @@
    "405b3bafbc0b7969ae696c5c245951a03e309819",
    "support"
   ],
+  "media-playback-quality/META.yml": [
+   "51b1b4e07ed2654d67d6e42083ed936e9d78848e",
+   "support"
+  ],
+  "media-playback-quality/idlharness.window.js": [
+   "2444e30c704457353145c252dcd7adf3432d35f0",
+   "testharness"
+  ],
   "media-source/META.yml": [
    "d1252f5af1b6718b54e4efbfb1f740e53b154561",
    "support"
@@ -483406,12 +483454,8 @@
    "a8b5a7154e94479460c1085c6b5cb584e9b6976c",
    "testharness"
   ],
-  "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel-expected.txt": [
-   "85e66d4dea10fca57cb5db88bda887a40502a586",
-   "support"
-  ],
   "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel.html": [
-   "a1a5f3fce54e11e33580ec875909e4e1645cf713",
+   "4f9a998c6ded83d564cbb1f8dc3e1edf0de3efb7",
    "testharness"
   ],
   "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-getChannelData.html": [
@@ -491235,7 +491279,7 @@
    "testharness"
   ],
   "webxr/idlharness.https.window-expected.txt": [
-   "519a938a41708a4dfabc26e0f29997267f84838c",
+   "b4ff722b1266759a41ff67988007d745067989cc",
    "support"
   ],
   "webxr/idlharness.https.window.js": [
@@ -491370,10 +491414,6 @@
    "f76c3c430e084709a73f6b419fba659667cd53a5",
    "testharness"
   ],
-  "webxr/xrRigidTransform_constructor.https-expected.txt": [
-   "b2e9421bda52b00e1db7563fe12617289086c58f",
-   "support"
-  ],
   "webxr/xrRigidTransform_constructor.https.html": [
    "15a7f2b5771a78dba2036ec46933e826c9a54355",
    "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/CSSAnimation-animationName.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-animations/CSSAnimation-animationName.tentative-expected.txt
deleted file mode 100644
index 8ac2b74..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-animations/CSSAnimation-animationName.tentative-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-FAIL Animation name makes keyframe rule assert_equals: Animation name matches keyframes rule name expected (string) "xyz" but got (undefined) undefined
-FAIL Escaped animation name assert_equals: Escaped animation name matches keyframes rule name expected (string) "xyz" but got (undefined) undefined
-FAIL Animation name with hex-escape assert_equals: Hex-escaped animation name matches keyframes rule name expected (string) "xyz" but got (undefined) undefined
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/CSSPseudoElement-getAnimations.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-animations/CSSPseudoElement-getAnimations.tentative-expected.txt
index 3d3f2b02..08e57b14 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-animations/CSSPseudoElement-getAnimations.tentative-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/CSSPseudoElement-getAnimations.tentative-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-FAIL getAnimations returns CSSAnimation objects assert_equals: CSS animation name matches expected (string) "anim1" but got (undefined) undefined
+PASS getAnimations returns CSSAnimation objects
 FAIL getAnimations returns CSS transitions/animations, and script-generated animations in the expected order assert_equals: 1st animation is the 1st transition sorted by name expected (string) "height" but got (undefined) undefined
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/Document-getAnimations.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-animations/Document-getAnimations.tentative-expected.txt
index 70dfff0..e2affb22 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-animations/Document-getAnimations.tentative-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/Document-getAnimations.tentative-expected.txt
@@ -1,12 +1,12 @@
 This is a testharness.js-based test.
 PASS getAnimations for non-animated content
 PASS getAnimations for CSS Animations
-FAIL Order of CSS Animations - within an element assert_equals: Order of first animation returned expected (string) "animLeft" but got (undefined) undefined
+PASS Order of CSS Animations - within an element
 FAIL Order of CSS Animations - across elements assert_equals: Order of second animation returned after tree surgery expected Element node <div style="animation: animLeft 100s"></div> but got Element node <div style="animation: animLeft 100s"></div>
-FAIL Order of CSS Animations - across and within elements assert_equals: Name of animation in position 0 expected (string) "animLeft" but got (undefined) undefined
-FAIL Order of CSS Animations - markup-bound vs free animations assert_equals: Originally, animLeft animation comes first expected (string) "animLeft" but got (undefined) undefined
+PASS Order of CSS Animations - across and within elements
+FAIL Order of CSS Animations - markup-bound vs free animations assert_equals: getAnimations returns markup-bound and free animations expected 2 but got 1
 FAIL Order of CSS Animations - free animations assert_equals: getAnimations returns free animations expected 2 but got 0
-FAIL Order of CSS Animations and CSS Transitions assert_equals: Transition comes first expected "[object CSSTransition]" but got "[object Animation]"
+FAIL Order of CSS Animations and CSS Transitions assert_equals: Transition comes first expected "[object CSSTransition]" but got "[object CSSAnimation]"
 PASS Finished but filling CSS Animations are returned
 PASS Finished but not filling CSS Animations are not returned
 PASS Yet-to-start CSS Animations are returned
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-snap-type-on-root-element-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-snap-type-on-root-element-expected.txt
deleted file mode 100644
index fd0d526..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-snap-type-on-root-element-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-FAIL The scroll-snap-type on the root element is applied assert_equals: expected 515 but got 800
-FAIL The writing-mode (vertical-lr) on the body is used assert_equals: inline should snap expected 515 but got 800
-FAIL The writing-mode (horizontal-tb) on the body is used  assert_equals: inline should snap expected 100 but got 200
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/computed/get-auto-min-size.html b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/computed/get-auto-min-size.html
new file mode 100644
index 0000000..3466fb2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/computed/get-auto-min-size.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#get-a-value-from-a-stylepropertymap">
+<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#valdef-width-auto">
+<meta name="assert" content="Tests computed StylePropertyMap.get of auto minimum sizes." />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<div style="display: flex;">
+  <div id="flex-inflow"></div>
+  <div id="flex-absolute" style="position: absolute;"></div>
+</div>
+<div style="display: grid;">
+  <div id="grid-inflow"></div>
+  <div id="grid-absolute" style="position: absolute;"></div>
+</div>
+<div id="block-inflow"></div>
+<div id="block-absolute" style="position: absolute;"></div>
+<script>
+'use strict';
+
+test(t => {
+  const targetMap = document.getElementById('flex-inflow').computedStyleMap();
+  assert_style_value_equals(targetMap.get('min-width'), new CSSKeywordValue('auto'));
+  assert_style_value_equals(targetMap.get('min-height'), new CSSKeywordValue('auto'));
+}, 'An inflow flex-item computed StylePropertyMap.get reports the auto minimum size correctly.');
+
+test(t => {
+  const targetMap = document.getElementById('flex-absolute').computedStyleMap();
+  assert_style_value_equals(targetMap.get('min-width'), new CSSKeywordValue('auto'));
+  assert_style_value_equals(targetMap.get('min-height'), new CSSKeywordValue('auto'));
+}, 'An absolute flex-child computed StylePropertyMap.get reports the auto minimum size correctly.');
+
+test(t => {
+  const targetMap = document.getElementById('grid-inflow').computedStyleMap();
+  assert_style_value_equals(targetMap.get('min-width'), new CSSKeywordValue('auto'));
+  assert_style_value_equals(targetMap.get('min-height'), new CSSKeywordValue('auto'));
+}, 'An inflow grid-item computed StylePropertyMap.get reports the auto minimum size correctly.');
+
+test(t => {
+  const targetMap = document.getElementById('grid-absolute').computedStyleMap();
+  assert_style_value_equals(targetMap.get('min-width'), new CSSKeywordValue('auto'));
+  assert_style_value_equals(targetMap.get('min-height'), new CSSKeywordValue('auto'));
+}, 'An absolute grid-child computed StylePropertyMap.get reports the auto minimum size correctly.');
+
+test(t => {
+  const targetMap = document.getElementById('block-inflow').computedStyleMap();
+  assert_style_value_equals(targetMap.get('min-width'), new CSSKeywordValue('auto'));
+  assert_style_value_equals(targetMap.get('min-height'), new CSSKeywordValue('auto'));
+}, 'An inflow block computed StylePropertyMap.get reports the auto minimum size correctly.');
+
+test(t => {
+  const targetMap = document.getElementById('block-absolute').computedStyleMap();
+  assert_style_value_equals(targetMap.get('min-width'), new CSSKeywordValue('auto'));
+  assert_style_value_equals(targetMap.get('min-height'), new CSSKeywordValue('auto'));
+}, 'An absolute block computed StylePropertyMap.get reports the auto minimum size correctly.');
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/elementFromPoint-list-001.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/elementFromPoint-list-001.html
new file mode 100644
index 0000000..e3c2c4d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/elementFromPoint-list-001.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Test elementFromPoint for list-item</title>
+<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint">
+<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ul.inside {
+  list-style-position: inside;
+}
+</style>
+<body>
+  <ul>
+    <li>Outside 1</li>
+    <li>Outside 2</li>
+    <li>Outside 3</li>
+  </ul>
+  <ul class="inside">
+    <li>Inside 1</li>
+    <li>Inside 2</li>
+    <li>Inside 3</li>
+  </ul>
+<script>
+for (let li of document.getElementsByTagName('li')) {
+  test(() => {
+    let bounds = li.getBoundingClientRect();
+    let target = document.elementFromPoint(bounds.x + 1, bounds.y + 1);
+    assert_equals(target, li);
+  }, `<li>${li.textContent}</li>`);
+}
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash.html b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash.html
index ef6f633..c063e285 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash.html
@@ -28,8 +28,6 @@
       var frameWin = document.getElementById("srcdoc-iframe").contentWindow;
       assert_equals(frameWin.location.href, "about:srcdoc");
       assert_equals(frameWin.scrollY, 0, "Should not have scrolled yet");
-      frameWin.location.hash = "";
-      assert_equals(frameWin.location.href, "about:srcdoc#", "Setting an empty hash should result in an empty fragment, not no fragment.");
       frameWin.location.hash = "test";
       assert_equals(frameWin.location.href, "about:srcdoc#test");
       assert_true(frameWin.scrollY > frameWin.innerHeight,
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/media-playback-quality.idl b/third_party/blink/web_tests/external/wpt/interfaces/media-playback-quality.idl
new file mode 100644
index 0000000..12b2c74
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/interfaces/media-playback-quality.idl
@@ -0,0 +1,15 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content was automatically extracted by Reffy into reffy-reports
+// (https://github.com/tidoust/reffy-reports)
+// Source: Media Playback Quality (https://w3c.github.io/media-playback-quality/)
+
+partial interface HTMLVideoElement {
+  VideoPlaybackQuality getVideoPlaybackQuality();
+};
+
+interface VideoPlaybackQuality {
+  readonly attribute DOMHighResTimeStamp creationTime;
+  readonly attribute unsigned long corruptedVideoFrames;
+  readonly attribute unsigned long droppedVideoFrames;
+  readonly attribute unsigned long totalVideoFrames;
+};
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-001.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-001.html
index 83eb924d..784491cf 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-001.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-001.html
@@ -8,7 +8,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/feature-detection.js"></script>
-<script src="helper.js"></script>
+<script src="/mathml/support/box-comparison.js"></script>
 <script>
   var epsilon = 1;
 
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-002.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-002.html
index cbf3efe..85a3dc2 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-002.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-002.html
@@ -8,7 +8,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/mathml-fragments.js"></script>
-<script src="helper.js"></script>
+<script src="/mathml/support/box-comparison.js"></script>
 <script>
   var epsilon = 1;
 
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-001.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-001.html
index c674d4c8..6714688 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-001.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-001.html
@@ -8,7 +8,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/feature-detection.js"></script>
-<script src="helper.js"></script>
+<script src="/mathml/support/box-comparison.js"></script>
 <script>
   var epsilon = 1;
 
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-002.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-002.html
index 78e99c42..87583b5 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-002.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-002.html
@@ -8,7 +8,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/mathml-fragments.js"></script>
-<script src="helper.js"></script>
+<script src="/mathml/support/box-comparison.js"></script>
 <script>
   var epsilon = 1;
 
@@ -54,6 +54,18 @@
             assert_approx_equals(s.element_width_delta, 0, epsilon, "element width");
             assert_approx_equals(s.element_height_delta, 0, epsilon, "element height");
         }, `Margin properties on ${tag} (rtl)`);
+
+        test(function() {
+            // Apply the same margin style on the parent mrow.
+            // The margins are not collapsed so they should be added twice.
+            var s = compareSpaceWithAndWithoutStyle(tag, style, style);
+            assert_approx_equals(s.left_delta, 30 * 2, epsilon, "left margin");
+            assert_approx_equals(s.right_delta, 40 * 2, epsilon, "right margin");
+            assert_approx_equals(s.top_delta, 50 * 2, epsilon, "top margin");
+            assert_approx_equals(s.bottom_delta, 60 * 2, epsilon, "bottom margin");
+            assert_approx_equals(s.element_width_delta, 0, epsilon, "element width");
+            assert_approx_equals(s.element_height_delta, 0, epsilon, "element height");
+        }, `Margin properties on ${tag} (no margin-collapsing)`);
     }
 
     done();
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-001.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-001.html
index f195d47..afcd930 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-001.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-001.html
@@ -8,7 +8,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/feature-detection.js"></script>
-<script src="helper.js"></script>
+<script src="/mathml/support/box-comparison.js"></script>
 <script>
   var epsilon = 1;
 
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-002.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-002.html
index 073faa1..c634e40 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-002.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-002.html
@@ -8,7 +8,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/mathml-fragments.js"></script>
-<script src="helper.js"></script>
+<script src="/mathml/support/box-comparison.js"></script>
 <script>
   var epsilon = 1;
 
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/width-height-001.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/width-height-001.html
new file mode 100644
index 0000000..8d52f48
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/width-height-001.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>width, height, inline-size and block-size</title>
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-algorithms">
+<meta name="assert" content="Verify that width, height, inline-size and block-size properties are ignored.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/mathml/support/mathml-fragments.js"></script>
+<script src="/mathml/support/box-comparison.js"></script>
+<script>
+  var epsilon = 1;
+
+  setup({ explicit_done: true });
+  window.addEventListener("load", runTests);
+
+  function runTests() {
+
+    for (tag in MathMLFragments) {
+        if (!FragmentHelper.isValidChildOfMrow(tag) || tag === "mtable")
+            continue;
+
+        test(function() {
+            var style = "width: 500px; height: 400px;";
+            var s = compareSizeWithAndWithoutStyle(tag, style);
+            assert_approx_equals(s.width_delta, 0, epsilon, "width");
+            assert_approx_equals(s.height_delta, 0, epsilon, "height");
+            assert_approx_equals(s.element_width_delta, 0, epsilon, "element width");
+            assert_approx_equals(s.element_height_delta, 0, epsilon, "element height");
+        }, `width and height properties on ${tag}`);
+
+        test(function() {
+            var style = "inline-size: 500px; block-size: 400px;";
+            var s = compareSizeWithAndWithoutStyle(tag, style);
+            assert_approx_equals(s.width_delta, 0, epsilon, "width");
+            assert_approx_equals(s.height_delta, 0, epsilon, "height");
+            assert_approx_equals(s.element_width_delta, 0, epsilon, "element width");
+            assert_approx_equals(s.element_height_delta, 0, epsilon, "element height");
+        }, `inline-size and block-size properties on ${tag}`);
+    }
+
+    done();
+  }
+</script>
+</head>
+<body>
+  <div id="log"></div>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/helper.js b/third_party/blink/web_tests/external/wpt/mathml/support/box-comparison.js
similarity index 91%
rename from third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/helper.js
rename to third_party/blink/web_tests/external/wpt/mathml/support/box-comparison.js
index c7b4b0a1..b1e91cd 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/helper.js
+++ b/third_party/blink/web_tests/external/wpt/mathml/support/box-comparison.js
@@ -15,18 +15,21 @@
     return spaceBetween(childBox, parentBox);
 }
 
-function compareSpaceWithAndWithoutStyle(tag, style) {
+function compareSpaceWithAndWithoutStyle(tag, style, parentStyle) {
     if (!FragmentHelper.isValidChildOfMrow(tag) ||
         FragmentHelper.isEmpty(tag))
         throw `Invalid argument: ${tag}`;
 
     document.body.insertAdjacentHTML("beforeend", `<div>\
-<math>${MathMLFragments[tag]}</math>\
-<math>${MathMLFragments[tag]}</math>\
+<math><mrow>${MathMLFragments[tag]}</mrow></math>\
+<math><mrow>${MathMLFragments[tag]}</mrow></math>\
 </div>`);
     var div = document.body.lastElementChild;
 
     var styleMath = div.firstElementChild;
+    var styleParent = styleMath.firstElementChild;
+    if (parentStyle)
+        styleParent.setAttribute("style", parentStyle);
     var styleElement = FragmentHelper.element(styleMath);
     styleElement.setAttribute("style", style);
     var styleChild = FragmentHelper.forceNonEmptyElement(styleElement);
diff --git a/third_party/blink/web_tests/external/wpt/media-playback-quality/META.yml b/third_party/blink/web_tests/external/wpt/media-playback-quality/META.yml
new file mode 100644
index 0000000..51b1b4e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/media-playback-quality/META.yml
@@ -0,0 +1,3 @@
+spec: https://w3c.github.io/media-playback-quality/
+suggested_reviewers:
+  - mounirlamouri
diff --git a/third_party/blink/web_tests/external/wpt/media-playback-quality/idlharness.window.js b/third_party/blink/web_tests/external/wpt/media-playback-quality/idlharness.window.js
new file mode 100644
index 0000000..2444e30
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/media-playback-quality/idlharness.window.js
@@ -0,0 +1,20 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://w3c.github.io/media-playback-quality/
+
+'use strict';
+
+idl_test(
+  ['media-playback-quality'],
+  ['html', 'dom'],
+  idl_array => {
+    idl_array.add_objects({
+      HTMLVideoElement: ['video'],
+      VideoPlaybackQuality: ['videoPlaybackQuality']
+    });
+
+    self.video = document.createElement('video');
+    self.videoPlaybackQuality = video.getVideoPlaybackQuality();
+  }
+);
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https-expected.txt
deleted file mode 100644
index b2e9421b..0000000
--- a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-FAIL XRRigidTransform constructor works assert_throws: Constructor should throw TypeError for non-1 position w values function "() => new XRRigidTransform(
-      coordDict([1.0, 2.0, 3.0, 0.5]),
-      coordDict([1.1, 2.1, 3.1, 1.0])
-  )" did not throw
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/resources/calendar-picker-common.js b/third_party/blink/web_tests/fast/forms/calendar-picker/resources/calendar-picker-common.js
index 36374f78..ae72773 100644
--- a/third_party/blink/web_tests/fast/forms/calendar-picker/resources/calendar-picker-common.js
+++ b/third_party/blink/web_tests/fast/forms/calendar-picker/resources/calendar-picker-common.js
@@ -69,8 +69,8 @@
     var y = offset[1];
     if (popupWindow.global.picker.calendarTableView.hasWeekNumberColumn)
         x += popupWindow.WeekNumberCell.Width;
-    x += (column + 0.5) * popupWindow.DayCell.Width;
-    y += (row + 0.5) * popupWindow.DayCell.Height + popupWindow.CalendarTableHeaderView.Height;
+    x += (column + 0.5) * popupWindow.DayCell.GetWidth();
+    y += (row + 0.5) * popupWindow.DayCell.GetHeight() + popupWindow.CalendarTableHeaderView.GetHeight();
     eventSender.mouseMoveTo(x, y);
 };
 
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..9fe2c52f
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse.html
new file mode 100644
index 0000000..44973ee
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script>
+testRunner.setUseMockTheme(false);
+testRunner.waitUntilDone();
+</script>
+<script src="../../../forms/resources/picker-common.js"></script>
+<input type=date id=date value="10000-12-31">
+<script>
+internals.settings.setAvailablePointerTypes('fine,coarse');
+internals.settings.setPrimaryPointerType('fine')
+openPicker(document.getElementById('date'), () => testRunner.notifyDone());
+</script>
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..13d12f25
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..b6881de
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl.html
new file mode 100644
index 0000000..5e92a8f
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html dir="rtl">
+<script>
+testRunner.setUseMockTheme(false);
+testRunner.waitUntilDone();
+if (window.internals)
+    internals.settings.setLangAttributeAwareFormControlUIEnabled(true);
+</script>
+<script src="../../../forms/resources/picker-common.js"></script>
+<input type=date id=date value="1800-05-12" lang="ar-AE">
+<script>
+openPicker(document.getElementById('date'), () => testRunner.notifyDone());
+</script>
+</html>
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..10e5d62
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step.html
new file mode 100644
index 0000000..0a287e8
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+testRunner.setUseMockTheme(false);
+testRunner.waitUntilDone();
+</script>
+<script src="../../../forms/resources/picker-common.js"></script>
+<!-- Check if step attribute is reflected in the appearance of the calendar picker.  -->
+<input type="date" id="date" value="2010-12-31" step="3">
+<script>
+openPicker(document.getElementById('date'), () => testRunner.notifyDone());
+</script>
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..2e52d8f
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150.html
new file mode 100644
index 0000000..13e65da
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<script>
+testRunner.setUseMockTheme(false);
+testRunner.waitUntilDone();
+</script>
+<script src="../../../forms/resources/picker-common.js"></script>
+<body style="zoom: 1.5">
+<p>Calendar picker should respect zoom level.</p>
+<input type=date id=date value="2013-01-10">
+<script>
+openPicker(document.getElementById('date'), () => testRunner.notifyDone());
+</script>
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance.html
new file mode 100644
index 0000000..2a24a302
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<script>
+testRunner.setUseMockTheme(false);
+testRunner.waitUntilDone();
+</script>
+<script src="../../../forms/resources/picker-common.js"></script>
+<input type=date id=date value="10000-12-31">
+<script>
+openPicker(document.getElementById('date'), () => testRunner.notifyDone());
+</script>
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..f8b63e9
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values.html
new file mode 100644
index 0000000..a304ae0
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<script>
+testRunner.setUseMockTheme(false);
+testRunner.waitUntilDone();
+</script>
+<script src="../../../forms/resources/picker-common.js"></script>
+<input type=date id=date min="2019-06-02" value="2019-06-11" max="2019-06-23">
+<script>
+openPicker(document.getElementById('date'), () => testRunner.notifyDone());
+</script>
diff --git a/third_party/blink/web_tests/fast/loader/hashchange-event-expected.txt b/third_party/blink/web_tests/fast/loader/hashchange-event-expected.txt
index d6dd0c2..8e69dc91 100644
--- a/third_party/blink/web_tests/fast/loader/hashchange-event-expected.txt
+++ b/third_party/blink/web_tests/fast/loader/hashchange-event-expected.txt
@@ -22,12 +22,6 @@
 ALERT: Test number 1.
 hashchange event received by body-onhashchange-attribute.
 A total of 8 events have been received.
-ALERT: Test number 1.
-hashchange event received by window-event-listener.
-A total of 9 events have been received.
-ALERT: Test number 1.
-hashchange event received by body-onhashchange-attribute.
-A total of 10 events have been received.
 ALERT: Test number 2.
 hashchange event received by window-event-listener.
 A total of 1 events have been received.
diff --git a/third_party/blink/web_tests/fast/loader/hashchange-event.html b/third_party/blink/web_tests/fast/loader/hashchange-event.html
index e5535606..44bbcba 100644
--- a/third_party/blink/web_tests/fast/loader/hashchange-event.html
+++ b/third_party/blink/web_tests/fast/loader/hashchange-event.html
@@ -7,7 +7,7 @@
     location.href = "http://webkit.org/";
 }
 
-var targetNumberOfEventsForFirstTest = 10;
+var targetNumberOfEventsForFirstTest = 8;
 var targetNumberOfEventsForSecondTest = 10;
 
 var testNumber = 1;
diff --git a/third_party/blink/web_tests/fast/scroll-snap/snap-scrolls-visual-viewport.html b/third_party/blink/web_tests/fast/scroll-snap/snap-scrolls-visual-viewport.html
index 071287a..9b66f8f 100644
--- a/third_party/blink/web_tests/fast/scroll-snap/snap-scrolls-visual-viewport.html
+++ b/third_party/blink/web_tests/fast/scroll-snap/snap-scrolls-visual-viewport.html
@@ -3,9 +3,11 @@
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
 <style>
+html {
+  scroll-snap-type: both proximity;
+}
 body {
   overflow: scroll;
-  scroll-snap-type: both proximity;
   height: 300px;
   width: 300px;
   margin: 0px;
diff --git a/third_party/blink/web_tests/http/tests/devtools/network/network-cookies-pane-expected.txt b/third_party/blink/web_tests/http/tests/devtools/network/network-cookies-pane-expected.txt
index 6e1b4ef3..148c514 100644
--- a/third_party/blink/web_tests/http/tests/devtools/network/network-cookies-pane-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/network/network-cookies-pane-expected.txt
@@ -10,6 +10,7 @@
 HttpOnly
 Secure
 SameSite
+Name	Value	Domain	Path	Expires / Max-Age	Size	HttpOnly	Secure	SameSite
 Request Cookies					33
 mycookie	myvalue	N/A	N/A	N/A	17
 myother	myvalue2	N/A	N/A	N/A	16
diff --git a/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle-expected.txt b/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle-expected.txt
index b549b5aa..0fd9419b 100644
--- a/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle-expected.txt
+++ b/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle-expected.txt
@@ -3,7 +3,6 @@
 main frame - didCommitLoadForFrame
 main frame - didReceiveTitle: 
 main frame - didFinishDocumentLoadForFrame
-main frame - didCommitLoadForFrame
 main frame - didHandleOnloadEventsForFrame
 main frame - didFinishLoadForFrame
 This test checks that no loader actions occur when setting window.location.hash to the empty string or "#". If this test fails when run in a browser, it will reload continuously. If this test fails when run in DumpRenderTree, the FrameLoader callback output will contain willPerformClientRedirectToURL callbacks.
diff --git a/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle.html b/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle.html
index 768c814..7dc51bc 100644
--- a/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle.html
+++ b/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle.html
@@ -5,7 +5,7 @@
 {
     if (window.testRunner)
         testRunner.dumpAsText();
-
+    
     window.location.hash = "";
     window.location.hash = "#";
 }
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..988d42a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..0dbb98f35
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..2654253
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..0de9f795
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..f60570a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..e49e4e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..f20b199
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..f20b199
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..4edd1b3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..136c580
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..0a49e19
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..b6bac0a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..c9ef490
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..ae4e839
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..bb67e7c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..5eff5f99
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..261137d8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..816def4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..f733abe
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..f733abe
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..b854a9a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..115ff473
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..03a5c4a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..e3252da3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..336923ee
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..62b88735
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..f9aef8b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..388b77b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..7065ada8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..45f59157
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..2d34bb6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..2d34bb6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..384b9f0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..361c7c2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..c1ac6850
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..39e8bb9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..941db107
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..0a4928e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..69c6e0b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..1e2baae
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..759f717
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..23942de
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..77307a2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..77307a2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..f95854f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..0aec8266
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..8c3a46a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..74f97842
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..07fe60a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..07fe60a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..930ea3ae
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..093b0e1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..df6ebb8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..5dd0905b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..eaa5350
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..43671ad
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..0e3daf2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..3dce6871
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..55b456a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..f7547b3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..07fe60a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..07fe60a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..930ea3ae
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..093b0e1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..df6ebb8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..5dd0905b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..77bf3be1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..77bf3be1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..aeb000f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..090ae1c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..0f0a004
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..10f3716
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..b671839
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..f07e582
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..8e8f349
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..08512390
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..ec0fe7d6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..ec0fe7d6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..3f2843dc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..e867750
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..34e58dff
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..47d84b90
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
new file mode 100644
index 0000000..2256a41
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
new file mode 100644
index 0000000..2256a41
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..c29a571
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
new file mode 100644
index 0000000..a9be530
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..fc955772
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
new file mode 100644
index 0000000..f4b9d21
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 5ee3295..4e29c3d 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -639,6 +639,10 @@
     static method vw
     attribute @@toStringTag
     method constructor
+interface CSSAnimation : Animation
+    attribute @@toStringTag
+    getter animationName
+    method constructor
 interface CSSConditionRule : CSSGroupingRule
     attribute @@toStringTag
     getter conditionText
diff --git a/third_party/byte_buddy/OWNERS b/third_party/byte_buddy/OWNERS
index 7fcd92b..99c5a7bc 100644
--- a/third_party/byte_buddy/OWNERS
+++ b/third_party/byte_buddy/OWNERS
@@ -1,3 +1,4 @@
 jbudorick@chromium.org
 mikecase@chromium.org
-yolandyan@chromium.org
\ No newline at end of file
+yolandyan@chromium.org
+# COMPONENT: Test>Android
diff --git a/third_party/polymer/v1_0/generate_gn.sh b/third_party/polymer/v1_0/generate_gn.sh
index fe93904f..2cae8c9 100755
--- a/third_party/polymer/v1_0/generate_gn.sh
+++ b/third_party/polymer/v1_0/generate_gn.sh
@@ -6,13 +6,26 @@
 dirs=$(find components-chromium -type d | grep -v 'components-chromium/polymer')
 
 gn_files=''
+polymer_version=$1
+
+if [ "$polymer_version" -eq 3 ];
+  then
+    file_extension="js";
+  else
+    file_extension="html";
+fi
 
 for dir in $dirs; do
-  htmls=$(\ls $dir/*.html 2>/dev/null)
-  if [ "$htmls" ]; then
+  files=$(\ls $dir/*.$file_extension 2>/dev/null)
+  if [ "$files" ]; then
     echo "Analyzing $dir"
     gn_file="$dir/BUILD.gn"
-    content=$(../../../tools/polymer/generate_gn.py $htmls)
+    if [ "$polymer_version" -eq 3 ];
+      then
+        content=$(../../../tools/polymer/generate_gn_v3.py $files);
+      else
+        content=$(../../../tools/polymer/generate_gn.py $files);
+    fi
     if [ "$content" ]; then
       echo "Writing $gn_file"
       echo "$content" > "$gn_file"
@@ -25,4 +38,12 @@
   fi
 done
 
+# Copy components-chromium/polymer BUILD.gn file manually, since it is not
+# auto-generated by generate_gn_v3.py.
+if [ "$polymer_version" -eq 3 ];
+  then
+    cp ./BUILD_polymer.gn "components-chromium/polymer/BUILD.gn"
+fi
+
+
 git cl format $gn_files
diff --git a/third_party/polymer/v1_0/reproduce.sh b/third_party/polymer/v1_0/reproduce.sh
index 9b73718f..30d4b37 100755
--- a/third_party/polymer/v1_0/reproduce.sh
+++ b/third_party/polymer/v1_0/reproduce.sh
@@ -108,7 +108,7 @@
 python create_components_summary.py > components_summary.txt
 
 echo 'Creating GN files for interfaces and externs...'
-./generate_gn.sh
+./generate_gn.sh 2 # polymer_version=2
 
 popd > /dev/null
 
diff --git a/third_party/polymer/v3_0/BUILD_polymer.gn b/third_party/polymer/v3_0/BUILD_polymer.gn
new file mode 100644
index 0000000..789242f
--- /dev/null
+++ b/third_party/polymer/v3_0/BUILD_polymer.gn
@@ -0,0 +1,15 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("polymer_bundled") {
+  externs_list = [
+    "./externs/closure-types.js",
+    "./externs/polymer-dom-api-externs.js",
+    "./externs/polymer-externs.js",
+    "./externs/shadycss-externs.js",
+    "./externs/webcomponents-externs.js",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/font-roboto/BUILD.gn b/third_party/polymer/v3_0/components-chromium/font-roboto/BUILD.gn
new file mode 100644
index 0000000..e5345d2
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/font-roboto/BUILD.gn
@@ -0,0 +1,10 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("roboto") {
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-a11y-announcer/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-a11y-announcer/BUILD.gn
new file mode 100644
index 0000000..91fc0d46f
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-a11y-announcer/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-a11y-announcer") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-a11y-keys-behavior/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-a11y-keys-behavior/BUILD.gn
new file mode 100644
index 0000000..953a4cfb
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-a11y-keys-behavior/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-a11y-keys-behavior") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-a11y-keys/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-a11y-keys/BUILD.gn
new file mode 100644
index 0000000..a95f20a8
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-a11y-keys/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-a11y-keys") {
+  deps = [
+    "../iron-a11y-keys-behavior:iron-a11y-keys-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-behaviors/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-behaviors/BUILD.gn
new file mode 100644
index 0000000..9622f7e
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-behaviors/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-button-state") {
+  deps = [
+    ".:iron-control-state",
+    "../iron-a11y-keys-behavior:iron-a11y-keys-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-control-state") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-collapse/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-collapse/BUILD.gn
new file mode 100644
index 0000000..51a622a
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-collapse/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-collapse") {
+  deps = [
+    "../iron-resizable-behavior:iron-resizable-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-dropdown/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-dropdown/BUILD.gn
new file mode 100644
index 0000000..4d12238
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-dropdown/BUILD.gn
@@ -0,0 +1,23 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-dropdown") {
+  deps = [
+    "../iron-a11y-keys-behavior:iron-a11y-keys-behavior",
+    "../iron-behaviors:iron-control-state",
+    "../iron-overlay-behavior:iron-overlay-behavior",
+    "../neon-animation:neon-animation-runner-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-dropdown-scroll-manager") {
+  deps = [
+    "../iron-overlay-behavior:iron-scroll-manager",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-fit-behavior/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-fit-behavior/BUILD.gn
new file mode 100644
index 0000000..49cc0041
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-fit-behavior/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-fit-behavior") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-flex-layout/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-flex-layout/BUILD.gn
new file mode 100644
index 0000000..3a0fc2cf
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-flex-layout/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-flex-layout") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-flex-layout-classes") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-icon/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-icon/BUILD.gn
new file mode 100644
index 0000000..9974bafe
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-icon/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-icon") {
+  deps = [
+    "../iron-flex-layout:iron-flex-layout",
+    "../iron-meta:iron-meta",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-iconset-svg/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-iconset-svg/BUILD.gn
new file mode 100644
index 0000000..e7ac6ba08
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-iconset-svg/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-iconset-svg") {
+  deps = [
+    "../iron-meta:iron-meta",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-input/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-input/BUILD.gn
new file mode 100644
index 0000000..f6a553c
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-input/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-input") {
+  deps = [
+    "../iron-a11y-announcer:iron-a11y-announcer",
+    "../iron-validatable-behavior:iron-validatable-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-list/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-list/BUILD.gn
new file mode 100644
index 0000000..b5f9129
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-list/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-list") {
+  deps = [
+    "../iron-a11y-keys-behavior:iron-a11y-keys-behavior",
+    "../iron-resizable-behavior:iron-resizable-behavior",
+    "../iron-scroll-target-behavior:iron-scroll-target-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-location/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-location/BUILD.gn
new file mode 100644
index 0000000..043c444e
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-location/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-location") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-query-params") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-media-query/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-media-query/BUILD.gn
new file mode 100644
index 0000000..d0a473f
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-media-query/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-media-query") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-meta/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-meta/BUILD.gn
new file mode 100644
index 0000000..dae2816e
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-meta/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-meta") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/BUILD.gn
new file mode 100644
index 0000000..1d276827
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/BUILD.gn
@@ -0,0 +1,44 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-focusables-helper") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-overlay-backdrop") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-overlay-behavior") {
+  deps = [
+    ".:iron-focusables-helper",
+    ".:iron-overlay-manager",
+    ".:iron-scroll-manager",
+    "../iron-fit-behavior:iron-fit-behavior",
+    "../iron-resizable-behavior:iron-resizable-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-overlay-manager") {
+  deps = [
+    ".:iron-overlay-backdrop",
+    "../iron-a11y-keys-behavior:iron-a11y-keys-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-scroll-manager") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-pages/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-pages/BUILD.gn
new file mode 100644
index 0000000..d29f7e9
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-pages/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-pages") {
+  deps = [
+    "../iron-resizable-behavior:iron-resizable-behavior",
+    "../iron-selector:iron-selectable",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-range-behavior/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-range-behavior/BUILD.gn
new file mode 100644
index 0000000..f4822f8
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-range-behavior/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-range-behavior") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-resizable-behavior/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-resizable-behavior/BUILD.gn
new file mode 100644
index 0000000..0f96c9d
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-resizable-behavior/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-resizable-behavior") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-scroll-target-behavior/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-scroll-target-behavior/BUILD.gn
new file mode 100644
index 0000000..26d261a9
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-scroll-target-behavior/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-scroll-target-behavior") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-scroll-threshold/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-scroll-threshold/BUILD.gn
new file mode 100644
index 0000000..d75b199
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-scroll-threshold/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-scroll-threshold") {
+  deps = [
+    "../iron-scroll-target-behavior:iron-scroll-target-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-selector/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-selector/BUILD.gn
new file mode 100644
index 0000000..9736a67b
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-selector/BUILD.gn
@@ -0,0 +1,34 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-multi-selectable") {
+  deps = [
+    ".:iron-selectable",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-selectable") {
+  deps = [
+    ".:iron-selection",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-selection") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("iron-selector") {
+  deps = [
+    ".:iron-multi-selectable",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-test-helpers/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-test-helpers/BUILD.gn
new file mode 100644
index 0000000..7c9dd2c
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-test-helpers/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("mock-interactions") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/iron-validatable-behavior/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-validatable-behavior/BUILD.gn
new file mode 100644
index 0000000..fd0d308a
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/iron-validatable-behavior/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("iron-validatable-behavior") {
+  deps = [
+    "../iron-meta:iron-meta",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/neon-animation/BUILD.gn b/third_party/polymer/v3_0/components-chromium/neon-animation/BUILD.gn
new file mode 100644
index 0000000..7a01eaba
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/neon-animation/BUILD.gn
@@ -0,0 +1,43 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("neon-animatable") {
+  deps = [
+    ".:neon-animatable-behavior",
+    "../iron-resizable-behavior:iron-resizable-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("neon-animatable-behavior") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("neon-animated-pages") {
+  deps = [
+    ".:neon-animation-runner-behavior",
+    "../iron-resizable-behavior:iron-resizable-behavior",
+    "../iron-selector:iron-selectable",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("neon-animation-behavior") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("neon-animation-runner-behavior") {
+  deps = [
+    ".:neon-animatable-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/neon-animation/animations/BUILD.gn b/third_party/polymer/v3_0/components-chromium/neon-animation/animations/BUILD.gn
new file mode 100644
index 0000000..0c6a170
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/neon-animation/animations/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("fade-in-animation") {
+  deps = [
+    "..:neon-animation-behavior",
+    "../../polymer:polymer_bundled",
+  ]
+}
+
+js_library("fade-out-animation") {
+  deps = [
+    "..:neon-animation-behavior",
+    "../../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/paper-behaviors/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-behaviors/BUILD.gn
new file mode 100644
index 0000000..2665a266
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/paper-behaviors/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("paper-inky-focus-behavior") {
+  deps = [
+    ".:paper-ripple-behavior",
+    "../iron-behaviors:iron-button-state",
+    "../iron-behaviors:iron-control-state",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("paper-ripple-behavior") {
+  deps = [
+    "../iron-behaviors:iron-button-state",
+    "../paper-ripple:paper-ripple",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/paper-input/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-input/BUILD.gn
new file mode 100644
index 0000000..575500af
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/paper-input/BUILD.gn
@@ -0,0 +1,31 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("paper-input-addon-behavior") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("paper-input-container") {
+  deps = [
+    "../iron-flex-layout:iron-flex-layout",
+    "../paper-styles:default-theme",
+    "../paper-styles:typography",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("paper-input-error") {
+  deps = [
+    ".:paper-input-addon-behavior",
+    "../paper-styles:default-theme",
+    "../paper-styles:typography",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/paper-progress/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-progress/BUILD.gn
new file mode 100644
index 0000000..1da4c66
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/paper-progress/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("paper-progress") {
+  deps = [
+    "../iron-flex-layout:iron-flex-layout",
+    "../iron-range-behavior:iron-range-behavior",
+    "../paper-styles:color",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/paper-ripple/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-ripple/BUILD.gn
new file mode 100644
index 0000000..79ddb10
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/paper-ripple/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("paper-ripple") {
+  deps = [
+    "../iron-a11y-keys-behavior:iron-a11y-keys-behavior",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/paper-spinner/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-spinner/BUILD.gn
new file mode 100644
index 0000000..4d998d0
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/paper-spinner/BUILD.gn
@@ -0,0 +1,25 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("paper-spinner-behavior") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("paper-spinner-lite") {
+  deps = [
+    ".:paper-spinner-behavior",
+    ".:paper-spinner-styles",
+    "../paper-styles:color",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("paper-spinner-styles") {
+}
diff --git a/third_party/polymer/v3_0/components-chromium/paper-styles/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-styles/BUILD.gn
new file mode 100644
index 0000000..2c4b5bf1
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/paper-styles/BUILD.gn
@@ -0,0 +1,43 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("color") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("default-theme") {
+  deps = [
+    ".:color",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("demo-pages") {
+  deps = [
+    ".:color",
+    ".:shadow",
+    ".:typography",
+    "../iron-flex-layout:iron-flex-layout",
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("shadow") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
+
+js_library("typography") {
+  deps = [
+    "../font-roboto:roboto",
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/paper-styles/classes/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-styles/classes/BUILD.gn
new file mode 100644
index 0000000..ced3624
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/paper-styles/classes/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("global") {
+  deps = [
+    "..:paper-styles-classes",
+    "../../polymer:polymer_bundled",
+  ]
+}
+
+js_library("shadow") {
+  deps = [
+    "../../polymer:polymer_bundled",
+  ]
+}
+
+js_library("typography") {
+  deps = [
+    "../../font-roboto:roboto",
+    "../../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/paper-styles/element-styles/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-styles/element-styles/BUILD.gn
new file mode 100644
index 0000000..00797a2d
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/paper-styles/element-styles/BUILD.gn
@@ -0,0 +1,23 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("paper-item-styles") {
+  deps = [
+    "..:color",
+    "..:default-theme",
+    "..:typography",
+    "../../polymer:polymer_bundled",
+  ]
+}
+
+js_library("paper-material-styles") {
+  deps = [
+    "..:shadow",
+    "../../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/paper-tooltip/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-tooltip/BUILD.gn
new file mode 100644
index 0000000..7af0c00
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/paper-tooltip/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# NOTE: Created with generate_gn_v3.py, please do not edit.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("paper-tooltip") {
+  deps = [
+    "../polymer:polymer_bundled",
+  ]
+}
diff --git a/third_party/polymer/v3_0/components-chromium/polymer/BUILD.gn b/third_party/polymer/v3_0/components-chromium/polymer/BUILD.gn
new file mode 100644
index 0000000..789242f
--- /dev/null
+++ b/third_party/polymer/v3_0/components-chromium/polymer/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("polymer_bundled") {
+  externs_list = [
+    "./externs/closure-types.js",
+    "./externs/polymer-dom-api-externs.js",
+    "./externs/polymer-externs.js",
+    "./externs/shadycss-externs.js",
+    "./externs/webcomponents-externs.js",
+  ]
+}
diff --git a/third_party/polymer/v3_0/package-lock.json b/third_party/polymer/v3_0/package-lock.json
index 3edb5c33..0873cdb 100644
--- a/third_party/polymer/v3_0/package-lock.json
+++ b/third_party/polymer/v3_0/package-lock.json
@@ -345,12 +345,14 @@
     "@types/estree": {
       "version": "0.0.39",
       "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
-      "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="
+      "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+      "dev": true
     },
     "@types/node": {
       "version": "12.0.3",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.3.tgz",
-      "integrity": "sha512-zkOxCS/fA+3SsdA+9Yun0iANxzhQRiNwTvJSr6N95JhuJ/x27z9G2URx1Jpt3zYFfCGUXZGL5UDxt5eyLE7wgw=="
+      "integrity": "sha512-zkOxCS/fA+3SsdA+9Yun0iANxzhQRiNwTvJSr6N95JhuJ/x27z9G2URx1Jpt3zYFfCGUXZGL5UDxt5eyLE7wgw==",
+      "dev": true
     },
     "@webcomponents/shadycss": {
       "version": "1.9.1",
@@ -360,12 +362,14 @@
     "acorn": {
       "version": "6.1.1",
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
-      "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA=="
+      "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
+      "dev": true
     },
     "rollup": {
       "version": "1.12.4",
       "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.12.4.tgz",
       "integrity": "sha512-sHg0F05oTMJzM592MWU8irsPx8LIFMKSCnEkcp6vp/gnj+oJ9GJEBW9hl8jUqy2L6Q2uUxFzPgvoExLbfuSODA==",
+      "dev": true,
       "requires": {
         "@types/estree": "0.0.39",
         "@types/node": "^12.0.2",
diff --git a/third_party/polymer/v3_0/package.json b/third_party/polymer/v3_0/package.json
index 73bbc37..5f65c73 100644
--- a/third_party/polymer/v3_0/package.json
+++ b/third_party/polymer/v3_0/package.json
@@ -37,7 +37,10 @@
     "@polymer/paper-styles": "3.0.1",
     "@polymer/paper-tooltip": "3.0.1",
     "@polymer/polymer": "3.2.0",
-    "@webcomponents/shadycss": "1.9.1",
+    "@webcomponents/shadycss": "1.9.1"
+  },
+  "devDependencies": {
+    "acorn": "6.1.1",
     "rollup": "1.12.4"
   }
 }
diff --git a/third_party/polymer/v3_0/reproduce.sh b/third_party/polymer/v3_0/reproduce.sh
index d75b595..1e86315 100755
--- a/third_party/polymer/v3_0/reproduce.sh
+++ b/third_party/polymer/v3_0/reproduce.sh
@@ -26,7 +26,9 @@
 
 rm -rf node_modules
 
-npm install --production
+# Note: The --production flag is omitted, such that devDependencies
+# referenced later by this script are also downloaded.
+npm install
 
 rsync -c --delete --delete-excluded -r -v --prune-empty-dirs \
     --exclude-from="rsync_exclude.txt" \
@@ -90,5 +92,8 @@
     components-chromium/paper-styles/color.js
 
 # TODO create components summary
-# TODO generate gn
+
+echo 'Creating GN files for interfaces and externs...'
+../v1_0/generate_gn.sh 3 # polymer_version=3
+
 # TODO find unused elements?
diff --git a/third_party/sqlite4java/OWNERS b/third_party/sqlite4java/OWNERS
index 2cfd26c3..99c5a7bc 100644
--- a/third_party/sqlite4java/OWNERS
+++ b/third_party/sqlite4java/OWNERS
@@ -1,3 +1,4 @@
 jbudorick@chromium.org
 mikecase@chromium.org
 yolandyan@chromium.org
+# COMPONENT: Test>Android
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py
index 714e5afe..8573b1aa 100755
--- a/tools/code_coverage/coverage.py
+++ b/tools/code_coverage/coverage.py
@@ -143,7 +143,7 @@
     'If it persists, please file a bug with the command you used, git revision '
     'and args.gn config here: '
     'https://bugs.chromium.org/p/chromium/issues/entry?'
-    'components=Tools%3ECodeCoverage')
+    'components=Infra%3ETest%3ECodeCoverage')
 
 # String to replace with actual llvm profile path.
 LLVM_PROFILE_FILE_PATH_SUBSTITUTION = '<llvm_profile_file_path>'
diff --git a/tools/json_schema_compiler/idl_schema.py b/tools/json_schema_compiler/idl_schema.py
index f52f7e3..ed8b08fa 100755
--- a/tools/json_schema_compiler/idl_schema.py
+++ b/tools/json_schema_compiler/idl_schema.py
@@ -190,7 +190,7 @@
     if self.node.GetProperty('deprecated'):
       properties['deprecated'] = self.node.GetProperty('deprecated')
 
-    for property_name in ['allowAmbiguousOptionalArguments', 'forIOThread',
+    for property_name in ['allowAmbiguousOptionalArguments',
                           'nodoc', 'nocompile', 'nodart', 'nodefine']:
       if self.node.GetProperty(property_name):
         properties[property_name] = True
diff --git a/tools/json_schema_compiler/idl_schema_test.py b/tools/json_schema_compiler/idl_schema_test.py
index b9d1435a..32550c9 100755
--- a/tools/json_schema_compiler/idl_schema_test.py
+++ b/tools/json_schema_compiler/idl_schema_test.py
@@ -79,17 +79,6 @@
         'c': {'name': 'c', 'type': 'string'}},
       getType(self.idl_basics, 'MyType1')['properties'])
 
-  def testIOThreadFunc(self):
-    schema = self.idl_basics
-
-    func = getFunction(schema, 'function32')
-    self.assertTrue(func is not None)
-    self.assertTrue(func['forIOThread'])
-
-    func = getFunction(schema, 'function1')
-    self.assertTrue(func is not None)
-    self.assertTrue('forIOThread' not in func)
-
   def testMemberOrdering(self):
     self.assertEquals(
         ['x', 'y', 'z', 'a', 'b', 'c'],
diff --git a/tools/json_schema_compiler/test/idl_basics.idl b/tools/json_schema_compiler/test/idl_basics.idl
index b0ca3fa..602f0c37 100644
--- a/tools/json_schema_compiler/test/idl_basics.idl
+++ b/tools/json_schema_compiler/test/idl_basics.idl
@@ -110,8 +110,6 @@
     static idl_other_namespace.SomeType[] function30();
 
     [nodefine] static void function31(long switch);
-
-    [forIOThread] static void function32();
   };
 
   interface Events {
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 40bbfa2..27b92b8 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -4787,6 +4787,13 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="CopyCustomTabBarUrl">
+  <owner>desktop-pwas-team@google.com</owner>
+  <description>
+    &quot;Copy URL&quot; option in right-click context menu on CustomTabBar.
+  </description>
+</action>
+
 <action name="CopyToFindPboard">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 3138e10..309974f 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -34319,6 +34319,7 @@
       label="AutofillUpstreamUseGooglePayOnAndroidBranding:enabled"/>
   <int value="-1672160462"
       label="SwapSideVolumeButtonsForOrientation:disabled"/>
+  <int value="-1671494049" label="TrimOnFreeze:disabled"/>
   <int value="-1670137340"
       label="OptimizeLoadingIPCForSmallResources:disabled"/>
   <int value="-1669486359" label="ImportantSitesInCBD:enabled"/>
@@ -35300,6 +35301,7 @@
   <int value="-340023285" label="WebNFC:enabled"/>
   <int value="-339103761" label="ArcGraphicBuffersVisualizationTool:enabled"/>
   <int value="-338978205" label="NavigationMojoResponse:enabled"/>
+  <int value="-338606027" label="TrimOnMemoryPressure:disabled"/>
   <int value="-334873793" label="MediaSessionNotification:enabled"/>
   <int value="-333216449" label="MouseSubframeNoImplicitCapture:enabled"/>
   <int value="-329727402" label="disable-files-quick-view"/>
@@ -35527,6 +35529,7 @@
   <int value="-18464041" label="AutofillPrefilledFields:disabled"/>
   <int value="-17698200" label="DoubleTapToZoomInTabletMode:disabled"/>
   <int value="-16824589" label="ash-shelf-color"/>
+  <int value="-16086999" label="TrimOnFreeze:enabled"/>
   <int value="-15879016"
       label="OmniboxUIExperimentUnboldSuggestionText:disabled"/>
   <int value="-13918890" label="disable-download-notification"/>
@@ -35822,6 +35825,7 @@
   <int value="413695227" label="NTPSuggestionsStandaloneUI:enabled"/>
   <int value="414114078" label="LitePageServerPreviews:disabled"/>
   <int value="415154056" label="enable-physical-keyboard-autocorrect"/>
+  <int value="415395210" label="TrimOnMemoryPressure:enabled"/>
   <int value="416887895" label="enable-password-change-support"/>
   <int value="417709910"
       label="AutofillSendExperimentIdsInPaymentsRPCs:disabled"/>
@@ -60001,7 +60005,7 @@
   <int value="3" label="FAILED_OTHER">Failed for other reason</int>
 </enum>
 
-<enum name="VAJDADecoderFailure">
+<enum name="VAJDAFailure">
   <int value="0" label="VAAPI_ERROR"/>
 </enum>
 
diff --git a/tools/metrics/histograms/extract_histograms.py b/tools/metrics/histograms/extract_histograms.py
index 1395c13..c1b91af8 100644
--- a/tools/metrics/histograms/extract_histograms.py
+++ b/tools/metrics/histograms/extract_histograms.py
@@ -61,7 +61,9 @@
 import re
 import xml.dom.minidom
 
-OWNER_FIELD_PLACEHOLDER = (
+BASIC_EMAIL_REGEXP = r'^[\w\-\+\%\.]+\@[\w\-\+\%\.]+$'
+
+OWNER_PLACEHOLDER = (
     'Please list the metric\'s owners. Add more owner tags as needed.')
 
 MAX_HISTOGRAM_SUFFIX_DEPENDENCY_DEPTH = 5
@@ -72,12 +74,13 @@
 EXPIRY_DATE_PATTERN = "%Y-%m-%d"
 EXPIRY_MILESTONE_RE = re.compile(r'M[0-9]{2,3}\Z')
 
+
 class Error(Exception):
   pass
 
 
 def _JoinChildNodes(tag):
-  """Join child nodes into a single text.
+  """Joins child nodes into a single text.
 
   Applicable to leafs like 'summary' and 'detail'. Removes any comment in the
   node.
@@ -94,7 +97,7 @@
 
 
 def _NormalizeString(s):
-  r"""Replaces all whitespace sequences with a single space.
+  """Replaces all whitespace sequences with a single space.
 
   The function properly handles multi-line strings and XML escaped characters.
 
@@ -188,7 +191,7 @@
 
 
 def ExtractEnumsFromXmlTree(tree):
-  """Extract all <enum> nodes in the tree into a dictionary."""
+  """Extracts all <enum> nodes in the tree into a dictionary."""
 
   enums = {}
   have_errors = False
@@ -251,31 +254,38 @@
   return enums, have_errors
 
 
-def _ExtractOwners(xml_node):
-  """Extract owners information from owner tag under |xml_node|.
+def _ExtractOwners(histogram):
+  """Extracts owners information from the given histogram element.
 
   Args:
-    xml_node: The histogram node in histograms.xml.
+    histogram: A DOM Element corresponding to a histogram.
 
   Returns:
-    A tuple of owners information where the first element is a list of owners
-    extract from |xml_node| excluding the owner placeholder string, and the
-    second element is whether the owner tag is presented in |xml_node|
-    including the owner placeholder string.
-  """
-  owners = []
-  hasOwner = False
-  for owner_node in xml_node.getElementsByTagName('owner'):
-    owner_entry = _NormalizeString(_JoinChildNodes(owner_node))
-    hasOwner = True
-    if OWNER_FIELD_PLACEHOLDER not in owner_entry:
-      owners.append(owner_entry)
-  return owners, hasOwner
+    A tuple of owner-related info, e.g. (['alice@chromium.org'], True)
 
+    The first element is a list of the owners' email addresses, excluding the
+    owner placeholder string. The second element is a boolean indicating
+    whether the histogram has an owner. A histogram whose owner is the owner
+    placeholder string has an owner.
+  """
+  email_pattern = re.compile(BASIC_EMAIL_REGEXP)
+  owners = []
+  has_owner = False
+
+  for owner_node in histogram.getElementsByTagName('owner'):
+    owner_text = _NormalizeString(_JoinChildNodes(owner_node))
+    is_email = email_pattern.match(owner_text)
+
+    if owner_text and (is_email or OWNER_PLACEHOLDER in owner_text):
+      has_owner = True
+      if is_email:
+        owners.append(owner_text)
+
+  return owners, has_owner
 
 
 def _ValidateDateString(date_str):
-  """Check if |date_str| matches 'YYYY-MM-DD'.
+  """Checks if |date_str| matches 'YYYY-MM-DD'.
 
   Args:
     date_str: string
@@ -302,7 +312,7 @@
 
 
 def _ExtractHistogramsFromXmlTree(tree, enums):
-  """Extract all <histogram> nodes in the tree into a dictionary."""
+  """Extracts all <histogram> nodes in the tree into a dictionary."""
 
   # Process the histograms. The descriptions can include HTML tags.
   histograms = {}
@@ -387,9 +397,14 @@
   return histograms, have_errors
 
 
-# Finds an <obsolete> node amongst |node|'s immediate children and returns its
-# content as a string. Returns None if no such node exists.
 def _GetObsoleteReason(node):
+  """If the node's histogram is obsolete, returns a string explanation.
+
+  Otherwise, returns None.
+
+  Args:
+    node: A DOM Element associated with a histogram.
+  """
   for child in node.childNodes:
     if child.localName == 'obsolete':
       # There can be at most 1 obsolete element per node.
@@ -398,7 +413,7 @@
 
 
 def _UpdateHistogramsWithSuffixes(tree, histograms):
-  """Process <histogram_suffixes> tags and combine with affected histograms.
+  """Processes <histogram_suffixes> tags and combines with affected histograms.
 
   The histograms dictionary will be updated in-place by adding new histograms
   created by combining histograms themselves with histogram_suffixes targeting
@@ -551,7 +566,7 @@
 
 
 def ExtractHistogramsFromDom(tree):
-  """Compute the histogram names and descriptions from the XML representation.
+  """Computes the histogram names and descriptions from the XML representation.
 
   Args:
     tree: A DOM tree of XML content.
@@ -571,7 +586,7 @@
 
 
 def ExtractHistograms(filename):
-  """Load histogram definitions from a disk file.
+  """Loads histogram definitions from a disk file.
 
   Args:
     filename: a file path to load data from.
diff --git a/tools/metrics/histograms/extract_histograms_test.py b/tools/metrics/histograms/extract_histograms_test.py
index 34ff8589..40704e1 100644
--- a/tools/metrics/histograms/extract_histograms_test.py
+++ b/tools/metrics/histograms/extract_histograms_test.py
@@ -21,12 +21,27 @@
 </histograms>
 </histogram-configuration>
 """)
-    (_, have_errors) = extract_histograms._ExtractHistogramsFromXmlTree(
+    _, have_errors = extract_histograms._ExtractHistogramsFromXmlTree(
         histogram_without_summary, {})
     self.assertTrue(have_errors)
 
-  def testNewHistogramWithoutOwner(self):
-    histogram_without_owner = xml.dom.minidom.parseString("""
+  def testNewHistogramWithEmptyOwnerTag(self):
+    histogram_with_empty_owner_tag = xml.dom.minidom.parseString("""
+<histogram-configuration>
+<histograms>
+ <histogram name="Test.Histogram" units="things">
+  <owner></owner>
+  <summary> This is a summary </summary>
+ </histogram>
+</histograms>
+</histogram-configuration>
+""")
+    _, have_errors = extract_histograms._ExtractHistogramsFromXmlTree(
+        histogram_with_empty_owner_tag, {})
+    self.assertTrue(have_errors)
+
+  def testNewHistogramWithoutOwnerTag(self):
+    histogram_without_owner_tag = xml.dom.minidom.parseString("""
 <histogram-configuration>
 <histograms>
  <histogram name="Test.Histogram" units="things">
@@ -35,8 +50,38 @@
 </histograms>
 </histogram-configuration>
 """)
-    (_, have_errors) = extract_histograms._ExtractHistogramsFromXmlTree(
-        histogram_without_owner, {})
+    _, have_errors = extract_histograms._ExtractHistogramsFromXmlTree(
+        histogram_without_owner_tag, {})
+    self.assertTrue(have_errors)
+
+  def testNewHistogramWithCommaSeparatedOwners(self):
+    histogram_with_comma_separated_owners = xml.dom.minidom.parseString("""
+<histogram-configuration>
+<histograms>
+ <histogram name="Test.Histogram" units="things">
+  <owner>cait@chromium.org, paul@chromium.org</owner>
+  <summary> This is a summary </summary>
+ </histogram>
+</histograms>
+</histogram-configuration>
+""")
+    _, have_errors = extract_histograms._ExtractHistogramsFromXmlTree(
+        histogram_with_comma_separated_owners, {})
+    self.assertTrue(have_errors)
+
+  def testNewHistogramWithInvalidOwner(self):
+    histogram_with_invalid_owner = xml.dom.minidom.parseString("""
+<histogram-configuration>
+<histograms>
+ <histogram name="Test.Histogram" units="things">
+  <owner>sarah</owner>
+  <summary> This is a summary </summary>
+ </histogram>
+</histograms>
+</histogram-configuration>
+""")
+    _, have_errors = extract_histograms._ExtractHistogramsFromXmlTree(
+        histogram_with_invalid_owner, {})
     self.assertTrue(have_errors)
 
   def testNewHistogramWithOwnerPlaceHolder(self):
@@ -55,7 +100,7 @@
 </histograms>
 </histogram-configuration>
 """)
-    (_, have_errors) = extract_histograms._ExtractHistogramsFromXmlTree(
+    _, have_errors = extract_histograms._ExtractHistogramsFromXmlTree(
         histogram_with_owner_placeholder, {})
     self.assertFalse(have_errors)
 
@@ -71,7 +116,7 @@
 </histograms>
 </histogram-configuration>
 """)
-    (hists, have_errors) = extract_histograms._ExtractHistogramsFromXmlTree(
+    hists, have_errors = extract_histograms._ExtractHistogramsFromXmlTree(
         histogram_with_owner_placeholder, {})
     self.assertFalse(have_errors)
     self.assertIn('Test.Histogram', hists)
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 198f816..b565018 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -12560,7 +12560,11 @@
   </summary>
 </histogram>
 
-<histogram name="Blacklist.RetryAttempts.Success" expires_after="M77">
+<histogram name="Blacklist.RetryAttempts.Success" expires_after="2019-07-26">
+  <obsolete>
+    Replaced by ChromeElf.Beacon.RetryAttemptsBeforeSuccess after the old
+    blacklist was deprecated.
+  </obsolete>
   <owner>csharp@chromium.org</owner>
   <owner>proberge@google.com</owner>
   <summary>
@@ -12569,7 +12573,12 @@
   </summary>
 </histogram>
 
-<histogram name="Blacklist.Setup" enum="BlacklistSetup" expires_after="M77">
+<histogram name="Blacklist.Setup" enum="BlacklistSetup"
+    expires_after="2019-07-26">
+  <obsolete>
+    Replaced by ChromeElf.Beacon.SetupStatus after the old blacklist was
+    deprecated.
+  </obsolete>
   <owner>csharp@chromium.org</owner>
   <summary>
     Records the successes and failures when running the browser blacklist setup
@@ -18631,6 +18640,29 @@
   </summary>
 </histogram>
 
+<histogram name="ChromeElf.Beacon.RetryAttemptsBeforeSuccess"
+    expires_after="M82">
+  <owner>chrisha@chromium.org</owner>
+  <owner>pmonette@chromium.org</owner>
+  <summary>
+    Records the number of attempts needed before third-party DLL blocking was
+    properly set up. This is logged immediately after a successful setup. Only
+    recorded on Windows.
+  </summary>
+</histogram>
+
+<histogram name="ChromeElf.Beacon.SetupStatus" enum="BlacklistSetup"
+    expires_after="M82">
+  <owner>chrisha@chromium.org</owner>
+  <owner>pmonette@chromium.org</owner>
+  <summary>
+    Records the successes and failures when running the third-party DLL blocking
+    setup code, taking into account the safety beacon. Used to determine how
+    often the third-party DLL blocking is disabled because it failed to
+    initialize properly twice in a row. Only recorded on Windows.
+  </summary>
+</histogram>
+
 <histogram name="ChromeElf.ThirdPartyStatus" enum="ThirdPartyStatus"
     expires_after="M77">
   <owner>pmonette@chromium.org</owner>
@@ -31098,6 +31130,9 @@
 
 <histogram name="Download.DangerousFile.Reason" enum="DangerousFile.Reason"
     expires_after="M77">
+  <obsolete>
+    Removed in M77 since the data was not being used.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -32552,6 +32587,9 @@
 
 <histogram name="Download.TargetConnectionSecurity"
     enum="DownloadConnectionSecurity" expires_after="M77">
+  <obsolete>
+    Removed in M77 since the data was not being used.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -57715,6 +57753,9 @@
 
 <histogram name="Media.AudioTrackProcessingStates"
     enum="AudioTrackProcessingStates" expires_after="M77">
+  <obsolete>
+    Deprecated July 2019. No longer needed.
+  </obsolete>
   <owner>grunell@chromium.org</owner>
   <summary>
     State of the media stream audio track processing, sampled once during the
@@ -60570,12 +60611,12 @@
   </summary>
 </histogram>
 
-<histogram name="Media.VAJDA.DecoderFailure" enum="VAJDADecoderFailure">
+<histogram name="Media.VAJDA.DecoderFailure" enum="VAJDAFailure">
   <owner>andrescj@chromium.org</owner>
   <owner>chromeos-gfx@chromium.org</owner>
   <summary>
-    Count of VAAPI errors that occur inside the VaapiWrapper due to
-    functionality needed by the VaapiJpegDecodeAccelerator.
+    Count of VAAPI errors that occur inside the VaapiWrapper due to decoding
+    functionality needed by the VaapiMjpegDecodeAccelerator.
   </summary>
 </histogram>
 
@@ -60590,6 +60631,15 @@
   </summary>
 </histogram>
 
+<histogram name="Media.VAJDA.VppFailure" enum="VAJDAFailure">
+  <owner>kamesan@chromium.org</owner>
+  <owner>chromeos-gfx@chromium.org</owner>
+  <summary>
+    Count of VAAPI errors that occur inside the VaapiWrapper due to VPP
+    functionality needed by the VaapiMjpegDecodeAccelerator.
+  </summary>
+</histogram>
+
 <histogram name="Media.VAJDAWorker.DecoderFailure"
     enum="VAJDAWorkerDecoderFailure" expires_after="2020-05-01">
   <owner>andrescj@chromium.org</owner>
@@ -65182,7 +65232,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.Navigation.OptedOut" enum="BooleanOptedOut"
-    expires_after="M79">
+    expires_after="M81">
   <owner>carlosil@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -65209,7 +65259,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.ResourceRequest.Failure.Type"
-    enum="ResourceType" expires_after="M79">
+    enum="ResourceType" expires_after="M81">
   <owner>carlosil@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -65219,7 +65269,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.ResourceRequest.Response.Type"
-    enum="ResourceType" expires_after="M79">
+    enum="ResourceType" expires_after="M81">
   <owner>carlosil@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -65229,7 +65279,7 @@
 </histogram>
 
 <histogram name="MixedAutoupgrade.ResourceRequest.Start.Type"
-    enum="ResourceType" expires_after="M79">
+    enum="ResourceType" expires_after="M81">
   <owner>carlosil@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -114676,6 +114726,9 @@
 
 <histogram name="SafeBrowsing.V4StoreVersionRead" units="version number"
     expires_after="M77">
+  <obsolete>
+    Removed in M78 since there's only ever been just 1 version number.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -117297,6 +117350,9 @@
 
 <histogram name="SBDownloadFeedback.Activations" enum="DownloadItem.DangerType"
     expires_after="M78">
+  <obsolete>
+    Removed in M77, since the information was not being used.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <owner>mattm@chromium.org</owner>
@@ -117329,6 +117385,9 @@
 
 <histogram name="SBDownloadFeedback.EmptyFilePathFailure" enum="Boolean"
     expires_after="M78">
+  <obsolete>
+    Removed in M77, since the information was not being used.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -117372,6 +117431,9 @@
 
 <histogram name="SBDownloadFeedback.SizeEligibleKB" units="KB"
     expires_after="M78">
+  <obsolete>
+    Removed in M77, since the information was not being used.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <owner>mattm@chromium.org</owner>
@@ -117413,6 +117475,9 @@
 
 <histogram name="SBDownloadFeedback.UploadRequestedByServer"
     enum="DownloadUploadRequestedByServer" expires_after="M78">
+  <obsolete>
+    Removed in M77, since the information was not being used.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -154895,6 +154960,13 @@
 
 <histogram name="XR.WebXR.RenderPath.Used" enum="XRRenderPath"
     expires_after="M80">
+  <obsolete>
+    Removed July 2019. This was being tracked in case the assumptions about
+    feature availability based on platform version turned out to be incorrect,
+    but it appears that this is working as intended. The webxr-render-path flag
+    that could be used to override this at runtime was previously removed in
+    https://crrev.com/c/1487074.
+  </obsolete>
   <owner>klausw@chromium.org</owner>
   <summary>
     Records the WebXR/WebVR render path used for presentation on presentation
diff --git a/tools/perf/benchmarks/rendering.py b/tools/perf/benchmarks/rendering.py
index 6669420..514c14e 100644
--- a/tools/perf/benchmarks/rendering.py
+++ b/tools/perf/benchmarks/rendering.py
@@ -35,10 +35,14 @@
         'Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin4',
         'Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin4',
         'Event.Latency.ScrollUpdate.Wheel.TimeToScrollUpdateSwapBegin4',
+        'Graphics.Smoothness.Throughput.MainThread.PinchZoom',
         'Graphics.Smoothness.Throughput.MainThread.RAF',
         'Graphics.Smoothness.Throughput.MainThread.TouchScroll',
+        'Graphics.Smoothness.Throughput.MainThread.WheelScroll',
         'Graphics.Smoothness.Throughput.CompositorThread.CompositorAnimation',
-        'Graphics.Smoothness.Throughput.CompositorThread.TouchScroll')
+        'Graphics.Smoothness.Throughput.CompositorThread.PinchZoom',
+        'Graphics.Smoothness.Throughput.CompositorThread.TouchScroll',
+        'Graphics.Smoothness.Throughput.CompositorThread.WheelScroll')
     options.SetTimelineBasedMetrics(['renderingMetric', 'umaMetric'])
     return options
 
diff --git a/tools/polymer/generate_gn_v3.py b/tools/polymer/generate_gn_v3.py
new file mode 100755
index 0000000..5d6ff1a
--- /dev/null
+++ b/tools/polymer/generate_gn_v3.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from datetime import date
+import json
+import os.path as path
+import sys
+
+_COMPILE_JS = '//third_party/closure_compiler/compile_js.gni'
+_WEB_ANIMATIONS_BASE = 'web-animations.html'
+_WEB_ANIMATIONS_EXTERNS = \
+    '//third_party/closure_compiler/externs/web_animations.js'
+_COMPILED_RESOURCES_TEMPLATE = '''
+# Copyright %d 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.
+#
+# NOTE: Created with %s, please do not edit.
+
+import("%s")
+
+%s
+'''.strip()
+
+_HERE_PATH = path.dirname(__file__)
+_SRC_PATH = path.normpath(path.join(_HERE_PATH, '..', '..'))
+sys.path.append(path.join(_SRC_PATH, 'third_party', 'node'))
+import node
+
+
+def main(created_by, input_files):
+    targets = ''
+
+    def _target_name(target_file):
+      return target_file[:-len('.js')]
+
+    def _extract_imports(input_file):
+      path_to_acorn = path.join('node_modules', 'acorn', 'bin', 'acorn');
+      ast = node.RunNode([path_to_acorn, '--module', input_file])
+      imports = map(lambda n: n['source']['raw'][1:-1],
+          filter(lambda n: n['type'] ==
+              'ImportDeclaration', json.loads(ast)['body']))
+      return set(imports)
+
+    for input_file in sorted(input_files, key=_target_name):
+      input_base = path.basename(input_file)
+      imports = _extract_imports(input_file)
+      dependencies = []
+      externs = ''
+
+      for i in sorted(imports):
+        import_dir, import_base = path.split(i.encode('ascii'))
+
+        if import_base == _WEB_ANIMATIONS_BASE:
+          externs += '\n  externs_list = [ "%s" ]' % _WEB_ANIMATIONS_EXTERNS
+          continue
+
+        # Redirect dependencies to minified Polymer to the non-minified version.
+        if import_base == 'polymer_bundled.min.js':
+          import_base = 'polymer_bundled.js'
+
+        target = ':' + _target_name(import_base)
+        dependencies.append(import_dir + target)
+
+      targets += '\njs_library("%s") {' % _target_name(input_base)
+      if dependencies:
+        targets += '\n  deps = ['
+        targets += '\n    "%s",' % '",\n    "'.join(dependencies)
+        targets += '\n  ]'
+      targets += externs
+      targets += '\n}\n'
+
+    targets = targets.strip()
+
+    if targets:
+      current_year = date.today().year
+      print _COMPILED_RESOURCES_TEMPLATE % (current_year, created_by,
+                                            _COMPILE_JS, targets)
+
+
+if __name__ == '__main__':
+  main(path.basename(sys.argv[0]), sys.argv[1:])
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 13606ef..486a0b1 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -177,18 +177,19 @@
     compositor_host_.reset();
   }
 
-  Layer* CreateLayer(LayerType type) {
-    return new Layer(type);
+  std::unique_ptr<Layer> CreateLayer(LayerType type) {
+    return std::make_unique<Layer>(type);
   }
 
-  Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
-    Layer* layer = new ColoredLayer(color);
+  std::unique_ptr<Layer> CreateColorLayer(SkColor color,
+                                          const gfx::Rect& bounds) {
+    auto layer = std::make_unique<ColoredLayer>(color);
     layer->SetBounds(bounds);
     return layer;
   }
 
-  Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
-    Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
+  std::unique_ptr<Layer> CreateNoTextureLayer(const gfx::Rect& bounds) {
+    std::unique_ptr<Layer> layer = CreateLayer(LAYER_NOT_DRAWN);
     layer->SetBounds(bounds);
     return layer;
   }
@@ -196,7 +197,7 @@
   std::unique_ptr<Layer> CreateDrawFadedStringLayerDelegate(
       const gfx::Rect& bounds,
       DrawFadedStringLayerDelegate* delegate) {
-    std::unique_ptr<Layer> layer(new Layer(LAYER_TEXTURED));
+    auto layer = std::make_unique<Layer>(LAYER_TEXTURED);
     layer->SetBounds(bounds);
     layer->set_delegate(delegate);
     return layer;
@@ -259,7 +260,7 @@
  private:
   class ReadbackHolder : public base::RefCountedThreadSafe<ReadbackHolder> {
    public:
-    ReadbackHolder() : run_loop_(new base::RunLoop) {}
+    ReadbackHolder() : run_loop_(std::make_unique<base::RunLoop>()) {}
 
     void OutputRequestCallback(std::unique_ptr<viz::CopyOutputResult> result) {
       if (result->IsEmpty())
@@ -481,8 +482,8 @@
 INSTANTIATE_TEST_SUITE_P(, LayerWithRealCompositorTest, ::testing::Bool());
 
 TEST_P(LayerWithRealCompositorTest, Draw) {
-  std::unique_ptr<Layer> layer(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 50, 50)));
+  std::unique_ptr<Layer> layer =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 50, 50));
   DrawTree(layer.get());
 }
 
@@ -493,14 +494,14 @@
 // +-- L4 - magenta
 //
 TEST_P(LayerWithRealCompositorTest, Hierarchy) {
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400)));
-  std::unique_ptr<Layer> l2(
-      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350)));
-  std::unique_ptr<Layer> l3(
-      CreateColorLayer(SK_ColorYELLOW, gfx::Rect(5, 5, 25, 25)));
-  std::unique_ptr<Layer> l4(
-      CreateColorLayer(SK_ColorMAGENTA, gfx::Rect(300, 300, 100, 100)));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400));
+  std::unique_ptr<Layer> l2 =
+      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350));
+  std::unique_ptr<Layer> l3 =
+      CreateColorLayer(SK_ColorYELLOW, gfx::Rect(5, 5, 25, 25));
+  std::unique_ptr<Layer> l4 =
+      CreateColorLayer(SK_ColorMAGENTA, gfx::Rect(300, 300, 100, 100));
 
   l1->Add(l2.get());
   l1->Add(l4.get());
@@ -536,18 +537,19 @@
 
   Compositor* compositor() { return compositor_host_->GetCompositor(); }
 
-  virtual Layer* CreateLayer(LayerType type) {
-    return new Layer(type);
+  virtual std::unique_ptr<Layer> CreateLayer(LayerType type) {
+    return std::make_unique<Layer>(type);
   }
 
-  Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
-    Layer* layer = new ColoredLayer(color);
+  std::unique_ptr<Layer> CreateColorLayer(SkColor color,
+                                          const gfx::Rect& bounds) {
+    auto layer = std::make_unique<ColoredLayer>(color);
     layer->SetBounds(bounds);
     return layer;
   }
 
-  virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
-    Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
+  virtual std::unique_ptr<Layer> CreateNoTextureLayer(const gfx::Rect& bounds) {
+    std::unique_ptr<Layer> layer = CreateLayer(LAYER_NOT_DRAWN);
     layer->SetBounds(bounds);
     return layer;
   }
@@ -590,7 +592,7 @@
 }
 
 TEST(LayerStandaloneTest, ReleaseMailboxOnDestruction) {
-  std::unique_ptr<Layer> layer(new Layer(LAYER_TEXTURED));
+  auto layer = std::make_unique<Layer>(LAYER_TEXTURED);
   bool callback_run = false;
 
   constexpr gfx::Size size(64, 64);
@@ -610,10 +612,10 @@
 // L1
 //  +-- L2
 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) {
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400)));
-  std::unique_ptr<Layer> l2(
-      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350)));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400));
+  std::unique_ptr<Layer> l2 =
+      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350));
   l1->Add(l2.get());
   DrawTree(l1.get());
 
@@ -632,12 +634,12 @@
 //  +-- L2
 //       +-- L3
 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Medium) {
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400)));
-  std::unique_ptr<Layer> l2(
-      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350)));
-  std::unique_ptr<Layer> l3(
-      CreateColorLayer(SK_ColorYELLOW, gfx::Rect(10, 10, 100, 100)));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400));
+  std::unique_ptr<Layer> l2 =
+      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350));
+  std::unique_ptr<Layer> l3 =
+      CreateColorLayer(SK_ColorYELLOW, gfx::Rect(10, 10, 100, 100));
   l1->Add(l2.get());
   l2->Add(l3.get());
   DrawTree(l1.get());
@@ -657,8 +659,8 @@
   // This test makes sure that whenever paint happens at a layer, its layer
   // delegate gets the paint, which in this test update its color and
   // |color_index|.
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorBLACK, gfx::Rect(20, 20, 400, 400)));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorBLACK, gfx::Rect(20, 20, 400, 400));
   GetCompositor()->SetRootLayer(l1.get());
   WaitForDraw();
 
@@ -686,12 +688,12 @@
 }
 
 TEST_P(LayerWithRealCompositorTest, DrawTree) {
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400)));
-  std::unique_ptr<Layer> l2(
-      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350)));
-  std::unique_ptr<Layer> l3(
-      CreateColorLayer(SK_ColorYELLOW, gfx::Rect(10, 10, 100, 100)));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400));
+  std::unique_ptr<Layer> l2 =
+      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350));
+  std::unique_ptr<Layer> l3 =
+      CreateColorLayer(SK_ColorYELLOW, gfx::Rect(10, 10, 100, 100));
   l1->Add(l2.get());
   l2->Add(l3.get());
 
@@ -714,9 +716,9 @@
 
 // Tests that scheduling paint on a layer with a mask updates the mask.
 TEST_P(LayerWithRealCompositorTest, SchedulePaintUpdatesMask) {
-  std::unique_ptr<Layer> layer(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400)));
-  std::unique_ptr<Layer> mask_layer(CreateLayer(ui::LAYER_TEXTURED));
+  std::unique_ptr<Layer> layer =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400));
+  std::unique_ptr<Layer> mask_layer = CreateLayer(ui::LAYER_TEXTURED);
   mask_layer->SetBounds(gfx::Rect(layer->GetTargetBounds().size()));
   layer->SetMaskLayer(mask_layer.get());
 
@@ -742,13 +744,13 @@
 // +-- L4 - magenta
 //
 TEST_P(LayerWithRealCompositorTest, HierarchyNoTexture) {
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400)));
-  std::unique_ptr<Layer> l2(CreateNoTextureLayer(gfx::Rect(10, 10, 350, 350)));
-  std::unique_ptr<Layer> l3(
-      CreateColorLayer(SK_ColorYELLOW, gfx::Rect(5, 5, 25, 25)));
-  std::unique_ptr<Layer> l4(
-      CreateColorLayer(SK_ColorMAGENTA, gfx::Rect(300, 300, 100, 100)));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400));
+  std::unique_ptr<Layer> l2 = CreateNoTextureLayer(gfx::Rect(10, 10, 350, 350));
+  std::unique_ptr<Layer> l3 =
+      CreateColorLayer(SK_ColorYELLOW, gfx::Rect(5, 5, 25, 25));
+  std::unique_ptr<Layer> l4 =
+      CreateColorLayer(SK_ColorMAGENTA, gfx::Rect(300, 300, 100, 100));
 
   l1->Add(l2.get());
   l1->Add(l4.get());
@@ -773,7 +775,7 @@
 }
 
 TEST_F(LayerWithDelegateTest, Cloning) {
-  std::unique_ptr<Layer> layer(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> layer = CreateLayer(LAYER_SOLID_COLOR);
 
   gfx::Transform transform;
   transform.Scale(2, 1);
@@ -836,7 +838,7 @@
 
   // A solid color layer with transparent color can be marked as opaque. The
   // clone should retain this state.
-  layer.reset(CreateLayer(LAYER_SOLID_COLOR));
+  layer = CreateLayer(LAYER_SOLID_COLOR);
   layer->SetColor(kTransparent);
   layer->SetFillsBoundsOpaquely(true);
 
@@ -847,7 +849,7 @@
   EXPECT_FALSE(clone->layer_inverted());
   EXPECT_TRUE(clone->fills_bounds_opaquely());
 
-  layer.reset(CreateLayer(LAYER_SOLID_COLOR));
+  layer = CreateLayer(LAYER_SOLID_COLOR);
   layer->SetVisible(true);
   layer->SetOpacity(1.0f);
   layer->SetColor(SK_ColorRED);
@@ -870,8 +872,8 @@
 }
 
 TEST_F(LayerWithDelegateTest, Mirroring) {
-  std::unique_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 100, 100)));
-  std::unique_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> root = CreateNoTextureLayer(gfx::Rect(0, 0, 100, 100));
+  std::unique_ptr<Layer> child = CreateLayer(LAYER_TEXTURED);
 
   const gfx::Rect bounds(0, 0, 50, 50);
   child->SetBounds(bounds);
@@ -946,7 +948,7 @@
 TEST_F(LayerWithDelegateTest, SurfaceLayerCloneAndMirror) {
   const viz::FrameSinkId arbitrary_frame_sink(1, 1);
   viz::ParentLocalSurfaceIdAllocator allocator;
-  std::unique_ptr<Layer> layer(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> layer = CreateLayer(LAYER_SOLID_COLOR);
 
   allocator.GenerateId();
   viz::LocalSurfaceId local_surface_id =
@@ -982,29 +984,30 @@
 
   void SetUp() override {
     LayerWithDelegateTest::SetUp();
-    default_layer_delegate_.reset(new NullLayerDelegate());
+    default_layer_delegate_ = std::make_unique<NullLayerDelegate>();
   }
 
-  Layer* CreateLayer(LayerType type) override {
-    Layer* layer = new Layer(type);
+  std::unique_ptr<Layer> CreateLayer(LayerType type) override {
+    auto layer = std::make_unique<Layer>(type);
     layer->set_delegate(default_layer_delegate_.get());
     return layer;
   }
 
-  Layer* CreateTextureRootLayer(const gfx::Rect& bounds) {
-    Layer* layer = CreateTextureLayer(bounds);
-    compositor()->SetRootLayer(layer);
+  std::unique_ptr<Layer> CreateTextureRootLayer(const gfx::Rect& bounds) {
+    std::unique_ptr<Layer> layer = CreateTextureLayer(bounds);
+    compositor()->SetRootLayer(layer.get());
     return layer;
   }
 
-  Layer* CreateTextureLayer(const gfx::Rect& bounds) {
-    Layer* layer = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> CreateTextureLayer(const gfx::Rect& bounds) {
+    std::unique_ptr<Layer> layer = CreateLayer(LAYER_TEXTURED);
     layer->SetBounds(bounds);
     return layer;
   }
 
-  Layer* CreateNoTextureLayer(const gfx::Rect& bounds) override {
-    Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
+  std::unique_ptr<Layer> CreateNoTextureLayer(
+      const gfx::Rect& bounds) override {
+    std::unique_ptr<Layer> layer = CreateLayer(LAYER_NOT_DRAWN);
     layer->SetBounds(bounds);
     return layer;
   }
@@ -1020,11 +1023,11 @@
 };
 
 TEST_F(LayerWithNullDelegateTest, EscapedDebugNames) {
-  std::unique_ptr<Layer> layer(CreateLayer(LAYER_NOT_DRAWN));
+  std::unique_ptr<Layer> layer = CreateLayer(LAYER_NOT_DRAWN);
   std::string name = "\"\'\\/\b\f\n\r\t\n";
   layer->set_name(name);
-  std::unique_ptr<base::trace_event::ConvertableToTraceFormat> debug_info(
-      layer->TakeDebugInfo(layer->cc_layer_for_testing()));
+  std::unique_ptr<base::trace_event::ConvertableToTraceFormat> debug_info =
+      layer->TakeDebugInfo(layer->cc_layer_for_testing());
   EXPECT_TRUE(debug_info.get());
   std::string json;
   debug_info->AppendAsTraceFormat(&json);
@@ -1038,7 +1041,7 @@
 }
 
 TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
-  std::unique_ptr<Layer> l1(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> l1 = CreateLayer(LAYER_SOLID_COLOR);
   l1->SetFillsBoundsOpaquely(true);
   l1->SetVisible(false);
   l1->SetBounds(gfx::Rect(4, 5));
@@ -1133,9 +1136,9 @@
 
 // Various visible/drawn assertions.
 TEST_F(LayerWithNullDelegateTest, Visibility) {
-  std::unique_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
+  auto l1 = std::make_unique<Layer>(LAYER_TEXTURED);
+  auto l2 = std::make_unique<Layer>(LAYER_TEXTURED);
+  auto l3 = std::make_unique<Layer>(LAYER_TEXTURED);
   l1->Add(l2.get());
   l2->Add(l3.get());
 
@@ -1183,8 +1186,8 @@
 
 // Various visible/drawn assertions.
 TEST_F(LayerWithNullDelegateTest, MirroringVisibility) {
-  std::unique_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
+  auto l1 = std::make_unique<Layer>(LAYER_TEXTURED);
+  auto l2 = std::make_unique<Layer>(LAYER_TEXTURED);
   std::unique_ptr<Layer> l2_mirror = l2->Mirror();
   l1->Add(l2.get());
   l1->Add(l2_mirror.get());
@@ -1297,7 +1300,7 @@
 TEST_F(LayerWithDelegateTest, RoundedCorner) {
   gfx::Rect layer_bounds(10, 20, 100, 100);
   constexpr gfx::RoundedCornersF kRadii(5, 10, 15, 20);
-  std::unique_ptr<Layer> layer(new Layer(LAYER_TEXTURED));
+  auto layer = std::make_unique<Layer>(LAYER_TEXTURED);
 
   NullLayerDelegate delegate;
   layer->set_delegate(&delegate);
@@ -1318,10 +1321,10 @@
 
 // Checks that stacking-related methods behave as advertised.
 TEST_F(LayerWithNullDelegateTest, Stacking) {
-  std::unique_ptr<Layer> root(new Layer(LAYER_NOT_DRAWN));
-  std::unique_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
+  auto root = std::make_unique<Layer>(LAYER_NOT_DRAWN);
+  auto l1 = std::make_unique<Layer>(LAYER_TEXTURED);
+  auto l2 = std::make_unique<Layer>(LAYER_TEXTURED);
+  auto l3 = std::make_unique<Layer>(LAYER_TEXTURED);
   l1->set_name("1");
   l2->set_name("2");
   l3->set_name("3");
@@ -1405,7 +1408,7 @@
 
 // Verifies SetBounds triggers the appropriate painting/drawing.
 TEST_F(LayerWithNullDelegateTest, SetBoundsSchedulesPaint) {
-  std::unique_ptr<Layer> l1(CreateTextureLayer(gfx::Rect(0, 0, 200, 200)));
+  std::unique_ptr<Layer> l1 = CreateTextureLayer(gfx::Rect(0, 0, 200, 200));
   compositor()->SetRootLayer(l1.get());
 
   Draw();
@@ -1429,7 +1432,7 @@
          bool is_lost) { run_loop->Quit(); },
       base::Unretained(&run_loop));
 
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_SOLID_COLOR);
   constexpr gfx::Size size(64, 64);
   auto resource = viz::TransferableResource::MakeGL(
       gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
@@ -1462,7 +1465,7 @@
 // Tests that in deferred paint request, the layer damage will be accumulated.
 TEST_F(LayerWithNullDelegateTest, UpdateDamageInDeferredPaint) {
   gfx::Rect bound(gfx::Rect(500, 500));
-  std::unique_ptr<Layer> root(CreateTextureRootLayer(bound));
+  std::unique_ptr<Layer> root = CreateTextureRootLayer(bound);
   EXPECT_EQ(bound, root->damaged_region_for_testing());
   WaitForCommit();
   EXPECT_EQ(gfx::Rect(), root->damaged_region_for_testing());
@@ -1510,8 +1513,8 @@
 // present, even if it shouldn't send its damaged regions itself.
 TEST_F(LayerWithNullDelegateTest, AlwaysSendsMaskDamagedRects) {
   gfx::Rect bound(gfx::Rect(2, 2));
-  std::unique_ptr<Layer> mask(CreateTextureLayer(bound));
-  std::unique_ptr<Layer> root(CreateTextureRootLayer(bound));
+  std::unique_ptr<Layer> mask = CreateTextureLayer(bound);
+  std::unique_ptr<Layer> root = CreateTextureRootLayer(bound);
   root->SetMaskLayer(mask.get());
 
   WaitForCommit();
@@ -1528,13 +1531,13 @@
 // Verifies that when a layer is reflecting other layers, mirror counts of
 // reflected layers are updated properly.
 TEST_F(LayerWithNullDelegateTest, SetShowReflectedLayerSubtree) {
-  std::unique_ptr<Layer> reflected_layer_1(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> reflected_layer_1 = CreateLayer(LAYER_SOLID_COLOR);
   auto* reflected_layer_1_cc = reflected_layer_1->cc_layer_for_testing();
 
-  std::unique_ptr<Layer> reflected_layer_2(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> reflected_layer_2 = CreateLayer(LAYER_SOLID_COLOR);
   auto* reflected_layer_2_cc = reflected_layer_2->cc_layer_for_testing();
 
-  std::unique_ptr<Layer> reflecting_layer(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> reflecting_layer = CreateLayer(LAYER_SOLID_COLOR);
 
   // Originally, mirror counts should be zero.
   auto* reflecting_layer_cc = reflecting_layer->mirror_layer_for_testing();
@@ -1575,10 +1578,10 @@
   const gfx::Rect reflected_bounds(0, 0, 50, 50);
   const gfx::Rect reflecting_bounds(0, 50, 10, 10);
 
-  std::unique_ptr<Layer> reflected_layer(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> reflected_layer = CreateLayer(LAYER_SOLID_COLOR);
   reflected_layer->SetBounds(reflected_bounds);
 
-  std::unique_ptr<Layer> reflecting_layer(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> reflecting_layer = CreateLayer(LAYER_SOLID_COLOR);
   reflecting_layer->SetBounds(reflecting_bounds);
 
   EXPECT_EQ(reflecting_bounds, reflecting_layer->bounds());
@@ -1619,10 +1622,10 @@
 
   int blue_height = 10;
 
-  std::unique_ptr<Layer> layer(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
-  std::unique_ptr<Layer> layer2(CreateColorLayer(
-      SK_ColorBLUE, gfx::Rect(0, 0, viewport_size.width(), blue_height)));
+  std::unique_ptr<Layer> layer =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size));
+  std::unique_ptr<Layer> layer2 = CreateColorLayer(
+      SK_ColorBLUE, gfx::Rect(0, 0, viewport_size.width(), blue_height));
 
   layer->Add(layer2.get());
 
@@ -1654,10 +1657,10 @@
   SkColor blue_with_alpha = SkColorSetARGB(40, 10, 20, 200);
   SkColor blend_color = SkColorSetARGB(255, 216, 3, 32);
 
-  std::unique_ptr<Layer> background_layer(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
-  std::unique_ptr<Layer> foreground_layer(
-      CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size)));
+  std::unique_ptr<Layer> background_layer =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size));
+  std::unique_ptr<Layer> foreground_layer =
+      CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size));
 
   // This must be set to false for layers with alpha to be blended correctly.
   foreground_layer->SetFillsBoundsOpaquely(false);
@@ -1690,10 +1693,10 @@
   SkColor blue_with_alpha = SkColorSetARGB(40, 0, 0, 255);
   SkColor blend_color = SkColorSetARGB(255, 215, 0, 40);
 
-  std::unique_ptr<Layer> background_layer(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
-  std::unique_ptr<Layer> foreground_layer(
-      CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size)));
+  std::unique_ptr<Layer> background_layer =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size));
+  std::unique_ptr<Layer> foreground_layer =
+      CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size));
 
   // Add a shape to restrict the visible part of the layer.
   auto shape = std::make_unique<Layer::ShapeRects>();
@@ -1721,10 +1724,10 @@
 // Checks the logic around Compositor::SetRootLayer and Layer::SetCompositor.
 TEST_P(LayerWithRealCompositorTest, SetRootLayer) {
   Compositor* compositor = GetCompositor();
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400)));
-  std::unique_ptr<Layer> l2(
-      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350)));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400));
+  std::unique_ptr<Layer> l2 =
+      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350));
 
   EXPECT_EQ(NULL, l1->GetCompositor());
   EXPECT_EQ(NULL, l2->GetCompositor());
@@ -1759,10 +1762,10 @@
 #define MAYBE_CompositorObservers CompositorObservers
 #endif
 TEST_P(LayerWithRealCompositorTest, MAYBE_CompositorObservers) {
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400)));
-  std::unique_ptr<Layer> l2(
-      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350)));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400));
+  std::unique_ptr<Layer> l2 =
+      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 350, 350));
   l1->Add(l2.get());
   TestCompositorObserver observer;
   GetCompositor()->AddObserver(&observer);
@@ -1833,14 +1836,14 @@
   //  +-l11
   //  | +-l21
   //  +-l12
-  std::unique_ptr<Layer> l0(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 50, 50)));
-  std::unique_ptr<Layer> l11(
-      CreateColorLayer(SK_ColorGREEN, gfx::Rect(0, 0, 25, 25)));
-  std::unique_ptr<Layer> l21(
-      CreateColorLayer(SK_ColorMAGENTA, gfx::Rect(0, 0, 15, 15)));
-  std::unique_ptr<Layer> l12(
-      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 25, 25)));
+  std::unique_ptr<Layer> l0 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 50, 50));
+  std::unique_ptr<Layer> l11 =
+      CreateColorLayer(SK_ColorGREEN, gfx::Rect(0, 0, 25, 25));
+  std::unique_ptr<Layer> l21 =
+      CreateColorLayer(SK_ColorMAGENTA, gfx::Rect(0, 0, 15, 15));
+  std::unique_ptr<Layer> l12 =
+      CreateColorLayer(SK_ColorBLUE, gfx::Rect(10, 10, 25, 25));
 
   base::FilePath ref_img1 = test_data_dir().AppendASCII("ModifyHierarchy1.png");
   base::FilePath ref_img2 = test_data_dir().AppendASCII("ModifyHierarchy2.png");
@@ -1901,13 +1904,13 @@
   // l0
   //  +-l1
   //  +-l2
-  std::unique_ptr<Layer> l0(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 200, 200)));
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorGREEN, gfx::Rect(100, 100, 100, 100)));
+  std::unique_ptr<Layer> l0 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 200, 200));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorGREEN, gfx::Rect(100, 100, 100, 100));
   SkColor blue_with_alpha = SkColorSetARGB(40, 10, 20, 200);
-  std::unique_ptr<Layer> l2(
-      CreateColorLayer(blue_with_alpha, gfx::Rect(50, 50, 100, 100)));
+  std::unique_ptr<Layer> l2 =
+      CreateColorLayer(blue_with_alpha, gfx::Rect(50, 50, 100, 100));
   l2->SetFillsBoundsOpaquely(false);
   l2->SetBackgroundBlur(15);
 
@@ -1945,13 +1948,13 @@
   // l0
   //  +-l1
   //  +-l2
-  std::unique_ptr<Layer> l0(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 200, 200)));
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorGREEN, gfx::Rect(100, 100, 100, 100)));
+  std::unique_ptr<Layer> l0 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 200, 200));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorGREEN, gfx::Rect(100, 100, 100, 100));
   SkColor blue_with_alpha = SkColorSetARGB(40, 10, 20, 200);
-  std::unique_ptr<Layer> l2(
-      CreateColorLayer(blue_with_alpha, gfx::Rect(50, 50, 100, 100)));
+  std::unique_ptr<Layer> l2 =
+      CreateColorLayer(blue_with_alpha, gfx::Rect(50, 50, 100, 100));
   l2->SetFillsBoundsOpaquely(false);
   l2->SetBackgroundBlur(15);
 
@@ -2001,8 +2004,8 @@
   GetCompositor()->SetScaleAndSize(
       1.0f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
   DrawFadedStringLayerDelegate delegate(SK_ColorBLUE, size);
-  std::unique_ptr<Layer> layer(
-      CreateDrawFadedStringLayerDelegate(gfx::Rect(size), &delegate));
+  std::unique_ptr<Layer> layer =
+      CreateDrawFadedStringLayerDelegate(gfx::Rect(size), &delegate);
   DrawTree(layer.get());
 
   SkBitmap bitmap;
@@ -2045,10 +2048,10 @@
 
   // l0
   //  +-l11
-  std::unique_ptr<Layer> l0(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 50, 50)));
-  std::unique_ptr<Layer> l11(
-      CreateColorLayer(SK_ColorGREEN, gfx::Rect(0, 0, 25, 25)));
+  std::unique_ptr<Layer> l0 =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 50, 50));
+  std::unique_ptr<Layer> l11 =
+      CreateColorLayer(SK_ColorGREEN, gfx::Rect(0, 0, 25, 25));
 
   base::FilePath ref_img = test_data_dir().AppendASCII("Opacity.png");
 
@@ -2114,11 +2117,11 @@
 // Verifies that if SchedulePaint is invoked during painting the layer is still
 // marked dirty.
 TEST_F(LayerWithDelegateTest, SchedulePaintFromOnPaintLayer) {
-  std::unique_ptr<Layer> root(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 500, 500)));
+  std::unique_ptr<Layer> root =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(0, 0, 500, 500));
   SchedulePaintLayerDelegate child_delegate;
-  std::unique_ptr<Layer> child(
-      CreateColorLayer(SK_ColorBLUE, gfx::Rect(0, 0, 200, 200)));
+  std::unique_ptr<Layer> child =
+      CreateColorLayer(SK_ColorBLUE, gfx::Rect(0, 0, 200, 200));
   child_delegate.set_layer(child.get());
 
   root->Add(child.get());
@@ -2143,15 +2146,15 @@
 }
 
 TEST_P(LayerWithRealCompositorTest, ScaleUpDown) {
-  std::unique_ptr<Layer> root(
-      CreateColorLayer(SK_ColorWHITE, gfx::Rect(10, 20, 200, 220)));
+  std::unique_ptr<Layer> root =
+      CreateColorLayer(SK_ColorWHITE, gfx::Rect(10, 20, 200, 220));
   TestLayerDelegate root_delegate;
   root_delegate.AddColor(SK_ColorWHITE);
   root->set_delegate(&root_delegate);
   root_delegate.set_layer_bounds(root->bounds());
 
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorWHITE, gfx::Rect(10, 20, 140, 180)));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorWHITE, gfx::Rect(10, 20, 140, 180));
   TestLayerDelegate l1_delegate;
   l1_delegate.AddColor(SK_ColorWHITE);
   l1->set_delegate(&l1_delegate);
@@ -2226,10 +2229,10 @@
 TEST_P(LayerWithRealCompositorTest, ScaleReparent) {
   viz::ParentLocalSurfaceIdAllocator allocator;
   allocator.GenerateId();
-  std::unique_ptr<Layer> root(
-      CreateColorLayer(SK_ColorWHITE, gfx::Rect(10, 20, 200, 220)));
-  std::unique_ptr<Layer> l1(
-      CreateColorLayer(SK_ColorWHITE, gfx::Rect(10, 20, 140, 180)));
+  std::unique_ptr<Layer> root =
+      CreateColorLayer(SK_ColorWHITE, gfx::Rect(10, 20, 200, 220));
+  std::unique_ptr<Layer> l1 =
+      CreateColorLayer(SK_ColorWHITE, gfx::Rect(10, 20, 140, 180));
   TestLayerDelegate l1_delegate;
   l1_delegate.AddColor(SK_ColorWHITE);
   l1->set_delegate(&l1_delegate);
@@ -2271,10 +2274,10 @@
 // - if just a move, then no painting should happen.
 // - if a resize, the layer should be repainted.
 TEST_F(LayerWithDelegateTest, SetBoundsWhenInvisible) {
-  std::unique_ptr<Layer> root(
-      CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
+  std::unique_ptr<Layer> root =
+      CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000));
 
-  std::unique_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> child = CreateLayer(LAYER_TEXTURED);
   child->SetBounds(gfx::Rect(0, 0, 500, 500));
   DrawTreeLayerDelegate delegate(child->bounds());
   child->set_delegate(&delegate);
@@ -2308,9 +2311,9 @@
 }
 
 TEST_F(LayerWithDelegateTest, ExternalContent) {
-  std::unique_ptr<Layer> root(
-      CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
-  std::unique_ptr<Layer> child(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> root =
+      CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000));
+  std::unique_ptr<Layer> child = CreateLayer(LAYER_SOLID_COLOR);
 
   child->SetBounds(gfx::Rect(0, 0, 10, 10));
   child->SetVisible(true);
@@ -2352,7 +2355,7 @@
 }
 
 TEST_F(LayerWithDelegateTest, ExternalContentMirroring) {
-  std::unique_ptr<Layer> layer(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> layer = CreateLayer(LAYER_SOLID_COLOR);
 
   viz::SurfaceId surface_id(
       viz::FrameSinkId(0, 1),
@@ -2383,7 +2386,7 @@
 }
 
 TEST_F(LayerWithDelegateTest, TransferableResourceMirroring) {
-  std::unique_ptr<Layer> layer(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> layer = CreateLayer(LAYER_SOLID_COLOR);
 
   constexpr gfx::Size size(64, 64);
   auto resource = viz::TransferableResource::MakeGL(
@@ -2439,7 +2442,7 @@
 // Verifies that layer filters still attached after changing implementation
 // layer.
 TEST_F(LayerWithDelegateTest, LayerFiltersSurvival) {
-  std::unique_ptr<Layer> layer(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> layer = CreateLayer(LAYER_TEXTURED);
   layer->SetBounds(gfx::Rect(0, 0, 10, 10));
   EXPECT_TRUE(layer->cc_layer_for_testing());
   EXPECT_EQ(0u, layer->cc_layer_for_testing()->filters().size());
@@ -2460,9 +2463,9 @@
 
 // Tests Layer::AddThreadedAnimation and Layer::RemoveThreadedAnimation.
 TEST_P(LayerWithRealCompositorTest, AddRemoveThreadedAnimations) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l2(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> l1 = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> l2 = CreateLayer(LAYER_TEXTURED);
 
   l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
   l2->SetAnimator(LayerAnimator::CreateImplicitAnimator());
@@ -2509,8 +2512,8 @@
 // Tests that in-progress threaded animations complete when a Layer's
 // cc::Layer changes.
 TEST_P(LayerWithRealCompositorTest, SwitchCCLayerAnimations) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> l1 = CreateLayer(LAYER_TEXTURED);
   GetCompositor()->SetRootLayer(root.get());
   root->Add(l1.get());
 
@@ -2532,7 +2535,7 @@
 // opaqueness and color set while not animating, are maintained.
 TEST_P(LayerWithRealCompositorTest, SwitchCCLayerSolidColorNotAnimating) {
   SkColor transparent = SK_ColorTRANSPARENT;
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_SOLID_COLOR);
   GetCompositor()->SetRootLayer(root.get());
   root->SetFillsBoundsOpaquely(false);
   root->SetColor(transparent);
@@ -2558,16 +2561,16 @@
 // targets are maintained.
 TEST_P(LayerWithRealCompositorTest, SwitchCCLayerSolidColorWhileAnimating) {
   SkColor transparent = SK_ColorTRANSPARENT;
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_SOLID_COLOR);
   GetCompositor()->SetRootLayer(root.get());
   root->SetColor(SK_ColorBLACK);
 
   EXPECT_TRUE(root->fills_bounds_opaquely());
   EXPECT_EQ(SK_ColorBLACK, root->GetTargetColor());
 
-  std::unique_ptr<ui::ScopedAnimationDurationScaleMode> long_duration_animation(
-      new ui::ScopedAnimationDurationScaleMode(
-          ui::ScopedAnimationDurationScaleMode::SLOW_DURATION));
+  auto long_duration_animation =
+      std::make_unique<ui::ScopedAnimationDurationScaleMode>(
+          ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
   {
     ui::ScopedLayerAnimationSettings animation(root->GetAnimator());
     animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000));
@@ -2602,8 +2605,8 @@
 // Tests that when a layer with cache_render_surface flag has its CC layer
 // switched, that the cache_render_surface flag is maintained.
 TEST_P(LayerWithRealCompositorTest, SwitchCCLayerCacheRenderSurface) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> l1 = CreateLayer(LAYER_TEXTURED);
   GetCompositor()->SetRootLayer(root.get());
   root->Add(l1.get());
 
@@ -2619,8 +2622,8 @@
 // Tests that when a layer with trilinear_filtering flag has its CC layer
 // switched, that the trilinear_filtering flag is maintained.
 TEST_P(LayerWithRealCompositorTest, SwitchCCLayerTrilinearFiltering) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> l1 = CreateLayer(LAYER_TEXTURED);
   GetCompositor()->SetRootLayer(root.get());
   root->Add(l1.get());
 
@@ -2654,9 +2657,9 @@
 // Tests that the animators in the layer tree is added to the
 // animator-collection when the root-layer is set to the compositor.
 TEST_F(LayerWithDelegateTest, RootLayerAnimatorsInCompositor) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
-  std::unique_ptr<Layer> child(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10)));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_SOLID_COLOR);
+  std::unique_ptr<Layer> child =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10));
   child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
   child->SetOpacity(0.5f);
   root->Add(child.get());
@@ -2669,10 +2672,10 @@
 // Tests that adding/removing a layer adds/removes the animator from its entire
 // subtree from the compositor's animator-collection.
 TEST_F(LayerWithDelegateTest, AddRemoveLayerUpdatesAnimatorsFromSubtree) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> grandchild(
-      CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10)));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> child = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> grandchild =
+      CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10));
   root->Add(child.get());
   child->Add(grandchild.get());
   compositor()->SetRootLayer(root.get());
@@ -2689,8 +2692,8 @@
 }
 
 TEST_F(LayerWithDelegateTest, DestroyingLayerRemovesTheAnimatorFromCollection) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> child = CreateLayer(LAYER_TEXTURED);
   root->Add(child.get());
   compositor()->SetRootLayer(root.get());
 
@@ -2730,9 +2733,9 @@
 // Verifies that empty LayerAnimators are not left behind when removing child
 // Layers that own an empty LayerAnimator. See http://crbug.com/552037.
 TEST_F(LayerWithDelegateTest, NonAnimatingAnimatorsAreRemovedFromCollection) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> parent(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> parent = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> child = CreateLayer(LAYER_TEXTURED);
   root->Add(parent.get());
   parent->Add(child.get());
   compositor()->SetRootLayer(root.get());
@@ -2765,9 +2768,9 @@
 }  // namespace
 
 TEST_P(LayerWithRealCompositorTest, SnapLayerToPixels) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> c1(CreateLayer(LAYER_TEXTURED));
-  std::unique_ptr<Layer> c11(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> c1 = CreateLayer(LAYER_TEXTURED);
+  std::unique_ptr<Layer> c11 = CreateLayer(LAYER_TEXTURED);
 
   viz::ParentLocalSurfaceIdAllocator allocator;
   allocator.GenerateId();
@@ -3126,7 +3129,7 @@
 }
 
 TEST_P(LayerWithRealCompositorTest, CompositorAnimationObserverTest) {
-  std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
+  std::unique_ptr<Layer> root = CreateLayer(LAYER_TEXTURED);
 
   root->SetAnimator(LayerAnimator::CreateImplicitAnimator());
 
diff --git a/ui/compositor_extra/shadow.cc b/ui/compositor_extra/shadow.cc
index f2cae01..4dd4c3ce 100644
--- a/ui/compositor_extra/shadow.cc
+++ b/ui/compositor_extra/shadow.cc
@@ -19,9 +19,9 @@
 
 }  // namespace
 
-Shadow::Shadow() {}
+Shadow::Shadow() : shadow_layer_owner_(this) {}
 
-Shadow::~Shadow() {}
+Shadow::~Shadow() = default;
 
 void Shadow::Init(int elevation) {
   DCHECK_GE(elevation, 0);
@@ -91,17 +91,33 @@
   UpdateLayerBounds();
 }
 
+// -----------------------------------------------------------------------------
+// Shadow::ShadowLayerOwner:
+
+Shadow::ShadowLayerOwner::ShadowLayerOwner(Shadow* owner,
+                                           std::unique_ptr<Layer> layer)
+    : LayerOwner(std::move(layer)), owner_shadow_(owner) {}
+
+Shadow::ShadowLayerOwner::~ShadowLayerOwner() = default;
+
+std::unique_ptr<Layer> Shadow::ShadowLayerOwner::RecreateLayer() {
+  auto result = ui::LayerOwner::RecreateLayer();
+  // Now update the newly recreated shadow layer with the correct nine patch
+  // image details.
+  owner_shadow_->details_ = nullptr;
+  owner_shadow_->UpdateLayerBounds();
+  return result;
+}
+
+// -----------------------------------------------------------------------------
+// Shadow:
+
 void Shadow::RecreateShadowLayer() {
-  if (shadow_layer_owner_.OwnsLayer()) {
-    shadow_layer_owner_.RecreateLayer();
-  } else {
-    shadow_layer_owner_.Reset(
-        std::make_unique<ui::Layer>(ui::LAYER_NINE_PATCH));
-    shadow_layer()->set_name("Shadow");
-    shadow_layer()->SetVisible(true);
-    shadow_layer()->SetFillsBoundsOpaquely(false);
-    layer()->Add(shadow_layer());
-  }
+  shadow_layer_owner_.Reset(std::make_unique<ui::Layer>(ui::LAYER_NINE_PATCH));
+  shadow_layer()->set_name("Shadow");
+  shadow_layer()->SetVisible(true);
+  shadow_layer()->SetFillsBoundsOpaquely(false);
+  layer()->Add(shadow_layer());
 
   UpdateLayerBounds();
 }
diff --git a/ui/compositor_extra/shadow.h b/ui/compositor_extra/shadow.h
index 50b0773c..cc920b88 100644
--- a/ui/compositor_extra/shadow.h
+++ b/ui/compositor_extra/shadow.h
@@ -57,6 +57,23 @@
   void OnImplicitAnimationsCompleted() override;
 
  private:
+  // A shadow layer owner that correctly updates the nine patch layer details
+  // when it gets recreated.
+  class ShadowLayerOwner : public ui::LayerOwner {
+   public:
+    explicit ShadowLayerOwner(Shadow* owner,
+                              std::unique_ptr<Layer> layer = nullptr);
+    ~ShadowLayerOwner() override;
+
+    // ui::LayerOwner:
+    std::unique_ptr<Layer> RecreateLayer() override;
+
+   private:
+    Shadow* const owner_shadow_;
+
+    DISALLOW_COPY_AND_ASSIGN(ShadowLayerOwner);
+  };
+
   // Updates the shadow layer and its image to reflect |desired_elevation_|.
   void RecreateShadowLayer();
 
@@ -82,7 +99,7 @@
   const gfx::ShadowDetails* details_ = nullptr;
 
   // The owner of the actual shadow layer corresponding to a cc::NinePatchLayer.
-  ui::LayerOwner shadow_layer_owner_;
+  ShadowLayerOwner shadow_layer_owner_;
 
   // When the elevation changes, the old shadow cross-fades with the new one.
   // When non-null, this owns an old |shadow_layer()| that's being animated out.
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc
index e2d51fc..4be6f418 100644
--- a/ui/views/controls/label.cc
+++ b/ui/views/controls/label.cc
@@ -36,6 +36,17 @@
 
 namespace {
 
+// An enum giving different RenderText properties unique keys for the
+// OnPropertyChanged call.
+enum LabelPropertyKey {
+  kLabelText = 1,
+  kLabelShadows,
+  kLabelHorizontalAlignment,
+  kLabelLineHeight,
+  kLabelObscured,
+  kLabelAllowCharacterBreak,
+};
+
 bool IsOpaque(SkColor color) {
   return SkColorGetA(color) == SK_AlphaOPAQUE;
 }
@@ -88,7 +99,7 @@
   if (new_text == GetText())
     return;
   full_text_->SetText(new_text);
-  OnPropertyChanged(&new_text, kPropertyEffectsLayout);
+  OnPropertyChanged(&full_text_ + kLabelText, kPropertyEffectsLayout);
   stored_selection_range_ = gfx::Range::InvalidRange();
 }
 
@@ -156,7 +167,7 @@
   OnPropertyChanged(&selection_background_color_, kPropertyEffectsPaint);
 }
 
-const gfx::ShadowValues& Label::shadows() const {
+const gfx::ShadowValues& Label::GetShadows() const {
   return full_text_->shadows();
 }
 
@@ -164,7 +175,7 @@
   if (full_text_->shadows() == shadows)
     return;
   full_text_->set_shadows(shadows);
-  ResetLayout();
+  OnPropertyChanged(&full_text_ + kLabelShadows, kPropertyEffectsLayout);
 }
 
 bool Label::GetSubpixelRenderingEnabled() const {
@@ -187,7 +198,8 @@
   if (GetHorizontalAlignment() == alignment)
     return;
   full_text_->SetHorizontalAlignment(alignment);
-  ResetLayout();
+  OnPropertyChanged(&full_text_ + kLabelHorizontalAlignment,
+                    kPropertyEffectsLayout);
 }
 
 int Label::GetLineHeight() const {
@@ -198,7 +210,7 @@
   if (GetLineHeight() == height)
     return;
   full_text_->SetMinLineHeight(height);
-  OnPropertyChanged(&height, kPropertyEffectsLayout);
+  OnPropertyChanged(&full_text_ + kLabelLineHeight, kPropertyEffectsLayout);
 }
 
 bool Label::GetMultiLine() const {
@@ -237,7 +249,7 @@
   full_text_->SetObscured(obscured);
   if (obscured)
     SetSelectable(false);
-  OnPropertyChanged(&obscured, kPropertyEffectsLayout);
+  OnPropertyChanged(&full_text_ + kLabelObscured, kPropertyEffectsLayout);
 }
 
 bool Label::GetAllowCharacterBreak() const {
@@ -251,7 +263,8 @@
   if (full_text_->word_wrap_behavior() == behavior)
     return;
   full_text_->SetWordWrapBehavior(behavior);
-  OnPropertyChanged(&allow_character_break, kPropertyEffectsLayout);
+  OnPropertyChanged(&full_text_ + kLabelAllowCharacterBreak,
+                    kPropertyEffectsLayout);
 }
 
 gfx::ElideBehavior Label::GetElideBehavior() const {
@@ -264,7 +277,7 @@
   if (elide_behavior_ == elide_behavior)
     return;
   elide_behavior_ = elide_behavior;
-  ResetLayout();
+  OnPropertyChanged(&elide_behavior_, kPropertyEffectsLayout);
 }
 
 base::string16 Label::GetTooltipText() const {
@@ -537,7 +550,7 @@
   render_text->SetObscured(GetObscured());
   render_text->SetMinLineHeight(GetLineHeight());
   render_text->SetFontList(font_list());
-  render_text->set_shadows(shadows());
+  render_text->set_shadows(GetShadows());
   render_text->SetCursorEnabled(false);
   render_text->SetText(GetText());
   render_text->SetMultiline(GetMultiLine());
@@ -951,7 +964,7 @@
   if (rect.IsEmpty())
     return;
 
-  rect.Inset(-gfx::ShadowValue::GetMargin(shadows()));
+  rect.Inset(-gfx::ShadowValue::GetMargin(GetShadows()));
   display_text_ = CreateRenderText();
   display_text_->SetDisplayRect(rect);
   stored_selection_range_ = gfx::Range::InvalidRange();
@@ -972,7 +985,7 @@
     full_text_->SetDisplayRect(gfx::Rect(0, 0, width(), 0));
     size = full_text_->GetStringSize();
   }
-  const gfx::Insets shadow_margin = -gfx::ShadowValue::GetMargin(shadows());
+  const gfx::Insets shadow_margin = -gfx::ShadowValue::GetMargin(GetShadows());
   size.Enlarge(shadow_margin.width(), shadow_margin.height());
   return size;
 }
@@ -1079,10 +1092,13 @@
 ADD_PROPERTY_METADATA(Label, bool, AutoColorReadabilityEnabled)
 ADD_PROPERTY_METADATA(Label, base::string16, Text)
 ADD_PROPERTY_METADATA(Label, SkColor, EnabledColor)
+ADD_PROPERTY_METADATA(Label, gfx::ElideBehavior, ElideBehavior)
 ADD_PROPERTY_METADATA(Label, SkColor, BackgroundColor)
 ADD_PROPERTY_METADATA(Label, SkColor, SelectionTextColor)
 ADD_PROPERTY_METADATA(Label, SkColor, SelectionBackgroundColor)
 ADD_PROPERTY_METADATA(Label, bool, SubpixelRenderingEnabled)
+ADD_PROPERTY_METADATA(Label, gfx::ShadowValues, Shadows)
+ADD_PROPERTY_METADATA(Label, gfx::HorizontalAlignment, HorizontalAlignment)
 ADD_PROPERTY_METADATA(Label, int, LineHeight)
 ADD_PROPERTY_METADATA(Label, bool, MultiLine)
 ADD_PROPERTY_METADATA(Label, int, MaxLines)
diff --git a/ui/views/controls/label.h b/ui/views/controls/label.h
index ce169b1..80f60e0 100644
--- a/ui/views/controls/label.h
+++ b/ui/views/controls/label.h
@@ -114,7 +114,7 @@
   void SetSelectionBackgroundColor(SkColor color);
 
   // Get/Set drop shadows underneath the text.
-  const gfx::ShadowValues& shadows() const;
+  const gfx::ShadowValues& GetShadows() const;
   void SetShadows(const gfx::ShadowValues& shadows);
 
   // Gets/Sets whether subpixel rendering is used; the default is true, but this
diff --git a/ui/views/controls/link.cc b/ui/views/controls/link.cc
index 9b200179..e9bb9fba 100644
--- a/ui/views/controls/link.cc
+++ b/ui/views/controls/link.cc
@@ -47,6 +47,21 @@
   return GetDefaultFocusStyle();
 }
 
+SkColor Link::GetColor() const {
+  // TODO(tapted): Use style::GetColor().
+  const ui::NativeTheme* theme = GetNativeTheme();
+  DCHECK(theme);
+  if (!GetEnabled())
+    return theme->GetSystemColor(ui::NativeTheme::kColorId_LinkDisabled);
+
+  if (requested_enabled_color_set_)
+    return requested_enabled_color_;
+
+  return GetNativeTheme()->GetSystemColor(
+      pressed_ ? ui::NativeTheme::kColorId_LinkPressed
+               : ui::NativeTheme::kColorId_LinkEnabled);
+}
+
 void Link::PaintFocusRing(gfx::Canvas* canvas) const {
   if (GetFocusStyle() == FocusStyle::RING) {
     gfx::Rect focus_ring_bounds = GetTextBounds();
@@ -200,11 +215,16 @@
   return false;
 }
 
+bool Link::GetUnderline() const {
+  return underline_;
+}
+
 void Link::SetUnderline(bool underline) {
   if (underline_ == underline)
     return;
   underline_ = underline;
   RecalculateFont();
+  OnPropertyChanged(&underline_, kPropertyEffectsPreferredSizeChanged);
 }
 
 void Link::Init() {
@@ -259,23 +279,15 @@
   }
 }
 
-SkColor Link::GetColor() {
-  // TODO(tapted): Use style::GetColor().
-  const ui::NativeTheme* theme = GetNativeTheme();
-  DCHECK(theme);
-  if (!GetEnabled())
-    return theme->GetSystemColor(ui::NativeTheme::kColorId_LinkDisabled);
-
-  if (requested_enabled_color_set_)
-    return requested_enabled_color_;
-
-  return GetNativeTheme()->GetSystemColor(
-      pressed_ ? ui::NativeTheme::kColorId_LinkPressed
-               : ui::NativeTheme::kColorId_LinkEnabled);
-}
-
+DEFINE_ENUM_CONVERTERS(Link::FocusStyle,
+                       {Link::FocusStyle::UNDERLINE,
+                        base::ASCIIToUTF16("UNDERLINE")},
+                       {Link::FocusStyle::RING, base::ASCIIToUTF16("RING")})
 BEGIN_METADATA(Link)
 METADATA_PARENT_CLASS(Label)
+ADD_READONLY_PROPERTY_METADATA(Link, SkColor, Color)
+ADD_READONLY_PROPERTY_METADATA(Link, Link::FocusStyle, FocusStyle)
+ADD_PROPERTY_METADATA(Link, bool, Underline)
 END_METADATA()
 
 }  // namespace views
diff --git a/ui/views/controls/link.h b/ui/views/controls/link.h
index 8f4f6af9..917d888e 100644
--- a/ui/views/controls/link.h
+++ b/ui/views/controls/link.h
@@ -53,6 +53,8 @@
   const LinkListener* listener() { return listener_; }
   void set_listener(LinkListener* listener) { listener_ = listener; }
 
+  SkColor GetColor() const;
+
   // Label:
   void PaintFocusRing(gfx::Canvas* canvas) const override;
   gfx::Insets GetInsets() const override;
@@ -74,6 +76,7 @@
   void SetEnabledColor(SkColor color) override;
   bool IsSelectionSupported() const override;
 
+  bool GetUnderline() const;
   // TODO(estade): almost all the places that call this pass false. With
   // Harmony, false is already the default so those callsites can be removed.
   // TODO(tapted): Then remove all callsites when client code sets a correct
@@ -89,8 +92,6 @@
 
   void ConfigureFocus();
 
-  SkColor GetColor();
-
   LinkListener* listener_;
 
   // Whether the link should be underlined when enabled.
diff --git a/ui/views/controls/scroll_view.cc b/ui/views/controls/scroll_view.cc
index f661662..05a9c961 100644
--- a/ui/views/controls/scroll_view.cc
+++ b/ui/views/controls/scroll_view.cc
@@ -308,7 +308,7 @@
   if (draw_overflow_indicator_ == draw_overflow_indicator)
     return;
   draw_overflow_indicator_ = draw_overflow_indicator;
-  OnPropertyChanged(&draw_overflow_indicator, kPropertyEffectsPaint);
+  OnPropertyChanged(&draw_overflow_indicator_, kPropertyEffectsPaint);
 }
 
 void ScrollView::ClipHeightTo(int min_height, int max_height) {
@@ -349,7 +349,7 @@
 
     focus_ring_->SchedulePaint();
   SchedulePaint();
-  OnPropertyChanged(&has_focus_indicator, kPropertyEffectsPaint);
+  OnPropertyChanged(&draw_focus_indicator_, kPropertyEffectsPaint);
 }
 
 gfx::Size ScrollView::CalculatePreferredSize() const {
diff --git a/ui/views/controls/styled_label.cc b/ui/views/controls/styled_label.cc
index 0d27d16f..8dd2c7c 100644
--- a/ui/views/controls/styled_label.cc
+++ b/ui/views/controls/styled_label.cc
@@ -233,7 +233,7 @@
     return;
 
   auto_color_readability_enabled_ = auto_color_readability;
-  OnPropertyChanged(&auto_color_readability, kPropertyEffectsNone);
+  OnPropertyChanged(&auto_color_readability_enabled_, kPropertyEffectsNone);
 }
 
 void StyledLabel::SizeToFit(int max_width) {
diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view.cc
index 84703890..966a899 100644
--- a/ui/views/controls/table/table_view.cc
+++ b/ui/views/controls/table/table_view.cc
@@ -133,9 +133,6 @@
 
 TableView::PaintRegion::~PaintRegion() = default;
 
-// static
-const char TableView::kViewClassName[] = "TableView";
-
 TableView::TableView(ui::TableModel* model,
                      const std::vector<ui::TableColumn>& columns,
                      TableTypes table_type,
@@ -196,7 +193,7 @@
   SortItemsAndUpdateMapping(/*schedule_paint=*/true);
 }
 
-int TableView::RowCount() const {
+int TableView::GetRowCount() const {
   return model_ ? model_->RowCount() : 0;
 }
 
@@ -207,7 +204,7 @@
   SelectByViewIndex(model_row == -1 ? -1 : ModelToView(model_row));
 }
 
-int TableView::FirstSelectedRow() {
+int TableView::GetFirstSelectedRow() const {
   return selection_model_.empty() ? -1 : selection_model_.selected_indices()[0];
 }
 
@@ -287,7 +284,7 @@
   return std::any_of(columns_.cbegin(), columns_.cend(), ids_match);
 }
 
-bool TableView::HasFocusIndicator() const {
+bool TableView::GetHasFocusIndicator() const {
   int active_row = selection_model_.active();
   return active_row != ui::ListSelectionModel::kUnselectedIndex &&
          active_visible_column_index_ !=
@@ -298,7 +295,7 @@
   if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell)
     return;
 
-  if (HasFocusIndicator()) {
+  if (GetHasFocusIndicator()) {
     // Draw a focus indicator around the active column.
     focus_ring_ = FocusRing::Install(this);
     const gfx::Rect cell_bounds(GetCellBounds(
@@ -333,19 +330,47 @@
 }
 
 int TableView::ModelToView(int model_index) const {
-  if (!is_sorted())
+  if (!GetIsSorted())
     return model_index;
   DCHECK_GE(model_index, 0) << " negative model_index " << model_index;
-  DCHECK_LT(model_index, RowCount()) << " out of bounds model_index " <<
-      model_index;
+  DCHECK_LT(model_index, GetRowCount())
+      << " out of bounds model_index " << model_index;
   return model_to_view_[model_index];
 }
 
 int TableView::ViewToModel(int view_index) const {
   DCHECK_GE(view_index, 0) << " negative view_index " << view_index;
-  DCHECK_LT(view_index, RowCount()) << " out of bounds view_index " <<
-      view_index;
-  return is_sorted() ? view_to_model_[view_index] : view_index;
+  DCHECK_LT(view_index, GetRowCount())
+      << " out of bounds view_index " << view_index;
+  return GetIsSorted() ? view_to_model_[view_index] : view_index;
+}
+
+bool TableView::GetSelectOnRemove() const {
+  return select_on_remove_;
+}
+
+void TableView::SetSelectOnRemove(bool select_on_remove) {
+  if (select_on_remove_ == select_on_remove)
+    return;
+
+  select_on_remove_ = select_on_remove;
+  OnPropertyChanged(&select_on_remove_, kPropertyEffectsNone);
+}
+
+TableTypes TableView::GetTableType() const {
+  return table_type_;
+}
+
+bool TableView::GetSortOnPaint() const {
+  return sort_on_paint_;
+}
+
+void TableView::SetSortOnPaint(bool sort_on_paint) {
+  if (sort_on_paint_ == sort_on_paint)
+    return;
+
+  sort_on_paint_ = sort_on_paint;
+  OnPropertyChanged(&sort_on_paint_, kPropertyEffectsNone);
 }
 
 void TableView::Layout() {
@@ -378,15 +403,11 @@
     focus_ring_->Layout();
 }
 
-const char* TableView::GetClassName() const {
-  return kViewClassName;
-}
-
 gfx::Size TableView::CalculatePreferredSize() const {
   int width = 50;
   if (header_ && !visible_columns_.empty())
     width = visible_columns_.back().x + visible_columns_.back().width;
-  return gfx::Size(width, RowCount() * row_height_);
+  return gfx::Size(width, GetRowCount() * row_height_);
 }
 
 bool TableView::OnKeyPressed(const ui::KeyEvent& event) {
@@ -396,10 +417,10 @@
   switch (event.key_code()) {
     case ui::VKEY_A:
       // control-a selects all.
-      if (IsCmdOrCtrl(event) && !single_selection_ && RowCount()) {
+      if (IsCmdOrCtrl(event) && !single_selection_ && GetRowCount()) {
         ui::ListSelectionModel selection_model;
         selection_model.SetSelectedIndex(selection_model_.active());
-        for (int i = 0; i < RowCount(); ++i)
+        for (int i = 0; i < GetRowCount(); ++i)
           selection_model.AddIndexToSelection(i);
         SetSelectionModel(std::move(selection_model));
         return true;
@@ -407,19 +428,19 @@
       break;
 
     case ui::VKEY_HOME:
-      if (RowCount())
+      if (GetRowCount())
         SelectByViewIndex(0);
       return true;
 
     case ui::VKEY_END:
-      if (RowCount())
-        SelectByViewIndex(RowCount() - 1);
+      if (GetRowCount())
+        SelectByViewIndex(GetRowCount() - 1);
       return true;
 
     case ui::VKEY_UP:
 #if defined(OS_MACOSX)
       if (event.IsAltDown()) {
-        if (RowCount())
+        if (GetRowCount())
           SelectByViewIndex(0);
       } else {
         AdvanceSelection(ADVANCE_DECREMENT);
@@ -432,8 +453,8 @@
     case ui::VKEY_DOWN:
 #if defined(OS_MACOSX)
       if (event.IsAltDown()) {
-        if (RowCount())
-          SelectByViewIndex(RowCount() - 1);
+        if (GetRowCount())
+          SelectByViewIndex(GetRowCount() - 1);
       } else {
         AdvanceSelection(ADVANCE_INCREMENT);
       }
@@ -499,7 +520,7 @@
     return true;
 
   const int row = event.y() / row_height_;
-  if (row < 0 || row >= RowCount())
+  if (row < 0 || row >= GetRowCount())
     return true;
 
   if (event.GetClickCount() == 2) {
@@ -522,7 +543,7 @@
   RequestFocus();
 
   const int row = event->y() / row_height_;
-  if (row < 0 || row >= RowCount())
+  if (row < 0 || row >= GetRowCount())
     return;
 
   event->StopPropagation();
@@ -533,7 +554,7 @@
 
 base::string16 TableView::GetTooltipText(const gfx::Point& p) const {
   const int row = p.y() / row_height_;
-  if (row < 0 || row >= RowCount() || visible_columns_.empty())
+  if (row < 0 || row >= GetRowCount() || visible_columns_.empty())
     return base::string16();
 
   const int x = GetMirroredXInView(p.x());
@@ -555,14 +576,14 @@
   node_data->SetNameExplicitlyEmpty();
 
   node_data->AddIntAttribute(ax::mojom::IntAttribute::kTableRowCount,
-                             static_cast<int32_t>(RowCount()));
+                             static_cast<int32_t>(GetRowCount()));
   node_data->AddIntAttribute(ax::mojom::IntAttribute::kTableColumnCount,
                              static_cast<int32_t>(visible_columns_.size()));
   node_data->relative_bounds.bounds = gfx::RectF(GetVisibleBounds());
 }
 
 bool TableView::HandleAccessibleAction(const ui::AXActionData& action_data) {
-  if (!RowCount())
+  if (!GetRowCount())
     return false;
 
   int active_row = selection_model_.active();
@@ -645,9 +666,9 @@
   // Determine the currently selected index in terms of the view. We inline the
   // implementation here since ViewToModel() has DCHECKs that fail since the
   // model has changed but |model_to_view_| has not been updated yet.
-  const int previously_selected_model_index = FirstSelectedRow();
+  const int previously_selected_model_index = GetFirstSelectedRow();
   int previously_selected_view_index = previously_selected_model_index;
-  if (previously_selected_model_index != -1 && is_sorted())
+  if (previously_selected_model_index != -1 && GetIsSorted())
     previously_selected_view_index =
         model_to_view_[previously_selected_model_index];
   for (int i = 0; i < length; ++i)
@@ -656,21 +677,21 @@
   // If the selection was empty and is no longer empty select the same visual
   // index.
   if (selection_model_.empty() && previously_selected_view_index != -1 &&
-      RowCount() && select_on_remove_) {
-    selection_model_.SetSelectedIndex(
-        ViewToModel(std::min(RowCount() - 1, previously_selected_view_index)));
+      GetRowCount() && select_on_remove_) {
+    selection_model_.SetSelectedIndex(ViewToModel(
+        std::min(GetRowCount() - 1, previously_selected_view_index)));
   }
   if (!selection_model_.empty() && selection_model_.active() == -1)
-    selection_model_.set_active(FirstSelectedRow());
+    selection_model_.set_active(GetFirstSelectedRow());
   if (!selection_model_.empty() && selection_model_.anchor() == -1)
-    selection_model_.set_anchor(FirstSelectedRow());
+    selection_model_.set_anchor(GetFirstSelectedRow());
   NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
   if (observer_)
     observer_->OnSelectionChanged();
 }
 
 gfx::Point TableView::GetKeyboardContextMenuLocation() {
-  int first_selected = FirstSelectedRow();
+  int first_selected = GetFirstSelectedRow();
   gfx::Rect vis_bounds(GetVisibleBounds());
   int y = vis_bounds.height() / 2;
   if (first_selected != -1) {
@@ -696,7 +717,7 @@
   canvas->DrawColor(GetNativeTheme()->GetSystemColor(
                         ui::NativeTheme::kColorId_TableBackground));
 
-  if (!RowCount() || visible_columns_.empty())
+  if (!GetRowCount() || visible_columns_.empty())
     return;
 
   const PaintRegion region(GetPaintRegion(GetPaintBounds(canvas)));
@@ -827,18 +848,18 @@
 }
 
 void TableView::SortItemsAndUpdateMapping(bool schedule_paint) {
-  if (!is_sorted()) {
+  if (!GetIsSorted()) {
     view_to_model_.clear();
     model_to_view_.clear();
   } else {
-    const int row_count = RowCount();
+    const int row_count = GetRowCount();
     view_to_model_.resize(row_count);
     model_to_view_.resize(row_count);
     for (int i = 0; i < row_count; ++i)
       view_to_model_[i] = i;
     if (grouper_) {
       GroupSortHelper sort_helper(this);
-      GetModelIndexToRangeStart(grouper_, RowCount(),
+      GetModelIndexToRangeStart(grouper_, GetRowCount(),
                                 &sort_helper.model_index_to_range_start);
       std::stable_sort(view_to_model_.begin(), view_to_model_.end(),
                        sort_helper);
@@ -936,15 +957,15 @@
 TableView::PaintRegion TableView::GetPaintRegion(
     const gfx::Rect& bounds) const {
   DCHECK(!visible_columns_.empty());
-  DCHECK(RowCount());
+  DCHECK(GetRowCount());
 
   PaintRegion region;
-  region.min_row = std::min(RowCount() - 1,
-                            std::max(0, bounds.y() / row_height_));
+  region.min_row =
+      std::min(GetRowCount() - 1, std::max(0, bounds.y() / row_height_));
   region.max_row = bounds.bottom() / row_height_;
   if (bounds.bottom() % row_height_ != 0)
     region.max_row++;
-  region.max_row = std::min(region.max_row, RowCount());
+  region.max_row = std::min(region.max_row, GetRowCount());
 
   if (!header_) {
     region.max_column = 1;
@@ -976,7 +997,7 @@
 
 void TableView::SchedulePaintForSelection() {
   if (selection_model_.size() == 1) {
-    const int first_model_row = FirstSelectedRow();
+    const int first_model_row = GetFirstSelectedRow();
     SchedulePaintInRect(GetRowBounds(ModelToView(first_model_row)));
     if (first_model_row != selection_model_.active())
       SchedulePaintInRect(GetRowBounds(ModelToView(selection_model_.active())));
@@ -1031,6 +1052,7 @@
 
   ResetFocusIndicator();
   UpdateAccessibilityFocus();
+  OnPropertyChanged(&active_visible_column_index_, kPropertyEffectsNone);
 }
 
 void TableView::SelectByViewIndex(int view_index) {
@@ -1085,7 +1107,7 @@
   if (direction == ADVANCE_DECREMENT)
     view_index = std::max(0, view_index - 1);
   else
-    view_index = std::min(RowCount() - 1, view_index + 1);
+    view_index = std::min(GetRowCount() - 1, view_index + 1);
   SelectByViewIndex(view_index);
 }
 
@@ -1093,7 +1115,7 @@
     const ui::LocatedEvent& event,
     ui::ListSelectionModel* model) const {
   const int view_index = event.y() / row_height_;
-  DCHECK(view_index >= 0 && view_index < RowCount());
+  DCHECK(view_index >= 0 && view_index < GetRowCount());
 
   if (selection_model_.anchor() == -1 || single_selection_ ||
       (!IsCmdOrCtrl(event) && !event.IsShiftDown())) {
@@ -1155,7 +1177,7 @@
 
 void TableView::UpdateVirtualAccessibilityChildren() {
   GetViewAccessibility().RemoveAllVirtualChildViews();
-  if (!RowCount() || visible_columns_.empty()) {
+  if (!GetRowCount() || visible_columns_.empty()) {
     NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, true);
     return;
   }
@@ -1209,7 +1231,7 @@
     GetViewAccessibility().AddVirtualChildView(std::move(ax_header));
   }
 
-  for (int view_index = 0; view_index < RowCount(); ++view_index) {
+  for (int view_index = 0; view_index < GetRowCount(); ++view_index) {
     const int model_index = ViewToModel(view_index);
     auto ax_row = std::make_unique<AXVirtualView>();
     ui::AXNodeData& row_data = ax_row->GetCustomData();
@@ -1344,7 +1366,7 @@
 
 AXVirtualView* TableView::GetVirtualAccessibilityRow(int row) {
   DCHECK_GE(row, 0);
-  DCHECK_LT(row, RowCount());
+  DCHECK_LT(row, GetRowCount());
   if (header_)
     ++row;
   if (size_t{row} < GetViewAccessibility().virtual_children().size()) {
@@ -1380,4 +1402,22 @@
   return i->get();
 }
 
+DEFINE_ENUM_CONVERTERS(TableTypes,
+                       {TableTypes::TEXT_ONLY, base::ASCIIToUTF16("TEXT_ONLY")},
+                       {TableTypes::ICON_AND_TEXT,
+                        base::ASCIIToUTF16("ICON_AND_TEXT")})
+
+BEGIN_METADATA(TableView)
+METADATA_PARENT_CLASS(View)
+ADD_READONLY_PROPERTY_METADATA(TableView, int, RowCount)
+ADD_READONLY_PROPERTY_METADATA(TableView, int, FirstSelectedRow)
+ADD_READONLY_PROPERTY_METADATA(TableView, bool, HasFocusIndicator)
+ADD_PROPERTY_METADATA(TableView, int, ActiveVisibleColumnIndex)
+ADD_READONLY_PROPERTY_METADATA(TableView, bool, IsSorted)
+ADD_READONLY_PROPERTY_METADATA(TableView, int, RowHeight)
+ADD_PROPERTY_METADATA(TableView, bool, SelectOnRemove)
+ADD_READONLY_PROPERTY_METADATA(TableView, TableTypes, TableType)
+ADD_PROPERTY_METADATA(TableView, bool, SortOnPaint)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/table/table_view.h b/ui/views/controls/table/table_view.h
index eeee3de..835b6db 100644
--- a/ui/views/controls/table/table_view.h
+++ b/ui/views/controls/table/table_view.h
@@ -63,8 +63,7 @@
     : public views::View,
       public ui::TableModelObserver {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(TableView);
 
   // Used by AdvanceActiveVisibleColumn(), AdvanceSelection() and
   // ResizeColumnViaKeyboard() to determine the direction to change the
@@ -130,13 +129,13 @@
   void SetGrouper(TableGrouper* grouper);
 
   // Returns the number of rows in the TableView.
-  int RowCount() const;
+  int GetRowCount() const;
 
   // Selects the specified item, making sure it's visible.
   void Select(int model_row);
 
   // Returns the first selected row in terms of the model.
-  int FirstSelectedRow();
+  int GetFirstSelectedRow() const;
 
   const ui::ListSelectionModel& selection_model() const {
     return selection_model_;
@@ -154,7 +153,7 @@
   bool HasColumn(int id) const;
 
   // Returns whether an active row and column have been set.
-  bool HasFocusIndicator() const;
+  bool GetHasFocusIndicator() const;
 
   // Moves the focus ring to its new location if the active cell has changed, or
   // hides the focus ring if the table is not focused.
@@ -187,7 +186,7 @@
 
   const SortDescriptors& sort_descriptors() const { return sort_descriptors_; }
   void SetSortDescriptors(const SortDescriptors& descriptors);
-  bool is_sorted() const { return !sort_descriptors_.empty(); }
+  bool GetIsSorted() const { return !sort_descriptors_.empty(); }
 
   // Maps from the index in terms of the model to that of the view.
   int ModelToView(int model_index) const;
@@ -195,11 +194,10 @@
   // Maps from the index in terms of the view to that of the model.
   int ViewToModel(int view_index) const;
 
-  int row_height() const { return row_height_; }
+  int GetRowHeight() const { return row_height_; }
 
-  void set_select_on_remove(bool select_on_remove) {
-    select_on_remove_ = select_on_remove;
-  }
+  bool GetSelectOnRemove() const;
+  void SetSelectOnRemove(bool select_on_remove);
 
   // WARNING: this function forces a sort on every paint, and is therefore
   // expensive! It assumes you are calling SchedulePaint() at intervals for
@@ -208,11 +206,13 @@
   // time the SchedulePaint() is called and the paint is processed, the
   // underlying data may change. Also, this only works if the number of rows
   // remains the same.
-  void set_sort_on_paint(bool sort_on_paint) { sort_on_paint_ = sort_on_paint; }
+  bool GetSortOnPaint() const;
+  void SetSortOnPaint(bool sort_on_paint);
+
+  TableTypes GetTableType() const;
 
   // View overrides:
   void Layout() override;
-  const char* GetClassName() const override;
   gfx::Size CalculatePreferredSize() const override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc
index addb250..5a68a4dc 100644
--- a/ui/views/controls/table/table_view_unittest.cc
+++ b/ui/views/controls/table/table_view_unittest.cc
@@ -191,7 +191,7 @@
 // Returns the view to model mapping as a string.
 std::string GetViewToModelAsString(TableView* table) {
   std::string result;
-  for (int i = 0; i < table->RowCount(); ++i) {
+  for (int i = 0; i < table->GetRowCount(); ++i) {
     if (i != 0)
       result += " ";
     result += base::NumberToString(table->ViewToModel(i));
@@ -202,7 +202,7 @@
 // Returns the model to view mapping as a string.
 std::string GetModelToViewAsString(TableView* table) {
   std::string result;
-  for (int i = 0; i < table->RowCount(); ++i) {
+  for (int i = 0; i < table->GetRowCount(); ++i) {
     if (i != 0)
       result += " ";
     result += base::NumberToString(table->ModelToView(i));
@@ -214,7 +214,7 @@
 // scrolled out of view are included; hidden columns are excluded.
 std::string GetRowsInViewOrderAsString(TableView* table) {
   std::string result;
-  for (int i = 0; i < table->RowCount(); ++i) {
+  for (int i = 0; i < table->GetRowCount(); ++i) {
     if (i != 0)
       result += ", ";  // Comma between each row.
 
@@ -344,7 +344,7 @@
 
  private:
   gfx::Point GetPointForRow(int row) {
-    const int y = (row + 0.5) * table_->row_height();
+    const int y = (row + 0.5) * table_->GetRowHeight();
     return table_->GetBoundsInScreen().origin() + gfx::Vector2d(5, y);
   }
 
@@ -368,14 +368,15 @@
   EXPECT_EQ(ax::mojom::Role::kListGrid, data.role);
   EXPECT_TRUE(data.HasState(ax::mojom::State::kFocusable));
   EXPECT_EQ(ax::mojom::Restriction::kReadOnly, data.GetRestriction());
-  EXPECT_EQ(table_->RowCount(), static_cast<int>(data.GetIntAttribute(
-                                    ax::mojom::IntAttribute::kTableRowCount)));
+  EXPECT_EQ(table_->GetRowCount(),
+            static_cast<int>(
+                data.GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount)));
   EXPECT_EQ(helper_->visible_col_count(),
             static_cast<size_t>(data.GetIntAttribute(
                 ax::mojom::IntAttribute::kTableColumnCount)));
 
   // The header takes up another row.
-  ASSERT_EQ(size_t{table_->RowCount() + 1},
+  ASSERT_EQ(size_t{table_->GetRowCount() + 1},
             view_accessibility.virtual_children().size());
   const auto& header = view_accessibility.virtual_children().front();
   ASSERT_TRUE(header);
@@ -393,7 +394,7 @@
 
   int i = 0;
   for (auto child_iter = view_accessibility.virtual_children().begin() + 1;
-       i < table_->RowCount(); ++child_iter, ++i) {
+       i < table_->GetRowCount(); ++child_iter, ++i) {
     const auto& row = *child_iter;
     ASSERT_TRUE(row);
     const ui::AXNodeData& row_data = row->GetData();
@@ -416,7 +417,7 @@
 }
 
 TEST_F(TableViewTest, GetVirtualAccessibilityRow) {
-  for (int i = 0; i < table_->RowCount(); ++i) {
+  for (int i = 0; i < table_->GetRowCount(); ++i) {
     const AXVirtualView* row = helper_->GetVirtualAccessibilityRow(i);
     ASSERT_TRUE(row);
     const ui::AXNodeData& row_data = row->GetData();
@@ -427,7 +428,7 @@
 }
 
 TEST_F(TableViewTest, GetVirtualAccessibilityCell) {
-  for (int i = 0; i < table_->RowCount(); ++i) {
+  for (int i = 0; i < table_->GetRowCount(); ++i) {
     for (int j = 0; j < static_cast<int>(helper_->visible_col_count()); ++j) {
       const AXVirtualView* cell = helper_->GetVirtualAccessibilityCell(i, j);
       ASSERT_TRUE(cell);
@@ -991,7 +992,7 @@
 TEST_F(TableViewTest, SelectionNoSelectOnRemove) {
   TableViewObserverImpl observer;
   table_->set_observer(&observer);
-  table_->set_select_on_remove(false);
+  table_->SetSelectOnRemove(false);
 
   // Initially no selection.
   EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
diff --git a/ui/views/metadata/type_conversion.cc b/ui/views/metadata/type_conversion.cc
index 44af4a8..28e0384 100644
--- a/ui/views/metadata/type_conversion.cc
+++ b/ui/views/metadata/type_conversion.cc
@@ -7,6 +7,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -59,6 +60,18 @@
   return base::UTF8ToUTF16(source_value);
 }
 
+base::string16 TypeConverter<gfx::ShadowValues>::ToString(
+    const gfx::ShadowValues& source_value) {
+  base::string16 ret = base::ASCIIToUTF16("[");
+  for (auto shadow_value : source_value) {
+    ret += base::ASCIIToUTF16(" " + shadow_value.ToString() + ";");
+  }
+
+  ret[ret.length() - 1] = ' ';
+  ret += base::ASCIIToUTF16("]");
+  return ret;
+}
+
 base::Optional<int8_t> TypeConverter<int8_t>::FromString(
     const base::string16& source_value) {
   int32_t ret = 0;
@@ -169,6 +182,34 @@
   return source_value;
 }
 
+base::Optional<gfx::ShadowValues> TypeConverter<gfx::ShadowValues>::FromString(
+    const base::string16& source_value) {
+  gfx::ShadowValues ret;
+  const auto shadow_value_strings =
+      base::SplitStringPiece(source_value, base::ASCIIToUTF16("[;]"),
+                             base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+  for (auto v : shadow_value_strings) {
+    base::string16 member_string;
+    base::RemoveChars(v.as_string(), base::ASCIIToUTF16("()rgba"),
+                      &member_string);
+    const auto members = base::SplitStringPiece(
+        member_string, base::ASCIIToUTF16(","), base::TRIM_WHITESPACE,
+        base::SPLIT_WANT_NONEMPTY);
+    int x, y, r, g, b, a;
+    double blur;
+
+    if ((members.size() == 7) && base::StringToInt(members[0], &x) &&
+        base::StringToInt(members[1], &y) &&
+        base::StringToDouble(UTF16ToASCII(members[2]), &blur) &&
+        base::StringToInt(members[3], &r) &&
+        base::StringToInt(members[4], &g) &&
+        base::StringToInt(members[5], &b) && base::StringToInt(members[6], &a))
+      ret.emplace_back(gfx::Vector2d(x, y), blur, SkColorSetARGB(a, r, g, b));
+  }
+  return ret;
+}
+
 }  // namespace metadata
 }  // namespace views
 
@@ -182,6 +223,16 @@
                        {gfx::HorizontalAlignment::ALIGN_TO_HEAD,
                         base::ASCIIToUTF16("ALIGN_TO_HEAD")})
 
+DEFINE_ENUM_CONVERTERS(
+    gfx::ElideBehavior,
+    {gfx::ElideBehavior::NO_ELIDE, base::ASCIIToUTF16("NO_ELIDE")},
+    {gfx::ElideBehavior::TRUNCATE, base::ASCIIToUTF16("TRUNCATE")},
+    {gfx::ElideBehavior::ELIDE_HEAD, base::ASCIIToUTF16("ELIDE_HEAD")},
+    {gfx::ElideBehavior::ELIDE_MIDDLE, base::ASCIIToUTF16("ELIDE_MIDDLE")},
+    {gfx::ElideBehavior::ELIDE_TAIL, base::ASCIIToUTF16("ELIDE_TAIL")},
+    {gfx::ElideBehavior::ELIDE_EMAIL, base::ASCIIToUTF16("ELIDE_EMAIL")},
+    {gfx::ElideBehavior::FADE_TAIL, base::ASCIIToUTF16("FADE_TAIL")})
+
 DEFINE_ENUM_CONVERTERS(ui::TextInputType,
                        {ui::TextInputType::TEXT_INPUT_TYPE_NONE,
                         base::ASCIIToUTF16("TEXT_INPUT_TYPE_NONE")},
diff --git a/ui/views/metadata/type_conversion.h b/ui/views/metadata/type_conversion.h
index f667b7a..189f610b 100644
--- a/ui/views/metadata/type_conversion.h
+++ b/ui/views/metadata/type_conversion.h
@@ -16,6 +16,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/shadow_value.h"
 #include "ui/gfx/text_constants.h"
 #include "ui/views/views_export.h"
 
@@ -114,6 +115,7 @@
 DECLARE_CONVERSIONS(gfx::Size)
 DECLARE_CONVERSIONS(base::string16)
 DECLARE_CONVERSIONS(const char*)
+DECLARE_CONVERSIONS(gfx::ShadowValues)
 
 #undef DECLARE_CONVERSIONS
 
diff --git a/ui/views/metadata/type_conversion_unittest.cc b/ui/views/metadata/type_conversion_unittest.cc
index 2d77b39..0fdfce3 100644
--- a/ui/views/metadata/type_conversion_unittest.cc
+++ b/ui/views/metadata/type_conversion_unittest.cc
@@ -62,3 +62,42 @@
                 base::ASCIIToUTF16("ab0")),
             base::nullopt);
 }
+
+TEST_F(TypeConversionTest, TestConversion_ShadowValuesToString) {
+  gfx::ShadowValues shadow_values;
+  shadow_values.emplace_back(gfx::Vector2d(1, 2), .3,
+                             SkColorSetARGB(128, 255, 0, 0));
+
+  EXPECT_EQ(MD::TypeConverter<gfx::ShadowValues>::ToString(shadow_values),
+            base::ASCIIToUTF16("[ (1,2),0.30,rgba(255,0,0,128) ]"));
+
+  shadow_values.emplace_back(gfx::Vector2d(9, 8), .76,
+                             SkColorSetARGB(20, 0, 64, 255));
+
+  EXPECT_EQ(
+      MD::TypeConverter<gfx::ShadowValues>::ToString(shadow_values),
+      base::ASCIIToUTF16(
+          "[ (1,2),0.30,rgba(255,0,0,128); (9,8),0.76,rgba(0,64,255,20) ]"));
+}
+
+TEST_F(TypeConversionTest, TestConversion_StringToShadowValues) {
+  base::Optional<gfx::ShadowValues> opt_result =
+      MD::TypeConverter<gfx::ShadowValues>::FromString(base::ASCIIToUTF16(
+          "[ (6,4),0.53,rgba(23,44,0,255); (93,83),4.33,rgba(10,20,0,15) ]"));
+
+  EXPECT_EQ(opt_result.has_value(), true);
+  gfx::ShadowValues result = opt_result.value();
+  EXPECT_EQ(result.size(), 2U);
+
+  EXPECT_EQ(result[0].color(), SkColorSetARGB(255, 23, 44, 0));
+  EXPECT_EQ(result[1].color(), SkColorSetARGB(15, 10, 20, 0));
+
+  EXPECT_EQ(result[0].x(), 6);
+  EXPECT_EQ(result[1].x(), 93);
+
+  EXPECT_EQ(result[0].y(), 4);
+  EXPECT_EQ(result[1].y(), 83);
+
+  EXPECT_EQ(result[0].blur(), 0.53);
+  EXPECT_EQ(result[1].blur(), 4.33);
+}