diff --git a/BUILD.gn b/BUILD.gn
index c3e85d9c..4c5a5b19 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -853,10 +853,10 @@
   ]
 
   if (!is_ios) {
-    deps += [
-      "//v8:postmortem-metadata",
-      "//v8:v8_snapshot",
-    ]
+    deps += [ "//v8:postmortem-metadata" ]
+    if (v8_use_snapshot) {
+      deps += [ "//v8:v8_snapshot" ]
+    }
   }
 }
 
diff --git a/DEPS b/DEPS
index 61ea18e5..73e06bf 100644
--- a/DEPS
+++ b/DEPS
@@ -75,15 +75,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling sfntly
   # and whatever else without interference from each other.
-  'sfntly_revision': '2439bd08ff93d4dce761dd6b825917938bd35a4f',
+  'sfntly_revision': '16f3404e41edc9708a51fbce481f22e46b809686',
   # 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': '16d0ad06b46841c78cce816406574314fab95c13',
+  'skia_revision': 'e168c3e8f9a13472983a567ecd679226c9d0d186',
   # 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': 'a998a1a64bdc4eea999ab37457d84b3792760cd8',
+  'v8_revision': '4918c096158e63a0d264b0a2b0fcbebae44a2207',
   # 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.
@@ -91,7 +91,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': '342b83d49c4d2d9ee5a51b89f8a60bf0cff1dfe9',
+  'angle_revision': '3c424b489c25552878a52c0fcb5305618221708e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -308,7 +308,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a84511a49c151bf28bde5551472dd8a673fe410b',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '10ace85c7a3e6c42cbc0805da3379fe70be70d68',
       'condition': 'checkout_linux',
   },
 
@@ -323,7 +323,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '1b879ee32f68c5e41c105868f7a60e644f949f40',
+      'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '5c8aa4d8a30e89added6423a242360225661c554',
       'condition': 'checkout_linux',
   },
 
@@ -333,7 +333,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'd12f91d8829fc30b7d19a89069b55c4b833f960d',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0f7b2007a53d5158e42e97b938fd03f57cdf9786',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -487,7 +487,7 @@
     Var('chromium_git') + '/webm/libwebm.git' + '@' + 'b03c65468b06d097f27235d93d76bfc45f490ede',
 
   'src/third_party/libyuv':
-    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '50f9e618fa4bcb0561622fd709bee5da922b0fd4',  # from r1688
+    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '09db0c4ce2008008f73b247f1a5b64cfbb29b72e',  # from r1690
 
   'src/third_party/lighttpd': {
       'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
@@ -649,7 +649,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd458ada06171a85af00367251a4ed55db7fe2018',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '565e3e07d7bad8f877ecd83ad0454272aa9ebb92', # commit position 20628
+    Var('webrtc_git') + '/src.git' + '@' + '58daf40bad33535ea1e931c9fc6ed409aee3e865', # commit position 20628
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -715,7 +715,7 @@
     'name': 'landmines',
     'pattern': '.',
     'action': [
-        'vpython',
+        'python',
         'src/build/landmines.py',
     ],
   },
@@ -725,7 +725,7 @@
     'name': 'disable_depot_tools_selfupdate',
     'pattern': '.',
     'action': [
-        'vpython',
+        'python',
         'src/third_party/depot_tools/update_depot_tools_toggle.py',
         '--disable',
     ],
@@ -738,7 +738,7 @@
     'name': 'remove_stale_pyc_files',
     'pattern': '.',
     'action': [
-        'vpython',
+        'python',
         'src/tools/remove_stale_pyc_files.py',
         'src/android_webview/tools',
         'src/build/android',
@@ -760,7 +760,7 @@
     'pattern': '.',
     'condition': 'checkout_nacl',
     'action': [
-        'vpython',
+        'python',
         'src/build/download_nacl_toolchains.py',
         '--mode', 'nacl_core_sdk',
         'sync', '--extract',
@@ -774,7 +774,7 @@
     'name': 'sysroot',
     'pattern': '.',
     'condition': 'checkout_linux',
-    'action': ['vpython', 'src/build/linux/sysroot_scripts/install-sysroot.py',
+    'action': ['python', 'src/build/linux/sysroot_scripts/install-sysroot.py',
                '--running-as-hook'],
   },
   {
@@ -782,7 +782,7 @@
     'name': 'win_toolchain',
     'pattern': '.',
     'condition': 'checkout_win',
-    'action': ['vpython', 'src/build/vs_toolchain.py', 'update', '--force'],
+    'action': ['python', 'src/build/vs_toolchain.py', 'update', '--force'],
   },
   {
     # Update the Mac toolchain if necessary.
@@ -807,7 +807,7 @@
     # Note: On Win, this should run after win_toolchain, as it may use it.
     'name': 'clang',
     'pattern': '.',
-    'action': ['vpython', 'src/tools/clang/scripts/update.py'],
+    'action': ['python', 'src/tools/clang/scripts/update.py'],
   },
   {
     # Mac doesn't use lld so it's not included in the default clang bundle
@@ -816,20 +816,20 @@
     'name': 'lld/mac',
     'pattern': '.',
     'condition': 'host_os == "mac" and checkout_win',
-    'action': ['vpython', 'src/tools/clang/scripts/download_lld_mac.py'],
+    'action': ['python', 'src/tools/clang/scripts/download_lld_mac.py'],
   },
   {
     # Update LASTCHANGE.
     'name': 'lastchange',
     'pattern': '.',
-    'action': ['vpython', 'src/build/util/lastchange.py',
+    'action': ['python', 'src/build/util/lastchange.py',
                '-o', 'src/build/util/LASTCHANGE'],
   },
   {
     # Update GPU lists version string (for gpu/config).
     'name': 'gpu_lists_version',
     'pattern': '.',
-    'action': ['vpython', 'src/build/util/lastchange.py',
+    'action': ['python', 'src/build/util/lastchange.py',
                '-m', 'GPU_LISTS_VERSION',
                '--revision-id-only',
                '--header', 'src/gpu/config/gpu_lists_version.h'],
@@ -838,7 +838,7 @@
     # Update skia_commit_hash.h.
     'name': 'lastchange_skia',
     'pattern': '.',
-    'action': ['vpython', 'src/build/util/lastchange.py',
+    'action': ['python', 'src/build/util/lastchange.py',
                '-m', 'SKIA_COMMIT_HASH',
                '-s', 'src/third_party/skia',
                '--header', 'src/skia/ext/skia_commit_hash.h'],
@@ -848,7 +848,7 @@
     'name': 'gn_win',
     'pattern': '.',
     'condition': 'host_os == "win"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -860,7 +860,7 @@
     'name': 'gn_mac',
     'pattern': '.',
     'condition': 'host_os == "mac"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -872,7 +872,7 @@
     'name': 'gn_linux64',
     'pattern': '.',
     'condition': 'host_os == "linux"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -885,7 +885,7 @@
     'name': 'clang_format_win',
     'pattern': '.',
     'condition': 'host_os == "win"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -897,7 +897,7 @@
     'name': 'clang_format_mac',
     'pattern': '.',
     'condition': 'host_os == "mac"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -909,7 +909,7 @@
     'name': 'clang_format_linux',
     'pattern': '.',
     'condition': 'host_os == "linux"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -922,7 +922,7 @@
     'name': 'rc_win',
     'pattern': '.',
     'condition': 'checkout_win and host_os == "win"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -934,7 +934,7 @@
     'name': 'rc_mac',
     'pattern': '.',
     'condition': 'checkout_win and host_os == "mac"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -946,7 +946,7 @@
     'name': 'rc_linux',
     'pattern': '.',
     'condition': 'checkout_win and host_os == "linux"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -971,7 +971,7 @@
     'name': 'orderfiles_win',
     'pattern': '.',
     'condition': 'checkout_win',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -984,7 +984,7 @@
     'name': 'luci-go_win',
     'pattern': '.',
     'condition': 'host_os == "win"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -996,7 +996,7 @@
     'name': 'luci-go_mac',
     'pattern': '.',
     'condition': 'host_os == "mac"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1008,7 +1008,7 @@
     'name': 'luci-go_linux',
     'pattern': '.',
     'condition': 'host_os == "linux"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1021,7 +1021,7 @@
     'name': 'syzygy-binaries',
     'pattern': '.',
     'condition': 'host_os == "win"',
-    'action': ['vpython',
+    'action': ['python',
                'src/build/get_syzygy_binaries.py',
                '--output-dir=src/third_party/syzygy/binaries',
                '--revision=8164b24ebde9c5649c9a09e88a7fc0b0fcbd1bc5',
@@ -1033,7 +1033,7 @@
     'name': 'apache_win32',
     'pattern': '\\.sha1',
     'condition': 'host_os == "win"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--directory',
@@ -1048,7 +1048,7 @@
     'name': 'msan_chained_origins',
     'pattern': '.',
     'condition': 'checkout_instrumented_libraries',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 "--no_resume",
                 "--no_auth",
@@ -1060,7 +1060,7 @@
     'name': 'msan_no_origins',
     'pattern': '.',
     'condition': 'checkout_instrumented_libraries',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 "--no_resume",
                 "--no_auth",
@@ -1071,7 +1071,7 @@
   {
     "name": "wasm_fuzzer",
     "pattern": ".",
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 "--no_resume",
                 "--no_auth",
@@ -1086,7 +1086,7 @@
     'name': 'node_linux64',
     'pattern': '.',
     'condition': 'host_os == "linux"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--extract',
@@ -1099,7 +1099,7 @@
     'name': 'node_mac',
     'pattern': '.',
     'condition': 'host_os == "mac"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--extract',
@@ -1112,7 +1112,7 @@
     'name': 'node_win',
     'pattern': '.',
     'condition': 'host_os == "win"',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1125,7 +1125,7 @@
   {
     'name': 'webui_node_modules',
     'pattern': '.',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--extract',
@@ -1150,7 +1150,7 @@
     'name': 'checkout_telemetry_benchmark_deps',
     'condition': 'checkout_telemetry_dependencies',
     'pattern': '.',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/tools/perf/fetch_benchmark_deps.py',
                 '-f',
     ],
@@ -1175,7 +1175,7 @@
     'name': 'tools_traffic_annotation_linux',
     'pattern': '.',
     'condition': 'host_os == "linux" and checkout_traffic_annotation_tools',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1191,7 +1191,7 @@
     'name': 'tools_traffic_annotation_windows',
     'pattern': '.',
     'condition': 'host_os == "windows" and checkout_traffic_annotation_tools',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1205,7 +1205,7 @@
   {
     'name': 'zucchini_testdata',
     'pattern': '.',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1233,7 +1233,7 @@
     'condition': 'checkout_android',
     # When adding a new sdk extras package to download, add the package
     # directory and zip file to .gitignore in third_party/android_tools.
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/build/android/play_services/update.py',
                 'download'
     ],
@@ -1244,7 +1244,7 @@
     'pattern': '.',
     # Must also be downloaded on linux for use on chromium_presubmit.
     'condition': 'checkout_android or checkout_linux',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1256,7 +1256,7 @@
     'name': 'gvr_static_shim_android_arm',
     'pattern': '\\.sha1',
     'condition': 'checkout_android',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1268,7 +1268,7 @@
     'name': 'gvr_static_shim_android_arm64',
     'pattern': '\\.sha1',
     'condition': 'checkout_android',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1280,7 +1280,7 @@
     'name': 'vr_assets',
     'pattern': '.',
     'condition': 'checkout_src_internal',
-    'action': ['vpython',
+    'action': ['python',
                'src/third_party/depot_tools/download_from_google_storage.py',
                '--bucket', 'chrome-vr-assets',
                '--recursive',
@@ -1292,7 +1292,7 @@
     'name': 'vr_controller_test_api',
     'pattern': '\\.sha1',
     'condition': 'checkout_android',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/depot_tools/download_from_google_storage.py',
                 '--no_resume',
                 '--no_auth',
@@ -1305,7 +1305,7 @@
     'name': 'vr_test_apks',
     'pattern': '.',
     'condition': 'checkout_android',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/third_party/gvr-android-sdk/test-apks/update.py',
     ],
   },
@@ -1314,7 +1314,7 @@
     'name': 'libovr',
     'pattern': '.',
     'condition': 'checkout_oculus_sdk',
-    'action': ['vpython',
+    'action': ['python',
                'src/third_party/depot_tools/download_from_google_storage.py',
                '--bucket', 'chrome-oculus-sdk',
                '--recursive',
@@ -1328,7 +1328,7 @@
     'name': 'doclava',
     'pattern': '.',
     'condition': 'checkout_android',
-    'action': [ 'vpython',
+    'action': [ 'python',
                 'src/build/android/download_doclava.py',
     ],
   },
@@ -1338,9 +1338,9 @@
     'pattern': '.',
     'condition': 'checkout_fuchsia',
     'action': [
-      'vpython',
+      'python',
       'src/build/fuchsia/update_sdk.py',
-      '6b4cb32d100d2ecfaaa9642adfb0de451c5b9a69',
+      '8a3a2690f5840f50237a9b71523e9f8dad79d769',
     ],
   },
 
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index c032bcf..fa205c04 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -77,7 +77,7 @@
 
 std::unique_ptr<net::ProxyConfigService> CreateProxyConfigService() {
   std::unique_ptr<net::ProxyConfigService> config_service =
-      net::ProxyService::CreateSystemProxyConfigService(
+      net::ProxyResolutionService::CreateSystemProxyConfigService(
           BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
 
   // TODO(csharrison) Architect the wrapper better so we don't need a cast for
diff --git a/android_webview/browser/deferred_gpu_command_service.cc b/android_webview/browser/deferred_gpu_command_service.cc
index 8aa9b00..d051d641 100644
--- a/android_webview/browser/deferred_gpu_command_service.cc
+++ b/android_webview/browser/deferred_gpu_command_service.cc
@@ -66,12 +66,12 @@
     gpu::GPUInfo gpu_info =
         content::GpuDataManager::GetInstance()->GetGPUInfo();
     DCHECK(base::CommandLine::InitializedForCurrentProcess());
-    gpu::GpuFeatureInfo gpu_feature_info =
-        gpu::ComputeGpuFeatureInfo(gpu_info,
-                                   false,  // ignore_gpu_blacklist
-                                   false,  // disable_gpu_driver_bug_workarounds
-                                   false,  // log_gpu_control_list_decisions
-                                   base::CommandLine::ForCurrentProcess());
+    gpu::GpuFeatureInfo gpu_feature_info = gpu::ComputeGpuFeatureInfo(
+        gpu_info,
+        false,  // ignore_gpu_blacklist
+        false,  // disable_gpu_driver_bug_workarounds
+        false,  // log_gpu_control_list_decisions
+        base::CommandLine::ForCurrentProcess(), nullptr);
     g_service.Get() = new DeferredGpuCommandService(gpu_info, gpu_feature_info);
   }
 }
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index 21ef172..9b17c7e 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -305,10 +305,11 @@
       *base::CommandLine::ForCurrentProcess();
   if (command_line.HasSwitch(kProxyServerSwitch)) {
     std::string proxy = command_line.GetSwitchValueASCII(kProxyServerSwitch);
-    builder.set_proxy_service(net::ProxyService::CreateFixed(proxy));
+    builder.set_proxy_resolution_service(net::ProxyResolutionService::CreateFixed(proxy));
   } else {
-    builder.set_proxy_service(net::ProxyService::CreateWithoutProxyResolver(
-        std::move(proxy_config_service_), net_log_));
+    builder.set_proxy_resolution_service(
+        net::ProxyResolutionService::CreateWithoutProxyResolver(
+            std::move(proxy_config_service_), net_log_));
   }
   builder.set_net_log(net_log_);
   builder.SetCookieAndChannelIdStores(std::make_unique<AwCookieStoreWrapper>(),
diff --git a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc
index f99284c..57fec56 100644
--- a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc
@@ -59,7 +59,7 @@
 
     getter_ = base::MakeRefCounted<android_webview::AwURLRequestContextGetter>(
         temp_dir_.GetPath(), temp_dir_.GetPath().AppendASCII("ChannelID"),
-        net::ProxyService::CreateSystemProxyConfigService(
+        net::ProxyResolutionService::CreateSystemProxyConfigService(
             content::BrowserThread::GetTaskRunnerForThread(
                 content::BrowserThread::IO)),
         pref_service_.get(), &net_log_);
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
index d52a10b..011159b 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
@@ -1281,7 +1281,6 @@
         }
     }
 
-    // TODO: Move to upstream.
     private static class AwHttpAuthHandlerAdapter extends android.webkit.HttpAuthHandler {
         private AwHttpAuthHandler mAwHandler;
 
@@ -1314,7 +1313,6 @@
 
     /**
      * Type adaptation class for PermissionRequest.
-     * TODO: Move to the upstream once the PermissionRequest is part of SDK.
      */
     public static class PermissionRequestAdapter extends PermissionRequest {
 
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc
index 2707e5e..90164b73 100644
--- a/ash/accessibility/accessibility_controller.cc
+++ b/ash/accessibility/accessibility_controller.cc
@@ -197,6 +197,13 @@
   }
 }
 
+void AccessibilityController::BrailleDisplayStateChanged(bool connected) {
+  braille_display_connected_ = connected;
+  if (braille_display_connected_)
+    SetSpokenFeedbackEnabled(true, A11Y_NOTIFICATION_SHOW);
+  NotifyAccessibilityStatusChanged(A11Y_NOTIFICATION_SHOW);
+}
+
 void AccessibilityController::OnSigninScreenPrefServiceInitialized(
     PrefService* prefs) {
   ObservePrefs(prefs);
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h
index d21b3498..26e7a49 100644
--- a/ash/accessibility/accessibility_controller.h
+++ b/ash/accessibility/accessibility_controller.h
@@ -61,6 +61,8 @@
                                 AccessibilityNotificationVisibility notify);
   bool IsSpokenFeedbackEnabled() const;
 
+  bool braille_display_connected() const { return braille_display_connected_; }
+
   // Triggers an accessibility alert to give the user feedback.
   void TriggerAccessibilityAlert(mojom::AccessibilityAlert alert);
 
@@ -83,6 +85,7 @@
   // mojom::AccessibilityController:
   void SetClient(mojom::AccessibilityControllerClientPtr client) override;
   void SetDarkenScreen(bool darken) override;
+  void BrailleDisplayStateChanged(bool connected) override;
 
   // SessionObserver:
   void OnSigninScreenPrefServiceInitialized(PrefService* prefs) override;
@@ -125,6 +128,7 @@
   int large_cursor_size_in_dip_ = kDefaultLargeCursorSize;
   bool mono_audio_enabled_ = false;
   bool spoken_feedback_enabled_ = false;
+  bool braille_display_connected_ = false;
 
   // TODO(warx): consider removing this and replacing it with a more reliable
   // way (https://crbug.com/800270).
diff --git a/ash/accessibility/accessibility_delegate.h b/ash/accessibility/accessibility_delegate.h
index 53ac3ca7..098a66d45 100644
--- a/ash/accessibility/accessibility_delegate.h
+++ b/ash/accessibility/accessibility_delegate.h
@@ -78,9 +78,6 @@
   // Returns true when the accessibility menu should be shown.
   virtual bool ShouldShowAccessibilityMenu() const = 0;
 
-  // Returns true if a braille display is connected to the system.
-  virtual bool IsBrailleDisplayConnected() const = 0;
-
   // Cancel all current and queued speech immediately.
   virtual void SilenceSpokenFeedback() const = 0;
 
diff --git a/ash/accessibility/default_accessibility_delegate.cc b/ash/accessibility/default_accessibility_delegate.cc
index 21593c8..499ebd2 100644
--- a/ash/accessibility/default_accessibility_delegate.cc
+++ b/ash/accessibility/default_accessibility_delegate.cc
@@ -97,10 +97,6 @@
          controller->IsHighContrastEnabled();
 }
 
-bool DefaultAccessibilityDelegate::IsBrailleDisplayConnected() const {
-  return false;
-}
-
 void DefaultAccessibilityDelegate::SilenceSpokenFeedback() const {}
 
 void DefaultAccessibilityDelegate::SaveScreenMagnifierScale(double scale) {}
diff --git a/ash/accessibility/default_accessibility_delegate.h b/ash/accessibility/default_accessibility_delegate.h
index 03b900da..01b9e3d 100644
--- a/ash/accessibility/default_accessibility_delegate.h
+++ b/ash/accessibility/default_accessibility_delegate.h
@@ -36,7 +36,6 @@
   void SetSwitchAccessEnabled(bool enabled) override;
   bool IsSwitchAccessEnabled() const override;
   bool ShouldShowAccessibilityMenu() const override;
-  bool IsBrailleDisplayConnected() const override;
   void SilenceSpokenFeedback() const override;
   void SaveScreenMagnifierScale(double scale) override;
   double GetSavedScreenMagnifierScale() override;
diff --git a/ash/message_center/message_center_button_bar.cc b/ash/message_center/message_center_button_bar.cc
index 0bb98bbf..a8d4eb5 100644
--- a/ash/message_center/message_center_button_bar.cc
+++ b/ash/message_center/message_center_button_bar.cc
@@ -169,6 +169,7 @@
   button_container_->AddChildView(CreateVerticalSeparator());
 
   collapse_button_ = new MessageCenterButton(this);
+  collapse_button_->SetVisible(false);
   collapse_button_->SetBackground(
       views::CreateSolidBackground(message_center_style::kBackgroundColor));
   collapse_button_->SetPaintToLayer();
@@ -222,6 +223,10 @@
   return settings_button_;
 }
 
+views::Button* MessageCenterButtonBar::GetCollapseButtonForTest() const {
+  return collapse_button_;
+}
+
 void MessageCenterButtonBar::SetBackArrowVisible(bool visible) {
   if (collapse_button_visible_ == visible)
     return;
diff --git a/ash/message_center/message_center_button_bar.h b/ash/message_center/message_center_button_bar.h
index e45c1211..a19638a 100644
--- a/ash/message_center/message_center_button_bar.h
+++ b/ash/message_center/message_center_button_bar.h
@@ -61,6 +61,7 @@
   ASH_EXPORT views::Button* GetCloseAllButtonForTest() const;
   ASH_EXPORT views::Button* GetSettingsButtonForTest() const;
   ASH_EXPORT views::Button* GetQuietModeButtonForTest() const;
+  ASH_EXPORT views::Button* GetCollapseButtonForTest() const;
 
   // Sometimes we shouldn't see the back arrow (not in settings).
   void SetBackArrowVisible(bool visible);
diff --git a/ash/message_center/message_center_view_unittest.cc b/ash/message_center/message_center_view_unittest.cc
index e44e7f9..9dec889 100644
--- a/ash/message_center/message_center_view_unittest.cc
+++ b/ash/message_center/message_center_view_unittest.cc
@@ -866,6 +866,8 @@
   ASSERT_NE(nullptr, quiet_mode_button);
   views::Button* settings_button = GetButtonBar()->GetSettingsButtonForTest();
   ASSERT_NE(nullptr, settings_button);
+  views::Button* collapse_button = GetButtonBar()->GetCollapseButtonForTest();
+  ASSERT_NE(nullptr, collapse_button);
 
   EXPECT_TRUE(close_button->visible());
   EXPECT_TRUE(quiet_mode_button->visible());
@@ -904,6 +906,7 @@
   EXPECT_FALSE(close_button->visible());
   EXPECT_FALSE(quiet_mode_button->visible());
   EXPECT_FALSE(settings_button->visible());
+  EXPECT_FALSE(collapse_button->visible());
 
   // Unlock!
   SetLockedState(false);
@@ -928,6 +931,7 @@
   EXPECT_FALSE(close_button->visible());
   EXPECT_FALSE(quiet_mode_button->visible());
   EXPECT_FALSE(settings_button->visible());
+  EXPECT_FALSE(collapse_button->visible());
 }
 
 TEST_F(MessageCenterViewTest, NoNotification) {
diff --git a/ash/public/interfaces/accessibility_controller.mojom b/ash/public/interfaces/accessibility_controller.mojom
index 54007333..ca3d311 100644
--- a/ash/public/interfaces/accessibility_controller.mojom
+++ b/ash/public/interfaces/accessibility_controller.mojom
@@ -46,6 +46,9 @@
   // Starts or stops darkening the screen (e.g. to allow chrome a11y extensions
   // to darken the screen).
   SetDarkenScreen(bool darken);
+
+  // Called when braille display state is changed.
+  BrailleDisplayStateChanged(bool connected);
 };
 
 // Interface for ash to request accessibility service from its client (e.g.
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index 3d64a13..0090440 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -86,12 +86,6 @@
   return parent && parent->id() == kShellWindowId_AppListContainer;
 }
 
-bool IsTabletModeEnabled() {
-  return Shell::Get()
-      ->tablet_mode_controller()
-      ->IsTabletModeWindowManagerEnabled();
-}
-
 }  // namespace
 
 // ShelfLayoutManager::UpdateShelfObserver -------------------------------------
@@ -1106,14 +1100,10 @@
     launcher_above_shelf_bottom_amount_ =
         shelf_bounds.bottom() - gesture_in_screen.location().y();
   } else {
-    // Only app list drags are allowed in tablet mode.
-    if (IsTabletModeEnabled())
-      return;
-
     // Disable the shelf dragging if the fullscreen app list is opened.
-    if (is_app_list_visible_)
+    if (is_app_list_visible_) {
       return;
-
+    }
     gesture_drag_status_ = GESTURE_DRAG_IN_PROGRESS;
     gesture_drag_auto_hide_state_ = visibility_state() == SHELF_AUTO_HIDE
                                         ? auto_hide_state()
@@ -1141,10 +1131,6 @@
     launcher_above_shelf_bottom_amount_ =
         shelf_bounds.bottom() - gesture_in_screen.location().y();
   } else {
-    // Only app list drags are allowed in tablet mode.
-    if (IsTabletModeEnabled())
-      return;
-
     gesture_drag_amount_ +=
         PrimaryAxisValue(gesture_in_screen.details().scroll_y(),
                          gesture_in_screen.details().scroll_x());
@@ -1154,10 +1140,6 @@
 
 void ShelfLayoutManager::CompleteGestureDrag(
     const ui::GestureEvent& gesture_in_screen) {
-  // Only app list drags are allowed in tablet mode.
-  if (IsTabletModeEnabled())
-    return;
-
   bool should_change = false;
   if (gesture_in_screen.type() == ui::ET_GESTURE_SCROLL_END) {
     // The visibility of the shelf changes only if the shelf was dragged X%
@@ -1230,7 +1212,9 @@
   } else {
     // Snap the app list to corresponding state according to the snapping
     // thresholds.
-    if (IsTabletModeEnabled()) {
+    if (Shell::Get()
+            ->tablet_mode_controller()
+            ->IsTabletModeWindowManagerEnabled()) {
       app_list_state = launcher_above_shelf_bottom_amount_ >
                                kAppListDragSnapToFullscreenThreshold
                            ? AppListState::FULLSCREEN_ALL_APPS
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index d1103680..31dca8c 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -1503,6 +1503,9 @@
   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
   EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
 
+  // Note: A window must be visible in order to hide the shelf.
+  views::Widget* widget = CreateTestWidget();
+
   app_list::test::TestAppListPresenter test_app_list_presenter;
   shell->app_list()->SetAppListPresenter(
       test_app_list_presenter.CreateInterfacePtrAndBind());
@@ -1543,12 +1546,35 @@
   EXPECT_EQ(app_list::mojom::AppListState::CLOSED,
             test_app_list_presenter.app_list_state());
 
-  // Swiping down on the shelf should do nothing in tablet mode.
+  // Swiping down on the shelf should hide it.
   end = start + delta;
   generator.GestureScrollSequence(start, end, kTimeDelta, kNumScrollSteps);
-  EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, shelf->alignment());
-  EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
+  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
+  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
+  EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+
+  // Swiping up should show the shelf but not the app list if shelf is hidden.
+  generator.GestureScrollSequence(end, start, kTimeDelta, kNumScrollSteps);
+  RunAllPendingInMessageLoop();
   EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
+  EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
+  EXPECT_EQ(2u, test_app_list_presenter.show_count());
+  EXPECT_GE(test_app_list_presenter.set_y_position_count(), 1u);
+  EXPECT_EQ(app_list::mojom::AppListState::CLOSED,
+            test_app_list_presenter.app_list_state());
+
+  // Swiping down should hide the shelf.
+  generator.GestureScrollSequence(start, end, kTimeDelta, kNumScrollSteps);
+  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
+  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
+  EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+
+  // Minimize the visible window, the shelf should be shown if there are no
+  // visible windows, even in auto-hide mode.
+  widget->Minimize();
+  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
+  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
+  EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
 
   // Swiping up on the shelf in this state should open the app list.
   delta.set_y(ShelfLayoutManager::kAppListDragSnapToFullscreenThreshold + 10);
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc
index c54c236c..53a4352 100644
--- a/ash/shell/app_list.cc
+++ b/ash/shell/app_list.cc
@@ -263,10 +263,6 @@
     }
   }
 
-  void ViewInitialized() override {
-    // Nothing needs to be done.
-  }
-
   void ViewShown() override {
     // Nothing needs to be done.
   }
@@ -280,10 +276,6 @@
     // Nothing needs to be done.
   }
 
-  views::View* CreateStartPageWebView(const gfx::Size& size) override {
-    return NULL;
-  }
-
   void GetWallpaperProminentColors(std::vector<SkColor>* colors) override {
     NOTIMPLEMENTED();
   }
diff --git a/ash/system/tray_accessibility.cc b/ash/system/tray_accessibility.cc
index 2ed114b..871a5f23 100644
--- a/ash/system/tray_accessibility.cc
+++ b/ash/system/tray_accessibility.cc
@@ -75,7 +75,7 @@
     state |= A11Y_AUTOCLICK;
   if (delegate->IsVirtualKeyboardEnabled())
     state |= A11Y_VIRTUAL_KEYBOARD;
-  if (delegate->IsBrailleDisplayConnected())
+  if (controller->braille_display_connected())
     state |= A11Y_BRAILLE_DISPLAY_CONNECTED;
   if (controller->IsMonoAudioEnabled())
     state |= A11Y_MONO_AUDIO;
diff --git a/ash/system/tray_accessibility_unittest.cc b/ash/system/tray_accessibility_unittest.cc
index 2940a63..5c28402 100644
--- a/ash/system/tray_accessibility_unittest.cc
+++ b/ash/system/tray_accessibility_unittest.cc
@@ -82,7 +82,7 @@
   controller->SetSpokenFeedbackEnabled(true, A11Y_NOTIFICATION_SHOW);
   message_center::NotificationList::Notifications notifications =
       MessageCenter::Get()->GetVisibleNotifications();
-  EXPECT_EQ(1u, notifications.size());
+  ASSERT_EQ(1u, notifications.size());
   EXPECT_EQ(kChromeVoxEnabledTitle, (*notifications.begin())->title());
   EXPECT_EQ(kChromeVoxEnabled, (*notifications.begin())->message());
 
@@ -92,5 +92,47 @@
   EXPECT_EQ(0u, notifications.size());
 }
 
+TEST_F(TrayAccessibilityTest, ShowNotificationOnBrailleDisplayStateChanged) {
+  const base::string16 kBrailleConnected =
+      base::ASCIIToUTF16("Braille display connected.");
+  const base::string16 kChromeVoxEnabled =
+      base::ASCIIToUTF16("Press Ctrl + Alt + Z to disable spoken feedback.");
+  const base::string16 kBrailleConnectedAndChromeVoxEnabledTitle =
+      base::ASCIIToUTF16("Braille and ChromeVox are enabled");
+  AccessibilityController* controller =
+      Shell::Get()->accessibility_controller();
+
+  controller->SetSpokenFeedbackEnabled(true, A11Y_NOTIFICATION_SHOW);
+  EXPECT_TRUE(controller->IsSpokenFeedbackEnabled());
+  // Connecting a braille display when spoken feedback is already enabled
+  // should only show the message about the braille display.
+  controller->BrailleDisplayStateChanged(true);
+  message_center::NotificationList::Notifications notifications =
+      MessageCenter::Get()->GetVisibleNotifications();
+  ASSERT_EQ(1u, notifications.size());
+  EXPECT_EQ(base::string16(), (*notifications.begin())->title());
+  EXPECT_EQ(kBrailleConnected, (*notifications.begin())->message());
+
+  // Neither disconnecting a braille display, nor disabling spoken feedback
+  // should show any notification.
+  controller->BrailleDisplayStateChanged(false);
+  EXPECT_TRUE(controller->IsSpokenFeedbackEnabled());
+  notifications = MessageCenter::Get()->GetVisibleNotifications();
+  EXPECT_EQ(0u, notifications.size());
+  controller->SetSpokenFeedbackEnabled(false, A11Y_NOTIFICATION_SHOW);
+  notifications = MessageCenter::Get()->GetVisibleNotifications();
+  EXPECT_EQ(0u, notifications.size());
+  EXPECT_FALSE(controller->IsSpokenFeedbackEnabled());
+
+  // Connecting a braille display should enable spoken feedback and show
+  // both messages.
+  controller->BrailleDisplayStateChanged(true);
+  EXPECT_TRUE(controller->IsSpokenFeedbackEnabled());
+  notifications = MessageCenter::Get()->GetVisibleNotifications();
+  EXPECT_EQ(kBrailleConnectedAndChromeVoxEnabledTitle,
+            (*notifications.begin())->title());
+  EXPECT_EQ(kChromeVoxEnabled, (*notifications.begin())->message());
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/build/config/arm.gni b/build/config/arm.gni
index 29434eb..abd4dd0 100644
--- a/build/config/arm.gni
+++ b/build/config/arm.gni
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/v8_target_cpu.gni")
+import("//build/secondary/third_party/catapult/devil/devil_arm.gni")
 
 # These are primarily relevant in current_cpu == "arm" contexts, where
 # ARM code is being compiled.  But they can also be relevant in the
@@ -79,8 +80,15 @@
     }
 
     if (arm_float_abi == "") {
-      if (current_os == "android" || target_os == "android") {
+      if (current_os == "android") {
         arm_float_abi = "softfp"
+      } else if (target_os == "android") {
+        if (build_devil_arm_deps) {
+          # Raspberry Pis require "hard"
+          arm_float_abi = "hard"
+        } else {
+          arm_float_abi = "softfp"
+        }
       } else if (current_os == "linux" && target_cpu != v8_target_cpu) {
         # Default to the same as Android for V8 simulator builds.
         arm_float_abi = "softfp"
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index 7f07aad..6fddf3d0 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -156,12 +156,10 @@
   # TODO(pcc): Enable lld on more architectures on Linux. E.g. we probably need
   # to fix some of crbug.com/742655 to enable it on ARM.
   # TODO(pcc): Remove !is_msan once crbug.com/772559 is fixed.
-  use_lld =
-      is_clang && !is_msan &&
-      ((is_win && host_os != "win") || is_fuchsia ||
-       (use_thin_lto && target_os != "chromeos") ||
-       (is_linux && current_cpu == "x64" && target_os != "chromeos") ||
-       (is_android && current_cpu != "mipsel" && current_cpu != "mips64el"))
+  use_lld = is_clang && !is_msan &&
+            ((is_win && host_os != "win") || is_fuchsia ||
+             (use_thin_lto && target_os != "chromeos") ||
+             (is_linux && current_cpu == "x64" && target_os != "chromeos"))
 }
 
 declare_args() {
diff --git a/build/config/gcc/BUILD.gn b/build/config/gcc/BUILD.gn
index f1950bf..6827f46 100644
--- a/build/config/gcc/BUILD.gn
+++ b/build/config/gcc/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/c++/c++.gni")
 import("//build/config/compiler/compiler.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/sysroot.gni")
@@ -110,7 +111,7 @@
   } else {
     # See the rpath_for... config above for why this is necessary for component
     # builds. Sanitizers use a custom libc++ where this is also necessary.
-    if (is_component_build || using_sanitizer) {
+    if (is_component_build || using_sanitizer || !libcpp_is_static) {
       configs = [ ":rpath_for_built_shared_libraries" ]
     }
     if (current_cpu == "mipsel" || current_cpu == "mips64el") {
diff --git a/build/secondary/third_party/catapult/devil/BUILD.gn b/build/secondary/third_party/catapult/devil/BUILD.gn
index 50e6050c..5e9707e 100644
--- a/build/secondary/third_party/catapult/devil/BUILD.gn
+++ b/build/secondary/third_party/catapult/devil/BUILD.gn
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/symlink.gni")
+import("//build/secondary/third_party/catapult/devil/devil_arm.gni")
 import("//testing/android/empty_apk/empty_apk.gni")
 
 empty_apk("empty_system_webview_apk") {
@@ -13,7 +15,36 @@
   testonly = true
   deps = [
     ":empty_system_webview_apk",
+    "//buildtools/third_party/libc++($host_toolchain)",
     "//tools/android/forwarder2",
     "//tools/android/md5sum",
   ]
+
+  if (build_devil_arm_deps) {
+    deps += [
+      ":host_forwarder_arm",
+      ":libcxx_arm",
+      ":md5sum_bin_host_arm",
+    ]
+  }
+}
+
+if (build_devil_arm_deps) {
+  binary_symlink("host_forwarder_arm") {
+    binary_label = "//tools/android/forwarder2:host_forwarder(//build/toolchain/linux:clang_arm)"
+    output_name = "host_forwarder_arm"
+  }
+
+  binary_symlink("md5sum_bin_host_arm") {
+    binary_label =
+        "//tools/android/md5sum:md5sum_bin(//build/toolchain/linux:clang_arm)"
+    output_name = "md5sum_bin_host_arm"
+  }
+
+  binary_symlink("libcxx_arm") {
+    binary_label =
+        "//buildtools/third_party/libc++(//build/toolchain/linux:clang_arm)"
+    binary_output_name = "libc++.so"
+    output_name = "libc++_arm"
+  }
 }
diff --git a/build/secondary/third_party/catapult/devil/devil_arm.gni b/build/secondary/third_party/catapult/devil/devil_arm.gni
new file mode 100644
index 0000000..04c5e40
--- /dev/null
+++ b/build/secondary/third_party/catapult/devil/devil_arm.gni
@@ -0,0 +1,9 @@
+# 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.
+
+declare_args() {
+  # Whether to build Devil host dependencies for Linux arm, e.g. for use on
+  # Raspberry Pis.
+  build_devil_arm_deps = false
+}
diff --git a/cc/paint/paint_filter.h b/cc/paint/paint_filter.h
index 716a153..fdabc8f 100644
--- a/cc/paint/paint_filter.h
+++ b/cc/paint/paint_filter.h
@@ -76,10 +76,19 @@
   SkIRect filter_bounds(const SkIRect& src,
                         const SkMatrix& ctm,
                         MapDirection direction) const {
+    if (!cached_sk_filter_)
+      return SkIRect::MakeEmpty();
     return cached_sk_filter_->filterBounds(src, ctm, direction);
   }
-  int count_inputs() const { return cached_sk_filter_->countInputs(); }
+  int count_inputs() const {
+    if (!cached_sk_filter_)
+      return 0;
+    return cached_sk_filter_->countInputs();
+  }
   std::string ToString() const {
+    if (!cached_sk_filter_)
+      return "Invalid filter";
+
     SkString str;
     cached_sk_filter_->toString(&str);
     return str.c_str();
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index f8cf3e4d..781d00f 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -2263,9 +2263,10 @@
 
     if (op->IsPaintOpWithFlags()) {
       const auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
+      const bool create_skia_shaders = true;
       const ScopedRasterFlags scoped_flags(
           &flags_op->flags, new_params.image_provider, canvas->getTotalMatrix(),
-          iter.alpha());
+          iter.alpha(), create_skia_shaders);
       if (const auto* raster_flags = scoped_flags.flags())
         flags_op->RasterWithFlags(canvas, raster_flags, new_params);
       continue;
diff --git a/cc/paint/paint_op_buffer_serializer.cc b/cc/paint/paint_op_buffer_serializer.cc
index 103484a..4cfe89a 100644
--- a/cc/paint/paint_op_buffer_serializer.cc
+++ b/cc/paint/paint_op_buffer_serializer.cc
@@ -86,9 +86,8 @@
   }
 
   if (!preamble.playback_rect.IsEmpty()) {
-    ClipRectOp clip_op(
-        SkRect::MakeFromIRect(gfx::RectToSkIRect(preamble.playback_rect)),
-        SkClipOp::kIntersect, false);
+    ClipRectOp clip_op(gfx::RectFToSkRect(preamble.playback_rect),
+                       SkClipOp::kIntersect, false);
     SerializeOp(&clip_op, options, params);
   }
 
@@ -98,8 +97,9 @@
     SerializeOp(&translate_op, options, params);
   }
 
-  if (preamble.post_scale != 1.f) {
-    ScaleOp scale_op(preamble.post_scale, preamble.post_scale);
+  if (preamble.post_scale.width() != 1.f ||
+      preamble.post_scale.height() != 1.f) {
+    ScaleOp scale_op(preamble.post_scale.width(), preamble.post_scale.height());
     SerializeOp(&scale_op, options, params);
   }
 }
@@ -150,9 +150,13 @@
     PaintOp::SerializeOptions* options,
     const PlaybackParams& params,
     uint8_t alpha) {
+  // We don't need the skia backing for decoded shaders during serialization,
+  // since those are created on the service side where the record is rasterized.
+  const bool create_skia_shaders = false;
+
   const ScopedRasterFlags scoped_flags(
       &flags_op->flags, options->image_provider,
-      options->canvas->getTotalMatrix(), alpha);
+      options->canvas->getTotalMatrix(), alpha, create_skia_shaders);
   const PaintFlags* flags_to_serialize = scoped_flags.flags();
   if (!flags_to_serialize)
     return true;
diff --git a/cc/paint/paint_op_buffer_serializer.h b/cc/paint/paint_op_buffer_serializer.h
index c2cb4f70..b7e55e5c 100644
--- a/cc/paint/paint_op_buffer_serializer.h
+++ b/cc/paint/paint_op_buffer_serializer.h
@@ -8,6 +8,7 @@
 #include "cc/paint/paint_op_buffer.h"
 
 #include "third_party/skia/include/utils/SkNoDrawCanvas.h"
+#include "ui/gfx/geometry/rect_f.h"
 
 namespace cc {
 
@@ -24,9 +25,9 @@
 
   struct Preamble {
     gfx::Vector2dF translation;
-    gfx::Rect playback_rect;
+    gfx::RectF playback_rect;
     gfx::Vector2dF post_translation;
-    float post_scale = 1.f;
+    gfx::SizeF post_scale = gfx::SizeF(1.f, 1.f);
   };
   // Serialize the buffer with a preamble. This function wraps the buffer in a
   // save/restore and includes any translations and/or scales as specified by
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index 8833e35..2c1b682 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -100,9 +100,14 @@
   ImageProvider* image_provider() { return this; }
   TransferCacheTestHelper* transfer_cache_helper() { return this; }
 
+  const std::vector<DrawImage>& decoded_images() const {
+    return decoded_images_;
+  }
+
  private:
   ScopedDecodedDrawImage GetDecodedDrawImage(
       const DrawImage& draw_image) override {
+    decoded_images_.push_back(draw_image);
     auto& entry = entry_map_[++transfer_cache_entry_id_];
     SkBitmap bitmap;
     const auto& paint_image = draw_image.paint_image();
@@ -131,6 +136,7 @@
   testing::StrictMock<MockCanvas> canvas_;
   PaintOp::SerializeOptions serialize_options_;
   PaintOp::DeserializeOptions deserialize_options_;
+  std::vector<DrawImage> decoded_images_;
 };
 
 TEST(PaintOpBufferTest, Empty) {
@@ -1978,7 +1984,7 @@
   PushDrawIRectOps(&buffer);
 
   PaintOpBufferSerializer::Preamble preamble;
-  preamble.playback_rect = gfx::Rect(1000.f, 1000.f);
+  preamble.playback_rect = gfx::RectF(1000.f, 1000.f);
 
   std::unique_ptr<char, base::AlignedFreeDeleter> memory(
       static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
@@ -2017,9 +2023,8 @@
       // Preamble.
       ASSERT_EQ(op->GetType(), PaintOpType::ClipRect)
           << PaintOpTypeToString(op->GetType());
-      EXPECT_EQ(
-          static_cast<const ClipRectOp*>(op)->rect,
-          SkRect::MakeFromIRect(gfx::RectToSkIRect(preamble.playback_rect)));
+      EXPECT_EQ(static_cast<const ClipRectOp*>(op)->rect,
+                gfx::RectFToSkRect(preamble.playback_rect));
       continue;
     }
 
@@ -2041,9 +2046,9 @@
 TEST(PaintOpSerializationTest, Preamble) {
   PaintOpBufferSerializer::Preamble preamble;
   preamble.translation = gfx::Vector2dF(10.f, 20.f);
-  preamble.playback_rect = gfx::Rect(5, 5);
+  preamble.playback_rect = gfx::RectF(5.f, 5.f);
   preamble.post_translation = gfx::Vector2dF(4.3f, 7.f);
-  preamble.post_scale = 0.5f;
+  preamble.post_scale = gfx::SizeF(0.5f, 0.5f);
 
   PaintOpBuffer buffer;
   buffer.push<DrawColorOp>(SK_ColorBLUE, SkBlendMode::kSrc);
@@ -2092,7 +2097,8 @@
       ASSERT_EQ(op->GetType(), PaintOpType::ClipRect)
           << PaintOpTypeToString(op->GetType());
       const auto* clip_op = static_cast<const ClipRectOp*>(op);
-      EXPECT_RECT_EQ(gfx::SkRectToRectF(clip_op->rect), preamble.playback_rect);
+      EXPECT_FLOAT_RECT_EQ(gfx::SkRectToRectF(clip_op->rect),
+                           preamble.playback_rect);
       continue;
     }
 
@@ -2111,8 +2117,8 @@
       ASSERT_EQ(op->GetType(), PaintOpType::Scale)
           << PaintOpTypeToString(op->GetType());
       const auto* scale_op = static_cast<const ScaleOp*>(op);
-      EXPECT_EQ(scale_op->sx, preamble.post_scale);
-      EXPECT_EQ(scale_op->sy, preamble.post_scale);
+      EXPECT_EQ(scale_op->sx, preamble.post_scale.width());
+      EXPECT_EQ(scale_op->sy, preamble.post_scale.height());
       continue;
     }
 
@@ -2210,7 +2216,7 @@
                                       options_provider.image_provider(),
                                       options_provider.transfer_cache_helper());
     PaintOpBufferSerializer::Preamble preamble;
-    preamble.playback_rect = test_case.clip_rect;
+    preamble.playback_rect = gfx::RectF(test_case.clip_rect);
     serializer.Serialize(&buffer, nullptr, preamble);
     ASSERT_NE(serializer.written(), 0u);
 
@@ -2252,7 +2258,7 @@
   buffer.push<RestoreOp>();
 
   PaintOpBufferSerializer::Preamble preamble;
-  preamble.playback_rect = gfx::Rect(1000.f, 1000.f);
+  preamble.playback_rect = gfx::RectF(1000.f, 1000.f);
 
   std::unique_ptr<char, base::AlignedFreeDeleter> memory(
       static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
@@ -3057,4 +3063,35 @@
   EXPECT_TRUE(*filter == *out_filter);
 }
 
+TEST(PaintOpBufferTest, RecordShadersSerializeScaledImages) {
+  auto record_buffer = sk_make_sp<PaintOpBuffer>();
+  record_buffer->push<DrawImageOp>(
+      CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f, nullptr);
+
+  auto shader = PaintShader::MakePaintRecord(
+      record_buffer, SkRect::MakeWH(10.f, 10.f),
+      SkShader::TileMode::kRepeat_TileMode,
+      SkShader::TileMode::kRepeat_TileMode, nullptr);
+  auto buffer = sk_make_sp<PaintOpBuffer>();
+  buffer->push<ScaleOp>(0.5f, 0.8f);
+  PaintFlags flags;
+  flags.setShader(shader);
+  buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags);
+
+  std::unique_ptr<char, base::AlignedFreeDeleter> memory(
+      static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
+                                            PaintOpBuffer::PaintOpAlign)));
+  TestOptionsProvider options_provider;
+  SimpleBufferSerializer serializer(memory.get(),
+                                    PaintOpBuffer::kInitialBufferSize,
+                                    options_provider.image_provider(),
+                                    options_provider.transfer_cache_helper());
+  serializer.Serialize(buffer.get());
+
+  ASSERT_EQ(options_provider.decoded_images().size(), 1u);
+  auto scale = options_provider.decoded_images().at(0).scale();
+  EXPECT_EQ(scale.width(), 0.5f);
+  EXPECT_EQ(scale.height(), 0.8f);
+}
+
 }  // namespace cc
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc
index 8940574..8421035 100644
--- a/cc/paint/paint_op_writer.cc
+++ b/cc/paint/paint_op_writer.cc
@@ -13,6 +13,7 @@
 #include "cc/paint/paint_typeface_transfer_cache_entry.h"
 #include "cc/paint/transfer_cache_serialize_helper.h"
 #include "third_party/skia/include/core/SkTextBlob.h"
+#include "ui/gfx/skia_util.h"
 
 namespace cc {
 namespace {
@@ -243,7 +244,13 @@
   Write(shader->image_);
   if (shader->record_) {
     Write(true);
-    Write(shader->record_.get());
+    base::Optional<PaintOpBufferSerializer::Preamble> preamble;
+    if (shader->tile_scale()) {
+      preamble.emplace();
+      preamble->playback_rect = gfx::SkRectToRectF(shader->tile());
+      preamble->post_scale = *shader->tile_scale();
+    }
+    Write(shader->record_.get(), std::move(preamble));
   } else {
     Write(false);
   }
@@ -558,7 +565,9 @@
   Write(filter.input().get());
 }
 
-void PaintOpWriter::Write(const PaintRecord* record) {
+void PaintOpWriter::Write(
+    const PaintRecord* record,
+    base::Optional<PaintOpBufferSerializer::Preamble> preamble) {
   // We need to record how many bytes we will serialize, but we don't know this
   // information until we do the serialization. So, skip the amount needed
   // before writing.
@@ -584,7 +593,11 @@
 
   SimpleBufferSerializer serializer(memory_, remaining_bytes_, image_provider_,
                                     transfer_cache_);
-  serializer.Serialize(record);
+  if (preamble)
+    serializer.Serialize(record, nullptr, *preamble);
+  else
+    serializer.Serialize(record);
+
   if (!serializer.valid()) {
     valid_ = false;
     return;
diff --git a/cc/paint/paint_op_writer.h b/cc/paint/paint_op_writer.h
index 04587c23..98ff494 100644
--- a/cc/paint/paint_op_writer.h
+++ b/cc/paint/paint_op_writer.h
@@ -10,6 +10,7 @@
 #include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_filter.h"
+#include "cc/paint/paint_op_buffer_serializer.h"
 
 struct SkRect;
 struct SkIRect;
@@ -119,7 +120,9 @@
   void Write(const LightingPointPaintFilter& filter);
   void Write(const LightingSpotPaintFilter& filter);
 
-  void Write(const PaintRecord* record);
+  void Write(const PaintRecord* record,
+             base::Optional<PaintOpBufferSerializer::Preamble> preamble =
+                 base::nullopt);
   void Write(const PaintImage& image);
   void Write(const SkRegion& region);
 
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc
index eb5a1232..33e31c2 100644
--- a/cc/paint/paint_shader.cc
+++ b/cc/paint/paint_shader.cc
@@ -14,12 +14,12 @@
 
 sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record,
                              const SkRect& bounds,
-                             const SkMatrix* matrix,
+                             const gfx::SizeF* raster_scale,
                              ImageProvider* image_provider) {
   SkPictureRecorder recorder;
   SkCanvas* canvas = recorder.beginRecording(bounds);
-  if (matrix)
-    canvas->setMatrix(*matrix);
+  if (raster_scale)
+    canvas->scale(raster_scale->width(), raster_scale->height());
   record->Playback(canvas, PlaybackParams(image_provider));
   return recorder.finishRecordingAsPicture();
 }
@@ -237,16 +237,13 @@
   shader->tx_ = tx_;
   shader->ty_ = ty_;
 
-  const SkSize tile_scale =
-      SkSize::Make(SkIntToScalar(tile_rect.width()) / tile_.width(),
-                   SkIntToScalar(tile_rect.height()) / tile_.height());
+  shader->tile_scale_ =
+      gfx::SizeF(SkIntToScalar(tile_rect.width()) / tile_.width(),
+                 SkIntToScalar(tile_rect.height()) / tile_.height());
   shader->local_matrix_ = GetLocalMatrix();
-  shader->local_matrix_->preScale(1 / tile_scale.width(),
-                                  1 / tile_scale.height());
+  shader->local_matrix_->preScale(1 / shader->tile_scale_->width(),
+                                  1 / shader->tile_scale_->height());
 
-  SkMatrix raster_matrix =
-      SkMatrix::MakeRectToRect(tile_, tile_rect, SkMatrix::kFill_ScaleToFit);
-  shader->CreateSkShader(image_provider, &raster_matrix);
   return shader;
 }
 
@@ -254,8 +251,7 @@
   return cached_shader_;
 }
 
-void PaintShader::CreateSkShader(ImageProvider* image_provider,
-                                 const SkMatrix* raster_matrix) {
+void PaintShader::CreateSkShader(ImageProvider* image_provider) {
   DCHECK(!cached_shader_);
 
   switch (shader_type_) {
@@ -301,7 +297,7 @@
     case Type::kPaintRecord: {
       // Create a recording at the desired scale if this record has images which
       // have been decoded before raster.
-      auto picture = ToSkPicture(record_, tile_, raster_matrix, image_provider);
+      auto picture = ToSkPicture(record_, tile_, tile_scale(), image_provider);
 
       switch (scaling_behavior_) {
         // For raster scale, we create a picture shader directly.
diff --git a/cc/paint/paint_shader.h b/cc/paint/paint_shader.h
index 919141fe..09a55c7 100644
--- a/cc/paint/paint_shader.h
+++ b/cc/paint/paint_shader.h
@@ -14,6 +14,7 @@
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkScalar.h"
 #include "third_party/skia/include/core/SkShader.h"
+#include "ui/gfx/geometry/size_f.h"
 
 namespace cc {
 class ImageProvider;
@@ -111,6 +112,9 @@
     return image_;
   }
 
+  const gfx::SizeF* tile_scale() const {
+    return tile_scale_ ? &*tile_scale_ : nullptr;
+  }
   const sk_sp<PaintRecord>& paint_record() const { return record_; }
   bool GetRasterizationTileRect(const SkMatrix& ctm, SkRect* tile_rect) const;
 
@@ -141,8 +145,7 @@
   explicit PaintShader(Type type);
 
   sk_sp<SkShader> GetSkShader() const;
-  void CreateSkShader(ImageProvider* = nullptr,
-                      const SkMatrix* raster_matrix = nullptr);
+  void CreateSkShader(ImageProvider* image_provider = nullptr);
 
   sk_sp<PaintShader> CreateDecodedPaintRecord(
       const SkMatrix& ctm,
@@ -179,6 +182,10 @@
   PaintImage image_;
   sk_sp<PaintRecord> record_;
 
+  // For decoded PaintRecord shaders, specifies the scale at which the record
+  // will be rasterized.
+  base::Optional<gfx::SizeF> tile_scale_;
+
   std::vector<SkColor> colors_;
   std::vector<SkScalar> positions_;
 
diff --git a/cc/paint/paint_shader_unittest.cc b/cc/paint/paint_shader_unittest.cc
index 9fd235a..7ecb917 100644
--- a/cc/paint/paint_shader_unittest.cc
+++ b/cc/paint/paint_shader_unittest.cc
@@ -114,7 +114,8 @@
 
   // Using the shader requests decode for images at the correct scale.
   EXPECT_EQ(image_provider.draw_image().paint_image(), paint_image);
-  EXPECT_EQ(image_provider.draw_image().scale(), SkSize::Make(0.25f, 0.25f));
+  EXPECT_EQ(image_provider.draw_image().scale().width(), 0.25f);
+  EXPECT_EQ(image_provider.draw_image().scale().height(), 0.25f);
 }
 
 }  // namespace cc
diff --git a/cc/paint/scoped_raster_flags.cc b/cc/paint/scoped_raster_flags.cc
index cd5a2d9..d2fe6197 100644
--- a/cc/paint/scoped_raster_flags.cc
+++ b/cc/paint/scoped_raster_flags.cc
@@ -11,7 +11,8 @@
 ScopedRasterFlags::ScopedRasterFlags(const PaintFlags* flags,
                                      ImageProvider* image_provider,
                                      const SkMatrix& ctm,
-                                     uint8_t alpha)
+                                     uint8_t alpha,
+                                     bool create_skia_shader)
     : original_flags_(flags) {
   if (flags->HasDiscardableImages() && image_provider) {
     DCHECK(flags->HasShader());
@@ -21,7 +22,7 @@
       DecodeImageShader(ctm);
     } else if (flags->getShader()->shader_type() ==
                PaintShader::Type::kPaintRecord) {
-      DecodeRecordShader(ctm);
+      DecodeRecordShader(ctm, create_skia_shader);
     } else {
       NOTREACHED();
     }
@@ -93,7 +94,8 @@
                              flags()->getShader()->ty(), &matrix));
 }
 
-void ScopedRasterFlags::DecodeRecordShader(const SkMatrix& ctm) {
+void ScopedRasterFlags::DecodeRecordShader(const SkMatrix& ctm,
+                                           bool create_skia_shader) {
   auto decoded_shader = flags()->getShader()->CreateDecodedPaintRecord(
       ctm, &*decode_stashing_image_provider_);
   if (!decoded_shader) {
@@ -101,6 +103,8 @@
     return;
   }
 
+  if (create_skia_shader)
+    decoded_shader->CreateSkShader(&*decode_stashing_image_provider_);
   MutableFlags()->setShader(std::move(decoded_shader));
 }
 
diff --git a/cc/paint/scoped_raster_flags.h b/cc/paint/scoped_raster_flags.h
index ad2ab88..5b2f859 100644
--- a/cc/paint/scoped_raster_flags.h
+++ b/cc/paint/scoped_raster_flags.h
@@ -21,7 +21,8 @@
   ScopedRasterFlags(const PaintFlags* flags,
                     ImageProvider* image_provider,
                     const SkMatrix& ctm,
-                    uint8_t alpha);
+                    uint8_t alpha,
+                    bool create_skia_shaders);
   ~ScopedRasterFlags();
 
   // The usage of these flags should not extend beyond the lifetime of this
@@ -35,7 +36,7 @@
 
  private:
   void DecodeImageShader(const SkMatrix& ctm);
-  void DecodeRecordShader(const SkMatrix& ctm);
+  void DecodeRecordShader(const SkMatrix& ctm, bool create_skia_shader);
   void AdjustStrokeIfNeeded(const SkMatrix& ctm);
 
   PaintFlags* MutableFlags() {
diff --git a/cc/paint/scoped_raster_flags_unittest.cc b/cc/paint/scoped_raster_flags_unittest.cc
index e3127f5..ce776c2 100644
--- a/cc/paint/scoped_raster_flags_unittest.cc
+++ b/cc/paint/scoped_raster_flags_unittest.cc
@@ -59,7 +59,7 @@
   PaintFlags flags;
   flags.setShader(record_shader);
   {
-    ScopedRasterFlags scoped_flags(&flags, &provider, SkMatrix::I(), 255);
+    ScopedRasterFlags scoped_flags(&flags, &provider, SkMatrix::I(), 255, true);
     ASSERT_TRUE(scoped_flags.flags());
     EXPECT_NE(scoped_flags.flags(), &flags);
     SkPaint paint = scoped_flags.flags()->ToSkPaint();
@@ -76,7 +76,7 @@
       CreateDiscardablePaintImage(gfx::Size(10, 10)),
       SkShader::TileMode::kClamp_TileMode, SkShader::TileMode::kClamp_TileMode,
       &SkMatrix::I()));
-  ScopedRasterFlags scoped_flags(&flags, nullptr, SkMatrix::I(), 10);
+  ScopedRasterFlags scoped_flags(&flags, nullptr, SkMatrix::I(), 10, true);
   EXPECT_NE(scoped_flags.flags(), &flags);
   EXPECT_EQ(scoped_flags.flags()->getAlpha(), SkMulDiv255Round(255, 10));
 }
@@ -107,7 +107,7 @@
   };
 
   for (const auto& test : tests) {
-    ScopedRasterFlags scoped_flags(&flags, nullptr, test.ctm, test.alpha);
+    ScopedRasterFlags scoped_flags(&flags, nullptr, test.ctm, test.alpha, true);
     ASSERT_TRUE(scoped_flags.flags());
 
     EXPECT_EQ(scoped_flags.flags() == &flags, test.expect_same_flags);
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc
index 41aea6f..515eec9 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -168,7 +168,8 @@
                                SkScalar y1,
                                const PaintFlags& flags) {
   ScopedRasterFlags raster_flags(&flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
   SkPaint paint = raster_flags.flags()->ToSkPaint();
@@ -178,7 +179,8 @@
 
 void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) {
   ScopedRasterFlags raster_flags(&flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
   SkPaint paint = raster_flags.flags()->ToSkPaint();
@@ -188,7 +190,8 @@
 
 void SkiaPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) {
   ScopedRasterFlags raster_flags(&flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
   SkPaint paint = raster_flags.flags()->ToSkPaint();
@@ -198,7 +201,8 @@
 
 void SkiaPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) {
   ScopedRasterFlags raster_flags(&flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
   SkPaint paint = raster_flags.flags()->ToSkPaint();
@@ -208,7 +212,8 @@
 
 void SkiaPaintCanvas::drawRRect(const SkRRect& rrect, const PaintFlags& flags) {
   ScopedRasterFlags raster_flags(&flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
   SkPaint paint = raster_flags.flags()->ToSkPaint();
@@ -220,7 +225,8 @@
                                  const SkRRect& inner,
                                  const PaintFlags& flags) {
   ScopedRasterFlags raster_flags(&flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
   SkPaint paint = raster_flags.flags()->ToSkPaint();
@@ -233,7 +239,8 @@
                                     SkScalar ry,
                                     const PaintFlags& flags) {
   ScopedRasterFlags raster_flags(&flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
   SkPaint paint = raster_flags.flags()->ToSkPaint();
@@ -243,7 +250,8 @@
 
 void SkiaPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) {
   ScopedRasterFlags raster_flags(&flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
   SkPaint paint = raster_flags.flags()->ToSkPaint();
@@ -256,7 +264,8 @@
                                 SkScalar top,
                                 const PaintFlags* flags) {
   ScopedRasterFlags raster_flags(flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
 
@@ -272,7 +281,8 @@
                                     const PaintFlags* flags,
                                     SrcRectConstraint constraint) {
   ScopedRasterFlags raster_flags(flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
 
@@ -288,7 +298,8 @@
                                  const PaintFlags* flags) {
   if (flags) {
     ScopedRasterFlags raster_flags(flags, image_provider_.get(),
-                                   canvas_->getTotalMatrix(), 255u);
+                                   canvas_->getTotalMatrix(), 255u,
+                                   kCreateSkiaShaders);
     if (!raster_flags.flags())
       return;
     SkPaint paint = raster_flags.flags()->ToSkPaint();
@@ -303,7 +314,8 @@
                                    SkScalar y,
                                    const PaintFlags& flags) {
   ScopedRasterFlags raster_flags(&flags, image_provider_.get(),
-                                 canvas_->getTotalMatrix(), 255u);
+                                 canvas_->getTotalMatrix(), 255u,
+                                 kCreateSkiaShaders);
   if (!raster_flags.flags())
     return;
   SkPaint paint = raster_flags.flags()->ToSkPaint();
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h
index aef0321..f4955a12 100644
--- a/cc/paint/skia_paint_canvas.h
+++ b/cc/paint/skia_paint_canvas.h
@@ -131,8 +131,12 @@
                    const PlaybackParams& params);
 
  private:
+  // We always need skia shaders since the ops will be played on an SkCanvas.
+  static const bool kCreateSkiaShaders = true;
+
   void WrapCanvasInColorSpaceXformCanvas(
       sk_sp<SkColorSpace> target_color_space);
+
   SkCanvas* canvas_;
   std::unique_ptr<SkCanvas> owned_;
   std::unique_ptr<SkCanvas> color_space_xform_canvas_;
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc
index c45ab46..b772a16 100644
--- a/cc/raster/raster_buffer_provider_perftest.cc
+++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -9,6 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "cc/base/lap_timer.h"
 #include "cc/raster/bitmap_raster_buffer_provider.h"
 #include "cc/raster/gpu_raster_buffer_provider.h"
@@ -558,7 +559,14 @@
   RunScheduleTasksTest("32_4", 32, 4);
 }
 
-TEST_P(RasterBufferProviderPerfTest, ScheduleAlternateTasks) {
+// Crashes on Android only.  http://crbug.com/803874
+#if defined(OS_ANDROID)
+#define MAYBE_ScheduleAlternateTasks DISABLED_ScheduleAlternateTasks
+#else
+#define MAYBE_ScheduleAlternateTasks ScheduleAlternateTasks
+#endif
+
+TEST_P(RasterBufferProviderPerfTest, MAYBE_ScheduleAlternateTasks) {
   RunScheduleAlternateTasksTest("1_0", 1, 0);
   RunScheduleAlternateTasksTest("32_0", 32, 0);
   RunScheduleAlternateTasksTest("1_1", 1, 1);
@@ -619,7 +627,14 @@
   }
 };
 
-TEST_F(RasterBufferProviderCommonPerfTest, BuildTileTaskGraph) {
+// Crashes on Android only.  http://crbug.com/803874
+#if defined(OS_ANDROID)
+#define MAYBE_BuildTileTaskGraph DISABLED_BuildTileTaskGraph
+#else
+#define MAYBE_BuildTileTaskGraph BuildTileTaskGraph
+#endif
+
+TEST_F(RasterBufferProviderCommonPerfTest, MAYBE_BuildTileTaskGraph) {
   RunBuildTileTaskGraphTest("1_0", 1, 0);
   RunBuildTileTaskGraphTest("32_0", 32, 0);
   RunBuildTileTaskGraphTest("1_1", 1, 1);
diff --git a/chrome/VERSION b/chrome/VERSION
index ece84aa..8bdd85a 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=66
 MINOR=0
-BUILD=3326
+BUILD=3329
 PATCH=0
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index e8841c9..dd82161 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1037,9 +1037,6 @@
   <message name="IDS_FILE_BROWSER_DRIVE_CANNOT_REACH" desc="Message informing the user that Google Drive can not be reached at this moment.">
     Google Drive cannot be reached at this time.
   </message>
-  <message name="IDS_FILE_BROWSER_DRIVE_LEARN_MORE" desc="In the Loading Google Drive page and in the Welcome to Google Drive banner, a text on the Learn More link.">
-    Learn more
-  </message>
   <message name="IDS_FILE_BROWSER_DRIVE_OUT_OF_SPACE_MESSAGE" desc="Message informing the user how to make more space available to save the selected file offline.">
     To save "<ph name="FILE_NAME">$1<ex>document.pdf</ex></ph>" offline you must free up an additional <ph name="TOTAL_FILE_SIZE">$2<ex>3.3 MB</ex></ph> of space:<ph name="MARKUP_1">&lt;br&gt;<ex>&lt;br&gt;</ex></ph>
     <ph name="MARKUP_2">&lt;ul&gt;&lt;li&gt;<ex>&lt;ul&gt;&lt;li&gt;</ex></ph>unpin files that you no longer need to access offline<ph name="MARKUP_3">&lt;/li&gt;<ex>>&lt;/li&gt;</ex></ph>
@@ -1899,9 +1896,6 @@
   <message name="IDS_WHITELIST_ERROR_TRY_AGAIN_BUTTON" desc="The text of the try again button on the whitelist error UI.">
     Try again
   </message>
-  <message name="IDS_WHITELIST_ERROR_LEARN_MORE_BUTTON" desc="The text of the learn more link on the whitelist error UI.">
-    Learn more
-  </message>
   <message name="IDS_BROWSE_WITHOUT_SIGNING_IN_HTML" desc="Text shown on side of Google sign-in UI.">
     You may also skip signing in and <ph name="LINK_START">$1<ex>&gt;a&lt;</ex></ph>browse as Guest<ph name="LINK_END">$2<ex>&gt;/a&lt;</ex></ph>.
   </message>
@@ -2919,9 +2913,6 @@
   </message>
 
   <!-- Keyboard overlay UI -->
-  <message name="IDS_KEYBOARD_OVERLAY_LEARN_MORE" desc="The text of the learn more link on the keyboard overlay.">
-    Learn more
-  </message>
   <message name="IDS_KEYBOARD_OVERLAY_TITLE" desc="The title of the keyboard overlay.">
     Keyboard Overlay
   </message>
@@ -3567,9 +3558,6 @@
   <message name="IDS_LOGIN_PUBLIC_ACCOUNT_MONITORING_WARNING" desc="Text shown in the public account user pod, warning the user about potential admin monitoring.">
     The device admin may monitor your browsing activity.
   </message>
-  <message name="IDS_LOGIN_PUBLIC_ACCOUNT_LEARN_MORE" desc="Link shown in the public account user pod, showing the user more information about the monitoring.">
-    Learn more
-  </message>
   <message name="IDS_LOGIN_PUBLIC_ACCOUNT_MONITORING_INFO" desc="Text shown in the warning dialog after user clicks on the learn more link, notifying the user of potential security and privacy implications of using the device">
     The device admin may monitor the following:
   </message>
@@ -3755,9 +3743,6 @@
   <message name="IDS_EOL_NOTIFICATION_EOL" desc="Notification shown to inform the user that this device will no longer receive latest software updates.">
     This device will no longer receive the latest software updates. Please consider upgrading.
   </message>
-  <message name="IDS_EOL_MORE_INFO_BUTTON" desc="A button label shown in the notification for eol status change to get more information.">
-    Learn more
-  </message>
   <message name="IDS_EOL_DISMISS_BUTTON" desc="A button label shown in the notification for eol status change to dismiss the notification.">
     Don't remind me again
   </message>
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index bf0479e..ebbc26f 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -584,6 +584,10 @@
         Customize and control Chromium
       </message>
 
+      <message name="IDS_APPMENU_TOOLTIP_UPDATE_AVAILABLE" desc="The tooltip to show for the browser menu when an update is available">
+        Customize and control Chromium. Update is available.
+      </message>
+
       <message name="IDS_OPEN_IN_CHROME" desc="The text label of the Open in Chrome menu item for the Hosted App app menu">
         &amp;Open in Chromium
       </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index cb6123e..8fbc3229 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1596,10 +1596,6 @@
         Show all downloads
       </message>
       <if expr="chromeos">
-        <message name="IDS_DOWNLOAD_LINK_LEARN_MORE_SCANNING"
-                 desc="In the download notification, a label of the button to show information about download scanning">
-          Learn more
-        </message>
       </if>
       <message name="IDS_DOWNLOAD_TAB_CANCELLED"
                desc="Text that appears next to the downloaded files that have been canceled">
@@ -6638,9 +6634,6 @@
       </message>
 
       <!-- Sad Tab Strings -->
-      <message name="IDS_SAD_TAB_LEARN_MORE_LINK" desc="The link text displayed on the sad tab page pointing the users to a help article.">
-        Learn more
-      </message>
       <message name="IDS_CRASHED_TAB_FEEDBACK_MESSAGE" desc="The text to auto-populate the feedback page with. The triple single quotes are needed to preserve the line break.">
         Help our engineers investigate and fix this crash. List exact steps if you can. No detail is too small!
 '''
@@ -7035,9 +7028,6 @@
         Advanced
       </message>
       <!-- Enterprise sign-in profile linking -->
-      <message name="IDS_ENTERPRISE_SIGNIN_PROFILE_LINK_LEARN_MORE" desc="The link to get more information about profile linking after signing in to an enterprise account">
-        Learn more
-      </message>
       <message name="IDS_ENTERPRISE_SIGNIN_CANCEL" desc="Text of the button to cancel sign-in">
         Cancel
       </message>
@@ -7234,10 +7224,6 @@
               desc="Heading used when a person enters Guest Session">
           You’re browsing as a Guest
         </message>
-        <message name="IDS_NEW_TAB_GUEST_SESSION_LEARN_MORE_LINK"
-              desc="Guest Session link text to learn more">
-          Learn more
-        </message>
         <if expr="chromeos">
           <message name="IDS_NEW_TAB_GUEST_SESSION_DESCRIPTION"
               desc="Used when a person enters Guest Session">
@@ -7300,10 +7286,6 @@
         desc="Used to indicate that the speech recognition service is not available for the user's locale.">
         Voice search in your language is not available.
       </message>
-      <message name="IDS_NEW_TAB_VOICE_LEARN_MORE"
-        desc="Used as text for a link to a help web page, in case speech recognition fails.">
-        Learn more
-      </message>
       <message name="IDS_NEW_TAB_VOICE_LISTENING"
         desc="Used to indicate that the speech recognition service has started and is still waiting for user input. This message appears if there is no activity for 2 seconds after the user has been instructed to start speaking.">
         Listening...
@@ -7561,9 +7543,6 @@
         <message name="IDS_PROFILES_PROFILE_HIDE_MANAGE_ACCOUNTS_BUTTON" desc="Button in the avatar menu bubble view used to hide the accounts for a profile.">
           Hide accounts
         </message>
-        <message name="IDS_PROFILES_PROFILE_TUTORIAL_LEARN_MORE" desc="The Learn More link in the avatar tutorial bubble.">
-          Learn more
-        </message>
         <message name="IDS_PROFILES_SWITCH_USERS_BUTTON" desc="Button in the avatar menu bubble view for launching the user manager.">
           Switch person
         </message>
@@ -7911,9 +7890,6 @@
       <message name="IDS_SIGNIN_ERROR_EMAIL_TITLE" desc="Title of the signin error tab modal dialog when username can be retrieved to display.">
         Can't sign in to <ph name="USERNAME">$1<ex>Jane.Doe@gmail.com</ex></ph>
       </message>
-      <message name="IDS_SIGNIN_ERROR_LEARN_MORE_LINK" desc="Label in the signin error tab modal dialog containing the link to go to the Chrome Help page for sync problems.">
-        Learn more
-      </message>
       <message name="IDS_SIGNIN_ERROR_CLOSE_BUTTON_LABEL" desc="Label of the Close button in the signin error dialog.">
         Close
       </message>
@@ -10531,9 +10507,6 @@
       <message name="IDS_EASY_UNLOCK_SETUP_ANDROID_SMART_LOCK_DONE_BUTTON_LABEL" desc="The text to show as the button label in the Easy Unlock dialog step for encouraging the user to enable Smart Lock for Android. Clicking this button advances the dialog to step 3.">
         Next
       </message>
-      <message name="IDS_EASY_UNLOCK_SETUP_ANDROID_SMART_LOCK_ABOUT_LINK_TEXT" desc="The text to show as the link text to access the Smart Lock for Android help article.">
-        Learn more
-      </message>
       <!-- Step 3: "You're all set" -->
       <message name="IDS_EASY_UNLOCK_SETUP_COMPLETE_HEADER_TITLE" desc="The text to show as the header title of the Easy Unlock dialog during the penultimate step, confirming success.">
         Smart Lock is all set
@@ -10552,9 +10525,6 @@
         Done
       </message>
       <!-- Error strings for the Easy Unlock setup dialog -->
-      <message name="IDS_EASY_UNLOCK_LEARN_MORE_LINK_TITLE" desc="Text to use for links that point to more information about Easy Unlock in the easy unlock setup dialog.">
-        Learn more
-     </message>
       <message name="IDS_EASY_UNLOCK_SETUP_ERROR_BLUETOOTH_UNAVAILBLE" desc="The error message to display when the user's Chromebook might not have Bluetooth functionality during Easy Unlock setup. Note that the &lt;a&gt; element surrounds a link; these HTML elements should be preserved in the translation.">
         Can’t find your phone. Make sure your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>'s Bluetooth is turned on. &lt;a&gt;Learn more&lt;/a&gt;
       </message>
@@ -10781,9 +10751,6 @@
       <message name="IDS_DATA_USE_TRACKING_ENDED_CONTINUE" desc="Continue button for the dialog shown when data use tracking has ended. When clicked, the page resumes loading.">
         Continue
       </message>
-      <message name="IDS_DATA_USE_LEARN_MORE_TITLE" desc="Title for the 'Learn more' link in the the dialog shown when data use tracking has ended.">
-        Learn more
-      </message>
       <message name="IDS_DATA_USE_LEARN_MORE_LINK_URL" desc="URL for the 'Learn more' link in the the dialog shown when data use tracking has ended.">
         <!-- Intentionally empty. This is overridden via Finch. -->
       </message>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 3a26441..cb6dc18 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -594,6 +594,10 @@
         Customize and control Google Chrome
       </message>
 
+      <message name="IDS_APPMENU_TOOLTIP_UPDATE_AVAILABLE" desc="The tooltip to show for the browser menu when an update is available">
+        Customize and control Google Chrome. Update is available.
+      </message>
+
       <message name="IDS_OPEN_IN_CHROME" desc="The text label of the Open in Chrome menu item for the Hosted App app menu">
         &amp;Open in Chrome
       </message>
diff --git a/chrome/app/md_extensions_strings.grdp b/chrome/app/md_extensions_strings.grdp
index 9d9b923..c27e357 100644
--- a/chrome/app/md_extensions_strings.grdp
+++ b/chrome/app/md_extensions_strings.grdp
@@ -39,9 +39,6 @@
       =1 {&lt;1 line not shown&gt;}
       other {&lt;$1 lines not shown&gt;}}
   </message>
-  <message name="IDS_MD_EXTENSIONS_LEARN_MORE" desc="Learn more text">
-    Learn more
-  </message>
   <message name="IDS_MD_EXTENSIONS_ITEM_ERRORS" desc="The label of the button to bring the user to the page showing an extension's errors.">
     Errors
   </message>
diff --git a/chrome/app/media_router_strings.grdp b/chrome/app/media_router_strings.grdp
index 2eebf2e..30ba1f2 100644
--- a/chrome/app/media_router_strings.grdp
+++ b/chrome/app/media_router_strings.grdp
@@ -11,9 +11,6 @@
   <message name="IDS_MEDIA_ROUTER_MENU_ITEM_TITLE" desc="Title of menu item for Media Router, which appears in the overflow menu and page contextual menus.">
     &amp;Cast...
   </message>
-  <message name="IDS_MEDIA_ROUTER_LEARN_MORE" desc="Text of a menu item or link which, on click, opens a page with more information or relevant help center page.">
-   Learn more
-  </message>
 
   <!-- Button Titles -->
   <message name="IDS_MEDIA_ROUTER_BACK_BUTTON_TITLE" desc="Back button title, which is spoken when a screen reader is being used.">
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 5e520bc..003af9b 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1407,9 +1407,6 @@
     <message name="IDS_SETTINGS_INTERNET_NETWORK_NAMESERVERS_GOOGLE" desc="Settings > Internet > Network details: Label for setting Google name servers.">
       Google name servers
     </message>
-    <message name="IDS_SETTINGS_INTERNET_NETWORK_NAMESERVERS_LEARN_MORE" desc="Settings > Internet > Network details: Text for the learn more link for the Google name servers option.">
-      Learn more
-    </message>
     <message name="IDS_SETTINGS_INTERNET_NETWORK_PROXY_WPAD" desc="Settings > Internet > Network details: Web Proxy Auto Discovery (WPAD) label.">
       Web Proxy Auto Discovery URL:
     </message>
@@ -2718,9 +2715,6 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_ADOBE_FLASH_SETTINGS" desc="The text for the link that points the user to the Adobe Flash Player Storage settings on the web">
     Adobe Flash Player Storage settings
   </message>
-  <message name="IDS_SETTINGS_SITE_SETTINGS_LEARN_MORE" desc="The text for the link to learn more about how managing exceptions work for Site Settings categories">
-    Learn more
-  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLER_IS_DEFAULT" desc="A label showing that a certain handler for a given protocol is the default.">
     Default
   </message>
@@ -3372,9 +3366,6 @@
     <message name="IDS_SETTINGS_TRADITIONAL_SCROLL_LABEL" desc="In Device Settings, the text next to the radio button that enables traditional scrolling.">
       Traditional
     </message>
-    <message name="IDS_SETTINGS_NATURAL_SCROLL_LEARN_MORE" desc="In Device Settings, the text for the link next to the Australian (natural) scrolling option; opens a page to learn more about natural scrolling.">
-      Learn more
-    </message>
     <!-- Mouse -->
     <message name="IDS_SETTINGS_MOUSE_SPEED_LABEL" desc="In Device Settings, the text next to the slider that sets the speed (sensitivity) of the mouse.">
       Mouse speed
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 1feab06..d9b6063 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -681,10 +681,6 @@
     "media/webrtc/native_desktop_media_list.h",
     "media/webrtc/permission_bubble_media_access_handler.cc",
     "media/webrtc/permission_bubble_media_access_handler.h",
-
-    # TODO(brettw) should this go with the webrtc sources?
-    "media/webrtc/webrtc_log_list.cc",
-    "media/webrtc/webrtc_log_list.h",
     "media/webrtc/window_icon_util.h",
     "media/webrtc/window_icon_util_chromeos.cc",
     "media/webrtc/window_icon_util_mac.mm",
@@ -4108,8 +4104,6 @@
     sources += [
       "media/webrtc/audio_debug_recordings_handler.cc",
       "media/webrtc/audio_debug_recordings_handler.h",
-
-      # TODO(brettw) should webrtc_log_list.cc go here?
       "media/webrtc/webrtc_log_uploader.cc",
       "media/webrtc/webrtc_log_uploader.h",
       "media/webrtc/webrtc_log_util.cc",
@@ -4124,6 +4118,8 @@
       "media/webrtc/webrtc_text_log_handler.h",
     ]
     deps += [
+      "//components/webrtc_logging/browser",
+      "//components/webrtc_logging/common",
       "//third_party/webrtc/modules/desktop_capture",
       "//third_party/webrtc_overrides",
       "//third_party/webrtc_overrides:init_webrtc",
diff --git a/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.cc b/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.cc
index 3405823..b7ed836 100644
--- a/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.cc
+++ b/chrome/browser/android/data_usage/data_use_tab_ui_manager_android.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/profiles/profile_android.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/sessions/core/session_id.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/web_contents.h"
 #include "jni/DataUseTabUIManager_jni.h"
@@ -56,7 +57,7 @@
             IDS_DATA_USE_TRACKING_ENDED_CHECKBOX_MESSAGE,
         [DATA_USE_TRACKING_ENDED_CONTINUE] =
             IDS_DATA_USE_TRACKING_ENDED_CONTINUE,
-        [DATA_USE_LEARN_MORE_TITLE] = IDS_DATA_USE_LEARN_MORE_TITLE,
+        [DATA_USE_LEARN_MORE_TITLE] = IDS_LEARN_MORE,
         [DATA_USE_LEARN_MORE_LINK_URL] = IDS_DATA_USE_LEARN_MORE_LINK_URL,
 };
 
diff --git a/chrome/browser/background/background_contents_service_unittest.cc b/chrome/browser/background/background_contents_service_unittest.cc
index b59570d..7ce93c8 100644
--- a/chrome/browser/background/background_contents_service_unittest.cc
+++ b/chrome/browser/background/background_contents_service_unittest.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/background/background_contents.h"
 #include "chrome/browser/background/background_contents_service_factory.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/notifications/message_center_notification_manager.h"
+#include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/extensions/extension_test_util.h"
 #include "chrome/common/pref_names.h"
@@ -29,9 +29,6 @@
 #include "extensions/common/extension.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
-#include "ui/message_center/fake_ui_delegate.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/message_center_observer.h"
 #include "ui/message_center/notification.h"
 #include "url/gurl.h"
 
@@ -117,52 +114,6 @@
   Profile* profile_;
 };
 
-// Wait for the notification created.
-class NotificationWaiter : public message_center::MessageCenterObserver {
- public:
-  explicit NotificationWaiter(const std::string& target_id, Profile* profile)
-      : target_id_(target_id), profile_(profile) {}
-  ~NotificationWaiter() override {}
-
-  void WaitForNotificationAdded() {
-    DCHECK(!run_loop_.running());
-    message_center::MessageCenter* message_center =
-        message_center::MessageCenter::Get();
-
-    message_center->AddObserver(this);
-    run_loop_.Run();
-    message_center->RemoveObserver(this);
-  }
-
- private:
-  // message_center::MessageCenterObserver overrides:
-  void OnNotificationAdded(const std::string& notification_id) override {
-    if (notification_id == FindNotificationIdFromDelegateId(target_id_))
-      run_loop_.Quit();
-  }
-
-  void OnNotificationUpdated(const std::string& notification_id) override {
-    if (notification_id == FindNotificationIdFromDelegateId(target_id_))
-      run_loop_.Quit();
-  }
-
-  std::string FindNotificationIdFromDelegateId(const std::string& delegate_id) {
-    MessageCenterNotificationManager* manager =
-        static_cast<MessageCenterNotificationManager*>(
-            g_browser_process->notification_ui_manager());
-    DCHECK(manager);
-    return manager
-        ->FindById(delegate_id, NotificationUIManager::GetProfileID(profile_))
-        ->id();
-  }
-
-  std::string target_id_;
-  Profile* profile_;
-  base::RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(NotificationWaiter);
-};
-
 class BackgroundContentsServiceNotificationTest
     : public BrowserWithTestWindowTest {
  public:
@@ -171,42 +122,29 @@
 
   // Overridden from testing::Test
   void SetUp() override {
-    // In ChromeOS environment, BrowserWithTestWindowTest initializes
-    // MessageCenter.
-#if !defined(OS_CHROMEOS)
-    message_center::MessageCenter::Initialize();
-#endif
     BrowserWithTestWindowTest::SetUp();
-
-    MessageCenterNotificationManager* manager =
-        static_cast<MessageCenterNotificationManager*>(
-            g_browser_process->notification_ui_manager());
-    manager->SetUiDelegateForTest(new message_center::FakeUiDelegate());
-  }
-
-  void TearDown() override {
-    BrowserWithTestWindowTest::TearDown();
-#if !defined(OS_CHROMEOS)
-    message_center::MessageCenter::Shutdown();
-#endif
+    display_service_ =
+        std::make_unique<NotificationDisplayServiceTester>(profile());
   }
 
  protected:
   // Creates crash notification for the specified extension and returns
   // the created one.
-  const message_center::Notification* CreateCrashNotification(
+  const message_center::Notification CreateCrashNotification(
       scoped_refptr<extensions::Extension> extension) {
     std::string notification_id = BackgroundContentsService::
         GetNotificationDelegateIdForExtensionForTesting(extension->id());
-    NotificationWaiter waiter(notification_id, profile());
     BackgroundContentsService::ShowBalloonForTesting(
         extension.get(), profile());
-    waiter.WaitForNotificationAdded();
-
-    return g_browser_process->notification_ui_manager()->FindById(
-        notification_id, profile());
+    base::RunLoop run_loop;
+    display_service_->SetNotificationAddedClosure(run_loop.QuitClosure());
+    run_loop.Run();
+    display_service_->SetNotificationAddedClosure(base::RepeatingClosure());
+    return *display_service_->GetNotification(notification_id);
   }
 
+  std::unique_ptr<NotificationDisplayServiceTester> display_service_;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(BackgroundContentsServiceNotificationTest);
 };
@@ -347,9 +285,9 @@
   ASSERT_TRUE(extension.get());
   ASSERT_TRUE(extension->GetManifestData("icons"));
 
-  const message_center::Notification* notification =
+  const message_center::Notification notification =
       CreateCrashNotification(extension);
-  EXPECT_FALSE(notification->icon().IsEmpty());
+  EXPECT_FALSE(notification.icon().IsEmpty());
 }
 
 TEST_F(BackgroundContentsServiceNotificationTest, TestShowBalloonShutdown) {
@@ -367,11 +305,7 @@
   static_cast<TestingBrowserProcess*>(g_browser_process)
       ->SetShuttingDown(false);
 
-  const message_center::Notification* notification =
-      g_browser_process->notification_ui_manager()->FindById(notification_id,
-                                                             profile());
-
-  ASSERT_EQ(nullptr, notification);
+  EXPECT_FALSE(display_service_->GetNotification(notification_id));
 }
 
 // Verify if a test notification can show the default extension icon for
@@ -383,9 +317,9 @@
   ASSERT_TRUE(extension.get());
   ASSERT_FALSE(extension->GetManifestData("icons"));
 
-  const message_center::Notification* notification =
+  const message_center::Notification notification =
       CreateCrashNotification(extension);
-  EXPECT_FALSE(notification->icon().IsEmpty());
+  EXPECT_FALSE(notification.icon().IsEmpty());
 }
 
 TEST_F(BackgroundContentsServiceNotificationTest, TestShowTwoBalloons) {
@@ -396,9 +330,8 @@
   CreateCrashNotification(extension);
   CreateCrashNotification(extension);
 
-  message_center::MessageCenter* message_center =
-      message_center::MessageCenter::Get();
-  message_center::NotificationList::Notifications notifications =
-      message_center->GetVisibleNotifications();
-  ASSERT_EQ(1u, notifications.size());
+  ASSERT_EQ(1u, display_service_
+                    ->GetDisplayedNotificationsForType(
+                        NotificationHandler::Type::TRANSIENT)
+                    .size());
 }
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 6297d9c..165ecf3 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -8,11 +8,6 @@
   </outputs>
   <release seq="1">
     <structures>
-      <if expr="enable_app_list">
-        <structure name="IDR_APP_LIST_START_PAGE_CSS" file="resources\app_list\start_page.css" flattenhtml="true" type="chrome_html" />
-        <structure name="IDR_APP_LIST_START_PAGE_HTML" file="resources\app_list\start_page.html" flattenhtml="true" type="chrome_html" />
-        <structure name="IDR_APP_LIST_START_PAGE_JS" file="resources\app_list\start_page.js" flattenhtml="true" type="chrome_html" />
-      </if>
       <if expr="enable_extensions">
         <structure name="IDR_EXTENSIONS_HTML" file="resources\extensions\extensions.html" flattenhtml="true" type="chrome_html" />
       </if>
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index 62e5035..763af68 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -121,8 +121,8 @@
 #endif
 
 #if BUILDFLAG(ENABLE_WEBRTC)
-#include "chrome/browser/media/webrtc/webrtc_log_list.h"
-#include "chrome/browser/media/webrtc/webrtc_log_util.h"
+#include "components/webrtc_logging/browser/log_cleanup.h"
+#include "components/webrtc_logging/browser/log_list.h"
 #endif
 
 #if BUILDFLAG(ENABLE_PLUGINS)
@@ -643,8 +643,8 @@
     base::PostTaskWithTraitsAndReply(
         FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
         base::BindOnce(
-            &WebRtcLogUtil::DeleteOldAndRecentWebRtcLogFiles,
-            WebRtcLogList::GetWebRtcLogDirectoryForBrowserContextPath(
+            &webrtc_logging::DeleteOldAndRecentWebRtcLogFiles,
+            webrtc_logging::LogList::GetWebRtcLogDirectoryForBrowserContextPath(
                 profile_->GetPath()),
             delete_begin_),
         clear_webrtc_logs_.GetCompletionCallback());
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h
index 6ca5517..baaa3be 100644
--- a/chrome/browser/chrome_notification_types.h
+++ b/chrome/browser/chrome_notification_types.h
@@ -318,8 +318,6 @@
   //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
   // 4. Boot into retail mode
   //    NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
-  // 5. Boot into kiosk mode
-  //    NOTIFICATION_KIOSK_APP_LAUNCHED
   NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
 
   // Send when kiosk auto-launch warning screen is visible.
@@ -340,9 +338,6 @@
   // Sent when kiosk app list is loaded in UI.
   NOTIFICATION_KIOSK_APPS_LOADED,
 
-  // Sent when a kiosk app is launched.
-  NOTIFICATION_KIOSK_APP_LAUNCHED,
-
   // Sent when the user list has changed.
   NOTIFICATION_USER_LIST_CHANGED,
 
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index c484e21..b03f9b6 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -504,6 +504,8 @@
     "dbus/chrome_proxy_resolution_service_provider_delegate.h",
     "dbus/chrome_virtual_file_request_service_provider_delegate.cc",
     "dbus/chrome_virtual_file_request_service_provider_delegate.h",
+    "dbus/finch_features_service_provider_delegate.cc",
+    "dbus/finch_features_service_provider_delegate.h",
     "dbus/kiosk_info_service_provider.cc",
     "dbus/kiosk_info_service_provider.h",
     "dbus/screen_lock_service_provider.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 12ed7023..2394943e 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -11,7 +11,6 @@
 #include <utility>
 #include <vector>
 
-#include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/accessibility_focus_ring_controller.h"
 #include "ash/autoclick/autoclick_controller.h"
 #include "ash/autoclick/mus/public/interfaces/autoclick.mojom.h"
@@ -1254,15 +1253,6 @@
     SetProfile(ProfileManager::GetActiveUserProfile());
 }
 
-void AccessibilityManager::SetProfileForTest(Profile* profile) {
-  SetProfile(profile);
-}
-
-void AccessibilityManager::SetBrailleControllerForTest(
-    BrailleController* controller) {
-  g_braille_controller_for_test = controller;
-}
-
 base::TimeDelta AccessibilityManager::PlayShutdownSound() {
   if (!PlayEarcon(SOUND_SHUTDOWN,
                   PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED)) {
@@ -1396,21 +1386,9 @@
 void AccessibilityManager::OnBrailleDisplayStateChanged(
     const DisplayState& display_state) {
   braille_display_connected_ = display_state.available;
-  if (braille_display_connected_) {
-    // TODO(crbug.com/594887): Fix for mash by moving notifying accessibility
-    // status change to ash for BrailleDisplayStateChanged.
-    if (GetAshConfig() == ash::Config::MASH)
-      return;
-
-    ash::Shell::Get()->accessibility_controller()->SetSpokenFeedbackEnabled(
-        true, ash::A11Y_NOTIFICATION_SHOW);
-  }
+  accessibility_controller_->BrailleDisplayStateChanged(
+      braille_display_connected_);
   UpdateBrailleImeState();
-
-  AccessibilityStatusEventDetails details(
-      ACCESSIBILITY_BRAILLE_DISPLAY_CONNECTION_STATE_CHANGED,
-      braille_display_connected_, ash::A11Y_NOTIFICATION_SHOW);
-  NotifyAccessibilityStatusChanged(details);
 }
 
 void AccessibilityManager::OnBrailleKeyEvent(const KeyEvent& event) {
@@ -1549,4 +1527,18 @@
   dictation_->OnToggleDictation();
 }
 
+void AccessibilityManager::SetProfileForTest(Profile* profile) {
+  SetProfile(profile);
+}
+
+// static
+void AccessibilityManager::SetBrailleControllerForTest(
+    BrailleController* controller) {
+  g_braille_controller_for_test = controller;
+}
+
+void AccessibilityManager::FlushForTesting() {
+  accessibility_controller_.FlushForTesting();
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index a314324..8e2f4153 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -55,7 +55,6 @@
   ACCESSIBILITY_TOGGLE_CURSOR_HIGHLIGHT,
   ACCESSIBILITY_TOGGLE_FOCUS_HIGHLIGHT,
   ACCESSIBILITY_TOGGLE_TAP_DRAGGING,
-  ACCESSIBILITY_BRAILLE_DISPLAY_CONNECTION_STATE_CHANGED
 };
 
 struct AccessibilityStatusEventDetails {
@@ -227,11 +226,6 @@
   // user_manager::UserManager::UserSessionStateObserver overrides:
   void ActiveUserChanged(const user_manager::User* active_user) override;
 
-  void SetProfileForTest(Profile* profile);
-
-  static void SetBrailleControllerForTest(
-      extensions::api::braille_display_private::BrailleController* controller);
-
   // Initiates play of shutdown sound and returns it's duration.
   base::TimeDelta PlayShutdownSound();
 
@@ -305,6 +299,12 @@
   // Starts or stops dictation (type what you speak).
   void ToggleDictation();
 
+  // Test helpers:
+  void SetProfileForTest(Profile* profile);
+  static void SetBrailleControllerForTest(
+      extensions::api::braille_display_private::BrailleController* controller);
+  void FlushForTesting();
+
  protected:
   AccessibilityManager();
   ~AccessibilityManager() override;
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc b/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
index 16b74c91..0136a38 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
@@ -289,6 +289,8 @@
     ash::Shell::Get()->accessibility_controller()->SetPrefServiceForTest(
         profile->GetPrefs());
     default_autoclick_delay_ = GetAutoclickDelay();
+    // Spin the message loop to ensure the initial CheckBrailleState() is done.
+    base::RunLoop().RunUntilIdle();
   }
 
   void TearDownOnMainThread() override {
@@ -299,6 +301,7 @@
     braille_controller_.SetAvailable(available);
     braille_controller_.GetObserver()->OnBrailleDisplayStateChanged(
         *braille_controller_.GetDisplayState());
+    AccessibilityManager::Get()->FlushForTesting();
   }
 
   int default_autoclick_delay() const { return default_autoclick_delay_; }
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
index be587754..687f41c 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
@@ -316,6 +316,9 @@
   app_session_ = CreateAppSession();
   if (app_session_)
     app_session_->Init(profile, app_id);
+
+  for (auto& observer : observers_)
+    observer.OnKioskSessionInitialized();
 }
 
 bool KioskAppManager::GetSwitchesForSessionRestore(
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h b/chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h
index ac93e12..4dcb243 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h
@@ -33,6 +33,10 @@
   // |success| indicates if all the updates are completed successfully.
   virtual void OnKioskAppExternalUpdateComplete(bool success) {}
 
+  // Called when kiosk app session initialization is complete - i.e. when
+  // KioskAppManager::InitSession() is called.
+  virtual void OnKioskSessionInitialized() {}
+
  protected:
   virtual ~KioskAppManagerObserver() {}
 };
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
index cbe9800..6371514 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
@@ -12,7 +12,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_diagnosis_runner.h"
 #include "chrome/browser/chromeos/app_mode/startup_app_launcher_update_checker.h"
@@ -27,7 +26,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "components/crx_file/id_util.h"
 #include "components/session_manager/core/session_manager.h"
-#include "content/public/browser/notification_service.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
@@ -392,11 +390,6 @@
   KioskAppManager::Get()->InitSession(profile_, app_id_);
   session_manager::SessionManager::Get()->SessionStarted();
 
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
-      content::NotificationService::AllSources(),
-      content::NotificationService::NoDetails());
-
   if (diagnostic_mode_)
     KioskDiagnosisRunner::Run(profile_, app_id_);
 
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 5e70e94f..6185b63 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -50,6 +50,7 @@
 #include "chrome/browser/chromeos/dbus/chrome_display_power_service_provider_delegate.h"
 #include "chrome/browser/chromeos/dbus/chrome_proxy_resolution_service_provider_delegate.h"
 #include "chrome/browser/chromeos/dbus/chrome_virtual_file_request_service_provider_delegate.h"
+#include "chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.h"
 #include "chrome/browser/chromeos/dbus/kiosk_info_service_provider.h"
 #include "chrome/browser/chromeos/dbus/screen_lock_service_provider.h"
 #include "chrome/browser/chromeos/display/quirks_manager_delegate_impl.h"
@@ -125,6 +126,7 @@
 #include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_policy_controller.h"
+#include "chromeos/dbus/services/chrome_features_service_provider.h"
 #include "chromeos/dbus/services/component_updater_service_provider.h"
 #include "chromeos/dbus/services/console_service_provider.h"
 #include "chromeos/dbus/services/cros_dbus_service.h"
@@ -365,6 +367,13 @@
                 std::make_unique<
                     ChromeComponentUpdaterServiceProviderDelegate>())));
 
+    finch_features_service_ = CrosDBusService::Create(
+        kChromeFeaturesServiceName,
+        dbus::ObjectPath(kChromeFeaturesServicePath),
+        CrosDBusService::CreateServiceProviderList(
+            std::make_unique<ChromeFeaturesServiceProvider>(
+                std::make_unique<FinchFeaturesServiceProviderDelegate>())));
+
     // Initialize PowerDataCollector after DBusThreadManager is initialized.
     PowerDataCollector::Initialize();
 
@@ -414,6 +423,7 @@
     liveness_service_.reset();
     virtual_file_request_service_.reset();
     component_updater_service_.reset();
+    finch_features_service_.reset();
     PowerDataCollector::Shutdown();
     PowerPolicyController::Shutdown();
     device::BluetoothAdapterFactory::Shutdown();
@@ -442,6 +452,7 @@
   std::unique_ptr<CrosDBusService> liveness_service_;
   std::unique_ptr<CrosDBusService> virtual_file_request_service_;
   std::unique_ptr<CrosDBusService> component_updater_service_;
+  std::unique_ptr<CrosDBusService> finch_features_service_;
 
   ChromeConsoleServiceProviderDelegate console_service_provider_delegate_;
 
diff --git a/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.cc b/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.cc
new file mode 100644
index 0000000..26926e5b
--- /dev/null
+++ b/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.cc
@@ -0,0 +1,20 @@
+// 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/chromeos/dbus/finch_features_service_provider_delegate.h"
+
+#include "base/feature_list.h"
+#include "chrome/common/chrome_features.h"
+
+namespace chromeos {
+
+FinchFeaturesServiceProviderDelegate::FinchFeaturesServiceProviderDelegate() {}
+
+FinchFeaturesServiceProviderDelegate::~FinchFeaturesServiceProviderDelegate() {}
+
+bool FinchFeaturesServiceProviderDelegate::IsCrostiniEnabled() {
+  return base::FeatureList::IsEnabled(features::kCrostini);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.h b/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.h
new file mode 100644
index 0000000..c4ddd19
--- /dev/null
+++ b/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.h
@@ -0,0 +1,29 @@
+// 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_CHROMEOS_DBUS_FINCH_FEATURES_SERVICE_PROVIDER_DELEGATE_H_
+#define CHROME_BROWSER_CHROMEOS_DBUS_FINCH_FEATURES_SERVICE_PROVIDER_DELEGATE_H_
+
+#include "base/macros.h"
+#include "chromeos/dbus/services/chrome_features_service_provider.h"
+
+namespace chromeos {
+
+// Finch implementation of ChromeFeaturesServiceProvider::Delegate.
+class FinchFeaturesServiceProviderDelegate
+    : public ChromeFeaturesServiceProvider::Delegate {
+ public:
+  FinchFeaturesServiceProviderDelegate();
+  ~FinchFeaturesServiceProviderDelegate() override;
+
+  // ChromeServiceProvider::Delegate:
+  bool IsCrostiniEnabled() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FinchFeaturesServiceProviderDelegate);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_DBUS_FINCH_FEATURES_SERVICE_PROVIDER_DELEGATE_H_
diff --git a/chrome/browser/chromeos/eol_notification.cc b/chrome/browser/chromeos/eol_notification.cc
index b7a8206..6ab8350 100644
--- a/chrome/browser/chromeos/eol_notification.cc
+++ b/chrome/browser/chromeos/eol_notification.cc
@@ -18,6 +18,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/update_engine_client.h"
 #include "components/prefs/pref_service.h"
+#include "components/strings/grit/components_strings.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/color_palette.h"
@@ -140,7 +141,7 @@
   message_center::RichNotificationData data;
 
   DCHECK_EQ(BUTTON_MORE_INFO, data.buttons.size());
-  data.buttons.emplace_back(GetStringUTF16(IDS_EOL_MORE_INFO_BUTTON));
+  data.buttons.emplace_back(GetStringUTF16(IDS_LEARN_MORE));
 
   DCHECK_EQ(BUTTON_DISMISS, data.buttons.size());
   data.buttons.emplace_back(GetStringUTF16(IDS_EOL_DISMISS_BUTTON));
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
index 4b2cecd..66c19524 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/system/statistics_provider.h"
+#include "components/strings/grit/components_strings.h"
 #include "extensions/common/extension_l10n_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/webui/web_ui_util.h"
@@ -122,7 +123,7 @@
              IDS_FILE_BROWSER_CONFIRM_MOVE_BUTTON_LABEL);
   SET_STRING("CONFIRM_COPY_BUTTON_LABEL",
              IDS_FILE_BROWSER_CONFIRM_COPY_BUTTON_LABEL);
-  SET_STRING("DRIVE_LEARN_MORE", IDS_FILE_BROWSER_DRIVE_LEARN_MORE);
+  SET_STRING("DRIVE_LEARN_MORE", IDS_LEARN_MORE);
   SET_STRING("DRIVE_MENU_HELP", IDS_FILE_BROWSER_DRIVE_MENU_HELP);
   SET_STRING("DRIVE_MOBILE_CONNECTION_OPTION",
              IDS_FILE_BROWSER_DRIVE_MOBILE_CONNECTION_OPTION);
diff --git a/chrome/browser/chromeos/hats/hats_notification_controller_unittest.cc b/chrome/browser/chromeos/hats/hats_notification_controller_unittest.cc
index e4dd098..b8fd208b 100644
--- a/chrome/browser/chromeos/hats/hats_notification_controller_unittest.cc
+++ b/chrome/browser/chromeos/hats/hats_notification_controller_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "base/run_loop.h"
 #include "base/strings/string_split.h"
-#include "chrome/browser/notifications/message_center_notification_manager.h"
 #include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/browser/notifications/notification_handler.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
@@ -50,7 +49,6 @@
   }
 
   void TearDown() override {
-    g_browser_process->notification_ui_manager()->StartShutdown();
     // The notifications may be deleted async.
     base::RunLoop loop;
     loop.RunUntilIdle();
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index a63d1b7..11abdd5 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -259,6 +259,25 @@
   base::SysInfo::SetChromeOSVersionInfoForTest(lsb_release, base::Time::Now());
 }
 
+class KioskSessionInitializedWaiter : public KioskAppManagerObserver {
+ public:
+  KioskSessionInitializedWaiter() : scoped_observer_(this) {
+    scoped_observer_.Add(KioskAppManager::Get());
+  }
+  ~KioskSessionInitializedWaiter() override = default;
+
+  void Wait() { run_loop_.Run(); }
+
+  // KioskAppManagerObserver:
+  void OnKioskSessionInitialized() override { run_loop_.Quit(); }
+
+ private:
+  ScopedObserver<KioskAppManager, KioskAppManagerObserver> scoped_observer_;
+  base::RunLoop run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(KioskSessionInitializedWaiter);
+};
+
 // Helper functions for CanConfigureNetwork mock.
 class ScopedCanConfigureNetwork {
  public:
@@ -629,10 +648,7 @@
         "launchData.isKioskSession = true", false);
 
     // Wait for the Kiosk App to launch.
-    content::WindowedNotificationObserver(
-        chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
-        content::NotificationService::AllSources())
-        .Wait();
+    KioskSessionInitializedWaiter().Wait();
 
     // Default profile switches to app profile after app is launched.
     Profile* app_profile = ProfileManager::GetPrimaryUserProfile();
@@ -2202,11 +2218,7 @@
   PrepareAppLaunch();
   LaunchApp(kTestEnterpriseKioskApp, false);
 
-  // Wait for the Kiosk App to launch.
-  content::WindowedNotificationObserver(
-      chrome::NOTIFICATION_KIOSK_APP_LAUNCHED,
-      content::NotificationService::AllSources())
-      .Wait();
+  KioskSessionInitializedWaiter().Wait();
 
   // Check installer status.
   EXPECT_EQ(chromeos::KioskAppLaunchError::NONE,
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index 0a226d4..9b567dc 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1040,6 +1040,30 @@
   btl->AddLoginTimeMarker("StartSession-End", false);
 }
 
+void UserSessionManager::OnUserNetworkPolicyParsed(bool send_password) {
+  // Sanity check that we only send the password for enterprise users. See
+  // https://crbug.com/386606.
+  const bool is_enterprise_managed = g_browser_process->platform_part()
+                                         ->browser_policy_connector_chromeos()
+                                         ->IsEnterpriseManaged();
+  if (!is_enterprise_managed) {
+    LOG(WARNING) << "Attempting to save user password for non enterprise user.";
+    user_context_.GetMutablePasswordKey()->ClearSecret();
+    return;
+  }
+
+  if (send_password) {
+    if (user_context_.GetPasswordKey()->GetSecret().size() > 0) {
+      DBusThreadManager::Get()->GetSessionManagerClient()->SaveLoginPassword(
+          user_context_.GetPasswordKey()->GetSecret());
+    } else {
+      LOG(WARNING) << "Not saving password because password is empty.";
+    }
+  }
+
+  user_context_.GetMutablePasswordKey()->ClearSecret();
+}
+
 void UserSessionManager::PrepareProfile() {
   const bool is_demo_session =
       DemoAppLauncher::IsDemoAppSession(user_context_.GetAccountId());
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.h b/chrome/browser/chromeos/login/session/user_session_manager.h
index 53aa021..ffd58acf 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.h
+++ b/chrome/browser/chromeos/login/session/user_session_manager.h
@@ -263,6 +263,12 @@
 
   void Shutdown();
 
+  // Called when the user network policy has been parsed. If |send_password| is
+  // true, the user's password will be sent over dbus to the session manager to
+  // save in a keyring. Before the function exits, it will clear the user
+  // password from the UserContext regardless of the value of |send_password|.
+  void OnUserNetworkPolicyParsed(bool send_password);
+
  private:
   friend class test::UserSessionManagerTestApi;
   friend struct base::DefaultSingletonTraits<UserSessionManager>;
diff --git a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
index 8d41d47..a26486e 100644
--- a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
+++ b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chrome/browser/net/nss_context.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
@@ -120,6 +121,14 @@
   DCHECK(user_);
   chromeos::onc::ExpandStringPlaceholdersInNetworksForUser(user_,
                                                            network_configs_onc);
+
+  // Call on UserSessionManager to send the user's password to session manager
+  // if the password substitution variable exists in the ONC.
+  bool send_password =
+      chromeos::onc::HasUserPasswordSubsitutionVariable(network_configs_onc);
+  chromeos::UserSessionManager::GetInstance()->OnUserNetworkPolicyParsed(
+      send_password);
+
   network_config_handler_->SetPolicy(onc_source_,
                                      user_->username_hash(),
                                      *network_configs_onc,
diff --git a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
index dafe2da..89edb3f 100644
--- a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
+++ b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/accessibility/accessibility_controller.h"
 #include "ash/login_status.h"
 #include "ash/public/cpp/accessibility_types.h"
 #include "ash/public/cpp/ash_pref_names.h"
@@ -15,7 +14,6 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
@@ -23,7 +21,6 @@
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
-#include "chrome/browser/extensions/api/braille_display_private/mock_braille_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/session_controller_client.h"
@@ -42,15 +39,10 @@
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
-#include "ui/message_center/message_center.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/widget/widget.h"
 
-using extensions::api::braille_display_private::BrailleObserver;
-using extensions::api::braille_display_private::DisplayState;
-using extensions::api::braille_display_private::MockBrailleController;
-using message_center::MessageCenter;
 using testing::Return;
 using testing::_;
 using testing::WithParamInterface;
@@ -146,12 +138,6 @@
     EXPECT_CALL(provider_, IsInitializationComplete(_))
         .WillRepeatedly(Return(true));
     policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
-    AccessibilityManager::SetBrailleControllerForTest(&braille_controller_);
-  }
-
-  void TearDownOnMainThread() override {
-    AccessibilityManager::SetBrailleControllerForTest(nullptr);
-    InProcessBrowserTest::TearDownOnMainThread();
   }
 
   void SetShowAccessibilityOptionsInSystemTrayMenu(bool value) {
@@ -402,17 +388,10 @@
            views::Button::STATE_NORMAL;
   }
 
-  void SetBrailleConnected(bool connected) {
-    braille_controller_.SetAvailable(connected);
-    braille_controller_.GetObserver()->OnBrailleDisplayStateChanged(
-        *braille_controller_.GetDisplayState());
-  }
-
   // Disable animations so that tray icons hide immediately.
   ui::ScopedAnimationDurationScaleMode disable_animations_;
 
   policy::MockConfigurationPolicyProvider provider_;
-  MockBrailleController braille_controller_;
 };
 
 using TrayAccessibilityLoginScreenTest = OobeBaseTest;
@@ -967,48 +946,6 @@
   EXPECT_TRUE(CanCreateMenuItem());
 }
 
-IN_PROC_BROWSER_TEST_P(TrayAccessibilityTest, ShowNotification) {
-  const base::string16 BRAILLE_CONNECTED =
-      base::ASCIIToUTF16("Braille display connected.");
-  const base::string16 CHROMEVOX_ENABLED =
-      base::ASCIIToUTF16("Press Ctrl + Alt + Z to disable spoken feedback.");
-  const base::string16 BRAILLE_CONNECTED_AND_CHROMEVOX_ENABLED_TITLE =
-      base::ASCIIToUTF16("Braille and ChromeVox are enabled");
-
-  EnableSpokenFeedback(true, ash::A11Y_NOTIFICATION_SHOW);
-  EXPECT_TRUE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
-  // Connecting a braille display when spoken feedback is already enabled
-  // should only show the message about the braille display.
-  SetBrailleConnected(true);
-  message_center::NotificationList::Notifications notifications =
-      MessageCenter::Get()->GetVisibleNotifications();
-  EXPECT_EQ(1u, notifications.size());
-  EXPECT_EQ(base::string16(), (*notifications.begin())->title());
-  EXPECT_EQ(BRAILLE_CONNECTED, (*notifications.begin())->message());
-
-  // Neither disconnecting a braille display, nor disabling spoken feedback
-  // should show any notification.
-  SetBrailleConnected(false);
-  EXPECT_TRUE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
-  notifications = MessageCenter::Get()->GetVisibleNotifications();
-  EXPECT_EQ(0u, notifications.size());
-  EnableSpokenFeedback(false, ash::A11Y_NOTIFICATION_SHOW);
-  notifications = MessageCenter::Get()->GetVisibleNotifications();
-  EXPECT_EQ(0u, notifications.size());
-  EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
-
-  // Connecting a braille display should enable spoken feedback and show
-  // both messages.
-  SetBrailleConnected(true);
-  // Spin the run loop to make sure ash see the change.
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
-  notifications = MessageCenter::Get()->GetVisibleNotifications();
-  EXPECT_EQ(BRAILLE_CONNECTED_AND_CHROMEVOX_ENABLED_TITLE,
-            (*notifications.begin())->title());
-  EXPECT_EQ(CHROMEVOX_ENABLED, (*notifications.begin())->message());
-}
-
 IN_PROC_BROWSER_TEST_P(TrayAccessibilityTest, KeepMenuVisibilityOnLockScreen) {
   // Enables high contrast mode.
   EnableHighContrast(true);
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc
index 60981875..e75a818 100644
--- a/chrome/browser/download/notification/download_item_notification.cc
+++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -25,6 +25,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/elide_url.h"
 #include "components/vector_icons/vector_icons.h"
 #include "content/public/browser/browser_context.h"
@@ -643,7 +644,7 @@
       id = IDS_DOWNLOAD_LINK_CANCEL;
       break;
     case DownloadCommands::LEARN_MORE_SCANNING:
-      id = IDS_DOWNLOAD_LINK_LEARN_MORE_SCANNING;
+      id = IDS_LEARN_MORE;
       break;
     case DownloadCommands::COPY_TO_CLIPBOARD:
       id = IDS_DOWNLOAD_NOTIFICATION_COPY_TO_CLIPBOARD;
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
index 7f41f2d..c8dc598 100644
--- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
+++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
@@ -43,6 +43,7 @@
 #include "components/proximity_auth/screenlock_state.h"
 #include "components/proximity_auth/switches.h"
 #include "components/signin/core/account_id/account_id.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -157,9 +158,8 @@
 #endif  // defined(OS_CHROMEOS)
 
   // Common strings.
-  strings->SetString(
-      "learnMoreLinkTitle",
-      l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_LEARN_MORE_LINK_TITLE));
+  strings->SetString("learnMoreLinkTitle",
+                     l10n_util::GetStringUTF16(IDS_LEARN_MORE));
   strings->SetString("deviceType", device_type);
 
   // Setup notification strings.
@@ -302,10 +302,8 @@
       "setupAndroidSmartLockDoneButtonText",
       l10n_util::GetStringUTF16(
           IDS_EASY_UNLOCK_SETUP_ANDROID_SMART_LOCK_DONE_BUTTON_LABEL));
-  strings->SetString(
-      "setupAndroidSmartLockAboutLinkText",
-      l10n_util::GetStringUTF16(
-          IDS_EASY_UNLOCK_SETUP_ANDROID_SMART_LOCK_ABOUT_LINK_TEXT));
+  strings->SetString("setupAndroidSmartLockAboutLinkText",
+                     l10n_util::GetStringUTF16(IDS_LEARN_MORE));
   // Step 3: Setup completed successfully.
   strings->SetString(
       "setupCompleteHeaderTitle",
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
index c1a9c2f..07b4d99 100644
--- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
@@ -7,8 +7,8 @@
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_browsertest_util.h"
-#include "chrome/browser/media/webrtc/webrtc_log_list.h"
 #include "chrome/common/chrome_switches.h"
+#include "components/webrtc_logging/browser/log_list.h"
 
 class WebrtcLoggingPrivateApiBrowserTest
     : public extensions::PlatformAppBrowserTest {
@@ -17,7 +17,7 @@
   ~WebrtcLoggingPrivateApiBrowserTest() override = default;
 
   base::FilePath webrtc_logs_path() {
-    return WebRtcLogList::GetWebRtcLogDirectoryForBrowserContextPath(
+    return webrtc_logging::LogList::GetWebRtcLogDirectoryForBrowserContextPath(
         profile()->GetPath());
   }
 
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc
index 6c6d5e0..30b58fd 100644
--- a/chrome/browser/infobars/infobars_browsertest.cc
+++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -61,6 +61,9 @@
 
 #if defined(OS_MACOSX)
 #include "chrome/browser/ui/cocoa/keystone_infobar_delegate.h"
+#endif
+
+#if defined(OS_MACOSX) && !BUILDFLAG(MAC_VIEWS_BROWSER)
 #include "chrome/browser/ui/startup/session_crashed_infobar_delegate.h"
 #endif
 
@@ -386,7 +389,7 @@
       break;
 
     case IBD::SESSION_CRASHED_INFOBAR_DELEGATE_MAC_IOS:
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !BUILDFLAG(MAC_VIEWS_BROWSER)
       SessionCrashedInfoBarDelegate::Create(browser());
 #else
       ADD_FAILURE() << "This infobar is not supported on this OS.";
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index c3d5264..e22c4914 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -88,8 +88,8 @@
 #include "net/net_features.h"
 #include "net/nqe/external_estimate_provider.h"
 #include "net/nqe/network_quality_estimator_params.h"
+#include "net/proxy/pac_file_fetcher_impl.h"
 #include "net/proxy/proxy_config_service.h"
-#include "net/proxy/proxy_script_fetcher_impl.h"
 #include "net/proxy/proxy_service.h"
 #include "net/quic/chromium/quic_utils_chromium.h"
 #include "net/socket/ssl_client_socket.h"
@@ -121,7 +121,7 @@
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
-#include "chromeos/network/dhcp_proxy_script_fetcher_factory_chromeos.h"
+#include "chromeos/network/dhcp_pac_file_fetcher_factory_chromeos.h"
 #include "chromeos/network/host_resolver_impl_chromeos.h"
 #endif
 
@@ -568,7 +568,7 @@
   UnregisterSTHObserver(ct_tree_tracker_.get());
   ct_tree_tracker_.reset();
 
-  globals_->system_request_context->proxy_service()->OnShutdown();
+  globals_->system_request_context->proxy_resolution_service()->OnShutdown();
 
 #if defined(USE_NSS_CERTS)
   net::SetURLRequestContextForNSSHttpIO(nullptr);
@@ -735,8 +735,8 @@
   builder->set_pac_quick_check_enabled(WpadQuickCheckEnabled());
   builder->set_pac_sanitize_url_policy(
       PacHttpsUrlStrippingEnabled()
-          ? net::ProxyService::SanitizeUrlPolicy::SAFE
-          : net::ProxyService::SanitizeUrlPolicy::UNSAFE);
+          ? net::ProxyResolutionService::SanitizeUrlPolicy::SAFE
+          : net::ProxyResolutionService::SanitizeUrlPolicy::UNSAFE);
 }
 
 certificate_transparency::TreeStateTracker* IOThread::ct_tree_tracker() const {
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h
index b2efc3a..796ba0c 100644
--- a/chrome/browser/io_thread.h
+++ b/chrome/browser/io_thread.h
@@ -211,7 +211,7 @@
   bool WpadQuickCheckEnabled() const;
   bool PacHttpsUrlStrippingEnabled() const;
 
-  // Configures |builder|'s ProxyService based on prefs and policies.
+  // Configures |builder|'s ProxyResolutionService based on prefs and policies.
   void SetUpProxyService(content::URLRequestContextBuilderMojo* builder) const;
 
   // Gets a pointer to the NetworkService. Can only be called on the UI thread.
diff --git a/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc b/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc
index 555d50f..db57611 100644
--- a/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc
+++ b/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc
@@ -13,7 +13,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/time/time.h"
-#include "chrome/browser/media/webrtc/webrtc_log_list.h"
+#include "components/webrtc_logging/browser/log_list.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
@@ -39,7 +39,7 @@
 base::FilePath GetLogDirectoryAndEnsureExists(
     content::BrowserContext* browser_context) {
   base::FilePath log_dir_path =
-      WebRtcLogList::GetWebRtcLogDirectoryForBrowserContextPath(
+      webrtc_logging::LogList::GetWebRtcLogDirectoryForBrowserContextPath(
           browser_context->GetPath());
   base::File::Error error;
   if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
diff --git a/chrome/browser/media/webrtc/webrtc_log_uploader.cc b/chrome/browser/media/webrtc/webrtc_log_uploader.cc
index 38c150b..d3bb681 100644
--- a/chrome/browser/media/webrtc/webrtc_log_uploader.cc
+++ b/chrome/browser/media/webrtc/webrtc_log_uploader.cc
@@ -18,10 +18,10 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/media/webrtc/webrtc_log_list.h"
-#include "chrome/browser/media/webrtc/webrtc_log_util.h"
-#include "chrome/common/partial_circular_buffer.h"
 #include "components/version_info/version_info.h"
+#include "components/webrtc_logging/browser/log_cleanup.h"
+#include "components/webrtc_logging/browser/log_list.h"
+#include "components/webrtc_logging/common/partial_circular_buffer.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/load_flags.h"
 #include "net/base/mime_util.h"
@@ -121,7 +121,7 @@
   std::string local_log_id;
 
   if (base::PathExists(upload_done_data.log_path)) {
-    WebRtcLogUtil::DeleteOldWebRtcLogFiles(upload_done_data.log_path);
+    webrtc_logging::DeleteOldWebRtcLogFiles(upload_done_data.log_path);
 
     local_log_id = base::NumberToString(base::Time::Now().ToDoubleT());
     base::FilePath log_file_path =
@@ -130,7 +130,7 @@
     WriteCompressedLogToFile(compressed_log, log_file_path);
 
     base::FilePath log_list_path =
-        WebRtcLogList::GetWebRtcLogListFileForDirectory(
+        webrtc_logging::LogList::GetWebRtcLogListFileForDirectory(
             upload_done_data.log_path);
     AddLocallyStoredLogInfoToUploadListFile(log_list_path, local_log_id);
   }
@@ -235,10 +235,11 @@
   DCHECK(log_buffer.get());
   DCHECK(!log_paths.log_path.empty());
 
-  WebRtcLogUtil::DeleteOldWebRtcLogFiles(log_paths.log_path);
+  webrtc_logging::DeleteOldWebRtcLogFiles(log_paths.log_path);
 
   base::FilePath log_list_path =
-      WebRtcLogList::GetWebRtcLogListFileForDirectory(log_paths.log_path);
+      webrtc_logging::LogList::GetWebRtcLogListFileForDirectory(
+          log_paths.log_path);
 
   // Store the native log with a ".gz" extension.
   std::string compressed_log;
@@ -306,7 +307,8 @@
         !it->second.log_path.empty()) {
       // TODO(jiayl): Add the RTP dump records to chrome://webrtc-logs.
       base::FilePath log_list_path =
-          WebRtcLogList::GetWebRtcLogListFileForDirectory(it->second.log_path);
+          webrtc_logging::LogList::GetWebRtcLogListFileForDirectory(
+              it->second.log_path);
       background_task_runner_->PostTask(
           FROM_HERE,
           base::BindOnce(&WebRtcLogUploader::AddUploadedLogInfoToUploadListFile,
@@ -395,7 +397,7 @@
   ResizeForNextOutput(compressed_log, &stream);
   uint32_t read = 0;
 
-  PartialCircularBuffer read_buffer(buffer->Read());
+  webrtc_logging::PartialCircularBuffer read_buffer(buffer->Read());
   do {
     if (stream.avail_in == 0) {
       read = read_buffer.Read(&intermediate_buffer[0],
diff --git a/chrome/browser/media/webrtc/webrtc_log_util.cc b/chrome/browser/media/webrtc/webrtc_log_util.cc
index debb4cc..850474fb 100644
--- a/chrome/browser/media/webrtc/webrtc_log_util.cc
+++ b/chrome/browser/media/webrtc/webrtc_log_util.cc
@@ -4,111 +4,18 @@
 
 #include "chrome/browser/media/webrtc/webrtc_log_util.h"
 
-#include <stddef.h>
-
-#include <string>
 #include <vector>
 
-#include "base/files/file_enumerator.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
 #include "base/task_scheduler/post_task.h"
-#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/media/webrtc/webrtc_log_list.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "components/webrtc_logging/browser/log_cleanup.h"
+#include "components/webrtc_logging/browser/log_list.h"
 #include "content/public/browser/browser_thread.h"
 
-namespace {
-
-const int kDaysToKeepLogs = 5;
-
-// Remove any empty entries from the log list. One line is one log entry, see
-// WebRtcLogUploader::AddLocallyStoredLogInfoToUploadListFile for more
-// information about the format.
-void RemoveEmptyEntriesInLogList(std::string* log_list) {
-  static const char kEmptyLine[] = ",,\n";
-  size_t pos = 0;
-  do {
-    pos = log_list->find(kEmptyLine, pos);
-    if (pos == std::string::npos)
-      break;
-    DCHECK(pos == 0 || (*log_list)[pos - 1] == '\n');
-    log_list->erase(pos, arraysize(kEmptyLine) - 1);
-  } while (true);
-}
-
-}  // namespace
-
-// static
-void WebRtcLogUtil::DeleteOldWebRtcLogFiles(const base::FilePath& log_dir) {
-  DeleteOldAndRecentWebRtcLogFiles(log_dir, base::Time::Max());
-}
-
-// static
-void WebRtcLogUtil::DeleteOldAndRecentWebRtcLogFiles(
-    const base::FilePath& log_dir,
-    const base::Time& delete_begin_time) {
-  base::AssertBlockingAllowed();
-
-  if (!base::PathExists(log_dir)) {
-    // This will happen if no logs have been stored or uploaded.
-    DVLOG(3) << "Could not find directory: " << log_dir.value();
-    return;
-  }
-
-  const base::Time now = base::Time::Now();
-  const base::TimeDelta time_to_keep_logs =
-      base::TimeDelta::FromDays(kDaysToKeepLogs);
-
-  base::FilePath log_list_path =
-      WebRtcLogList::GetWebRtcLogListFileForDirectory(log_dir);
-  std::string log_list;
-  const bool update_log_list = base::PathExists(log_list_path);
-  if (update_log_list) {
-    bool read_ok = base::ReadFileToString(log_list_path, &log_list);
-    DPCHECK(read_ok);
-  }
-
-  base::FileEnumerator log_files(log_dir, false, base::FileEnumerator::FILES);
-  bool delete_ok = true;
-  for (base::FilePath name = log_files.Next(); !name.empty();
-       name = log_files.Next()) {
-    if (name == log_list_path)
-      continue;
-    base::FileEnumerator::FileInfo file_info(log_files.GetInfo());
-    base::TimeDelta file_age = now - file_info.GetLastModifiedTime();
-    if (file_age > time_to_keep_logs ||
-        (!delete_begin_time.is_max() &&
-         file_info.GetLastModifiedTime() > delete_begin_time)) {
-      if (!base::DeleteFile(name, false))
-        delete_ok = false;
-
-      // Remove the local ID from the log list file. The ID is guaranteed to be
-      // unique.
-      std::string id = file_info.GetName().RemoveExtension().MaybeAsASCII();
-      size_t id_pos = log_list.find(id);
-      if (id_pos == std::string::npos)
-        continue;
-      log_list.erase(id_pos, id.size());
-    }
-  }
-
-  if (!delete_ok)
-    LOG(WARNING) << "Could not delete all old WebRTC logs.";
-
-  RemoveEmptyEntriesInLogList(&log_list);
-
-  if (update_log_list) {
-    int written = base::WriteFile(log_list_path, &log_list[0], log_list.size());
-    DPCHECK(written == static_cast<int>(log_list.size()));
-  }
-}
-
 // static
 void WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -120,8 +27,8 @@
     base::PostTaskWithTraits(
         FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
         base::BindOnce(
-            &DeleteOldWebRtcLogFiles,
-            WebRtcLogList::GetWebRtcLogDirectoryForBrowserContextPath(
+            &webrtc_logging::DeleteOldWebRtcLogFiles,
+            webrtc_logging::LogList::GetWebRtcLogDirectoryForBrowserContextPath(
                 entry->GetPath())));
   }
 }
diff --git a/chrome/browser/media/webrtc/webrtc_log_util.h b/chrome/browser/media/webrtc/webrtc_log_util.h
index 34a9f866..8f06b483 100644
--- a/chrome/browser/media/webrtc/webrtc_log_util.h
+++ b/chrome/browser/media/webrtc/webrtc_log_util.h
@@ -5,25 +5,10 @@
 #ifndef CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_LOG_UTIL_H_
 #define CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_LOG_UTIL_H_
 
-#include "base/files/file_path.h"
-#include "base/time/time.h"
-
 class WebRtcLogUtil {
  public:
-  // Deletes logs files older that 5 days. Updates the log file list. Must be
-  // called on the FILE thread.
-  static void DeleteOldWebRtcLogFiles(const base::FilePath& log_dir);
-
-  // Deletes logs files older that 5 days and logs younger than
-  // |delete_begin_time|. Updates the log file list. If |delete_begin_time| is
-  // base::time::Max(), no recent logs will be deleted, and the function is
-  // equal to DeleteOldWebRtcLogFiles(). Must be called on the FILE thread.
-  static void DeleteOldAndRecentWebRtcLogFiles(
-      const base::FilePath& log_dir,
-      const base::Time& delete_begin_time);
-
-  // Calls DeleteOldWebRtcLogFiles() for all profiles. Must be called on the UI
-  // thread.
+  // Calls webrtc_logging::DeleteOldWebRtcLogFiles() for all profiles. Must be
+  // called on the UI thread.
   static void DeleteOldWebRtcLogFilesForAllProfiles();
 };
 
diff --git a/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc b/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc
index 37e7b738..f28c05f 100644
--- a/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc
+++ b/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc
@@ -14,10 +14,10 @@
 #include "base/task_scheduler/post_task.h"
 #include "build/build_config.h"
 #include "chrome/browser/bad_message.h"
-#include "chrome/browser/media/webrtc/webrtc_log_list.h"
 #include "chrome/browser/media/webrtc/webrtc_log_uploader.h"
 #include "chrome/browser/media/webrtc/webrtc_rtp_dump_handler.h"
 #include "chrome/common/media/webrtc_logging_messages.h"
+#include "components/webrtc_logging/browser/log_list.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
@@ -402,7 +402,7 @@
 base::FilePath WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists() {
   DCHECK(log_uploader_->background_task_runner()->RunsTasksInCurrentSequence());
   base::FilePath log_dir_path =
-      WebRtcLogList::GetWebRtcLogDirectoryForBrowserContextPath(
+      webrtc_logging::LogList::GetWebRtcLogDirectoryForBrowserContextPath(
           browser_context_->GetPath());
   base::File::Error error;
   if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
diff --git a/chrome/browser/media/webrtc/webrtc_text_log_handler.cc b/chrome/browser/media/webrtc/webrtc_text_log_handler.cc
index 086306b..0e2129e 100644
--- a/chrome/browser/media/webrtc/webrtc_text_log_handler.cc
+++ b/chrome/browser/media/webrtc/webrtc_text_log_handler.cc
@@ -119,10 +119,10 @@
   circular_.Write(&eol, 1);
 }
 
-PartialCircularBuffer WebRtcLogBuffer::Read() {
+webrtc_logging::PartialCircularBuffer WebRtcLogBuffer::Read() {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(read_only_);
-  return PartialCircularBuffer(&buffer_[0], sizeof(buffer_));
+  return webrtc_logging::PartialCircularBuffer(&buffer_[0], sizeof(buffer_));
 }
 
 void WebRtcLogBuffer::SetComplete() {
diff --git a/chrome/browser/media/webrtc/webrtc_text_log_handler.h b/chrome/browser/media/webrtc/webrtc_text_log_handler.h
index 4f6c0cd..5e6b76fe 100644
--- a/chrome/browser/media/webrtc/webrtc_text_log_handler.h
+++ b/chrome/browser/media/webrtc/webrtc_text_log_handler.h
@@ -12,7 +12,7 @@
 #include "base/callback.h"
 #include "base/threading/thread_checker.h"
 #include "chrome/common/media/webrtc_logging_message_data.h"
-#include "chrome/common/partial_circular_buffer.h"
+#include "components/webrtc_logging/common/partial_circular_buffer.h"
 #include "net/base/network_interfaces.h"
 
 #if defined(OS_ANDROID)
@@ -36,7 +36,7 @@
   // Must only be called after the log has been marked as complete
   // (see SetComplete) and the caller must ensure that the WebRtcLogBuffer
   // instance remains in scope for the lifetime of the returned circular buffer.
-  PartialCircularBuffer Read();
+  webrtc_logging::PartialCircularBuffer Read();
 
   // Switches the buffer to read-only mode, where access to the internal
   // buffer is allowed from different threads than were used to contribute
@@ -48,7 +48,7 @@
  private:
   base::ThreadChecker thread_checker_;
   uint8_t buffer_[kWebRtcLogSize];
-  PartialCircularBuffer circular_;
+  webrtc_logging::PartialCircularBuffer circular_;
   bool read_only_;
 };
 
diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc
index 995b3438..3d44b80 100644
--- a/chrome/browser/net/predictor.cc
+++ b/chrome/browser/net/predictor.cc
@@ -153,7 +153,7 @@
           TimeDelta::FromMilliseconds(g_max_queueing_delay_ms)),
       transport_security_state_(nullptr),
       ssl_config_service_(nullptr),
-      proxy_service_(nullptr),
+      proxy_resolution_service_(nullptr),
       consecutive_omnibox_preconnect_count_(0),
       referrers_(kMaxReferrers),
       observer_(nullptr),
@@ -651,7 +651,7 @@
       url_request_context_getter_->GetURLRequestContext();
   transport_security_state_ = context->transport_security_state();
   ssl_config_service_ = context->ssl_config_service();
-  proxy_service_ = context->proxy_service();
+  proxy_resolution_service_ = context->proxy_resolution_service();
 
   // base::WeakPtrFactory instances need to be created and destroyed
   // on the same thread. Initialize the IO thread weak factory now.
@@ -978,11 +978,11 @@
 }
 
 bool Predictor::WouldLikelyProxyURL(const GURL& url) {
-  if (!proxy_service_)
+  if (!proxy_resolution_service_)
     return false;
 
   net::ProxyInfo info;
-  bool synchronous_success = proxy_service_->TryResolveProxySynchronously(
+  bool synchronous_success = proxy_resolution_service_->TryResolveProxySynchronously(
       url, std::string(), &info, nullptr, net::NetLogWithSource());
 
   return synchronous_success && !info.is_direct();
diff --git a/chrome/browser/net/predictor.h b/chrome/browser/net/predictor.h
index f68d0ec1..8d082def 100644
--- a/chrome/browser/net/predictor.h
+++ b/chrome/browser/net/predictor.h
@@ -52,7 +52,7 @@
 namespace net {
 class HostResolver;
 class SSLConfigService;
-class ProxyService;
+class ProxyResolutionService;
 class TransportSecurityState;
 class URLRequestContextGetter;
 }
@@ -468,8 +468,8 @@
   // redirects).
   net::SSLConfigService* ssl_config_service_;
 
-  // The ProxyService, used to determine whether preresolve is useful.
-  net::ProxyService* proxy_service_;
+  // The ProxyResolutionService, used to determine whether preresolve is useful.
+  net::ProxyResolutionService* proxy_resolution_service_;
 
   // Most recent suggestion from Omnibox provided via AnticipateOmniboxUrl().
   std::string last_omnibox_host_;
diff --git a/chrome/browser/net/predictor_unittest.cc b/chrome/browser/net/predictor_unittest.cc
index fb4f014..fed16f3 100644
--- a/chrome/browser/net/predictor_unittest.cc
+++ b/chrome/browser/net/predictor_unittest.cc
@@ -510,9 +510,9 @@
 
   net::ProxyConfig config;
   config.proxy_rules().ParseFromString("http=socks://localhost:12345");
-  std::unique_ptr<net::ProxyService> proxy_service(
-      net::ProxyService::CreateFixed(config));
-  testing_master.proxy_service_ = proxy_service.get();
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+      net::ProxyResolutionService::CreateFixed(config));
+  testing_master.proxy_resolution_service_ = proxy_resolution_service.get();
 
   GURL goog("http://www.google.com:80");
   testing_master.Resolve(goog, UrlInfo::OMNIBOX_MOTIVATED);
@@ -529,9 +529,9 @@
 
   Predictor testing_master(true);
   net::ProxyConfig config = net::ProxyConfig::CreateDirect();
-  std::unique_ptr<net::ProxyService> proxy_service(
-      net::ProxyService::CreateFixed(config));
-  testing_master.proxy_service_ = proxy_service.get();
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+      net::ProxyResolutionService::CreateFixed(config));
+  testing_master.proxy_resolution_service_ = proxy_resolution_service.get();
 
   GURL goog("http://www.google.com:80");
   testing_master.Resolve(goog, UrlInfo::OMNIBOX_MOTIVATED);
@@ -549,9 +549,9 @@
   Predictor testing_master(true);
   net::ProxyConfig config = net::ProxyConfig::CreateFromCustomPacURL(GURL(
       "http://foopy/proxy.pac"));
-  std::unique_ptr<net::ProxyService> proxy_service(
-      net::ProxyService::CreateFixed(config));
-  testing_master.proxy_service_ = proxy_service.get();
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+      net::ProxyResolutionService::CreateFixed(config));
+  testing_master.proxy_resolution_service_ = proxy_resolution_service.get();
 
   GURL goog("http://www.google.com:80");
   testing_master.Resolve(goog, UrlInfo::OMNIBOX_MOTIVATED);
diff --git a/chrome/browser/net/proxy_service_factory.cc b/chrome/browser/net/proxy_service_factory.cc
index 705df94..22ce598 100644
--- a/chrome/browser/net/proxy_service_factory.cc
+++ b/chrome/browser/net/proxy_service_factory.cc
@@ -34,7 +34,7 @@
   // configuration in case nothing is configured through prefs (Note: prefs
   // include command line and configuration policy).
 
-  base_service = net::ProxyService::CreateSystemProxyConfigService(
+  base_service = net::ProxyResolutionService::CreateSystemProxyConfigService(
       BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
 #endif  // !defined(OS_CHROMEOS)
 
diff --git a/chrome/browser/notifications/notification_display_service_tester.h b/chrome/browser/notifications/notification_display_service_tester.h
index fe20e7e3..63dde03 100644
--- a/chrome/browser/notifications/notification_display_service_tester.h
+++ b/chrome/browser/notifications/notification_display_service_tester.h
@@ -21,8 +21,7 @@
 }
 
 // Helper class that enables use of the NotificationDisplayService in tests. The
-// Profile* passed when constructing an instance must outlive this class, as
-// the service (or internals of the service) may be overridden.
+// Profile* passed when constructing an instance may outlive this class.
 //
 // This class must only be used for testing purposes. Unlike most production
 // NotificationDisplayService implementations, all operations on this tester are
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index 997286a..29b0b657 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -63,6 +63,7 @@
 #include "content/public/common/referrer.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/download_test_observer.h"
+#include "content/public/test/navigation_handle_observer.h"
 #include "net/base/net_errors.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/http/failing_http_transaction_factory.h"
@@ -80,19 +81,6 @@
 
 namespace {
 
-void FailAllNetworkTransactions(net::URLRequestContextGetter* getter) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  net::HttpCache* cache(
-      getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
-  DCHECK(cache);
-  std::unique_ptr<net::FailingHttpTransactionFactory> factory =
-      std::make_unique<net::FailingHttpTransactionFactory>(cache->GetSession(),
-                                                           net::ERR_FAILED);
-  // Throw away old version; since this is a browser test, there is no
-  // need to restore the old state.
-  cache->SetHttpNetworkTransactionFactoryForTesting(std::move(factory));
-}
-
 // Waits until specified timing and metadata expectations are satisfied.
 class PageLoadMetricsWaiter
     : public page_load_metrics::MetricsWebContentsObserver::TestingObserver {
@@ -671,18 +659,13 @@
 
 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, ChromeErrorPage) {
   ASSERT_TRUE(embedded_test_server()->Start());
-
-  // Configure the network stack to fail all attempted loads with a network
-  // error, which will cause Chrome to display an error page.
-  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
-      browser()->profile()->GetRequestContext();
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO, FROM_HERE,
-      base::BindOnce(&FailAllNetworkTransactions,
-                     base::RetainedRef(url_request_context_getter)));
-
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title1.html"));
+  GURL url = embedded_test_server()->GetURL("/title1.html");
+  // By shutting down the server, we ensure a failure.
+  ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+  content::NavigationHandleObserver observer(
+      browser()->tab_strip_model()->GetActiveWebContents(), url);
+  ui_test_utils::NavigateToURL(browser(), url);
+  ASSERT_TRUE(observer.is_error());
   NavigateToUntrackedUrl();
   EXPECT_TRUE(NoPageLoadMetricsRecorded())
       << "Recorded metrics: " << GetRecordedPageLoadMetricNames();
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index 59761b2..3c8f57d 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -346,7 +346,7 @@
 
   auto* client = PrintCompositeClient::FromWebContents(web_contents());
   if (IsOopifEnabled() && !client->for_preview() &&
-      !document->settings().is_modifiable()) {
+      document->settings().is_modifiable()) {
     client->DoComposite(params.metafile_data_handle, params.data_size,
                         base::BindOnce(&PrintViewManagerBase::OnComposePdfDone,
                                        weak_ptr_factory_.GetWeakPtr(), params));
diff --git a/chrome/browser/resources/app_list/OWNERS b/chrome/browser/resources/app_list/OWNERS
deleted file mode 100644
index ed54f09..0000000
--- a/chrome/browser/resources/app_list/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-calamity@chromium.org
-khmel@chromium.org
diff --git a/chrome/browser/resources/app_list/start_page.css b/chrome/browser/resources/app_list/start_page.css
deleted file mode 100644
index 3efaef19..0000000
--- a/chrome/browser/resources/app_list/start_page.css
+++ /dev/null
@@ -1,32 +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. */
-
-html,
-body {
-  height: 100%;
-  margin: 0;
-  overflow: hidden;
-  padding: 0;
-  user-select: none;
-  width: 100%;
-}
-
-#doodle {
-  display: none;
-  justify-content: center;
-}
-
-#default_logo {
-  background-image: url(../../../../ui/webui/resources/images/google_logo.svg);
-  background-repeat: no-repeat;
-  height: 92px;
-  margin: auto;
-  width: 272px;
-}
-
-#logo_container {
-  bottom: 0;
-  position: absolute;
-  width: 100%;
-}
diff --git a/chrome/browser/resources/app_list/start_page.html b/chrome/browser/resources/app_list/start_page.html
deleted file mode 100644
index 5388e65d..0000000
--- a/chrome/browser/resources/app_list/start_page.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!doctype html>
-<html i18n-values="dir:textdirection;lang:language">
-<head>
-  <meta charset="utf-8">
-  <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
-  <link rel="stylesheet" href="chrome://app-list/start_page.css">
-  <script src="chrome://resources/js/load_time_data.js"></script>
-  <script src="chrome://resources/js/cr.js"></script>
-  <script src="chrome://resources/js/cr/event_target.js"></script>
-  <script src="chrome://resources/js/cr/ui.js"></script>
-  <script src="chrome://resources/js/util.js"></script>
-  <script src="chrome://app-list/strings.js"></script>
-  <script src="chrome://app-list/start_page.js"></script>
-  <base id="base">
-</head>
-
-<body>
-  <div id="logo_container">
-    <div id="default_logo"></div>
-  </div>
-  <script src="chrome://resources/js/i18n_template.js"></script>
-</body>
-</html>
diff --git a/chrome/browser/resources/app_list/start_page.js b/chrome/browser/resources/app_list/start_page.js
deleted file mode 100644
index 2a01e13..0000000
--- a/chrome/browser/resources/app_list/start_page.js
+++ /dev/null
@@ -1,120 +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.
-
-/**
- * @fileoverview App launcher start page implementation.
- */
-
-/**
- * The maximum height of the Google Doodle. Note this value should be consistent
- * with kWebViewHeight in start_page_view.cc.
- */
-var doodleMaxHeight = 224;
-
-cr.define('appList.startPage', function() {
-  'use strict';
-
-  // The element containing the current Google Doodle.
-  var doodle = null;
-
-  /**
-   * Initialize the page.
-   */
-  function initialize() {
-    chrome.send('initialize');
-  }
-
-  /**
-   * Invoked when the app-list bubble is shown.
-   */
-  function onAppListShown() {
-    chrome.send('appListShown', [this.doodle != null]);
-  }
-
-  /**
-   * Sets the doodle's visibility, hiding or showing the default logo.
-   *
-   * @param {boolean} visible Whether the doodle should be made visible.
-   */
-  function setDoodleVisible(visible) {
-    var doodle = $('doodle');
-    var defaultLogo = $('default_logo');
-    if (visible) {
-      doodle.style.display = 'flex';
-      defaultLogo.style.display = 'none';
-    } else {
-      if (doodle)
-        doodle.style.display = 'none';
-
-      defaultLogo.style.display = 'block';
-    }
-  }
-
-  /**
-   * Invoked when the app-list doodle is updated.
-   *
-   * @param {Object} data The data object representing the current doodle.
-   */
-  function onAppListDoodleUpdated(data, base_url) {
-    if (this.doodle) {
-      this.doodle.parentNode.removeChild(this.doodle);
-      this.doodle = null;
-    }
-
-    var doodleData = data.ddljson;
-    if (!doodleData || !doodleData.transparent_large_image) {
-      setDoodleVisible(false);
-      return;
-    }
-
-    // Set the page's base URL so that links will resolve relative to the Google
-    // homepage.
-    $('base').href = base_url;
-
-    this.doodle = document.createElement('div');
-    this.doodle.id = 'doodle';
-    this.doodle.style.display = 'none';
-
-    var doodleImage = document.createElement('img');
-    doodleImage.id = 'doodle_image';
-    if (doodleData.transparent_large_image.height > doodleMaxHeight)
-      doodleImage.setAttribute('height', doodleMaxHeight);
-    if (doodleData.alt_text) {
-      doodleImage.alt = doodleData.alt_text;
-      doodleImage.title = doodleData.alt_text;
-    }
-
-    doodleImage.onload = function() {
-      setDoodleVisible(true);
-    };
-    doodleImage.src = doodleData.transparent_large_image.url;
-
-    if (doodleData.target_url) {
-      var doodleLink = document.createElement('a');
-      doodleLink.id = 'doodle_link';
-      doodleLink.href = doodleData.target_url;
-      doodleLink.target = '_blank';
-      doodleLink.appendChild(doodleImage);
-      doodleLink.onclick = function() {
-        chrome.send('doodleClicked');
-        return true;
-      };
-      this.doodle.appendChild(doodleLink);
-    } else {
-      this.doodle.appendChild(doodleImage);
-    }
-    $('logo_container').appendChild(this.doodle);
-  }
-
-  return {
-    initialize: initialize,
-    onAppListDoodleUpdated: onAppListDoodleUpdated,
-    onAppListShown: onAppListShown,
-  };
-});
-
-document.addEventListener('contextmenu', function(e) {
-  e.preventDefault();
-});
-document.addEventListener('DOMContentLoaded', appList.startPage.initialize);
diff --git a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js
index 0cbb5e9..5a961999 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js
+++ b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js
@@ -611,17 +611,31 @@
     let focusOffset = focusedNode.root.focusOffset || 0;
     if (anchorObject === focusObject && anchorOffset == focusOffset)
       return;
+    let anchorPosition =
+        getDeepEquivalentForSelection(anchorObject, anchorOffset);
+    let focusPosition = getDeepEquivalentForSelection(focusObject, focusOffset);
     let firstPosition;
     let lastPosition;
-    let dir = AutomationUtil.getDirection(anchorObject, focusObject);
-    // Highlighting may be forwards or backwards. Make sure we start at the
-    // first node.
-    if (dir == constants.Dir.FORWARD) {
-      firstPosition = getDeepEquivalentForSelection(anchorObject, anchorOffset);
-      lastPosition = getDeepEquivalentForSelection(focusObject, focusOffset);
+    if (anchorPosition.node === focusPosition.node) {
+      if (anchorPosition.offset < focusPosition.offset) {
+        firstPosition = anchorPosition;
+        lastPosition = focusPosition;
+      } else {
+        lastPosition = anchorPosition;
+        firstPosition = focusPosition;
+      }
     } else {
-      lastPosition = getDeepEquivalentForSelection(anchorObject, anchorOffset);
-      firstPosition = getDeepEquivalentForSelection(focusObject, focusOffset);
+      let dir =
+          AutomationUtil.getDirection(anchorPosition.node, focusPosition.node);
+      // Highlighting may be forwards or backwards. Make sure we start at the
+      // first node.
+      if (dir == constants.Dir.FORWARD) {
+        firstPosition = anchorPosition;
+        lastPosition = focusPosition;
+      } else {
+        lastPosition = anchorPosition;
+        firstPosition = focusPosition;
+      }
     }
 
     // Adjust such that non-text types don't have offsets into their names.
@@ -630,7 +644,7 @@
       firstPosition.offset = 0;
     }
     if (lastPosition.node.role != 'staticText' &&
-        lastPosition.node.role != 'inlineTextBox') {
+        lastPosition.node.role != 'inlineTextBox' && lastPosition.node.name) {
       lastPosition.offset = lastPosition.node.name.length;
     }
 
diff --git a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak_keystroke_selection_test.extjs b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak_keystroke_selection_test.extjs
index b9706c7..2c648f7 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak_keystroke_selection_test.extjs
+++ b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak_keystroke_selection_test.extjs
@@ -161,3 +161,36 @@
         });
       }, 'This is some bold text');
 });
+
+TEST_F('SelectToSpeakKeystrokeSelectionTest',
+    'SpeakTextSurroundedByBrs', function() {
+  // If you load this html and double-click on "Selected text", this is the
+  // document selection that occurs -- into the second <br/> element.
+
+  let setFocusCallback = function(desktop) {
+    let firstNode = this.findTextNode(desktop, 'Selected text');
+    let lastNode = desktop.findAll({role: 'lineBreak'})[1];
+    chrome.automation.setDocumentSelection({
+        anchorObject: firstNode, anchorOffset: 0,
+        focusObject: lastNode, focusOffset: 1
+    });
+  };
+  setFocusCallback = this.newCallback(setFocusCallback);
+  this.runWithLoadedTree('data:text/html;charset=utf-8,<br/><p>Selected text</p></br>',
+    function(desktop) {
+      // Add an event listener that will start the user interaction
+      // of the test once the selection is completed.
+      desktop.addEventListener('documentSelectionChanged',
+        this.newCallback(function(event) {
+          this.triggerReadSelectedText();
+          assertTrue(this.mockTts.currentlySpeaking());
+          this.assertEqualsCollapseWhitespace(
+              this.mockTts.pendingUtterances()[0], 'Selected text');
+          if (this.mockTts.pendingUtterances().length == 2) {
+            this.assertEqualsCollapseWhitespace(
+                this.mockTts.pendingUtterances()[1], '');
+          }
+      }), false);
+      setFocusCallback(desktop);
+  });
+});
\ No newline at end of file
diff --git a/chrome/browser/resources/plugin_metadata/plugins_linux.json b/chrome/browser/resources/plugin_metadata/plugins_linux.json
index 99b6cf67..e9af78d3 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_linux.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_linux.json
@@ -1,5 +1,5 @@
 {
-  "x-version": 26,
+  "x-version": 27,
   "google-talk": {
     "mime_types": [
     ],
@@ -80,9 +80,9 @@
     ],
     "versions": [
       {
-        "version": "27.0.0.187",
+        "version": "28.0.0.137",
         "status": "up_to_date",
-        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-33.html"
+        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb18-01.html"
       }
     ],
     "lang": "en-US",
diff --git a/chrome/browser/resources/plugin_metadata/plugins_mac.json b/chrome/browser/resources/plugin_metadata/plugins_mac.json
index a853428..6192e09 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_mac.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_mac.json
@@ -1,5 +1,5 @@
 {
-  "x-version": 32,
+  "x-version": 33,
   "google-talk": {
     "mime_types": [
     ],
@@ -115,9 +115,9 @@
     ],
     "versions": [
       {
-        "version": "27.0.0.187",
+        "version": "28.0.0.137",
         "status": "requires_authorization",
-        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-33.html"
+        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb18-01.html"
       }
     ],
     "lang": "en-US",
diff --git a/chrome/browser/resources/plugin_metadata/plugins_win.json b/chrome/browser/resources/plugin_metadata/plugins_win.json
index c5b325b..9b5418e3 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_win.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_win.json
@@ -1,5 +1,5 @@
 {
-  "x-version": 41,
+  "x-version": 42,
   "google-talk": {
     "mime_types": [
     ],
@@ -137,9 +137,9 @@
     ],
     "versions": [
       {
-        "version": "27.0.0.187",
+        "version": "28.0.0.137",
         "status": "requires_authorization",
-        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-33.html"
+        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb18-01.html"
       }
     ],
     "lang": "en-US",
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index 28ceeee..9cda2cf 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -138,8 +138,7 @@
               IDS_TOOLTIP_MIC_SEARCH);
     AddString(translated_strings.get(), "languageError",
               IDS_NEW_TAB_VOICE_LANGUAGE_ERROR);
-    AddString(translated_strings.get(), "learnMore",
-              IDS_NEW_TAB_VOICE_LEARN_MORE);
+    AddString(translated_strings.get(), "learnMore", IDS_LEARN_MORE);
     AddString(translated_strings.get(), "listening",
               IDS_NEW_TAB_VOICE_LISTENING);
     AddString(translated_strings.get(), "networkError",
diff --git a/chrome/browser/signin/signin_error_notifier_ash_unittest.cc b/chrome/browser/signin/signin_error_notifier_ash_unittest.cc
index f1db424..437c79d 100644
--- a/chrome/browser/signin/signin_error_notifier_ash_unittest.cc
+++ b/chrome/browser/signin/signin_error_notifier_ash_unittest.cc
@@ -13,7 +13,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
-#include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/browser/signin/fake_signin_manager_builder.h"
 #include "chrome/browser/signin/signin_error_controller_factory.h"
 #include "chrome/browser/signin/signin_error_notifier_factory_ash.h"
@@ -50,7 +50,8 @@
     error_controller_ =
         SigninErrorControllerFactory::GetForProfile(GetProfile());
     SigninErrorNotifierFactory::GetForProfile(GetProfile());
-    notification_ui_manager_ = g_browser_process->notification_ui_manager();
+    display_service_ =
+        std::make_unique<NotificationDisplayServiceTester>(profile());
   }
 
   TestingProfile::TestingFactories GetTestingFactories() override {
@@ -58,54 +59,39 @@
   }
 
  protected:
-  void GetMessage(base::string16* message) {
-    const message_center::Notification* notification =
-        g_browser_process->notification_ui_manager()->FindById(
-            kNotificationId, NotificationUIManager::GetProfileID(GetProfile()));
-    ASSERT_FALSE(notification == NULL);
-    *message = notification->message();
-  }
-
   SigninErrorController* error_controller_;
-  NotificationUIManager* notification_ui_manager_;
+  std::unique_ptr<NotificationDisplayServiceTester> display_service_;
   chromeos::MockUserManager* mock_user_manager_;  // Not owned.
   std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
 };
 
 TEST_F(SigninErrorNotifierTest, NoErrorAuthStatusProviders) {
-  ASSERT_FALSE(notification_ui_manager_->FindById(
-      kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
+  EXPECT_FALSE(display_service_->GetNotification(kNotificationId));
   {
     // Add a provider (removes itself on exiting this scope).
     FakeAuthStatusProvider provider(error_controller_);
-    ASSERT_FALSE(notification_ui_manager_->FindById(
-        kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
+    EXPECT_FALSE(display_service_->GetNotification(kNotificationId));
   }
-  ASSERT_FALSE(notification_ui_manager_->FindById(
-      kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
+  EXPECT_FALSE(display_service_->GetNotification(kNotificationId));
 }
 
 TEST_F(SigninErrorNotifierTest, ErrorAuthStatusProvider) {
   {
     FakeAuthStatusProvider provider(error_controller_);
-    ASSERT_FALSE(notification_ui_manager_->FindById(
-        kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
+    EXPECT_FALSE(display_service_->GetNotification(kNotificationId));
     {
       FakeAuthStatusProvider error_provider(error_controller_);
       error_provider.SetAuthError(
           kTestAccountId,
           GoogleServiceAuthError(
               GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-      ASSERT_TRUE(notification_ui_manager_->FindById(
-          kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
+      EXPECT_TRUE(display_service_->GetNotification(kNotificationId));
     }
     // error_provider is removed now that we've left that scope.
-    ASSERT_FALSE(notification_ui_manager_->FindById(
-        kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
+    EXPECT_FALSE(display_service_->GetNotification(kNotificationId));
   }
   // All providers should be removed now.
-  ASSERT_FALSE(notification_ui_manager_->FindById(
-      kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
+  EXPECT_FALSE(display_service_->GetNotification(kNotificationId));
 }
 
 TEST_F(SigninErrorNotifierTest, AuthStatusProviderErrorTransition) {
@@ -116,12 +102,12 @@
         kTestAccountId,
         GoogleServiceAuthError(
             GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-    ASSERT_TRUE(notification_ui_manager_->FindById(
-        kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
 
-    base::string16 message;
-    GetMessage(&message);
-    ASSERT_FALSE(message.empty());
+    base::Optional<message_center::Notification> notification =
+        display_service_->GetNotification(kNotificationId);
+    ASSERT_TRUE(notification);
+    base::string16 message = notification->message();
+    EXPECT_FALSE(message.empty());
 
     // Now set another auth error and clear the original.
     provider1.SetAuthError(
@@ -132,19 +118,16 @@
         kTestAccountId,
         GoogleServiceAuthError::AuthErrorNone());
 
-    ASSERT_TRUE(notification_ui_manager_->FindById(
-        kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
-
-    base::string16 new_message;
-    GetMessage(&new_message);
-    ASSERT_FALSE(new_message.empty());
+    notification = display_service_->GetNotification(kNotificationId);
+    ASSERT_TRUE(notification);
+    base::string16 new_message = notification->message();
+    EXPECT_FALSE(new_message.empty());
 
     ASSERT_NE(new_message, message);
 
     provider1.SetAuthError(
         kTestAccountId, GoogleServiceAuthError::AuthErrorNone());
-    ASSERT_FALSE(notification_ui_manager_->FindById(
-        kNotificationId, NotificationUIManager::GetProfileID(GetProfile())));
+    EXPECT_FALSE(display_service_->GetNotification(kNotificationId));
   }
 }
 
@@ -180,10 +163,9 @@
     FakeAuthStatusProvider provider(error_controller_);
     provider.SetAuthError(kTestAccountId,
                           GoogleServiceAuthError(table[i].error_state));
-    const message_center::Notification* notification =
-        notification_ui_manager_->FindById(
-            kNotificationId, NotificationUIManager::GetProfileID(GetProfile()));
-    ASSERT_EQ(table[i].is_error, notification != NULL);
+    base::Optional<message_center::Notification> notification =
+        display_service_->GetNotification(kNotificationId);
+    ASSERT_EQ(table[i].is_error, !!notification);
     if (table[i].is_error) {
       EXPECT_FALSE(notification->title().empty());
       EXPECT_FALSE(notification->message().empty());
diff --git a/chrome/browser/sync/sync_error_notifier_ash_unittest.cc b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
index 1dc61b5..54c9ea5 100644
--- a/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
+++ b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
@@ -10,7 +10,7 @@
 
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
-#include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
@@ -80,7 +80,8 @@
     error_notifier_ =
         std::make_unique<SyncErrorNotifier>(error_controller_.get(), profile());
 
-    notification_ui_manager_ = g_browser_process->notification_ui_manager();
+    display_service_ =
+        std::make_unique<NotificationDisplayServiceTester>(profile());
   }
 
   void TearDown() override {
@@ -107,13 +108,12 @@
     error_controller_->OnStateChanged(service_.get());
     EXPECT_EQ(is_error, error_controller_->HasError());
 
-    const message_center::Notification* notification =
-        notification_ui_manager_->FindById(
-            kNotificationId, NotificationUIManager::GetProfileID(profile()));
+    base::Optional<message_center::Notification> notification =
+        display_service_->GetNotification(kNotificationId);
     if (expected_notification) {
       ASSERT_TRUE(notification);
-      ASSERT_FALSE(notification->title().empty());
-      ASSERT_FALSE(notification->message().empty());
+      EXPECT_FALSE(notification->title().empty());
+      EXPECT_FALSE(notification->message().empty());
     } else {
       ASSERT_FALSE(notification);
     }
@@ -123,7 +123,7 @@
   std::unique_ptr<SyncErrorNotifier> error_notifier_;
   std::unique_ptr<browser_sync::ProfileSyncServiceMock> service_;
   FakeLoginUI login_ui_;
-  NotificationUIManager* notification_ui_manager_;
+  std::unique_ptr<NotificationDisplayServiceTester> display_service_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SyncErrorNotifierTest);
@@ -134,8 +134,7 @@
 TEST_F(SyncErrorNotifierTest, PassphraseNotification) {
   user_manager::ScopedUserManager scoped_enabler(
       std::make_unique<chromeos::MockUserManager>());
-  ASSERT_FALSE(notification_ui_manager_->FindById(
-      kNotificationId, NotificationUIManager::GetProfileID(profile())));
+  ASSERT_FALSE(display_service_->GetNotification(kNotificationId));
 
   syncer::SyncEngine::Status status;
   EXPECT_CALL(*service_, QueryDetailedSyncStatus(_))
@@ -152,9 +151,9 @@
                                   true /* expecting notification */);
   }
 
-  // Sumulate discarded notification and check that notification is not shown.
-  notification_ui_manager_->CancelById(
-      kNotificationId, NotificationUIManager::GetProfileID(profile()));
+  // Simulate discarded notification and check that notification is not shown.
+  display_service_->RemoveNotification(NotificationHandler::Type::TRANSIENT,
+                                       kNotificationId, true /* by_user */);
   {
     SCOPED_TRACE("Not expecting notification, one was already discarded");
     VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE,
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index 6ecba2c..276665f 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -750,14 +750,7 @@
 }
 
 // Checks that task manager counts idle wakeups.
-// Flakily fails on Mac: http://crbug.com/639939
-#if defined(OS_MACOSX)
-#define MAYBE_IdleWakeups DISABLED_IdleWakeups
-#else
-#define MAYBE_IdleWakeups IdleWakeups
-#endif  // defined(OS_MACOSX)
-IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,
-                       MAYBE_IdleWakeups) {
+IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, IdleWakeups) {
   ShowTaskManager();
   model()->ToggleColumnVisibility(ColumnSpecifier::IDLE_WAKEUPS);
 
@@ -775,10 +768,17 @@
       browser()->tab_strip_model()->GetActiveWebContents(), test_js, &ok));
   ASSERT_EQ("okay", ok);
 
-  // The script above should trigger a lot of idle wakeups - up to 1000 per
-  // second. Let's make sure we get at least 100 (in case the test runs slow).
+// The script above should trigger a lot of idle wakeups - up to 1000 per
+// second. Let's make sure we get at least 100 (in case the test runs slow).
+// On Mac, set a lower threshold because Chrome Mac generates fewer wakes.
+#if defined(OS_MACOSX)
+  const int kMinExpectedWakeCount = 50;
+#else
+  const int kMinExpectedWakeCount = 100;
+#endif  // defined(OS_MACOSX)
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerStatToExceed(
-      MatchTab("title1.html"), ColumnSpecifier::IDLE_WAKEUPS, 100));
+      MatchTab("title1.html"), ColumnSpecifier::IDLE_WAKEUPS,
+      kMinExpectedWakeCount));
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchTab("title1.html")));
 }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 458fcea949..1621bcd 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3420,14 +3420,6 @@
       "app_list/search/webstore/webstore_provider.h",
       "app_list/search/webstore/webstore_result.cc",
       "app_list/search/webstore/webstore_result.h",
-      "app_list/start_page_service.cc",
-      "app_list/start_page_service.h",
-      "app_list/start_page_service_factory.cc",
-      "app_list/start_page_service_factory.h",
-      "webui/app_list/start_page_handler.cc",
-      "webui/app_list/start_page_handler.h",
-      "webui/app_list/start_page_ui.cc",
-      "webui/app_list/start_page_ui.h",
     ]
     deps += [
       "//ui/app_list",
@@ -3679,6 +3671,7 @@
       "webui/media/webrtc_logs_ui.cc",
       "webui/media/webrtc_logs_ui.h",
     ]
+    deps += [ "//components/webrtc_logging/browser" ]
   }
 
   if (safe_browsing_mode == 1) {
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc
index 1b4b36e..946f7b05 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -20,7 +20,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
@@ -28,7 +27,6 @@
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 #include "chrome/browser/ui/app_list/search/search_controller_factory.h"
 #include "chrome/browser/ui/app_list/search/search_resource_manager.h"
-#include "chrome/browser/ui/app_list/start_page_service.h"
 #include "chrome/browser/ui/apps/chrome_app_delegate.h"
 #include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h"
 #include "chrome/browser/ui/chrome_pages.h"
@@ -91,7 +89,6 @@
       model_(nullptr),
       search_model_(nullptr),
       model_updater_(nullptr),
-      template_url_service_observer_(this),
       observer_binding_(this),
       weak_ptr_factory_(this) {
   CHECK(controller_);
@@ -134,8 +131,6 @@
     model_updater_ = nullptr;
   }
 
-  template_url_service_observer_.RemoveAll();
-
   profile_ = new_profile;
   if (!profile_)
     return;
@@ -147,10 +142,6 @@
   DCHECK(!profile_->IsGuestSession() || profile_->IsOffTheRecord())
       << "Guest mode must use incognito profile";
 
-  TemplateURLService* template_url_service =
-      TemplateURLServiceFactory::GetForProfile(profile_);
-  template_url_service_observer_.Add(template_url_service);
-
   app_list::AppListSyncableService* syncable_service =
       app_list::AppListSyncableServiceFactory::GetForProfile(profile_);
   model_ = syncable_service->GetModel();
@@ -167,7 +158,6 @@
       std::make_unique<AppSyncUIStateWatcher>(profile_, model_updater_);
 
   SetUpSearchUI();
-  OnTemplateURLServiceChanged();
 
   // Clear search query.
   model_updater_->UpdateSearchBox(base::string16(),
@@ -233,14 +223,6 @@
   search_controller_->InvokeResultAction(result, action_index, event_flags);
 }
 
-void AppListViewDelegate::ViewInitialized() {
-  app_list::StartPageService* service =
-      app_list::StartPageService::Get(profile_);
-  if (service) {
-    service->AppListShown();
-  }
-}
-
 void AppListViewDelegate::ViewShown() {
   base::RecordAction(base::UserMetricsAction("Launcher_Show"));
   base::UmaHistogramSparse("Apps.AppListBadgedAppsCount",
@@ -253,36 +235,6 @@
 
 void AppListViewDelegate::ViewClosing() {
   controller_->ViewClosing();
-
-  if (!profile_)
-    return;
-
-  app_list::StartPageService* service =
-      app_list::StartPageService::Get(profile_);
-  if (service)
-    service->AppListHidden();
-}
-
-views::View* AppListViewDelegate::CreateStartPageWebView(
-    const gfx::Size& size) {
-  app_list::StartPageService* service =
-      app_list::StartPageService::Get(profile_);
-  if (!service)
-    return NULL;
-
-  service->LoadContentsIfNeeded();
-
-  content::WebContents* web_contents = service->GetStartPageContents();
-  if (!web_contents)
-    return NULL;
-
-  DCHECK_EQ(profile_, web_contents->GetBrowserContext());
-  views::WebView* web_view =
-      new views::WebView(web_contents->GetBrowserContext());
-  web_view->SetPreferredSize(size);
-  web_view->SetResizeBackgroundColor(SK_ColorTRANSPARENT);
-  web_view->SetWebContents(web_contents);
-  return web_view;
 }
 
 void AppListViewDelegate::GetWallpaperProminentColors(
@@ -308,23 +260,6 @@
   observers_.RemoveObserver(observer);
 }
 
-void AppListViewDelegate::OnTemplateURLServiceChanged() {
-  TemplateURLService* template_url_service =
-      TemplateURLServiceFactory::GetForProfile(profile_);
-  const TemplateURL* default_provider =
-      template_url_service->GetDefaultSearchProvider();
-  const bool is_google =
-      default_provider->GetEngineType(
-          template_url_service->search_terms_data()) == SEARCH_ENGINE_GOOGLE;
-
-  model_updater_->SetSearchEngineIsGoogle(is_google);
-
-  app_list::StartPageService* start_page_service =
-      app_list::StartPageService::Get(profile_);
-  if (start_page_service)
-    start_page_service->set_search_engine_is_google(is_google);
-}
-
 void AppListViewDelegate::Observe(int type,
                                   const content::NotificationSource& source,
                                   const content::NotificationDetails& details) {
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h
index 72f4871..166f5c6 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.h
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -18,8 +18,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_model_updater.h"
-#include "components/search_engines/template_url_service.h"
-#include "components/search_engines/template_url_service_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
@@ -43,8 +41,7 @@
 
 class AppListViewDelegate : public app_list::AppListViewDelegate,
                             public ash::mojom::WallpaperObserver,
-                            public content::NotificationObserver,
-                            public TemplateURLServiceObserver {
+                            public content::NotificationObserver {
  public:
   // Constructs Chrome's AppListViewDelegate with a NULL Profile.
   // Does not take ownership of |controller|. TODO(tapted): It should.
@@ -67,20 +64,15 @@
   void InvokeSearchResultAction(app_list::SearchResult* result,
                                 int action_index,
                                 int event_flags) override;
-  void ViewInitialized() override;
   void ViewShown() override;
   void Dismiss() override;
   void ViewClosing() override;
-  views::View* CreateStartPageWebView(const gfx::Size& size) override;
   void GetWallpaperProminentColors(std::vector<SkColor>* colors) override;
   void ActivateItem(const std::string& id, int event_flags) override;
   ui::MenuModel* GetContextMenuModel(const std::string& id) override;
   void AddObserver(app_list::AppListViewDelegateObserver* observer) override;
   void RemoveObserver(app_list::AppListViewDelegateObserver* observer) override;
 
-  // Overridden from TemplateURLServiceObserver:
-  void OnTemplateURLServiceChanged() override;
-
  private:
   // Callback for ash::mojom::GetWallpaperColors.
   void OnGetWallpaperColorsCallback(const std::vector<SkColor>& colors);
@@ -116,9 +108,6 @@
 
   std::unique_ptr<AppSyncUIStateWatcher> app_sync_ui_state_watcher_;
 
-  ScopedObserver<TemplateURLService, AppListViewDelegate>
-      template_url_service_observer_;
-
   // Registers for NOTIFICATION_APP_TERMINATING to unload custom launcher pages.
   content::NotificationRegistrar registrar_;
 
diff --git a/chrome/browser/ui/app_list/search/search_resource_manager.cc b/chrome/browser/ui/app_list/search/search_resource_manager.cc
index 9a37439..725e0de 100644
--- a/chrome/browser/ui/app_list/search/search_resource_manager.cc
+++ b/chrome/browser/ui/app_list/search/search_resource_manager.cc
@@ -8,7 +8,6 @@
 
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/start_page_service.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/app_list/start_page_service.cc b/chrome/browser/ui/app_list/start_page_service.cc
deleted file mode 100644
index b4146c13..0000000
--- a/chrome/browser/ui/app_list/start_page_service.cc
+++ /dev/null
@@ -1,446 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/app_list/start_page_service.h"
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_string_value_serializer.h"
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/metrics/user_metrics.h"
-#include "base/strings/string_piece.h"
-#include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/media/webrtc/media_stream_devices_controller.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
-#include "chrome/browser/ui/app_list/start_page_service_factory.h"
-#include "chrome/browser/ui/browser_navigator.h"
-#include "chrome/browser/ui/browser_navigator_params.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "chromeos/audio/cras_audio_handler.h"
-#include "components/prefs/pref_service.h"
-#include "components/search_engines/template_url_service.h"
-#include "components/zoom/zoom_controller.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/speech_recognition_session_preamble.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "content/public/common/content_switches.h"
-#include "extensions/browser/extension_system_provider.h"
-#include "extensions/browser/extensions_browser_client.h"
-#include "extensions/common/extension.h"
-#include "net/base/load_flags.h"
-#include "net/base/network_change_notifier.h"
-#include "net/url_request/url_fetcher.h"
-#include "ui/app_list/app_list_switches.h"
-
-using base::RecordAction;
-using base::UserMetricsAction;
-
-namespace app_list {
-
-namespace {
-
-// Path to google.com's doodle JSON.
-const char kDoodleJsonPath[] = "async/ddljson";
-
-// Maximum delay between checking for a new doodle when the doodle cannot be
-// retrieved. This is also used as the delay once a doodle is retrieved.
-const int kMaximumRecheckDelayMs = 1000 * 60 * 30;  // 30 minutes.
-
-// Delay before loading the start page WebContents on initialization.
-const int kLoadContentsDelaySeconds = 5;
-
-const net::BackoffEntry::Policy kDoodleBackoffPolicy = {
-  // Number of initial errors (in sequence) to ignore before applying
-  // exponential back-off rules.
-  0,
-
-  // Initial delay for exponential back-off in ms.
-  2500,
-
-  // Factor by which the waiting time will be multiplied.
-  2,
-
-  // Fuzzing percentage. ex: 10% will spread requests randomly
-  // between 90%-100% of the calculated time.
-  0.4,
-
-  // Maximum amount of time we are willing to delay our request in ms.
-  kMaximumRecheckDelayMs,
-
-  // Time to keep an entry from being discarded even when it
-  // has no significant state, -1 to never discard.
-  -1,
-
-  // Don't use initial delay unless the last request was an error.
-  false,
-};
-
-}  // namespace
-
-class StartPageService::ProfileDestroyObserver
-    : public content::NotificationObserver {
- public:
-  explicit ProfileDestroyObserver(StartPageService* service)
-      : service_(service) {
-    if (service_->profile()->IsOffTheRecord()) {
-      // We need to be notified when the original profile gets destroyed as well
-      // as the OTR profile, because the original profile will be destroyed
-      // first, and a DCHECK at that time ensures that the OTR profile has 0
-      // hosts. See http://crbug.com/463419.
-      registrar_.Add(
-          this, chrome::NOTIFICATION_PROFILE_DESTROYED,
-          content::Source<Profile>(service_->profile()->GetOriginalProfile()));
-    }
-    registrar_.Add(this,
-                   chrome::NOTIFICATION_PROFILE_DESTROYED,
-                   content::Source<Profile>(service_->profile()));
-  }
-  ~ProfileDestroyObserver() override {}
-
- private:
-  // content::NotificationObserver
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override {
-    DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
-    DCHECK(service_->profile()->IsSameProfile(
-        content::Source<Profile>(source).ptr()));
-    registrar_.RemoveAll();
-    service_->Shutdown();
-  }
-
-  StartPageService* service_;  // Owner of this class.
-  content::NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProfileDestroyObserver);
-};
-
-class StartPageService::StartPageWebContentsDelegate
-    : public content::WebContentsDelegate {
- public:
-  explicit StartPageWebContentsDelegate(Profile* profile) : profile_(profile) {}
-  ~StartPageWebContentsDelegate() override {}
-
-  void AddNewContents(content::WebContents* source,
-                      content::WebContents* new_contents,
-                      WindowOpenDisposition disposition,
-                      const gfx::Rect& initial_pos,
-                      bool user_gesture,
-                      bool* was_blocked) override {
-    chrome::ScopedTabbedBrowserDisplayer displayer(profile_);
-    // Force all links to open in a new tab, even if they were trying to open a
-    // new window.
-    disposition = disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB
-                      ? disposition
-                      : WindowOpenDisposition::NEW_FOREGROUND_TAB;
-    chrome::AddWebContents(displayer.browser(), nullptr, new_contents,
-                           disposition, initial_pos, user_gesture);
-  }
-
-  content::WebContents* OpenURLFromTab(
-      content::WebContents* source,
-      const content::OpenURLParams& params) override {
-    // Force all links to open in a new tab, even if they were trying to open a
-    // window.
-    NavigateParams new_tab_params(static_cast<Browser*>(nullptr), params.url,
-                                  params.transition);
-    if (params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) {
-      new_tab_params.disposition = WindowOpenDisposition::NEW_BACKGROUND_TAB;
-    } else {
-      new_tab_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
-      new_tab_params.window_action = NavigateParams::SHOW_WINDOW;
-    }
-
-    new_tab_params.initiating_profile = profile_;
-    Navigate(&new_tab_params);
-
-    return new_tab_params.target_contents;
-  }
-
-  bool PreHandleGestureEvent(content::WebContents* /*source*/,
-                             const blink::WebGestureEvent& event) override {
-    // Disable pinch zooming on the start page web contents.
-    return blink::WebInputEvent::IsPinchGestureEventType(event.GetType());
-  }
-
-
- private:
-  Profile* profile_;
-
-  DISALLOW_COPY_AND_ASSIGN(StartPageWebContentsDelegate);
-};
-
-class StartPageService::NetworkChangeObserver
-    : public net::NetworkChangeNotifier::NetworkChangeObserver {
- public:
-  explicit NetworkChangeObserver(StartPageService* start_page_service)
-      : start_page_service_(start_page_service) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    // NOTE: This is used to detect network connectivity changes. However, what
-    // we really want is internet connectivity changes because voice recognition
-    // needs to talk to a web service. However, this information isn't
-    // available, so network changes are the best we can do.
-    net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
-
-    last_type_ = net::NetworkChangeNotifier::GetConnectionType();
-    // Handle the case where we're started with no network available.
-    if (last_type_ == net::NetworkChangeNotifier::CONNECTION_NONE)
-      start_page_service_->OnNetworkChanged(false);
-  }
-
-  ~NetworkChangeObserver() override {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
-  }
-
- private:
-  void OnNetworkChanged(
-      net::NetworkChangeNotifier::ConnectionType type) override {
-    // Threading note: NetworkChangeNotifier's contract is that observers are
-    // called on the same thread that they're registered. In this case, it
-    // should always be the UI thread.
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    if (type == net::NetworkChangeNotifier::CONNECTION_NONE) {
-      start_page_service_->OnNetworkChanged(false);
-    } else if (last_type_ == net::NetworkChangeNotifier::CONNECTION_NONE &&
-               type != net::NetworkChangeNotifier::CONNECTION_NONE) {
-      start_page_service_->OnNetworkChanged(true);
-    }
-    last_type_ = type;
-  }
-
-  StartPageService* start_page_service_;
-  net::NetworkChangeNotifier::ConnectionType last_type_;
-
-  DISALLOW_COPY_AND_ASSIGN(NetworkChangeObserver);
-};
-
-// static
-StartPageService* StartPageService::Get(Profile* profile) {
-  return StartPageServiceFactory::GetForProfile(profile);
-}
-
-StartPageService::StartPageService(Profile* profile)
-    : profile_(profile),
-      profile_destroy_observer_(new ProfileDestroyObserver(this)),
-      webui_finished_loading_(false),
-      network_available_(true),
-      search_engine_is_google_(false),
-      backoff_entry_(&kDoodleBackoffPolicy),
-      weak_factory_(this) {
-  TemplateURLService* template_url_service =
-      TemplateURLServiceFactory::GetForProfile(profile_);
-  const TemplateURL* default_provider =
-      template_url_service->GetDefaultSearchProvider();
-  search_engine_is_google_ =
-      default_provider->GetEngineType(
-          template_url_service->search_terms_data()) == SEARCH_ENGINE_GOOGLE;
-
-  network_change_observer_.reset(new NetworkChangeObserver(this));
-}
-
-StartPageService::~StartPageService() {
-}
-
-void StartPageService::OnNetworkChanged(bool available) {
-  network_available_ = available;
-}
-
-void StartPageService::Init() {
-  // Do not load the start page web contents in tests because many tests assume
-  // no WebContents exist except the ones they make.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType))
-    return;
-
-  content::BrowserThread::PostDelayedTask(
-      content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&StartPageService::LoadContentsIfNeeded,
-                 weak_factory_.GetWeakPtr()),
-      base::TimeDelta::FromSeconds(kLoadContentsDelaySeconds));
-}
-
-void StartPageService::LoadContentsIfNeeded() {
-  if (!contents_)
-    LoadContents();
-}
-
-void StartPageService::AppListShown() {
-  if (!contents_) {
-    LoadContents();
-  } else if (contents_->IsCrashed()) {
-    LoadStartPageURL();
-  } else if (contents_->GetWebUI()) {
-    contents_->GetWebUI()->CallJavascriptFunctionUnsafe(
-        "appList.startPage.onAppListShown");
-  }
-}
-
-void StartPageService::AppListHidden() {
-}
-
-content::WebContents* StartPageService::GetStartPageContents() {
-  return contents_.get();
-}
-
-void StartPageService::Shutdown() {
-  UnloadContents();
-  network_change_observer_.reset();
-}
-
-void StartPageService::DidFinishNavigation(
-    content::NavigationHandle* navigation_handle) {
-  if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted())
-    return;
-
-  if (navigation_handle->IsErrorPage()) {
-    // This avoids displaying a "Webpage Blocked" error or similar (which can
-    // happen if the URL is blacklisted by enterprise policy).
-    content::BrowserThread::PostTask(
-        content::BrowserThread::UI, FROM_HERE,
-        base::Bind(&StartPageService::UnloadContents,
-                   weak_factory_.GetWeakPtr()));
-    return;
-  }
-
-  // Set the zoom level in DidFinishNavigation, as this is the earliest point
-  // at which it can be done and not be affected by the ZoomController's
-  // DidFinishNavigation handler.
-  //
-  // Use a temporary zoom level for this web contents (aka isolated zoom
-  // mode) so changes to its zoom aren't reflected in any preferences.
-  zoom::ZoomController::FromWebContents(contents_.get())
-      ->SetZoomMode(zoom::ZoomController::ZOOM_MODE_ISOLATED);
-  // Set to have a zoom level of 0, which corresponds to 100%, so the
-  // contents aren't affected by the browser's default zoom level.
-  zoom::ZoomController::FromWebContents(contents_.get())->SetZoomLevel(0);
-}
-
-void StartPageService::WebUILoaded() {
-  // There's a race condition between the WebUI loading, and calling its JS
-  // functions. Specifically, calling LoadContents() doesn't mean that the page
-  // has loaded, but several code paths make this assumption. This function
-  // allows us to defer calling JS functions until after the page has finished
-  // loading.
-  webui_finished_loading_ = true;
-  for (const auto& cb : pending_webui_callbacks_)
-    cb.Run();
-  pending_webui_callbacks_.clear();
-
-  FetchDoodleJson();
-}
-
-void StartPageService::LoadContents() {
-  contents_.reset(content::WebContents::Create(
-      content::WebContents::CreateParams(profile_)));
-  contents_delegate_.reset(new StartPageWebContentsDelegate(profile_));
-  contents_->SetDelegate(contents_delegate_.get());
-
-  // The ZoomController needs to be created before the web contents is observed
-  // by this object. Otherwise it will react to DidNavigateMainFrame after this
-  // object does, resetting the zoom mode in the process.
-  zoom::ZoomController::CreateForWebContents(contents_.get());
-  Observe(contents_.get());
-
-  LoadStartPageURL();
-}
-
-void StartPageService::UnloadContents() {
-  contents_.reset();
-  webui_finished_loading_ = false;
-}
-
-void StartPageService::LoadStartPageURL() {
-  contents_->GetController().LoadURL(
-      GURL(chrome::kChromeUIAppListStartPageURL),
-      content::Referrer(),
-      ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
-      std::string());
-
-  contents_->GetRenderViewHost()->GetWidget()->GetView()->SetBackgroundColor(
-      SK_ColorTRANSPARENT);
-}
-
-void StartPageService::FetchDoodleJson() {
-  if (!search_engine_is_google_)
-    return;
-
-  GURL::Replacements replacements;
-  replacements.SetPathStr(kDoodleJsonPath);
-
-  GURL google_base_url(UIThreadSearchTermsData(profile_).GoogleBaseURLValue());
-  GURL doodle_url = google_base_url.ReplaceComponents(replacements);
-  doodle_fetcher_ =
-      net::URLFetcher::Create(0, doodle_url, net::URLFetcher::GET, this);
-  doodle_fetcher_->SetRequestContext(profile_->GetRequestContext());
-  doodle_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
-  doodle_fetcher_->Start();
-}
-
-void StartPageService::OnURLFetchComplete(const net::URLFetcher* source) {
-  std::string json_data;
-  source->GetResponseAsString(&json_data);
-
-  // Remove XSSI guard for JSON parsing.
-  size_t json_start_index = json_data.find("{");
-  base::StringPiece json_data_substr(json_data);
-  if (json_start_index != std::string::npos)
-    json_data_substr.remove_prefix(json_start_index);
-
-  JSONStringValueDeserializer deserializer(json_data_substr,
-                                           base::JSON_ALLOW_TRAILING_COMMAS);
-  int error_code = 0;
-  std::unique_ptr<base::Value> doodle_json =
-      deserializer.Deserialize(&error_code, nullptr);
-
-  base::TimeDelta recheck_delay;
-  if (error_code != 0) {
-    // On failure, use expotential backoff.
-    backoff_entry_.InformOfRequest(false);
-    recheck_delay = backoff_entry_.GetTimeUntilRelease();
-  } else {
-    // If we received information, even if there's no doodle, reset the backoff
-    // entry and start rechecking for the doodle at the maximum interval.
-    backoff_entry_.Reset();
-    recheck_delay = base::TimeDelta::FromMilliseconds(kMaximumRecheckDelayMs);
-
-    if (contents_ && contents_->GetWebUI()) {
-      contents_->GetWebUI()->CallJavascriptFunctionUnsafe(
-          "appList.startPage.onAppListDoodleUpdated", *doodle_json,
-          base::Value(UIThreadSearchTermsData(profile_).GoogleBaseURLValue()));
-    }
-  }
-
-  // Check for a new doodle.
-  content::BrowserThread::PostDelayedTask(
-      content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&StartPageService::FetchDoodleJson,
-                 weak_factory_.GetWeakPtr()),
-      recheck_delay);
-}
-
-}  // namespace app_list
diff --git a/chrome/browser/ui/app_list/start_page_service.h b/chrome/browser/ui/app_list/start_page_service.h
deleted file mode 100644
index 5b93f11..0000000
--- a/chrome/browser/ui/app_list/start_page_service.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_APP_LIST_START_PAGE_SERVICE_H_
-#define CHROME_BROWSER_UI_APP_LIST_START_PAGE_SERVICE_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/strings/string16.h"
-#include "base/time/default_clock.h"
-#include "build/build_config.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "net/base/backoff_entry.h"
-#include "net/url_request/url_fetcher_delegate.h"
-
-namespace content {
-struct SpeechRecognitionSessionPreamble;
-}
-
-namespace extensions {
-class Extension;
-}
-
-namespace net {
-class URLFetcher;
-}
-
-class Profile;
-class SpeechRecognizer;
-
-namespace app_list {
-
-// StartPageService collects data to be displayed in app list's start page
-// and hosts the start page contents.
-class StartPageService : public KeyedService,
-                         public content::WebContentsObserver,
-                         public net::URLFetcherDelegate {
- public:
-  typedef std::vector<scoped_refptr<const extensions::Extension> >
-      ExtensionList;
-  // Gets the instance for the given profile. May return nullptr.
-  static StartPageService* Get(Profile* profile);
-
-  void Init();
-
-  // Loads the start page WebContents if it hasn't already been loaded.
-  void LoadContentsIfNeeded();
-
-  void AppListShown();
-  void AppListHidden();
-
-  // Called when the WebUI has finished loading.
-  void WebUILoaded();
-
-  // They return essentially the same web contents but might return NULL when
-  // some flag disables the feature.
-  content::WebContents* GetStartPageContents();
-
-  void set_search_engine_is_google(bool search_engine_is_google) {
-    search_engine_is_google_ = search_engine_is_google;
-  }
-  Profile* profile() { return profile_; }
-
- protected:
-  // Protected for testing.
-  explicit StartPageService(Profile* profile);
-  ~StartPageService() override;
-
- private:
-  friend class StartPageServiceFactory;
-
-  // ProfileDestroyObserver to shutdown the service on exiting. WebContents
-  // depends on the profile and needs to be closed before the profile and its
-  // keyed service shutdown.
-  class ProfileDestroyObserver;
-
-  // The WebContentsDelegate implementation for the start page. This allows
-  // getUserMedia() request from the web contents.
-  class StartPageWebContentsDelegate;
-
-  // This class observes network change events and disables/enables voice search
-  // based on network connectivity.
-  class NetworkChangeObserver;
-
-  void LoadContents();
-  void UnloadContents();
-
-  // Loads the start page URL for |contents_|.
-  void LoadStartPageURL();
-
-  // Fetch the Google Doodle JSON data and update the app list start page.
-  void FetchDoodleJson();
-
-  // net::URLFetcherDelegate overrides:
-  void OnURLFetchComplete(const net::URLFetcher* source) override;
-
-  // KeyedService overrides:
-  void Shutdown() override;
-
-  // contents::WebContentsObserver overrides;
-  void DidFinishNavigation(
-      content::NavigationHandle* navigation_handle) override;
-
-  // Change the known network connectivity state. |available| should be true if
-  // at least one network is connected to.
-  void OnNetworkChanged(bool available);
-
-  Profile* profile_;
-  std::unique_ptr<content::WebContents> contents_;
-  std::unique_ptr<StartPageWebContentsDelegate> contents_delegate_;
-  std::unique_ptr<ProfileDestroyObserver> profile_destroy_observer_;
-
-  bool webui_finished_loading_;
-  std::vector<base::Closure> pending_webui_callbacks_;
-
-  base::DefaultClock clock_;
-
-  bool network_available_;
-  std::unique_ptr<NetworkChangeObserver> network_change_observer_;
-
-  bool search_engine_is_google_;
-  std::unique_ptr<net::URLFetcher> doodle_fetcher_;
-  net::BackoffEntry backoff_entry_;
-
-  base::WeakPtrFactory<StartPageService> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(StartPageService);
-};
-
-}  // namespace app_list
-
-#endif  // CHROME_BROWSER_UI_APP_LIST_START_PAGE_SERVICE_H_
diff --git a/chrome/browser/ui/app_list/start_page_service_factory.cc b/chrome/browser/ui/app_list/start_page_service_factory.cc
deleted file mode 100644
index c34c289..0000000
--- a/chrome/browser/ui/app_list/start_page_service_factory.cc
+++ /dev/null
@@ -1,56 +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 "chrome/browser/ui/app_list/start_page_service_factory.h"
-
-#include "base/command_line.h"
-#include "chrome/browser/extensions/install_tracker_factory.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/ui/app_list/start_page_service.h"
-#include "chrome/common/chrome_switches.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "extensions/browser/extension_system_provider.h"
-#include "extensions/browser/extensions_browser_client.h"
-#include "ui/app_list/app_list_switches.h"
-
-namespace app_list {
-
-// static
-StartPageService* StartPageServiceFactory::GetForProfile(Profile* profile) {
-  return static_cast<StartPageService*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-StartPageServiceFactory* StartPageServiceFactory::GetInstance() {
-  return base::Singleton<StartPageServiceFactory>::get();
-}
-
-StartPageServiceFactory::StartPageServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-        "AppListStartPageService",
-        BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(
-      extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
-  DependsOn(extensions::InstallTrackerFactory::GetInstance());
-  DependsOn(TemplateURLServiceFactory::GetInstance());
-}
-
-StartPageServiceFactory::~StartPageServiceFactory() {}
-
-KeyedService* StartPageServiceFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-  Profile* profile = static_cast<Profile*>(context);
-  return new StartPageService(profile);
-}
-
-content::BrowserContext* StartPageServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // The start page service needs an instance in ChromeOS guest mode.
-  return chrome::GetBrowserContextOwnInstanceInIncognito(context);
-}
-
-}  // namespace app_list
diff --git a/chrome/browser/ui/app_list/start_page_service_factory.h b/chrome/browser/ui/app_list/start_page_service_factory.h
deleted file mode 100644
index 02dcc11..0000000
--- a/chrome/browser/ui/app_list/start_page_service_factory.h
+++ /dev/null
@@ -1,44 +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.
-
-#ifndef CHROME_BROWSER_UI_APP_LIST_START_PAGE_SERVICE_FACTORY_H_
-#define CHROME_BROWSER_UI_APP_LIST_START_PAGE_SERVICE_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-class Profile;
-
-namespace app_list {
-class StartPageService;
-
-// Singleton factory to create StartPageService.
-class StartPageServiceFactory : public BrowserContextKeyedServiceFactory {
- public:
-  // Gets or creates the instance of StartPageService for |profile|. May return
-  // nullptr.
-  static StartPageService* GetForProfile(Profile* profile);
-
-  // Gets the singleton instance of this factory.
-  static StartPageServiceFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<StartPageServiceFactory>;
-
-  StartPageServiceFactory();
-  ~StartPageServiceFactory() override;
-
-  // BrowserContextKeyedServiceFactory overrides:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-    content::BrowserContext* context) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(StartPageServiceFactory);
-};
-
-}  // namespace app_list
-
-#endif  // CHROME_BROWSER_UI_APP_LIST_START_PAGE_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc b/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc
index 7190115..4b988a5 100644
--- a/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc
+++ b/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc
@@ -38,6 +38,7 @@
     was_client_set_ = true;
   }
   void SetDarkenScreen(bool darken) override {}
+  void BrailleDisplayStateChanged(bool connected) override {}
 
   bool was_client_set() const { return was_client_set_; }
 
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
index 2063401..fd682962 100644
--- a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
@@ -15,7 +15,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_view_delegate.h"
-#include "chrome/browser/ui/app_list/start_page_service.h"
 #include "chrome/browser/ui/ash/app_list/app_list_controller_ash.h"
 #include "chrome/browser/ui/ash/app_list/app_list_presenter_delegate_mus.h"
 #include "chrome/browser/ui/ash/app_list/app_list_presenter_service.h"
@@ -113,13 +112,6 @@
 
 void AppListServiceAsh::Init(Profile* initial_profile) {
   app_list_presenter_service_->Init();
-
-  // Ensure the StartPageService is created here. This early initialization is
-  // necessary to allow the WebContents to load before the app list is shown.
-  app_list::StartPageService* service =
-      app_list::StartPageService::Get(initial_profile);
-  if (service)
-    service->Init();
 }
 
 void AppListServiceAsh::OnProfileWillBeRemoved(
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc
index d92fc3a..a65f2f5 100644
--- a/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc
+++ b/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc
@@ -6,7 +6,7 @@
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/chrome_screenshot_grabber.h"
 #include "chrome/browser/ui/browser.h"
@@ -18,18 +18,24 @@
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/clipboard_monitor.h"
 #include "ui/base/clipboard/clipboard_observer.h"
-#include "ui/message_center/message_center.h"
 #include "ui/message_center/message_center_observer.h"
 
 class ChromeScreenshotGrabberBrowserTest
     : public InProcessBrowserTest,
       public ui::ScreenshotGrabberObserver,
-      public message_center::MessageCenterObserver,
       public ui::ClipboardObserver {
  public:
-  ChromeScreenshotGrabberBrowserTest() : InProcessBrowserTest() {}
+  ChromeScreenshotGrabberBrowserTest() = default;
   ~ChromeScreenshotGrabberBrowserTest() override = default;
 
+  void SetUpOnMainThread() override {
+    display_service_ = std::make_unique<NotificationDisplayServiceTester>(
+        browser()->profile());
+    display_service_->SetNotificationAddedClosure(base::BindRepeating(
+        &ChromeScreenshotGrabberBrowserTest::OnNotificationAdded,
+        base::Unretained(this)));
+  }
+
   // Overridden from ui::ScreenshotGrabberObserver
   void OnScreenshotCompleted(
       ScreenshotGrabberObserver::Result screenshot_result,
@@ -38,8 +44,7 @@
     screenshot_path_ = screenshot_path;
   }
 
-  // Overridden from message_center::MessageCenterObserver
-  void OnNotificationAdded(const std::string& notification_id) override {
+  void OnNotificationAdded() {
     notification_added_ = true;
     message_loop_runner_->Quit();
   }
@@ -62,15 +67,17 @@
 
   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
 
+  std::unique_ptr<NotificationDisplayServiceTester> display_service_;
   ScreenshotGrabberObserver::Result screenshot_result_;
   base::FilePath screenshot_path_;
   bool notification_added_ = false;
   bool clipboard_changed_ = false;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ChromeScreenshotGrabberBrowserTest);
 };
 
 IN_PROC_BROWSER_TEST_F(ChromeScreenshotGrabberBrowserTest, TakeScreenshot) {
-  message_center::MessageCenter::Get()->AddObserver(this);
-
   ChromeScreenshotGrabber* chrome_screenshot_grabber =
       ChromeScreenshotGrabber::Get();
   chrome_screenshot_grabber->screenshot_grabber()->AddObserver(this);
@@ -89,11 +96,7 @@
   chrome_screenshot_grabber->screenshot_grabber()->RemoveObserver(this);
 
   EXPECT_TRUE(notification_added_);
-  const message_center::Notification* notification =
-      g_browser_process->notification_ui_manager()->FindById(
-          std::string("screenshot"),
-          NotificationUIManager::GetProfileID(browser()->profile()));
-  EXPECT_NE(nullptr, notification);
+  EXPECT_TRUE(display_service_->GetNotification(std::string("screenshot")));
 
   EXPECT_EQ(ScreenshotGrabberObserver::SCREENSHOT_SUCCESS, screenshot_result_);
   EXPECT_TRUE(base::PathExists(screenshot_path_));
@@ -102,13 +105,12 @@
   ui::ClipboardMonitor::GetInstance()->AddObserver(this);
 
   // Copy to clipboard button.
-  notification->ButtonClick(0);
+  display_service_->SimulateClick(NotificationHandler::Type::TRANSIENT,
+                                  std::string("screenshot"), 0, base::nullopt);
 
   RunLoop();
   ui::ClipboardMonitor::GetInstance()->RemoveObserver(this);
 
   EXPECT_TRUE(clipboard_changed_);
   EXPECT_TRUE(IsImageClipboardAvailable());
-
-  g_browser_process->notification_ui_manager()->CancelAll();
 }
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index a12f7692..9f58c5d 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -192,11 +192,6 @@
     return AccessibilityManager::Get()->ShouldShowAccessibilityMenu();
   }
 
-  bool IsBrailleDisplayConnected() const override {
-    DCHECK(AccessibilityManager::Get());
-    return AccessibilityManager::Get()->IsBrailleDisplayConnected();
-  }
-
   void SilenceSpokenFeedback() const override {
     TtsController::GetInstance()->Stop();
   }
diff --git a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm
index 1de79f5d..48ae51f 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm
@@ -23,6 +23,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "skia/ext/skia_utils_mac.h"
 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
@@ -245,8 +246,7 @@
   // Explanation text.
   std::vector<size_t> offsets;
   const base::string16 learn_more_text =
-      l10n_util::GetStringUTF16(
-          IDS_ENTERPRISE_SIGNIN_PROFILE_LINK_LEARN_MORE);
+      l10n_util::GetStringUTF16(IDS_LEARN_MORE);
   const base::string16 explanation_text =
       l10n_util::GetStringFUTF16(
           offerProfileCreation_ ?
diff --git a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm
index 21c79eb0c..e3c96d89 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm
@@ -15,6 +15,7 @@
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/strings/grit/components_strings.h"
 #import "testing/gtest_mac.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -81,8 +82,7 @@
     return "foo@bar.com";
   }
   base::string16 learn_more() {
-    return l10n_util::GetStringUTF16(
-        IDS_ENTERPRISE_SIGNIN_PROFILE_LINK_LEARN_MORE);
+    return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
   }
 
   void OnClose() { closed_ = true; }
diff --git a/chrome/browser/ui/sad_tab.cc b/chrome/browser/ui/sad_tab.cc
index ff830f5c..08aa87d 100644
--- a/chrome/browser/ui/sad_tab.cc
+++ b/chrome/browser/ui/sad_tab.cc
@@ -154,7 +154,7 @@
 }
 
 int SadTab::GetHelpLinkTitle() {
-  return IDS_SAD_TAB_LEARN_MORE_LINK;
+  return IDS_LEARN_MORE;
 }
 
 const char* SadTab::GetHelpLinkURL() {
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
index d7ac460..46b5dd8 100644
--- a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
+++ b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
@@ -27,6 +27,7 @@
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/signin/core/browser/signin_manager.h"
+#include "components/strings/grit/components_strings.h"
 #include "components/vector_icons/vector_icons.h"
 #include "extensions/common/constants.h"
 #include "ui/base/models/menu_model_delegate.h"
@@ -58,8 +59,7 @@
   menu_model_.AddItemWithStringId(IDC_MEDIA_ROUTER_ABOUT,
                                   IDS_MEDIA_ROUTER_ABOUT);
   menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
-  menu_model_.AddItemWithStringId(IDC_MEDIA_ROUTER_LEARN_MORE,
-                                  IDS_MEDIA_ROUTER_LEARN_MORE);
+  menu_model_.AddItemWithStringId(IDC_MEDIA_ROUTER_LEARN_MORE, IDS_LEARN_MORE);
   menu_model_.AddItemWithStringId(IDC_MEDIA_ROUTER_HELP,
                                   IDS_MEDIA_ROUTER_HELP);
   if (shown_by_policy) {
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index 6fdf833f..0c9ee7ac 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -791,8 +791,7 @@
       layout_provider->GetInsetsMetric(views::INSETS_DIALOG).left();
   // A permissions row will have an icon, title, and combobox, with a padding
   // column on either side to match the dialog insets. Note the combobox can be
-  // variable widths depending on the text inside, so allow that column to
-  // expand.
+  // variable widths depending on the text inside.
   // *----------------------------------------------*
   // |++| Icon | Permission Title     | Combobox |++|
   // *----------------------------------------------*
@@ -804,12 +803,12 @@
   permissions_set->AddPaddingColumn(
       kFixed, layout_provider->GetDistanceMetric(
                   views::DISTANCE_RELATED_LABEL_HORIZONTAL));
-  permissions_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, kFixed,
+  permissions_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, kStretchy,
                              GridLayout::USE_PREF, 0, 0);
   permissions_set->AddPaddingColumn(
-      1, layout_provider->GetDistanceMetric(
-             views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
-  permissions_set->AddColumn(GridLayout::TRAILING, GridLayout::FILL, kStretchy,
+      kFixed, layout_provider->GetDistanceMetric(
+                  views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
+  permissions_set->AddColumn(GridLayout::TRAILING, GridLayout::FILL, kFixed,
                              GridLayout::USE_PREF, 0, 0);
   permissions_set->AddPaddingColumn(kFixed, side_margin);
 
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row.cc b/chrome/browser/ui/views/page_info/permission_selector_row.cc
index 19bd5b1..21275ca 100644
--- a/chrome/browser/ui/views/page_info/permission_selector_row.cc
+++ b/chrome/browser/ui/views/page_info/permission_selector_row.cc
@@ -275,7 +275,10 @@
     const GURL& url,
     const PageInfoUI::PermissionInfo& permission,
     views::GridLayout* layout)
-    : profile_(profile), icon_(NULL), menu_button_(NULL), combobox_(NULL) {
+    : profile_(profile),
+      icon_(nullptr),
+      menu_button_(nullptr),
+      combobox_(nullptr) {
   const int list_item_padding = ChromeLayoutProvider::Get()->GetDistanceMetric(
                                     DISTANCE_CONTROL_LIST_VERTICAL) /
                                 2;
@@ -317,19 +320,36 @@
   if (!reason.empty()) {
     layout->StartRow(1, PageInfoBubbleView::kPermissionColumnSetId);
     layout->SkipColumns(1);
-    views::Label* permission_decision_reason = new views::Label(reason);
-    permission_decision_reason->SetEnabledColor(
-        PageInfoUI::GetSecondaryTextColor());
+    views::Label* secondary_label = new views::Label(reason);
+    secondary_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    secondary_label->SetEnabledColor(PageInfoUI::GetSecondaryTextColor());
+    // The |secondary_label| should wrap when it's too long instead of
+    // stretching its parent view horizontally, but also ensure long strings
+    // aren't wrapped too early.
+    int preferred_width = secondary_label->GetPreferredSize().width();
+    secondary_label->SetMultiLine(true);
 
     views::ColumnSet* column_set =
         layout->GetColumnSet(PageInfoBubbleView::kPermissionColumnSetId);
     DCHECK(column_set);
-    // Long labels should span the remaining width of the row (minus the end
-    // margin). This includes the permission label, combobox, and space between
-    // them (3 columns total).
-    constexpr int kColumnSpan = 3;
-    layout->AddView(permission_decision_reason, kColumnSpan, 1,
-                    views::GridLayout::LEADING, views::GridLayout::CENTER);
+    // Secondary labels in Harmony may not overlap into space shared with the
+    // combobox column.
+    const int column_span =
+        ui::MaterialDesignController::IsSecondaryUiMaterial() ? 1 : 3;
+
+    // In Harmony, long labels that cannot fit in the existing space under the
+    // permission label should be allowed to use up to |kMaxSecondaryLabelWidth|
+    // for display.
+    constexpr int kMaxSecondaryLabelWidth = 140;
+    if (ui::MaterialDesignController::IsSecondaryUiMaterial() &&
+        preferred_width > kMaxSecondaryLabelWidth) {
+      layout->AddView(secondary_label, column_span, 1,
+                      views::GridLayout::LEADING, views::GridLayout::CENTER,
+                      kMaxSecondaryLabelWidth, 0);
+    } else {
+      layout->AddView(secondary_label, column_span, 1, views::GridLayout::FILL,
+                      views::GridLayout::CENTER);
+    }
   }
   layout->AddPaddingRow(0,
                         CalculatePaddingBeneathPermissionRow(!reason.empty()));
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
index cefffd1a..e1cc7fd 100644
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
+++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -20,6 +20,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "components/signin/core/browser/profile_management_switches.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -186,8 +187,7 @@
   // Create the explanation label.
   std::vector<size_t> offsets;
   const base::string16 learn_more_text =
-      l10n_util::GetStringUTF16(
-          IDS_ENTERPRISE_SIGNIN_PROFILE_LINK_LEARN_MORE);
+      l10n_util::GetStringUTF16(IDS_LEARN_MORE);
   const base::string16 signin_explanation_text =
       l10n_util::GetStringFUTF16(prompt_for_new_profile_ ?
           IDS_ENTERPRISE_SIGNIN_EXPLANATION_WITH_PROFILE_CREATION :
diff --git a/chrome/browser/ui/views/toolbar/app_menu_button.cc b/chrome/browser/ui/views/toolbar/app_menu_button.cc
index 43cd707..8527fd9 100644
--- a/chrome/browser/ui/views/toolbar/app_menu_button.cc
+++ b/chrome/browser/ui/views/toolbar/app_menu_button.cc
@@ -26,6 +26,8 @@
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/common/chrome_features.h"
+#include "chrome/grit/chromium_strings.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/canvas.h"
@@ -75,6 +77,11 @@
                                 bool animate) {
   type_ = type;
   severity_ = severity;
+
+  SetTooltipText(
+      severity_ == AppMenuIconController::Severity::NONE
+          ? l10n_util::GetStringUTF16(IDS_APPMENU_TOOLTIP)
+          : l10n_util::GetStringUTF16(IDS_APPMENU_TOOLTIP_UPDATE_AVAILABLE));
   UpdateIcon(animate);
 }
 
diff --git a/chrome/browser/ui/webui/app_list/OWNERS b/chrome/browser/ui/webui/app_list/OWNERS
deleted file mode 100644
index ed54f09..0000000
--- a/chrome/browser/ui/webui/app_list/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-calamity@chromium.org
-khmel@chromium.org
diff --git a/chrome/browser/ui/webui/app_list/start_page_browsertest.js b/chrome/browser/ui/webui/app_list/start_page_browsertest.js
deleted file mode 100644
index 84869c4..0000000
--- a/chrome/browser/ui/webui/app_list/start_page_browsertest.js
+++ /dev/null
@@ -1,161 +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.
-
-/**
- * TestFixture for kiosk app settings WebUI testing.
- * @extends {testing.Test}
- * @constructor
- */
-function AppListStartPageWebUITest() {}
-
-/**
- * Mock of audioContext.
- * @constructor
- */
-function mockAudioContext() {
-  this.sampleRate = 44100; /* some dummy number */
-}
-
-mockAudioContext.prototype = {
-  createMediaStreamSource: function(stream) {
-    return {connect: function(audioProc) {},
-            disconnect: function() {}};
-  },
-  createScriptProcessor: function(bufSize, in_channels, out_channels) {
-    return {connect: function(destination) {},
-            disconnect: function() {}};
-  }
-};
-
-AppListStartPageWebUITest.prototype = {
-  __proto__: testing.Test.prototype,
-
-  /**
-   * Browser to app launcher start page.
-   */
-  browsePreload: 'chrome://app-list/',
-
-  /**
-   * Placeholder for mock speech recognizer.
-   */
-  speechRecognizer: null,
-
-  /**
-   * Sends the speech recognition result.
-   *
-   * @param {string} result The testing result.
-   * @param {boolean} isFinal Whether the result is final or not.
-   */
-  sendSpeechResult: function(result, isFinal) {
-    var speechEvent = new Event('test');
-    // Each result contains a list of alternatives and 'isFinal' flag.
-    var speechResult = [{transcript: result}];
-    speechResult.isFinal = isFinal;
-    speechEvent.results = [speechResult];
-    this.speechRecognizer.onresult(speechEvent);
-  },
-
-  /**
-   * Registers the webkitSpeechRecognition mock for test.
-   * @private
-   */
-  registerMockSpeechRecognition_: function() {
-    var owner = this;
-    function mockSpeechRecognition() {
-      this.inSpeech_ = false;
-      owner.speechRecognizer = this;
-    }
-
-    mockSpeechRecognition.prototype = {
-      start: function() {
-        this.onstart();
-      },
-
-      abort: function() {
-        if (this.inSpeech_)
-          this.onspeechend();
-        this.onerror(new Error());
-        this.onend();
-      }
-    },
-
-    window.webkitSpeechRecognition = mockSpeechRecognition;
-  },
-
-  /**
-   * Mock of webkitGetUserMedia for start page.
-   *
-   * @private
-   * @param {object} constraint The constraint parameter.
-   * @param {Function} success The success callback.
-   * @param {Function} error The error callback.
-   */
-  mockGetUserMedia_: function(constraint, success, error) {
-    function getAudioTracks() {
-    }
-    assertTrue(constraint.audio);
-    assertNotEquals(null, error, 'error callback must not be null');
-    var audioTracks = [];
-    for (var i = 0; i < 2; ++i) {
-      audioTracks.push(this.audioTrackMocks[i].proxy());
-    }
-    success({getAudioTracks: function() { return audioTracks; }});
-  },
-
-  /** @override */
-  preLoad: function() {
-    this.makeAndRegisterMockHandler(['initialize',
-                                     'launchApp',
-                                     'setSpeechRecognitionState',
-                                     'speechResult']);
-    this.mockHandler.stubs().initialize();
-    this.mockHandler.stubs().launchApp(ANYTHING);
-
-    this.registerMockSpeechRecognition_();
-    window.AudioContext = mockAudioContext;
-    navigator.webkitGetUserMedia = this.mockGetUserMedia_.bind(this);
-    this.audioTrackMocks = [mock(MediaStreamTrack), mock(MediaStreamTrack)];
-  }
-};
-
-TEST_F('AppListStartPageWebUITest', 'Basic', function() {
-  assertEquals(this.browsePreload, document.location.href);
-});
-
-TEST_F('AppListStartPageWebUITest', 'LoadDoodle', function() {
-  var doodleData = {
-    'ddljson': {
-      'transparent_large_image': {
-        'url': 'doodle.png'
-      },
-      'alt_text': 'Doodle alt text',
-      'target_url': '/target.html'
-    }
-  };
-
-  assertEquals(null, $('doodle'));
-
-  // Load the doodle with a target url and alt text.
-  appList.startPage.onAppListDoodleUpdated(doodleData,
-                                           'http://example.com/x/');
-  assertNotEquals(null, $('doodle'));
-  assertEquals('http://example.com/x/doodle.png', $('doodle_image').src);
-  assertEquals(doodleData.ddljson.alt_text, $('doodle_image').title);
-  assertEquals('http://example.com/target.html', $('doodle_link').href);
-
-  // Reload the doodle without a target url and alt text.
-  doodleData.ddljson.alt_text = undefined;
-  doodleData.ddljson.target_url = undefined;
-  appList.startPage.onAppListDoodleUpdated(doodleData,
-                                           'http://example.com/x/');
-  assertNotEquals(null, $('doodle'));
-  assertEquals('http://example.com/x/doodle.png', $('doodle_image').src);
-  assertEquals('', $('doodle_image').title);
-  assertEquals(null, $('doodle_link'));
-
-
-  appList.startPage.onAppListDoodleUpdated({},
-                                           'http://example.com/');
-  assertEquals(null, $('doodle'));
-});
diff --git a/chrome/browser/ui/webui/app_list/start_page_handler.cc b/chrome/browser/ui/webui/app_list/start_page_handler.cc
deleted file mode 100644
index d8fd5b02..0000000
--- a/chrome/browser/ui/webui/app_list/start_page_handler.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/app_list/start_page_handler.h"
-
-#include <memory>
-#include <string>
-
-#include "base/bind.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/values.h"
-#include "base/version.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/app_list_service.h"
-#include "chrome/browser/ui/app_list/start_page_service.h"
-#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
-#include "chrome/common/pref_names.h"
-#include "components/update_client/update_query_params.h"
-#include "content/public/browser/web_ui.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/common/constants.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/extension_icon_set.h"
-#include "ui/app_list/app_list_switches.h"
-#include "ui/events/event_constants.h"
-
-namespace app_list {
-
-namespace {
-
-const char kAppListDoodleActionHistogram[] = "Apps.AppListDoodleAction";
-
-// Interactions a user has with the app list doodle. This enum must not have its
-// order altered as it is used in histograms.
-enum DoodleAction {
-  DOODLE_SHOWN = 0,
-  DOODLE_CLICKED,
-  // Add values here.
-
-  DOODLE_ACTION_LAST,
-};
-
-}  // namespace
-
-StartPageHandler::StartPageHandler() {
-}
-
-StartPageHandler::~StartPageHandler() {
-}
-
-void StartPageHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback(
-      "appListShown", base::Bind(&StartPageHandler::HandleAppListShown,
-                                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(
-      "doodleClicked", base::Bind(&StartPageHandler::HandleDoodleClicked,
-                                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(
-      "initialize",
-      base::Bind(&StartPageHandler::HandleInitialize, base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(
-      "launchApp",
-      base::Bind(&StartPageHandler::HandleLaunchApp, base::Unretained(this)));
-}
-
-void StartPageHandler::HandleAppListShown(const base::ListValue* args) {
-  bool doodle_shown = false;
-  if (args->GetBoolean(0, &doodle_shown) && doodle_shown) {
-    UMA_HISTOGRAM_ENUMERATION(kAppListDoodleActionHistogram, DOODLE_SHOWN,
-                              DOODLE_ACTION_LAST);
-  }
-}
-
-void StartPageHandler::HandleDoodleClicked(const base::ListValue* args) {
-  UMA_HISTOGRAM_ENUMERATION(kAppListDoodleActionHistogram, DOODLE_CLICKED,
-                            DOODLE_ACTION_LAST);
-}
-
-void StartPageHandler::HandleInitialize(const base::ListValue* args) {
-  Profile* profile = Profile::FromWebUI(web_ui());
-  StartPageService* service = StartPageService::Get(profile);
-  if (!service)
-    return;
-
-  service->WebUILoaded();
-}
-
-void StartPageHandler::HandleLaunchApp(const base::ListValue* args) {
-  std::string app_id;
-  CHECK(args->GetString(0, &app_id));
-
-  Profile* profile = Profile::FromWebUI(web_ui());
-  const extensions::Extension* app =
-      extensions::ExtensionRegistry::Get(profile)
-          ->GetExtensionById(app_id, extensions::ExtensionRegistry::EVERYTHING);
-  if (!app) {
-    NOTREACHED();
-    return;
-  }
-
-  AppListControllerDelegate* controller =
-      AppListService::Get()->GetControllerDelegate();
-  controller->ActivateApp(profile,
-                          app,
-                          AppListControllerDelegate::LAUNCH_FROM_APP_LIST,
-                          ui::EF_NONE);
-}
-
-}  // namespace app_list
diff --git a/chrome/browser/ui/webui/app_list/start_page_handler.h b/chrome/browser/ui/webui/app_list/start_page_handler.h
deleted file mode 100644
index 516413a..0000000
--- a/chrome/browser/ui/webui/app_list/start_page_handler.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_APP_LIST_START_PAGE_HANDLER_H_
-#define CHROME_BROWSER_UI_WEBUI_APP_LIST_START_PAGE_HANDLER_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "components/prefs/pref_change_registrar.h"
-#include "content/public/browser/web_ui_message_handler.h"
-
-namespace base {
-class ListValue;
-}
-
-namespace app_list {
-
-// Handler for the app launcher start page.
-class StartPageHandler : public content::WebUIMessageHandler {
- public:
-  StartPageHandler();
-  ~StartPageHandler() override;
-
- private:
-  // content::WebUIMessageHandler overrides:
-  void RegisterMessages() override;
-
-  // JS callbacks.
-  void HandleAppListShown(const base::ListValue* args);
-  void HandleDoodleClicked(const base::ListValue* args);
-  void HandleInitialize(const base::ListValue* args);
-  void HandleLaunchApp(const base::ListValue* args);
-
-  PrefChangeRegistrar pref_change_registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(StartPageHandler);
-};
-
-}  // namespace app_list
-
-#endif  // CHROME_BROWSER_UI_WEBUI_APP_LIST_START_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/app_list/start_page_ui.cc b/chrome/browser/ui/webui/app_list/start_page_ui.cc
deleted file mode 100644
index a5160c2..0000000
--- a/chrome/browser/ui/webui/app_list/start_page_ui.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/app_list/start_page_ui.h"
-
-#include <memory>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/sys_info.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/app_list/start_page_handler.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/common/extension.h"
-
-namespace app_list {
-
-StartPageUI::StartPageUI(content::WebUI* web_ui)
-    : content::WebUIController(web_ui) {
-  web_ui->AddMessageHandler(std::make_unique<StartPageHandler>());
-  InitDataSource();
-}
-
-StartPageUI::~StartPageUI() {}
-
-void StartPageUI::InitDataSource() {
-  std::unique_ptr<content::WebUIDataSource> source(
-      content::WebUIDataSource::Create(chrome::kChromeUIAppListStartPageHost));
-
-  source->SetJsonPath("strings.js");
-
-  source->AddResourcePath("start_page.css", IDR_APP_LIST_START_PAGE_CSS);
-  source->AddResourcePath("start_page.js", IDR_APP_LIST_START_PAGE_JS);
-  source->SetDefaultResource(IDR_APP_LIST_START_PAGE_HTML);
-
-  content::WebUIDataSource::Add(Profile::FromWebUI(web_ui()), source.release());
-}
-
-}  // namespace app_list
diff --git a/chrome/browser/ui/webui/app_list/start_page_ui.h b/chrome/browser/ui/webui/app_list/start_page_ui.h
deleted file mode 100644
index 0408914..0000000
--- a/chrome/browser/ui/webui/app_list/start_page_ui.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_APP_LIST_START_PAGE_UI_H_
-#define CHROME_BROWSER_UI_WEBUI_APP_LIST_START_PAGE_UI_H_
-
-#include "base/macros.h"
-#include "content/public/browser/web_ui_controller.h"
-
-namespace app_list {
-
-// StartPageUI for the app launcher start page.
-class StartPageUI : public content::WebUIController {
- public:
-  explicit StartPageUI(content::WebUI* web_ui);
-  ~StartPageUI() override;
-
- private:
-  // Initializes the data source used for this webui.
-  void InitDataSource();
-
-  DISALLOW_COPY_AND_ASSIGN(StartPageUI);
-};
-
-}  // namespace app_list
-
-#endif  // CHROME_BROWSER_UI_WEBUI_APP_LIST_START_PAGE_UI_H_
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 1edbf61..ac0fc32 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -192,10 +192,6 @@
 #include "chrome/browser/ui/webui/local_discovery/local_discovery_ui.h"
 #endif
 
-#if BUILDFLAG(ENABLE_APP_LIST)
-#include "chrome/browser/ui/webui/app_list/start_page_ui.h"
-#endif
-
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "chrome/browser/extensions/extension_web_ui.h"
 #include "chrome/browser/ui/webui/extensions/extensions_ui.h"
@@ -546,10 +542,6 @@
   }
 #endif
 
-#if BUILDFLAG(ENABLE_APP_LIST)
-  if (url.host_piece() == chrome::kChromeUIAppListStartPageHost)
-    return &NewWebUI<app_list::StartPageUI>;
-#endif
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   if (url.host_piece() == chrome::kChromeUIExtensionsFrameHost)
     return &NewWebUI<extensions::ExtensionsUI>;
diff --git a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
index 3942113..8293c53 100644
--- a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
@@ -25,6 +25,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/chromeos_switches.h"
 #include "components/prefs/pref_service.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
@@ -76,7 +77,7 @@
      IDS_KEYBOARD_OVERLAY_SYSTEM_MENU_KEY_LABEL},
     {"keyboardOverlayLauncherKeyLabel",
      IDS_KEYBOARD_OVERLAY_LAUNCHER_KEY_LABEL},
-    {"keyboardOverlayLearnMore", IDS_KEYBOARD_OVERLAY_LEARN_MORE},
+    {"keyboardOverlayLearnMore", IDS_LEARN_MORE},
     {"keyboardOverlayTitle", IDS_KEYBOARD_OVERLAY_TITLE},
     {"keyboardOverlayEscKeyLabel", IDS_KEYBOARD_OVERLAY_ESC_KEY_LABEL},
     {"keyboardOverlayBackKeyLabel", IDS_KEYBOARD_OVERLAY_BACK_KEY_LABEL},
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index d03ae5f..21c1cab4 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -451,7 +451,7 @@
   builder->Add("whitelistErrorEnterprise",
                IDS_ENTERPRISE_LOGIN_ERROR_WHITELIST);
   builder->Add("tryAgainButton", IDS_WHITELIST_ERROR_TRY_AGAIN_BUTTON);
-  builder->Add("learnMoreButton", IDS_WHITELIST_ERROR_LEARN_MORE_BUTTON);
+  builder->Add("learnMoreButton", IDS_LEARN_MORE);
   builder->Add("gaiaLoading", IDS_LOGIN_GAIA_LOADING_MESSAGE);
 
   // Strings used by the SAML fatal error dialog.
@@ -696,6 +696,13 @@
 
   UserContext user_context(GetAccountId(email, gaia_id, AccountType::GOOGLE));
   user_context.SetKey(Key(password));
+  // Only save the password for enterprise users. See https://crbug.com/386606.
+  const bool is_enterprise_managed = g_browser_process->platform_part()
+                                         ->browser_policy_connector_chromeos()
+                                         ->IsEnterpriseManaged();
+  if (is_enterprise_managed) {
+    user_context.SetPasswordKey(Key(password));
+  }
   user_context.SetAuthCode(auth_code);
   user_context.SetAuthFlow(using_saml
                                ? UserContext::AUTH_FLOW_GAIA_WITH_SAML
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index 07b957a7..78027b4 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -92,6 +92,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/proximity_auth/screenlock_bridge.h"
+#include "components/strings/grit/components_strings.h"
 #include "components/user_manager/known_user.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
@@ -418,7 +419,7 @@
                IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME);
   builder->Add("publicAccountMonitoringWarning",
                IDS_LOGIN_PUBLIC_ACCOUNT_MONITORING_WARNING);
-  builder->Add("publicAccountLearnMore", IDS_LOGIN_PUBLIC_ACCOUNT_LEARN_MORE);
+  builder->Add("publicAccountLearnMore", IDS_LEARN_MORE);
   builder->Add("publicAccountMonitoringInfo",
                IDS_LOGIN_PUBLIC_ACCOUNT_MONITORING_INFO);
   builder->Add("publicAccountMonitoringInfoItem1",
@@ -1182,6 +1183,13 @@
 
   UserContext user_context(account_id);
   user_context.SetKey(Key(password));
+  // Only save the password for enterprise users. See https://crbug.com/386606.
+  const bool is_enterprise_managed = g_browser_process->platform_part()
+                                         ->browser_policy_connector_chromeos()
+                                         ->IsEnterpriseManaged();
+  if (is_enterprise_managed) {
+    user_context.SetPasswordKey(Key(password));
+  }
   user_context.SetIsUsingPin(authenticated_by_pin);
   const user_manager::User* user =
       user_manager::UserManager::Get()->FindUser(account_id);
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index a55a100..6ac50e8f 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -253,7 +253,7 @@
       l10n_util::GetStringFUTF16(
           IDS_EXTENSIONS_ADDED_WITHOUT_KNOWLEDGE,
           l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)));
-  source->AddLocalizedString("learnMore", IDS_MD_EXTENSIONS_LEARN_MORE);
+  source->AddLocalizedString("learnMore", IDS_LEARN_MORE);
   source->AddLocalizedString(
       "loadErrorCouldNotLoadManifest",
       IDS_MD_EXTENSIONS_LOAD_ERROR_COULD_NOT_LOAD_MANIFEST);
diff --git a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
index a461fb4d..782ea7d 100644
--- a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
+++ b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
@@ -19,7 +19,6 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/media/webrtc/webrtc_log_list.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
@@ -27,6 +26,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/upload_list/upload_list.h"
 #include "components/version_info/version_info.h"
+#include "components/webrtc_logging/browser/log_list.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -110,11 +110,12 @@
 };
 
 WebRtcLogsDOMHandler::WebRtcLogsDOMHandler(Profile* profile)
-    : log_dir_(WebRtcLogList::GetWebRtcLogDirectoryForBrowserContextPath(
-          profile->GetPath())),
+    : log_dir_(
+          webrtc_logging::LogList::GetWebRtcLogDirectoryForBrowserContextPath(
+              profile->GetPath())),
       list_available_(false),
       js_request_pending_(false) {
-  upload_list_ = WebRtcLogList::CreateWebRtcLogList(profile);
+  upload_list_ = webrtc_logging::LogList::CreateWebRtcLogList(profile);
 }
 
 WebRtcLogsDOMHandler::~WebRtcLogsDOMHandler() {
diff --git a/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc
index f709b87..fc3afe5 100644
--- a/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.h"
 
 #include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_ui_data_source.h"
 
 namespace {
@@ -15,7 +16,7 @@
 
 void AddMediaRouterStrings(content::WebUIDataSource* html_source) {
   html_source->AddLocalizedString("mediaRouterTitle", IDS_MEDIA_ROUTER_TITLE);
-  html_source->AddLocalizedString("learnMoreText", IDS_MEDIA_ROUTER_LEARN_MORE);
+  html_source->AddLocalizedString("learnMoreText", IDS_LEARN_MORE);
   html_source->AddLocalizedString("backButtonTitle",
                                   IDS_MEDIA_ROUTER_BACK_BUTTON_TITLE);
   html_source->AddLocalizedString("closeButtonTitle",
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index 158173b..f99e3ff 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -683,7 +683,7 @@
 void NetInternalsMessageHandler::IOThreadImpl::OnReloadProxySettings(
     const base::ListValue* list) {
   DCHECK(!list);
-  GetMainContext()->proxy_service()->ForceReloadProxyConfig();
+  GetMainContext()->proxy_resolution_service()->ForceReloadProxyConfig();
 
   // Cause the renderer to be notified of the new values.
   SendNetInfo(net::NET_INFO_PROXY_SETTINGS);
@@ -692,7 +692,7 @@
 void NetInternalsMessageHandler::IOThreadImpl::OnClearBadProxies(
     const base::ListValue* list) {
   DCHECK(!list);
-  GetMainContext()->proxy_service()->ClearBadProxiesCache();
+  GetMainContext()->proxy_resolution_service()->ClearBadProxiesCache();
 
   // Cause the renderer to be notified of the new values.
   SendNetInfo(net::NET_INFO_BAD_PROXIES);
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index 0ce8d87..4c243a3 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -292,7 +292,7 @@
   int guest_tab_ids = IDR_GUEST_TAB_HTML;
   int guest_tab_description_ids = IDS_NEW_TAB_GUEST_SESSION_DESCRIPTION;
   int guest_tab_heading_ids = IDS_NEW_TAB_GUEST_SESSION_HEADING;
-  int guest_tab_link_ids = IDS_NEW_TAB_GUEST_SESSION_LEARN_MORE_LINK;
+  int guest_tab_link_ids = IDS_LEARN_MORE;
 
 #if defined(OS_CHROMEOS)
   guest_tab_ids = IDR_GUEST_SESSION_TAB_HTML;
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 9aaebc4..cd9632ae 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -542,7 +542,7 @@
       {"scrollLabel", IDS_SETTINGS_SCROLL_LABEL},
       {"traditionalScrollLabel", IDS_SETTINGS_TRADITIONAL_SCROLL_LABEL},
       {"naturalScrollLabel", IDS_SETTINGS_NATURAL_SCROLL_LABEL},
-      {"naturalScrollLearnMore", IDS_SETTINGS_NATURAL_SCROLL_LEARN_MORE},
+      {"naturalScrollLearnMore", IDS_LEARN_MORE},
   };
   AddLocalizedStringsBulk(html_source, device_strings,
                           arraysize(device_strings));
@@ -1058,8 +1058,7 @@
       {"networkConnectNotAllowed", IDS_SETTINGS_INTERNET_CONNECT_NOT_ALLOWED},
       {"networkIPAddress", IDS_SETTINGS_INTERNET_NETWORK_IP_ADDRESS},
       {"networkIPConfigAuto", IDS_SETTINGS_INTERNET_NETWORK_IP_CONFIG_AUTO},
-      {"networkNameserversLearnMore",
-       IDS_SETTINGS_INTERNET_NETWORK_NAMESERVERS_LEARN_MORE},
+      {"networkNameserversLearnMore", IDS_LEARN_MORE},
       {"networkPrefer", IDS_SETTINGS_INTERNET_NETWORK_PREFER},
       {"networkPrimaryUserControlled",
        IDS_SETTINGS_INTERNET_NETWORK_PRIMARY_USER_CONTROLLED},
@@ -2084,7 +2083,7 @@
     {"handlerSetDefault", IDS_SETTINGS_SITE_SETTINGS_HANDLER_SET_DEFAULT},
     {"handlerRemove", IDS_SETTINGS_SITE_SETTINGS_REMOVE},
     {"adobeFlashStorage", IDS_SETTINGS_SITE_SETTINGS_ADOBE_FLASH_SETTINGS},
-    {"learnMore", IDS_SETTINGS_SITE_SETTINGS_LEARN_MORE},
+    {"learnMore", IDS_LEARN_MORE},
     {"incognitoSite", IDS_SETTINGS_SITE_SETTINGS_INCOGNITO},
     {"incognitoSiteOnly", IDS_SETTINGS_SITE_SETTINGS_INCOGNITO_ONLY},
     {"embeddedIncognitoSite", IDS_SETTINGS_SITE_SETTINGS_INCOGNITO_EMBEDDED},
diff --git a/chrome/browser/ui/webui/signin/signin_error_ui.cc b/chrome/browser/ui/webui/signin/signin_error_ui.cc
index e127aefb..7e2b869 100644
--- a/chrome/browser/ui/webui/signin/signin_error_ui.cc
+++ b/chrome/browser/ui/webui/signin/signin_error_ui.cc
@@ -19,6 +19,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -133,8 +134,7 @@
   source->AddString("signinErrorSwitchLabel",
                     l10n_util::GetStringFUTF16(
                         IDS_SIGNIN_ERROR_SWITCH_BUTTON_LABEL, existing_name));
-  source->AddLocalizedString("signinErrorLearnMore",
-                             IDS_SIGNIN_ERROR_LEARN_MORE_LINK);
+  source->AddLocalizedString("signinErrorLearnMore", IDS_LEARN_MORE);
   source->AddLocalizedString("signinErrorCloseLabel",
                              IDS_SIGNIN_ERROR_CLOSE_BUTTON_LABEL);
   source->AddLocalizedString("signinErrorOkLabel",
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index d08a945..fa3f70a7 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -155,8 +155,6 @@
     "page_load_metrics/page_load_timing.h",
     "page_load_metrics/page_track_decider.cc",
     "page_load_metrics/page_track_decider.h",
-    "partial_circular_buffer.cc",
-    "partial_circular_buffer.h",
     "pdf_uma.cc",
     "pdf_uma.h",
     "pref_names_util.cc",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 251e0d55..b113b581 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -181,6 +181,11 @@
                                    base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
+#if defined(OS_CHROMEOS)
+// Enable project Crostini, Linux VMs on Chrome OS.
+const base::Feature kCrostini{"Crostini", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
 #if defined(OS_WIN)
 // Enables or disables desktop ios promotion, which shows a promotion to the
 // user promoting Chrome for iOS.
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 7b032d18..e71e7b5 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -93,6 +93,10 @@
 extern const base::Feature kCopylessPaste;
 #endif
 
+#if defined(OS_CHROMEOS)
+extern const base::Feature kCrostini;
+#endif
+
 #if defined(OS_WIN)
 extern const base::Feature kDesktopIOSPromotion;
 #endif  // defined(OS_WIN)
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index b846a8ec..5bccb5f 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -6,59 +6,27 @@
 
 namespace chrome {
 
+const char kAppLauncherHelpURL[] =
+    "https://support.google.com/chrome_webstore/?p=cws_app_launcher";
+
+const char kAutomaticSettingsResetLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=ui_automatic_settings_reset";
+
+const char kBluetoothAdapterOffHelpURL[] =
 #if defined(OS_CHROMEOS)
-const char kCrosScheme[] = "cros";
-#endif
-
-#if defined(OS_ANDROID)
-const char kAndroidAppScheme[] = "android-app";
-#endif
-
-#if defined(OS_CHROMEOS)
-const char kCupsPrintLearnMoreURL[] =
-    "https://support.google.com/chromebook?p=chromebook_printing";
-#endif  // defined(OS_CHROMEOS)
-
-#if defined(OS_CHROMEOS)
-const char kEULAPathFormat[] = "/usr/share/chromeos-assets/eula/%s/eula.html";
-const char kOemEulaURLPath[] = "oem";
-const char kOnlineEulaURLPath[] =
-    "https://www.google.com/intl/%s/chrome/eula_text.html";
-
-const char kChromeOSCreditsPath[] =
-    "/opt/google/chrome/resources/about_os_credits.html";
-
-const char kChromeOSAssetHost[] = "chromeos-asset";
-const char kChromeOSAssetPath[] = "/usr/share/chromeos-assets/";
-#endif  // defined(OS_CHROMEOS)
-
-const char kExtensionInvalidRequestURL[] = "chrome-extension://invalid/";
-
-const char kSyncGoogleDashboardURL[] =
-    "https://www.google.com/settings/chrome/sync/";
-
-const char kGoogleAccountActivityControlsURL[] =
-    "https://myaccount.google.com/activitycontrols/search";
-
-const char kContentSettingsExceptionsLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=settings_manage_exceptions";
-
-const char kPasswordManagerLearnMoreURL[] =
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/?p=settings_password";
+    "chrome://settings/?search=bluetooth";
 #else
-    "https://support.google.com/chrome/?p=settings_password";
+    "https://support.google.com/chrome?p=bluetooth";
 #endif
 
-const char kUpgradeHelpCenterBaseURL[] =
-    "https://support.google.com/installer/?product="
-    "{8A69D345-D564-463c-AFF1-A69D9E530F96}&error=";
+const char kChooserBluetoothOverviewURL[] =
+    "https://support.google.com/chrome?p=bluetooth";
 
-const char kSmartLockHelpPage[] =
-    "https://support.google.com/accounts/answer/6197437";
+const char kChooserUsbOverviewURL[] =
+    "https://support.google.com/chrome?p=webusb";
 
-const char kExtensionControlledSettingLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=ui_settings_api_extension";
+const char kChromeBetaForumURL[] =
+    "https://support.google.com/chrome/?p=beta_forum";
 
 const char kChromeHelpViaKeyboardURL[] =
 #if defined(OS_CHROMEOS)
@@ -93,142 +61,21 @@
     "https://support.google.com/chrome/?p=help&ctx=settings";
 #endif  // defined(OS_CHROMEOS)
 
-const char kChromeBetaForumURL[] =
-    "https://support.google.com/chrome/?p=beta_forum";
+const char kChromeNativeScheme[] = "chrome-native";
 
-#if defined(OS_CHROMEOS)
-const char kChromeAccessibilityHelpURL[] =
-    "https://support.google.com/chromebook/topic/6323347";
-const char kChromeAccessibilitySettingsURL[] =
-    "/chromevox/background/options.html";
-const char kChromePaletteHelpURL[] =
-    "https://support.google.com/chromebook?p=stylus_help";
-#endif  // defined(OS_CHROMEOS)
+const char kChromeSearchLocalNtpHost[] = "local-ntp";
+const char kChromeSearchLocalNtpUrl[] =
+    "chrome-search://local-ntp/local-ntp.html";
 
-#if BUILDFLAG(ENABLE_ONE_CLICK_SIGNIN)
-const char kChromeSyncLearnMoreURL[] =
-    "https://support.google.com/chrome/answer/165139";
+const char kChromeSearchMostVisitedHost[] = "most-visited";
+const char kChromeSearchMostVisitedUrl[] = "chrome-search://most-visited/";
 
-const char kChromeSyncMergeTroubleshootingURL[] =
-    "https://support.google.com/chrome/answer/1181420#merge";
-#endif  // BUILDFLAG(ENABLE_ONE_CLICK_SIGNIN)
+const char kChromeSearchRemoteNtpHost[] = "remote-ntp";
 
-#if defined(OS_MACOSX)
-const char kChromeEnterpriseSignInLearnMoreURL[] =
-    "https://support.google.com/chromebook/answer/1331549";
-#endif
-
-const char kResetProfileSettingsLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=ui_reset_settings";
-
-const char kAutomaticSettingsResetLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=ui_automatic_settings_reset";
-
-const char kLegacySupervisedUserManagementURL[] =
-    "https://www.chrome.com/manage";
-const char kLegacySupervisedUserManagementDisplayURL[] =
-    "www.chrome.com/manage";
-
-const char kSettingsSearchHelpURL[] =
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/?p=settings_search_help";
-#else
-    "https://support.google.com/chrome/?p=settings_search_help";
-#endif
-
-const char kOmniboxLearnMoreURL[] =
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/?p=settings_omnibox";
-#else
-    "https://support.google.com/chrome/?p=settings_omnibox";
-#endif
-
-const char kPageInfoHelpCenterURL[] =
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/?p=ui_security_indicator";
-#else
-    "https://support.google.com/chrome/?p=ui_security_indicator";
-#endif
-
-const char kCrashReasonURL[] =
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/?p=e_awsnap";
-#else
-    "https://support.google.com/chrome/?p=e_awsnap";
-#endif
-
-const char kCrashReasonFeedbackDisplayedURL[] =
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/?p=e_awsnap_rl";
-#else
-    "https://support.google.com/chrome/?p=e_awsnap_rl";
-#endif
-
-const char kPrivacyLearnMoreURL[] =
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/?p=settings_privacy";
-#else
-    "https://support.google.com/chrome/?p=settings_privacy";
-#endif
-
-const char kMyActivityUrlInClearBrowsingData[] =
-    "https://myactivity.google.com/myactivity/?utm_source=chrome_cbd";
-
-const char kDoNotTrackLearnMoreURL[] =
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/?p=settings_do_not_track";
-#else
-    "https://support.google.com/chrome/?p=settings_do_not_track";
-#endif
-
-#if defined(OS_CHROMEOS)
-const char kAttestationForContentProtectionLearnMoreURL[] =
-    "https://support.google.com/chromebook/?p=verified_access";
-#endif
-
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
-const char kEnhancedPlaybackNotificationLearnMoreURL[] =
-#endif
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/?p=enhanced_playback";
-#elif defined(OS_ANDROID)
-// Keep in sync with chrome/android/java/strings/android_chrome_strings.grd
-    "https://support.google.com/chrome/?p=mobile_protected_content";
-#endif
+const char kChromeSearchScheme[] = "chrome-search";
 
 const char kChromiumProjectURL[] = "https://www.chromium.org/";
 
-const char kLearnMoreReportingURL[] =
-    "https://support.google.com/chrome/?p=ui_usagestat";
-
-#if BUILDFLAG(ENABLE_PLUGINS)
-const char kOutdatedPluginLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=ib_outdated_plugin";
-
-const char kBlockedPluginLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=ib_blocked_plugin";
-#endif
-
-const char kLearnMoreRegisterProtocolHandlerURL[] =
-    "https://support.google.com/chrome/?p=ib_protocol_handler";
-
-const char kSyncLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=settings_sign_in";
-
-const char kDownloadScanningLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=ib_download_blocked";
-
-const char kDownloadInterruptedLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=ui_download_errors";
-
-const char kSyncEverythingLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=settings_sync_all";
-
-#if defined(OS_CHROMEOS)
-const char kCrosPrintingLearnMoreURL[] =
-    "https://support.google.com/chromebook?p=chromebook_printing";
-#endif
-
 const char kCloudPrintLearnMoreURL[] =
 #if defined(OS_CHROMEOS)
     "https://support.google.com/chromebook/?p=settings_cloud_print";
@@ -252,8 +99,117 @@
 const char kCloudPrintNoDestinationsLearnMoreURL[] =
     "https://www.google.com/cloudprint/learn/";
 
-const char kAppLauncherHelpURL[] =
-    "https://support.google.com/chrome_webstore/?p=cws_app_launcher";
+const char kContentSettingsExceptionsLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=settings_manage_exceptions";
+
+const char kCrashReasonURL[] =
+#if defined(OS_CHROMEOS)
+    "https://support.google.com/chromebook/?p=e_awsnap";
+#else
+    "https://support.google.com/chrome/?p=e_awsnap";
+#endif
+
+const char kCrashReasonFeedbackDisplayedURL[] =
+#if defined(OS_CHROMEOS)
+    "https://support.google.com/chromebook/?p=e_awsnap_rl";
+#else
+    "https://support.google.com/chrome/?p=e_awsnap_rl";
+#endif
+
+const char kDoNotTrackLearnMoreURL[] =
+#if defined(OS_CHROMEOS)
+    "https://support.google.com/chromebook/?p=settings_do_not_track";
+#else
+    "https://support.google.com/chrome/?p=settings_do_not_track";
+#endif
+
+const char kDownloadInterruptedLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=ui_download_errors";
+
+const char kDownloadScanningLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=ib_download_blocked";
+
+const char kEasyUnlockLearnMoreUrl[] =
+    "https://support.google.com/chromebook/?p=smart_lock";
+
+const char kExtensionControlledSettingLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=ui_settings_api_extension";
+
+const char kExtensionInvalidRequestURL[] = "chrome-extension://invalid/";
+
+const char kGoogleAccountActivityControlsURL[] =
+    "https://myaccount.google.com/activitycontrols/search";
+
+const char kLanguageSettingsLearnMoreUrl[] =
+#if defined(OS_CHROMEOS)
+    "https://support.google.com/chromebook/answer/1059490";
+#else
+    "https://support.google.com/chrome/topic/1678461";
+#endif
+
+const char kLearnMoreRegisterProtocolHandlerURL[] =
+    "https://support.google.com/chrome/?p=ib_protocol_handler";
+
+const char kLearnMoreReportingURL[] =
+    "https://support.google.com/chrome/?p=ui_usagestat";
+
+const char kLegacySupervisedUserManagementDisplayURL[] =
+    "www.chrome.com/manage";
+const char kLegacySupervisedUserManagementURL[] =
+    "https://www.chrome.com/manage";
+
+const char kMediaAccessLearnMoreUrl[] =
+    "https://support.google.com/chrome/?p=ib_access_cam_mic";
+
+const char kMyActivityUrlInClearBrowsingData[] =
+    "https://myactivity.google.com/myactivity/?utm_source=chrome_cbd";
+
+const char kOmniboxLearnMoreURL[] =
+#if defined(OS_CHROMEOS)
+    "https://support.google.com/chromebook/?p=settings_omnibox";
+#else
+    "https://support.google.com/chrome/?p=settings_omnibox";
+#endif
+
+const char kPageInfoHelpCenterURL[] =
+#if defined(OS_CHROMEOS)
+    "https://support.google.com/chromebook/?p=ui_security_indicator";
+#else
+    "https://support.google.com/chrome/?p=ui_security_indicator";
+#endif
+
+const char kPasswordManagerLearnMoreURL[] =
+#if defined(OS_CHROMEOS)
+    "https://support.google.com/chromebook/?p=settings_password";
+#else
+    "https://support.google.com/chrome/?p=settings_password";
+#endif
+
+const char kPrivacyLearnMoreURL[] =
+#if defined(OS_CHROMEOS)
+    "https://support.google.com/chromebook/?p=settings_privacy";
+#else
+    "https://support.google.com/chrome/?p=settings_privacy";
+#endif
+
+const char kRemoveNonCWSExtensionURL[] =
+    "https://support.google.com/chrome/?p=ui_remove_non_cws_extensions";
+
+const char kResetProfileSettingsLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=ui_reset_settings";
+
+const char kSafeSearchSafeParameter[] = "safe=active";
+const char kSafeSearchSsuiParameter[] = "ssui=on";
+
+const char kSettingsSearchHelpURL[] =
+#if defined(OS_CHROMEOS)
+    "https://support.google.com/chromebook/?p=settings_search_help";
+#else
+    "https://support.google.com/chrome/?p=settings_search_help";
+#endif
+
+const char kSmartLockHelpPage[] =
+    "https://support.google.com/accounts/answer/6197437";
 
 const char kSyncEncryptionHelpURL[] =
 #if defined(OS_CHROMEOS)
@@ -265,81 +221,117 @@
 const char kSyncErrorsHelpURL[] =
     "https://support.google.com/chrome/?p=settings_sync_error";
 
+const char kSyncEverythingLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=settings_sync_all";
+
+const char kSyncGoogleDashboardURL[] =
+    "https://www.google.com/settings/chrome/sync/";
+
+const char kSyncLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=settings_sign_in";
+
+const char kUpgradeHelpCenterBaseURL[] =
+    "https://support.google.com/installer/?product="
+    "{8A69D345-D564-463c-AFF1-A69D9E530F96}&error=";
+
+#if defined(OS_ANDROID)
+const char kAndroidAppScheme[] = "android-app";
+#endif
+
+#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+const char kEnhancedPlaybackNotificationLearnMoreURL[] =
+#endif
 #if defined(OS_CHROMEOS)
-const char kNaturalScrollHelpURL[] =
-    "https://support.google.com/chromebook/?p=simple_scrolling";
-const char kLearnMoreEnterpriseURL[] =
-    "https://support.google.com/chromebook/?p=managed";
+    "https://support.google.com/chromebook/?p=enhanced_playback";
+#elif defined(OS_ANDROID)
+// Keep in sync with chrome/android/java/strings/android_chrome_strings.grd
+    "https://support.google.com/chrome/?p=mobile_protected_content";
+#endif
+
+#if defined(OS_CHROMEOS)
 const char kAndroidAppsLearnMoreURL[] =
     "https://support.google.com/chromebook/?p=playapps";
-const char kInstantTetheringLearnMoreURL[] =
-    "https://support.google.com/chromebook?p=instant_tethering";
-const char kTPMFirmwareUpdateLearnMoreURL[] =
-    "https://support.google.com/chromebook/?p=tpm_update";
-#endif
 
-const char kRemoveNonCWSExtensionURL[] =
-    "https://support.google.com/chrome/?p=ui_remove_non_cws_extensions";
+const char kAttestationForContentProtectionLearnMoreURL[] =
+    "https://support.google.com/chromebook/?p=verified_access";
 
-#if defined(OS_WIN)
-const char kNotificationsHelpURL[] =
-    "https://support.google.com/chrome/?p=ui_notifications";
+const char kChromeAccessibilityHelpURL[] =
+    "https://support.google.com/chromebook/topic/6323347";
+const char kChromeAccessibilitySettingsURL[] =
+    "/chromevox/background/options.html";
 
-const char kChromeCleanerLearnMoreURL[] =
-    "https://support.google.com/chrome/?p=chrome_cleanup_tool";
-#endif
+const char kChromeOSAssetHost[] = "chromeos-asset";
+const char kChromeOSAssetPath[] = "/usr/share/chromeos-assets/";
 
-const char kChromeNativeScheme[] = "chrome-native";
+const char kChromeOSCreditsPath[] =
+    "/opt/google/chrome/resources/about_os_credits.html";
 
-const char kChromeSearchScheme[] = "chrome-search";
-const char kChromeSearchLocalNtpHost[] = "local-ntp";
-const char kChromeSearchLocalNtpUrl[] =
-    "chrome-search://local-ntp/local-ntp.html";
-const char kChromeSearchRemoteNtpHost[] = "remote-ntp";
+const char kChromePaletteHelpURL[] =
+    "https://support.google.com/chromebook?p=stylus_help";
 
-const char kChromeSearchMostVisitedHost[] = "most-visited";
-const char kChromeSearchMostVisitedUrl[] = "chrome-search://most-visited/";
+const char kCrosPrintingLearnMoreURL[] =
+    "https://support.google.com/chromebook?p=chromebook_printing";
 
-const char kEasyUnlockLearnMoreUrl[] =
-    "https://support.google.com/chromebook/?p=smart_lock";
+const char kCrosScheme[] = "cros";
 
-// Google SafeSearch query parameters.
-const char kSafeSearchSafeParameter[] = "safe=active";
-const char kSafeSearchSsuiParameter[] = "ssui=on";
+const char kCupsPrintLearnMoreURL[] =
+    "https://support.google.com/chromebook?p=chromebook_printing";
 
-const char kMediaAccessLearnMoreUrl[] =
-    "https://support.google.com/chrome/?p=ib_access_cam_mic";
+const char kEULAPathFormat[] = "/usr/share/chromeos-assets/eula/%s/eula.html";
 
-const char kLanguageSettingsLearnMoreUrl[] =
-#if defined(OS_CHROMEOS)
-    "https://support.google.com/chromebook/answer/1059490";
-#else
-    "https://support.google.com/chrome/topic/1678461";
-#endif
-
-#if defined(OS_WIN)
-const char kWindowsXPVistaDeprecationURL[] =
-    "https://chrome.blogspot.com/2015/11/updates-to-chrome-platform-support.html";
-#endif
-
-const char kChooserBluetoothOverviewURL[] =
-    "https://support.google.com/chrome?p=bluetooth";
-
-const char kBluetoothAdapterOffHelpURL[] =
-#if defined(OS_CHROMEOS)
-    "chrome://settings/?search=bluetooth";
-#else
-    "https://support.google.com/chrome?p=bluetooth";
-#endif
-
-const char kChooserUsbOverviewURL[] =
-    "https://support.google.com/chrome?p=webusb";
-
-#if defined(OS_CHROMEOS)
 const char kEolNotificationURL[] = "https://www.google.com/chromebook/older/";
 
 const char kGoogleNameserversLearnMoreURL[] =
     "https://developers.google.com/speed/public-dns";
+
+const char kInstantTetheringLearnMoreURL[] =
+    "https://support.google.com/chromebook?p=instant_tethering";
+
+const char kLearnMoreEnterpriseURL[] =
+    "https://support.google.com/chromebook/?p=managed";
+
+const char kNaturalScrollHelpURL[] =
+    "https://support.google.com/chromebook/?p=simple_scrolling";
+
+const char kOemEulaURLPath[] = "oem";
+
+const char kOnlineEulaURLPath[] =
+    "https://www.google.com/intl/%s/chrome/eula_text.html";
+
+const char kTPMFirmwareUpdateLearnMoreURL[] =
+    "https://support.google.com/chromebook/?p=tpm_update";
+#endif  // defined(OS_CHROMEOS)
+
+#if defined(OS_MACOSX)
+const char kChromeEnterpriseSignInLearnMoreURL[] =
+    "https://support.google.com/chromebook/answer/1331549";
+#endif
+
+#if defined(OS_WIN)
+const char kChromeCleanerLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=chrome_cleanup_tool";
+
+const char kNotificationsHelpURL[] =
+    "https://support.google.com/chrome/?p=ui_notifications";
+
+const char kWindowsXPVistaDeprecationURL[] =
+    "https://chrome.blogspot.com/2015/11/updates-to-chrome-platform-support.html";
+#endif
+
+#if BUILDFLAG(ENABLE_ONE_CLICK_SIGNIN)
+const char kChromeSyncLearnMoreURL[] =
+    "https://support.google.com/chrome/answer/165139";
+
+const char kChromeSyncMergeTroubleshootingURL[] =
+    "https://support.google.com/chrome/answer/1181420#merge";
+#endif  // BUILDFLAG(ENABLE_ONE_CLICK_SIGNIN)
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+const char kBlockedPluginLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=ib_blocked_plugin";
+
+const char kOutdatedPluginLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=ib_outdated_plugin";
 #endif
 
 }  // namespace chrome
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 538ae89e..0864753 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -5,6 +5,11 @@
 // Contains constants for known URLs and portions thereof.
 // Except for WebUI UI/Host/SubPage constants. Those go in
 // chrome/common/webui_url_constants.h.
+//
+// - Use the same order in this header and url_constants.cc.
+// - Keep the constants sorted by name.
+// - Put platform/feature specific constants towards the end in the appropriate
+//   section.
 
 #ifndef CHROME_COMMON_URL_CONSTANTS_H_
 #define CHROME_COMMON_URL_CONSTANTS_H_
@@ -16,194 +21,48 @@
 #include "chrome/common/webui_url_constants.h"
 #include "content/public/common/url_constants.h"
 #include "ppapi/features/features.h"
-#include "printing/features/features.h"
 
 namespace chrome {
 
-#if defined(OS_CHROMEOS)
-extern const char kCupsPrintLearnMoreURL[];
-#endif  // defined(OS_CHROMEOS)
+// The URL for information on how to use the app launcher.
+extern const char kAppLauncherHelpURL[];
 
-#if defined(OS_CHROMEOS)
-extern const char kEULAPathFormat[];
-extern const char kOemEulaURLPath[];
-extern const char kOnlineEulaURLPath[];
+// "Learn more" URL for when profile settings are automatically reset.
+extern const char kAutomaticSettingsResetLearnMoreURL[];
 
-extern const char kChromeOSCreditsPath[];
+// The URL for providing help when the Bluetooth adapter is off.
+extern const char kBluetoothAdapterOffHelpURL[];
 
-extern const char kChromeOSAssetHost[];
-extern const char kChromeOSAssetPath[];
-#endif  // defined(OS_CHROMEOS)
+// The URL for the Bluetooth Overview help center article in the Web Bluetooth
+// Chooser.
+extern const char kChooserBluetoothOverviewURL[];
 
-// URL used to indicate that an extension resource load request was invalid.
-extern const char kExtensionInvalidRequestURL[];
+// The URL for the WebUsb help center article.
+extern const char kChooserUsbOverviewURL[];
 
-extern const char kSyncGoogleDashboardURL[];
-
-// URL of the 'Activity controls' section of the privacy settings page.
-extern const char kGoogleAccountActivityControlsURL[];
-
-extern const char kContentSettingsExceptionsLearnMoreURL[];
-extern const char kPasswordManagerLearnMoreURL[];
-extern const char kUpgradeHelpCenterBaseURL[];
-extern const char kSmartLockHelpPage[];
-
-// "Learn more" URL for the Settings API, NTP bubble and other settings bubbles
-// showing which extension is controlling them.
-extern const char kExtensionControlledSettingLearnMoreURL[];
+// Link to the forum for Chrome Beta.
+extern const char kChromeBetaForumURL[];
 
 // General help links for Chrome, opened using various actions.
 extern const char kChromeHelpViaKeyboardURL[];
 extern const char kChromeHelpViaMenuURL[];
 extern const char kChromeHelpViaWebUIURL[];
 
-// Link to the forum for Chrome Beta.
-extern const char kChromeBetaForumURL[];
-
-#if defined(OS_CHROMEOS)
-// Accessibility help link for Chrome.
-extern const char kChromeAccessibilityHelpURL[];
-// Accessibility settings link for Chrome.
-extern const char kChromeAccessibilitySettingsURL[];
-// Palette help link for Chrome.
-extern const char kChromePaletteHelpURL[];
-#endif
-
-#if BUILDFLAG(ENABLE_ONE_CLICK_SIGNIN)
-// "Learn more" URL for the one click signin infobar.
-extern const char kChromeSyncLearnMoreURL[];
-
-// "Learn more" URL for the "Sign in with a different account" confirmation
-// dialog.
-extern const char kChromeSyncMergeTroubleshootingURL[];
-#endif
-
-#if defined(OS_MACOSX)
-// "Learn more" URL for the enterprise sign-in confirmation dialog.
-extern const char kChromeEnterpriseSignInLearnMoreURL[];
-#endif
-
-// "Learn more" URL for resetting profile preferences.
-extern const char kResetProfileSettingsLearnMoreURL[];
-
-// "Learn more" URL for when profile settings are automatically reset.
-extern const char kAutomaticSettingsResetLearnMoreURL[];
-
-// Management URL for Chrome Supervised Users.
-extern const char kLegacySupervisedUserManagementURL[];
-
-// Management URL for Chrome Supervised Users - version without scheme, used
-// for display.
-extern const char kLegacySupervisedUserManagementDisplayURL[];
-
-// Help URL for the settings page's search feature.
-extern const char kSettingsSearchHelpURL[];
-
-// Help URL for the Omnibox setting.
-extern const char kOmniboxLearnMoreURL[];
-
-// "What do these mean?" URL for the Page Info bubble.
-extern const char kPageInfoHelpCenterURL[];
-
-// "Learn more" URL for "Aw snap" page when showing "Reload" button.
-extern const char kCrashReasonURL[];
-
-// "Learn more" URL for "Aw snap" page when showing "Send feedback" button.
-extern const char kCrashReasonFeedbackDisplayedURL[];
-
-// "Learn more" URL for killed tab page.
-extern const char kKillReasonURL[];
-
-// "Learn more" URL for the Privacy section under Options.
-extern const char kPrivacyLearnMoreURL[];
-
-// "myactivity.google.com" URL for the history checkbox in ClearBrowsingData.
-extern const char kMyActivityUrlInClearBrowsingData[];
-
-// "Learn more" URL for the "Do not track" setting in the privacy section.
-extern const char kDoNotTrackLearnMoreURL[];
-
-#if defined(OS_CHROMEOS)
-// "Learn more" URL for the attestation of content protection setting.
-extern const char kAttestationForContentProtectionLearnMoreURL[];
-#endif
-
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
-// "Learn more" URL for the enhanced playback notification dialog.
-extern const char kEnhancedPlaybackNotificationLearnMoreURL[];
-#endif
-
-// The URL for the Chromium project used in the About dialog.
-extern const char kChromiumProjectURL[];
-
-// The URL for the "Learn more" page for the usage/crash reporting option in the
-// first run dialog.
-extern const char kLearnMoreReportingURL[];
-
-#if BUILDFLAG(ENABLE_PLUGINS)
-// The URL for the "Learn more" page for the outdated plugin infobar.
-extern const char kOutdatedPluginLearnMoreURL[];
-#endif
-
-// The URL for the "Learn more" page for the blocked plugin infobar.
-extern const char kBlockedPluginLearnMoreURL[];
-
-// The URL for the "Learn more" page for register protocol handler infobars.
-extern const char kLearnMoreRegisterProtocolHandlerURL[];
-
-// The URL for the "Learn more" page for sync setup on the personal stuff page.
-extern const char kSyncLearnMoreURL[];
-
-// The URL for the "Learn more" page for download scanning.
-extern const char kDownloadScanningLearnMoreURL[];
-
-// The URL for the "Learn more" page for interrupted downloads.
-extern const char kDownloadInterruptedLearnMoreURL[];
-
-// The URL for the "Learn more" page on the sync setup dialog, when syncing
-// everything.
-extern const char kSyncEverythingLearnMoreURL[];
-
-// The URL for information on how to use the app launcher.
-extern const char kAppLauncherHelpURL[];
-
-// The URL for the "Learn more" page on sync encryption.
-extern const char kSyncEncryptionHelpURL[];
-
-// The URL for the "Learn more" link when there is a sync error.
-extern const char kSyncErrorsHelpURL[];
-
-#if defined(OS_CHROMEOS)
-// The URL for the "Learn more" link for natural scrolling on ChromeOS.
-extern const char kNaturalScrollHelpURL[];
-
-// The URL for the Learn More page about enterprise enrolled devices.
-extern const char kLearnMoreEnterpriseURL[];
-
-// The URL for the "learn more" link for Google Play Store (ARC) settings.
-extern const char kAndroidAppsLearnMoreURL[];
-
-// The URL for the "learn more" link for Instant Tethering.
-extern const char kInstantTetheringLearnMoreURL[];
-
-// The URL for the "learn more" link for TPM firmware update.
-extern const char kTPMFirmwareUpdateLearnMoreURL[];
-#endif
-
-// The URL for the Learn More link of the non-CWS bubble.
-extern const char kRemoveNonCWSExtensionURL[];
-
-#if defined(OS_WIN)
-extern const char kNotificationsHelpURL[];
-
-// The URL for the Learn More link in the Chrome Cleanup settings card.
-extern const char kChromeCleanerLearnMoreURL[];
-#endif
-
 // The chrome-native: scheme is used show pages rendered with platform specific
 // widgets instead of using HTML.
 extern const char kChromeNativeScheme[];
 
+// Pages under chrome-search.
+extern const char kChromeSearchLocalNtpHost[];
+extern const char kChromeSearchLocalNtpUrl[];
+
+// Host and URL for most visited iframes used on the Instant Extended NTP.
+extern const char kChromeSearchMostVisitedHost[];
+extern const char kChromeSearchMostVisitedUrl[];
+
+// Page under chrome-search.
+extern const char kChromeSearchRemoteNtpHost[];
+
 // The chrome-search: scheme is served by the same backend as chrome:.  However,
 // only specific URLDataSources are enabled to serve requests via the
 // chrome-search: scheme.  See |InstantIOContext::ShouldServiceRequest| and its
@@ -222,77 +81,208 @@
 //     coming from a blessed Instant process, and deny the request.
 extern const char kChromeSearchScheme[];
 
-// Pages under chrome-search.
-extern const char kChromeSearchLocalNtpHost[];
-extern const char kChromeSearchLocalNtpUrl[];
-extern const char kChromeSearchRemoteNtpHost[];
-
-// Host and URL for most visited iframes used on the Instant Extended NTP.
-extern const char kChromeSearchMostVisitedHost[];
-extern const char kChromeSearchMostVisitedUrl[];
-
-#if defined(OS_CHROMEOS)
-extern const char kCrosScheme[];
-#endif
-
-#if defined(OS_ANDROID)
-extern const char kAndroidAppScheme[];
-#endif
-
-#if defined(OS_CHROMEOS)
-// "Learn more" URL for the Printing section under Options.
-extern const char kCrosPrintingLearnMoreURL[];
-#endif
+// The URL for the Chromium project used in the About dialog.
+extern const char kChromiumProjectURL[];
 
 // "Learn more" URL for the Cloud Print section under Options.
 extern const char kCloudPrintLearnMoreURL[];
 
-// "Learn more" URL for the Cloud Print Preview No Destinations Promotion.
-extern const char kCloudPrintNoDestinationsLearnMoreURL[];
-
 // "Learn more" URL for the Cloud Print Preview certificate error.
 extern const char kCloudPrintCertificateErrorLearnMoreURL[];
 
+// "Learn more" URL for the Cloud Print Preview No Destinations Promotion.
+extern const char kCloudPrintNoDestinationsLearnMoreURL[];
+
+extern const char kContentSettingsExceptionsLearnMoreURL[];
+
+// "Learn more" URL for "Aw snap" page when showing "Reload" button.
+extern const char kCrashReasonURL[];
+
+// "Learn more" URL for "Aw snap" page when showing "Send feedback" button.
+extern const char kCrashReasonFeedbackDisplayedURL[];
+
+// "Learn more" URL for the "Do not track" setting in the privacy section.
+extern const char kDoNotTrackLearnMoreURL[];
+
+// The URL for the "Learn more" page for interrupted downloads.
+extern const char kDownloadInterruptedLearnMoreURL[];
+
+// The URL for the "Learn more" page for download scanning.
+extern const char kDownloadScanningLearnMoreURL[];
+
 // The URL for the "Learn more" link the the Easy Unlock settings.
+// TODO(thestig): Move into OS_CHROMEOS section.
 extern const char kEasyUnlockLearnMoreUrl[];
 
-// Parameters that get appended to force SafeSearch.
-extern const char kSafeSearchSafeParameter[];
-extern const char kSafeSearchSsuiParameter[];
+// "Learn more" URL for the Settings API, NTP bubble and other settings bubbles
+// showing which extension is controlling them.
+extern const char kExtensionControlledSettingLearnMoreURL[];
 
-// The URL for the "Learn more" link in the media access infobar.
-extern const char kMediaAccessLearnMoreUrl[];
+// URL used to indicate that an extension resource load request was invalid.
+extern const char kExtensionInvalidRequestURL[];
+
+// URL of the 'Activity controls' section of the privacy settings page.
+extern const char kGoogleAccountActivityControlsURL[];
 
 // The URL for the "Learn more" link in the language settings.
 // TODO(michaelpg): Compile on Chrome OS only when Options is removed.
 extern const char kLanguageSettingsLearnMoreUrl[];
 
-#if defined(OS_MACOSX)
-// The URL for the Mac OS X 10.6/10.7/10.8 deprecation help center article.
-extern const char kMac10_678_DeprecationURL[];
+// The URL for the "Learn more" page for register protocol handler infobars.
+extern const char kLearnMoreRegisterProtocolHandlerURL[];
+
+// The URL for the "Learn more" page for the usage/crash reporting option in the
+// first run dialog.
+extern const char kLearnMoreReportingURL[];
+
+// Management URL for Chrome Supervised Users - version without scheme, used
+// for display.
+extern const char kLegacySupervisedUserManagementDisplayURL[];
+
+// Management URL for Chrome Supervised Users.
+extern const char kLegacySupervisedUserManagementURL[];
+
+// The URL for the "Learn more" link in the media access infobar.
+extern const char kMediaAccessLearnMoreUrl[];
+
+// "myactivity.google.com" URL for the history checkbox in ClearBrowsingData.
+extern const char kMyActivityUrlInClearBrowsingData[];
+
+// Help URL for the Omnibox setting.
+extern const char kOmniboxLearnMoreURL[];
+
+// "What do these mean?" URL for the Page Info bubble.
+extern const char kPageInfoHelpCenterURL[];
+
+extern const char kPasswordManagerLearnMoreURL[];
+
+// "Learn more" URL for the Privacy section under Options.
+extern const char kPrivacyLearnMoreURL[];
+
+// The URL for the Learn More link of the non-CWS bubble.
+extern const char kRemoveNonCWSExtensionURL[];
+
+// "Learn more" URL for resetting profile preferences.
+extern const char kResetProfileSettingsLearnMoreURL[];
+
+// Parameters that get appended to force SafeSearch.
+extern const char kSafeSearchSafeParameter[];
+extern const char kSafeSearchSsuiParameter[];
+
+// Help URL for the settings page's search feature.
+extern const char kSettingsSearchHelpURL[];
+
+extern const char kSmartLockHelpPage[];
+
+// The URL for the "Learn more" page on sync encryption.
+extern const char kSyncEncryptionHelpURL[];
+
+// The URL for the "Learn more" link when there is a sync error.
+extern const char kSyncErrorsHelpURL[];
+
+// The URL for the "Learn more" page on the sync setup dialog, when syncing
+// everything.
+extern const char kSyncEverythingLearnMoreURL[];
+
+extern const char kSyncGoogleDashboardURL[];
+
+// The URL for the "Learn more" page for sync setup on the personal stuff page.
+extern const char kSyncLearnMoreURL[];
+
+extern const char kUpgradeHelpCenterBaseURL[];
+
+#if defined(OS_ANDROID)
+extern const char kAndroidAppScheme[];
 #endif
 
-#if defined(OS_WIN)
-// The URL for the Windows XP/Vista deprecation help center article.
-extern const char kWindowsXPVistaDeprecationURL[];
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+// "Learn more" URL for the enhanced playback notification dialog.
+extern const char kEnhancedPlaybackNotificationLearnMoreURL[];
 #endif
 
-// The URL for the Bluetooth Overview help center article in the Web Bluetooth
-// Chooser.
-extern const char kChooserBluetoothOverviewURL[];
-
-// The URL for providing help when the Bluetooth adapter is off.
-extern const char kBluetoothAdapterOffHelpURL[];
-
-// The URL for the WebUsb help center article.
-extern const char kChooserUsbOverviewURL[];
-
 #if defined(OS_CHROMEOS)
+// The URL for the "learn more" link for Google Play Store (ARC) settings.
+extern const char kAndroidAppsLearnMoreURL[];
+
+// "Learn more" URL for the attestation of content protection setting.
+extern const char kAttestationForContentProtectionLearnMoreURL[];
+
+// Accessibility help link for Chrome.
+extern const char kChromeAccessibilityHelpURL[];
+
+// Accessibility settings link for Chrome.
+extern const char kChromeAccessibilitySettingsURL[];
+
+extern const char kChromeOSAssetHost[];
+extern const char kChromeOSAssetPath[];
+
+extern const char kChromeOSCreditsPath[];
+
+// Palette help link for Chrome.
+extern const char kChromePaletteHelpURL[];
+
+// "Learn more" URL for the Printing section under Options.
+extern const char kCrosPrintingLearnMoreURL[];
+
+extern const char kCrosScheme[];
+
+extern const char kCupsPrintLearnMoreURL[];
+
+extern const char kEULAPathFormat[];
+
 // The URL for EOL notification
 extern const char kEolNotificationURL[];
 
 // The URL for providing more information about Google nameservers.
 extern const char kGoogleNameserversLearnMoreURL[];
+
+// The URL for the "learn more" link for Instant Tethering.
+extern const char kInstantTetheringLearnMoreURL[];
+
+// The URL for the Learn More page about enterprise enrolled devices.
+extern const char kLearnMoreEnterpriseURL[];
+
+// The URL for the "Learn more" link for natural scrolling on ChromeOS.
+extern const char kNaturalScrollHelpURL[];
+
+extern const char kOemEulaURLPath[];
+
+extern const char kOnlineEulaURLPath[];
+
+// The URL for the "learn more" link for TPM firmware update.
+extern const char kTPMFirmwareUpdateLearnMoreURL[];
+#endif  // defined(OS_CHROMEOS)
+
+#if defined(OS_MACOSX)
+// "Learn more" URL for the enterprise sign-in confirmation dialog.
+extern const char kChromeEnterpriseSignInLearnMoreURL[];
+#endif
+
+#if defined(OS_WIN)
+// The URL for the Learn More link in the Chrome Cleanup settings card.
+extern const char kChromeCleanerLearnMoreURL[];
+
+extern const char kNotificationsHelpURL[];
+
+// The URL for the Windows XP/Vista deprecation help center article.
+extern const char kWindowsXPVistaDeprecationURL[];
+#endif
+
+#if BUILDFLAG(ENABLE_ONE_CLICK_SIGNIN)
+// "Learn more" URL for the one click signin infobar.
+extern const char kChromeSyncLearnMoreURL[];
+
+// "Learn more" URL for the "Sign in with a different account" confirmation
+// dialog.
+extern const char kChromeSyncMergeTroubleshootingURL[];
+#endif
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+// The URL for the "Learn more" page for the blocked plugin infobar.
+extern const char kBlockedPluginLearnMoreURL[];
+
+// The URL for the "Learn more" page for the outdated plugin infobar.
+extern const char kOutdatedPluginLearnMoreURL[];
 #endif
 
 }  // namespace chrome
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index e83c0d34..24d33b2 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -19,7 +19,6 @@
 const char kChromeUIAboutHost[] = "about";
 const char kChromeUIAboutURL[] = "chrome://about/";
 const char kChromeUIAppLauncherPageHost[] = "apps";
-const char kChromeUIAppListStartPageHost[] = "app-list";
 const char kChromeUIAppListStartPageURL[] = "chrome://app-list/";
 const char kChromeUIAppsURL[] = "chrome://apps/";
 const char kChromeUIBluetoothInternalsHost[] = "bluetooth-internals";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index fad9a860..9bbafb13 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -26,7 +26,6 @@
 extern const char kChromeUIAboutHost[];
 extern const char kChromeUIAboutURL[];
 extern const char kChromeUIAppLauncherPageHost[];
-extern const char kChromeUIAppListStartPageHost[];
 extern const char kChromeUIAppListStartPageURL[];
 extern const char kChromeUIAppsURL[];
 extern const char kChromeUIBluetoothInternalsHost[];
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn
index 3f65aa2..7395373 100644
--- a/chrome/installer/mini_installer/BUILD.gn
+++ b/chrome/installer/mini_installer/BUILD.gn
@@ -132,11 +132,14 @@
       "$root_out_dir/chrome.exe",
       "$root_out_dir/locales/en-US.pak",
       "$root_out_dir/setup.exe",
-      "$root_out_dir/v8_context_snapshot.bin",
       "//chrome/tools/build/win/makecab.py",
       release_file,
     ]
 
+    if (v8_use_snapshot) {
+      inputs += [ "$root_out_dir/v8_context_snapshot.bin" ]
+    }
+
     outputs = [
       # See also chrome.packed.7z conditionally added below.
       "$output_dir/chrome.7z",
diff --git a/chrome/renderer/media/DEPS b/chrome/renderer/media/DEPS
index 83e7d84..d0acd5d 100644
--- a/chrome/renderer/media/DEPS
+++ b/chrome/renderer/media/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/webrtc_logging/common",
   "+media/audio",  # For basic audio functions.
   "+media/video",  # For basic video functions.
   "+media/base",  # For basic media functions.
diff --git a/chrome/renderer/media/chrome_webrtc_log_message_delegate.cc b/chrome/renderer/media/chrome_webrtc_log_message_delegate.cc
index a5e39873..fc432a6 100644
--- a/chrome/renderer/media/chrome_webrtc_log_message_delegate.cc
+++ b/chrome/renderer/media/chrome_webrtc_log_message_delegate.cc
@@ -6,8 +6,8 @@
 
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
-#include "chrome/common/partial_circular_buffer.h"
 #include "chrome/renderer/media/webrtc_logging_message_filter.h"
+#include "components/webrtc_logging/common/partial_circular_buffer.h"
 
 ChromeWebRtcLogMessageDelegate::ChromeWebRtcLogMessageDelegate(
     const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
diff --git a/chrome/service/net/service_url_request_context_getter.cc b/chrome/service/net/service_url_request_context_getter.cc
index e731bb3..8c94a29 100644
--- a/chrome/service/net/service_url_request_context_getter.cc
+++ b/chrome/service/net/service_url_request_context_getter.cc
@@ -99,8 +99,9 @@
     : user_agent_(MakeUserAgentForServiceProcess()),
       network_task_runner_(g_service_process->io_task_runner()) {
   DCHECK(g_service_process);
-  proxy_config_service_ = net::ProxyService::CreateSystemProxyConfigService(
-      g_service_process->io_task_runner());
+  proxy_config_service_ =
+      net::ProxyResolutionService::CreateSystemProxyConfigService(
+          g_service_process->io_task_runner());
 }
 
 net::URLRequestContext*
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 71f8393..8e8ba28 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2558,7 +2558,6 @@
     "../common/origin_trials/chrome_origin_trial_policy_unittest.cc",
     "../common/page_load_metrics/test/weak_mock_timer.cc",
     "../common/page_load_metrics/test/weak_mock_timer.h",
-    "../common/partial_circular_buffer_unittest.cc",
     "../common/pref_names_util_unittest.cc",
     "../common/secure_origin_whitelist_unittest.cc",
     "../renderer/app_categorizer_unittest.cc",
@@ -3736,7 +3735,6 @@
   if (enable_webrtc) {
     sources += [
       "../browser/media/webrtc/webrtc_log_uploader_unittest.cc",
-      "../browser/media/webrtc/webrtc_log_util_unittest.cc",
       "../browser/media/webrtc/webrtc_rtp_dump_handler_unittest.cc",
       "../browser/media/webrtc/webrtc_rtp_dump_writer_unittest.cc",
       "../renderer/media/chrome_webrtc_log_message_delegate_unittest.cc",
diff --git a/chrome/test/base/browser_perf_tests_main.cc b/chrome/test/base/browser_perf_tests_main.cc
index efea5db..237524a 100644
--- a/chrome/test/base/browser_perf_tests_main.cc
+++ b/chrome/test/base/browser_perf_tests_main.cc
@@ -6,6 +6,8 @@
 #include "chrome/test/base/chrome_test_suite.h"
 
 int main(int argc, char** argv) {
+  base::CommandLine::Init(argc, argv);
+
   // Always run browser perf tests serially - parallel running would be less
   // deterministic and distort perf measurements.
   size_t parallel_jobs = 1U;
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 940e14ec..f791ec1 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -34,7 +34,6 @@
   # and are handled by a rule, but in the GN build they're in a separate
   # action so need to be separated out.
   sources = [
-    "../../../browser/ui/webui/app_list/start_page_browsertest.js",
     "../../../browser/ui/webui/chromeos/bluetooth_pairing_dialog_browsertest.js",
     "../../../browser/ui/webui/chromeos/certificate_manager_dialog_browsertest.js",
     "../../../browser/ui/webui/chromeos/set_time_ui_browsertest.js",
@@ -118,9 +117,7 @@
       "sys_internals/sys_internals_browsertest.js",
     ]
   } else {
-    sources += [
-      "signin/signin_browsertest.js",
-    ]
+    sources += [ "signin/signin_browsertest.js" ]
   }
 
   if (is_chrome_branded) {
@@ -132,10 +129,6 @@
   } else {
     sources -= [ "md_user_manager/user_manager_browsertest.js" ]
   }
-  if (!enable_app_list) {
-    sources -=
-        [ "../../../browser/ui/webui/app_list/start_page_browsertest.js" ]
-  }
   if (enable_print_preview) {
     sources += [
       "print_preview/new_print_preview_ui_browsertest.js",
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc
index cf52d3aa..79c10767 100644
--- a/chromecast/browser/url_request_context_factory.cc
+++ b/chromecast/browser/url_request_context_factory.cc
@@ -246,7 +246,7 @@
   http_server_properties_.reset(new net::HttpServerPropertiesImpl);
 
   DCHECK(proxy_config_service_);
-  proxy_service_ = net::ProxyService::CreateUsingSystemProxyResolver(
+  proxy_resolution_service_ = net::ProxyResolutionService::CreateUsingSystemProxyResolver(
       std::move(proxy_config_service_), NULL);
   system_dependencies_initialized_ = true;
 }
@@ -342,7 +342,7 @@
   system_context->set_cert_transparency_verifier(
       cert_transparency_verifier_.get());
   system_context->set_ct_policy_enforcer(ct_policy_enforcer_.get());
-  system_context->set_proxy_service(proxy_service_.get());
+  system_context->set_proxy_resolution_service(proxy_resolution_service_.get());
   system_context->set_ssl_config_service(ssl_config_service_.get());
   system_context->set_transport_security_state(
       transport_security_state_.get());
@@ -409,7 +409,7 @@
   main_context->set_cert_transparency_verifier(
       cert_transparency_verifier_.get());
   main_context->set_ct_policy_enforcer(ct_policy_enforcer_.get());
-  main_context->set_proxy_service(proxy_service_.get());
+  main_context->set_proxy_resolution_service(proxy_resolution_service_.get());
   main_context->set_ssl_config_service(ssl_config_service_.get());
   main_context->set_transport_security_state(transport_security_state_.get());
   main_context->set_http_auth_handler_factory(
diff --git a/chromecast/browser/url_request_context_factory.h b/chromecast/browser/url_request_context_factory.h
index 86ad3cc..dce8ffb 100644
--- a/chromecast/browser/url_request_context_factory.h
+++ b/chromecast/browser/url_request_context_factory.h
@@ -113,7 +113,7 @@
   std::unique_ptr<net::CTVerifier> cert_transparency_verifier_;
   std::unique_ptr<net::CTPolicyEnforcer> ct_policy_enforcer_;
   std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
-  std::unique_ptr<net::ProxyService> proxy_service_;
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory_;
   std::unique_ptr<net::HttpServerProperties> http_server_properties_;
   std::unique_ptr<net::HttpUserAgentSettings> http_user_agent_settings_;
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 88bbc4bc6..467c53e1 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -240,6 +240,8 @@
     "dbus/power_manager_client.h",
     "dbus/power_policy_controller.cc",
     "dbus/power_policy_controller.h",
+    "dbus/services/chrome_features_service_provider.cc",
+    "dbus/services/chrome_features_service_provider.h",
     "dbus/services/component_updater_service_provider.cc",
     "dbus/services/component_updater_service_provider.h",
     "dbus/services/console_service_provider.cc",
@@ -340,10 +342,10 @@
     "network/client_cert_util.h",
     "network/device_state.cc",
     "network/device_state.h",
-    "network/dhcp_proxy_script_fetcher_chromeos.cc",
-    "network/dhcp_proxy_script_fetcher_chromeos.h",
-    "network/dhcp_proxy_script_fetcher_factory_chromeos.cc",
-    "network/dhcp_proxy_script_fetcher_factory_chromeos.h",
+    "network/dhcp_pac_file_fetcher_chromeos.cc",
+    "network/dhcp_pac_file_fetcher_chromeos.h",
+    "network/dhcp_pac_file_fetcher_factory_chromeos.cc",
+    "network/dhcp_pac_file_fetcher_factory_chromeos.h",
     "network/firewall_hole.cc",
     "network/firewall_hole.h",
     "network/geolocation_handler.cc",
@@ -516,6 +518,7 @@
 
 copy("dbus_service_files") {
   sources = [
+    "dbus/services/org.chromium.ChromeFeaturesService.conf",
     "dbus/services/org.chromium.ComponentUpdaterService.conf",
     "dbus/services/org.chromium.DisplayService.conf",
     "dbus/services/org.chromium.KioskAppService.conf",
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 0f0f677d..27e9a18 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-10322.0.0
\ No newline at end of file
+10324.0.0
\ No newline at end of file
diff --git a/chromeos/dbus/fake_session_manager_client.cc b/chromeos/dbus/fake_session_manager_client.cc
index 043c0dc..c834741 100644
--- a/chromeos/dbus/fake_session_manager_client.cc
+++ b/chromeos/dbus/fake_session_manager_client.cc
@@ -96,6 +96,8 @@
                                           const std::vector<std::string>& argv,
                                           VoidDBusMethodCallback callback) {}
 
+void FakeSessionManagerClient::SaveLoginPassword(const std::string& password) {}
+
 void FakeSessionManagerClient::StartSession(
     const cryptohome::Identification& cryptohome_id) {
   DCHECK_EQ(0UL, user_sessions_.count(cryptohome_id));
diff --git a/chromeos/dbus/fake_session_manager_client.h b/chromeos/dbus/fake_session_manager_client.h
index d13d57e..406ee96 100644
--- a/chromeos/dbus/fake_session_manager_client.h
+++ b/chromeos/dbus/fake_session_manager_client.h
@@ -37,6 +37,7 @@
   void RestartJob(int socket_fd,
                   const std::vector<std::string>& argv,
                   VoidDBusMethodCallback callback) override;
+  void SaveLoginPassword(const std::string& password) override;
   void StartSession(const cryptohome::Identification& cryptohome_id) override;
   void StopSession() override;
   void NotifySupervisedUserCreationStarted() override;
diff --git a/chromeos/dbus/services/chrome_features_service_provider.cc b/chromeos/dbus/services/chrome_features_service_provider.cc
new file mode 100644
index 0000000..f4983c8
--- /dev/null
+++ b/chromeos/dbus/services/chrome_features_service_provider.cc
@@ -0,0 +1,52 @@
+// 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 "chromeos/dbus/services/chrome_features_service_provider.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+ChromeFeaturesServiceProvider::ChromeFeaturesServiceProvider(
+    std::unique_ptr<Delegate> delegate)
+    : delegate_(std::move(delegate)), weak_ptr_factory_(this) {}
+
+ChromeFeaturesServiceProvider::~ChromeFeaturesServiceProvider() = default;
+
+void ChromeFeaturesServiceProvider::Start(
+    scoped_refptr<dbus::ExportedObject> exported_object) {
+  exported_object->ExportMethod(
+      kChromeFeaturesServiceInterface,
+      kChromeFeaturesServiceIsCrostiniEnabledMethod,
+      base::BindRepeating(&ChromeFeaturesServiceProvider::IsCrostiniEnabled,
+                          weak_ptr_factory_.GetWeakPtr()),
+      base::BindRepeating(&ChromeFeaturesServiceProvider::OnExported,
+                          weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ChromeFeaturesServiceProvider::OnExported(
+    const std::string& interface_name,
+    const std::string& method_name,
+    bool success) {
+  if (!success) {
+    LOG(ERROR) << "Failed to export " << interface_name << "." << method_name;
+  }
+}
+
+void ChromeFeaturesServiceProvider::IsCrostiniEnabled(
+    dbus::MethodCall* method_call,
+    dbus::ExportedObject::ResponseSender response_sender) {
+  std::unique_ptr<dbus::Response> response =
+      dbus::Response::FromMethodCall(method_call);
+  dbus::MessageWriter writer(response.get());
+  writer.AppendBool(delegate_->IsCrostiniEnabled());
+  response_sender.Run(std::move(response));
+}
+
+}  // namespace chromeos
diff --git a/chromeos/dbus/services/chrome_features_service_provider.h b/chromeos/dbus/services/chrome_features_service_provider.h
new file mode 100644
index 0000000..91d394b
--- /dev/null
+++ b/chromeos/dbus/services/chrome_features_service_provider.h
@@ -0,0 +1,76 @@
+// 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 CHROMEOS_DBUS_SERVICES_CHROME_FEATURES_SERVICE_PROVIDER_H_
+#define CHROMEOS_DBUS_SERVICES_CHROME_FEATURES_SERVICE_PROVIDER_H_
+
+#include <memory>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/dbus/services/cros_dbus_service.h"
+#include "dbus/exported_object.h"
+
+namespace dbus {
+class MethodCall;
+}
+
+namespace chromeos {
+
+// This class exports D-Bus methods for querying Chrome Features enablement.
+//
+// IsCrostiniEnabled:
+// % dbus-send --system --type=method_call --print-reply
+//     --dest=org.chromium.ChromeFeaturesService
+//     /org/chromium/ChromeFeaturesService
+//     org.chromium.ChromeFeaturesService.IsCrostiniEnabled
+//
+// % (returns true if Crostini is enabled, otherwise returns false)
+class CHROMEOS_EXPORT ChromeFeaturesServiceProvider
+    : public CrosDBusService::ServiceProviderInterface {
+ public:
+  // Delegate interface providing additional resources to
+  // ChromeFeaturesServiceProvider.
+  class Delegate {
+   public:
+    Delegate() {}
+    virtual ~Delegate() {}
+
+    virtual bool IsCrostiniEnabled() = 0;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Delegate);
+  };
+
+  explicit ChromeFeaturesServiceProvider(std::unique_ptr<Delegate> delegate);
+  ~ChromeFeaturesServiceProvider() override;
+
+  // CrosDBusService::ServiceProviderInterface overrides:
+  void Start(scoped_refptr<dbus::ExportedObject> exported_object) override;
+
+ private:
+  // Called from ExportedObject when IsCrostiniEnabled() is exported as a D-Bus
+  // method or failed to be exported.
+  void OnExported(const std::string& interface_name,
+                  const std::string& method_name,
+                  bool success);
+
+  // Called on UI thread in response to a D-Bus request.
+  void IsCrostiniEnabled(dbus::MethodCall* method_call,
+                         dbus::ExportedObject::ResponseSender response_sender);
+
+  std::unique_ptr<Delegate> delegate_;
+  // Keep this last so that all weak pointers will be invalidated at the
+  // beginning of destruction.
+  base::WeakPtrFactory<ChromeFeaturesServiceProvider> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeFeaturesServiceProvider);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_DBUS_SERVICES_CHROME_FEATURES_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/services/org.chromium.ChromeFeaturesService.conf b/chromeos/dbus/services/org.chromium.ChromeFeaturesService.conf
new file mode 100644
index 0000000..9048bde
--- /dev/null
+++ b/chromeos/dbus/services/org.chromium.ChromeFeaturesService.conf
@@ -0,0 +1,18 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+  "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<!--
+  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.
+-->
+<busconfig>
+  <policy user="chronos">
+    <allow own="org.chromium.ChromeFeaturesService"/>
+  </policy>
+
+  <!-- vmc runs as chronos -->
+  <policy user="chronos">
+    <allow send_destination="org.chromium.ChromeFeaturesService"
+           send_interface="org.chromium.ChromeFeaturesService"/>
+  </policy>
+</busconfig>
diff --git a/chromeos/dbus/services/proxy_resolution_service_provider.cc b/chromeos/dbus/services/proxy_resolution_service_provider.cc
index 846d658..cf61b7d 100644
--- a/chromeos/dbus/services/proxy_resolution_service_provider.cc
+++ b/chromeos/dbus/services/proxy_resolution_service_provider.cc
@@ -124,9 +124,9 @@
                  weak_ptr_factory_.GetWeakPtr());
 
   // This would ideally call PostTaskAndReply() instead of PostTask(), but
-  // ResolveProxyOnNetworkThread()'s call to net::ProxyService::ResolveProxy()
-  // can result in an asynchronous lookup, in which case the result won't be
-  // available immediately.
+  // ResolveProxyOnNetworkThread()'s call to
+  // net::ProxyResolutionService::ResolveProxy() can result in an asynchronous
+  // lookup, in which case the result won't be available immediately.
   context_getter->GetNetworkTaskRunner()->PostTask(
       FROM_HERE,
       base::Bind(&ProxyResolutionServiceProvider::ResolveProxyOnNetworkThread,
@@ -142,9 +142,9 @@
   DCHECK(request->context_getter->GetNetworkTaskRunner()
              ->BelongsToCurrentThread());
 
-  net::ProxyService* proxy_service =
-      request->context_getter->GetURLRequestContext()->proxy_service();
-  if (!proxy_service) {
+  net::ProxyResolutionService* proxy_resolution_service =
+      request->context_getter->GetURLRequestContext()->proxy_resolution_service();
+  if (!proxy_resolution_service) {
     request->error = "No proxy service in chrome";
     OnResolutionComplete(std::move(request), notify_thread, notify_callback,
                          net::ERR_UNEXPECTED);
@@ -158,7 +158,7 @@
 
   VLOG(1) << "Starting network proxy resolution for "
           << request_ptr->source_url;
-  const int result = proxy_service->ResolveProxy(
+  const int result = proxy_resolution_service->ResolveProxy(
       GURL(request_ptr->source_url), std::string(), &request_ptr->proxy_info,
       callback, nullptr, nullptr, net::NetLogWithSource());
   if (result != net::ERR_IO_PENDING) {
diff --git a/chromeos/dbus/services/proxy_resolution_service_provider.h b/chromeos/dbus/services/proxy_resolution_service_provider.h
index 0e3ebdc..365cdeaa 100644
--- a/chromeos/dbus/services/proxy_resolution_service_provider.h
+++ b/chromeos/dbus/services/proxy_resolution_service_provider.h
@@ -105,8 +105,9 @@
       scoped_refptr<base::SingleThreadTaskRunner> notify_thread,
       NotifyCallback notify_callback);
 
-  // Callback on network thread for when net::ProxyService::ResolveProxy()
-  // completes, synchronously or asynchronously.
+  // Callback on network thread for when
+  // net::ProxyResolutionService::ResolveProxy() completes, synchronously or
+  // asynchronously.
   static void OnResolutionComplete(
       std::unique_ptr<Request> request,
       scoped_refptr<base::SingleThreadTaskRunner> notify_thread,
diff --git a/chromeos/dbus/services/proxy_resolution_service_provider_unittest.cc b/chromeos/dbus/services/proxy_resolution_service_provider_unittest.cc
index 4e409e8..7f5aa4e 100644
--- a/chromeos/dbus/services/proxy_resolution_service_provider_unittest.cc
+++ b/chromeos/dbus/services/proxy_resolution_service_provider_unittest.cc
@@ -143,36 +143,36 @@
   }
 
  private:
-  // Helper method for the constructor that initializes |proxy_service_| and
-  // injects it into |context_getter_|'s context.
+  // Helper method for the constructor that initializes
+  // |proxy_resolution_service_| and injects it into |context_getter_|'s context.
   void CreateProxyServiceOnNetworkThread() {
     CHECK(context_getter_->GetNetworkTaskRunner()->BelongsToCurrentThread());
 
-    // Setting a mandatory PAC URL makes |proxy_service_| query
+    // Setting a mandatory PAC URL makes |proxy_resolution_service_| query
     // |proxy_resolver_| and also lets us generate
     // net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED errors.
     net::ProxyConfig config;
     config.set_pac_url(GURL("http://www.example.com"));
     config.set_pac_mandatory(true);
-    proxy_service_ = std::make_unique<net::ProxyService>(
+    proxy_resolution_service_ = std::make_unique<net::ProxyResolutionService>(
         std::make_unique<net::ProxyConfigServiceFixed>(config),
         std::make_unique<TestProxyResolverFactory>(proxy_resolver_),
         nullptr /* net_log */);
-    context_getter_->GetURLRequestContext()->set_proxy_service(
-        proxy_service_.get());
+    context_getter_->GetURLRequestContext()->set_proxy_resolution_service(
+        proxy_resolution_service_.get());
   }
 
-  // Helper method for the destructor that resets |proxy_service_|.
+  // Helper method for the destructor that resets |proxy_resolution_service_|.
   void DeleteProxyServiceOnNetworkThread() {
     CHECK(context_getter_->GetNetworkTaskRunner()->BelongsToCurrentThread());
-    proxy_service_.reset();
+    proxy_resolution_service_.reset();
   }
 
   net::ProxyResolver* proxy_resolver_;  // Not owned.
 
-  // Created, used, and destroyed on the network thread (since net::ProxyService
-  // is thread-affine (uses ThreadChecker)).
-  std::unique_ptr<net::ProxyService> proxy_service_;
+  // Created, used, and destroyed on the network thread (since
+  // net::ProxyResolutionService is thread-affine (uses ThreadChecker)).
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service_;
 
   scoped_refptr<net::TestURLRequestContextGetter> context_getter_;
 
diff --git a/chromeos/dbus/session_manager_client.cc b/chromeos/dbus/session_manager_client.cc
index 13a44a2..ae2ce82 100644
--- a/chromeos/dbus/session_manager_client.cc
+++ b/chromeos/dbus/session_manager_client.cc
@@ -165,6 +165,27 @@
   return descriptor;
 }
 
+// Creates a pipe that contains the given data. The data will be prefixed by a
+// size_t sized variable containing the size of the data to read.
+base::ScopedFD CreatePasswordPipe(const std::string& data) {
+  int pipe_fds[2];
+  if (!base::CreateLocalNonBlockingPipe(pipe_fds)) {
+    DLOG(ERROR) << "Failed to create pipe";
+    return base::ScopedFD();
+  }
+  base::ScopedFD pipe_read_end(pipe_fds[0]);
+  base::ScopedFD pipe_write_end(pipe_fds[1]);
+
+  const size_t data_size = data.size();
+
+  base::WriteFileDescriptor(pipe_write_end.get(),
+                            reinterpret_cast<const char*>(&data_size),
+                            sizeof(data_size));
+  base::WriteFileDescriptor(pipe_write_end.get(), data.c_str(), data.size());
+
+  return pipe_read_end;
+}
+
 }  // namespace
 
 // The SessionManagerClient implementation used in production.
@@ -214,6 +235,25 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
+  void SaveLoginPassword(const std::string& password) override {
+    dbus::MethodCall method_call(
+        login_manager::kSessionManagerInterface,
+        login_manager::kSessionManagerSaveLoginPassword);
+    dbus::MessageWriter writer(&method_call);
+
+    base::ScopedFD fd = CreatePasswordPipe(password);
+    if (fd.get() == -1) {
+      LOG(WARNING) << "Could not create password pipe.";
+      return;
+    }
+
+    writer.AppendFileDescriptor(fd.get());
+
+    session_manager_proxy_->CallMethod(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        dbus::ObjectProxy::EmptyResponseCallback());
+  }
+
   void StartSession(const cryptohome::Identification& cryptohome_id) override {
     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
                                  login_manager::kSessionManagerStartSession);
@@ -850,6 +890,7 @@
   void RestartJob(int socket_fd,
                   const std::vector<std::string>& argv,
                   VoidDBusMethodCallback callback) override {}
+  void SaveLoginPassword(const std::string& password) override {}
   void StartSession(const cryptohome::Identification& cryptohome_id) override {}
   void StopSession() override {}
   void NotifySupervisedUserCreationStarted() override {}
diff --git a/chromeos/dbus/session_manager_client.h b/chromeos/dbus/session_manager_client.h
index d2a828b..b73d8ae 100644
--- a/chromeos/dbus/session_manager_client.h
+++ b/chromeos/dbus/session_manager_client.h
@@ -118,6 +118,9 @@
                           const std::vector<std::string>& argv,
                           VoidDBusMethodCallback callback) = 0;
 
+  // Sends the user's password to the session manager.
+  virtual void SaveLoginPassword(const std::string& password) = 0;
+
   // Starts the session for the user.
   virtual void StartSession(
       const cryptohome::Identification& cryptohome_id) = 0;
diff --git a/chromeos/login/auth/user_context.cc b/chromeos/login/auth/user_context.cc
index ae87767..5920a501 100644
--- a/chromeos/login/auth/user_context.cc
+++ b/chromeos/login/auth/user_context.cc
@@ -59,6 +59,14 @@
   return &key_;
 }
 
+const Key* UserContext::GetPasswordKey() const {
+  return &password_key_;
+}
+
+Key* UserContext::GetMutablePasswordKey() {
+  return &password_key_;
+}
+
 const std::string& UserContext::GetAuthCode() const {
   return auth_code_;
 }
@@ -129,6 +137,10 @@
   key_ = key;
 }
 
+void UserContext::SetPasswordKey(const Key& key) {
+  password_key_ = key;
+}
+
 void UserContext::SetAuthCode(const std::string& auth_code) {
   auth_code_ = auth_code;
 }
@@ -188,6 +200,7 @@
 
 void UserContext::ClearSecrets() {
   key_.ClearSecret();
+  password_key_.ClearSecret();
   auth_code_.clear();
   refresh_token_.clear();
 }
diff --git a/chromeos/login/auth/user_context.h b/chromeos/login/auth/user_context.h
index fb873265..2e6bb58 100644
--- a/chromeos/login/auth/user_context.h
+++ b/chromeos/login/auth/user_context.h
@@ -52,6 +52,8 @@
   const std::string& GetGaiaID() const;
   const Key* GetKey() const;
   Key* GetKey();
+  const Key* GetPasswordKey() const;
+  Key* GetMutablePasswordKey();
   const std::string& GetAuthCode() const;
   const std::string& GetRefreshToken() const;
   const std::string& GetAccessToken() const;
@@ -72,6 +74,7 @@
 
   void SetAccountId(const AccountId& account_id);
   void SetKey(const Key& key);
+  void SetPasswordKey(const Key& key);
   void SetAuthCode(const std::string& auth_code);
   void SetRefreshToken(const std::string& refresh_token);
   void SetAccessToken(const std::string& access_token);
@@ -93,6 +96,7 @@
  private:
   AccountId account_id_;
   Key key_;
+  Key password_key_;
   std::string auth_code_;
   std::string refresh_token_;
   std::string access_token_;  // OAuthLogin scoped access token.
diff --git a/chromeos/network/dhcp_proxy_script_fetcher_chromeos.cc b/chromeos/network/dhcp_pac_file_fetcher_chromeos.cc
similarity index 94%
rename from chromeos/network/dhcp_proxy_script_fetcher_chromeos.cc
rename to chromeos/network/dhcp_pac_file_fetcher_chromeos.cc
index 0998de1..341cdfa 100644
--- a/chromeos/network/dhcp_proxy_script_fetcher_chromeos.cc
+++ b/chromeos/network/dhcp_pac_file_fetcher_chromeos.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/network/dhcp_proxy_script_fetcher_chromeos.h"
+#include "chromeos/network/dhcp_pac_file_fetcher_chromeos.h"
 
 #include "base/location.h"
 #include "base/task_runner_util.h"
@@ -10,8 +10,8 @@
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "net/proxy/proxy_script_fetcher.h"
-#include "net/proxy/proxy_script_fetcher_impl.h"
+#include "net/proxy/pac_file_fetcher.h"
+#include "net/proxy/pac_file_fetcher_impl.h"
 #include "net/url_request/url_request_context.h"
 
 namespace chromeos {
diff --git a/chromeos/network/dhcp_proxy_script_fetcher_chromeos.h b/chromeos/network/dhcp_pac_file_fetcher_chromeos.h
similarity index 87%
rename from chromeos/network/dhcp_proxy_script_fetcher_chromeos.h
rename to chromeos/network/dhcp_pac_file_fetcher_chromeos.h
index b61c9031..36acc485 100644
--- a/chromeos/network/dhcp_proxy_script_fetcher_chromeos.h
+++ b/chromeos/network/dhcp_pac_file_fetcher_chromeos.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_DHCP_PROXY_SCRIPT_FETCHER_CHROMEOS_H_
-#define CHROMEOS_NETWORK_DHCP_PROXY_SCRIPT_FETCHER_CHROMEOS_H_
+#ifndef CHROMEOS_NETWORK_DHCP_PAC_FILE_FETCHER_CHROMEOS_H_
+#define CHROMEOS_NETWORK_DHCP_PAC_FILE_FETCHER_CHROMEOS_H_
 
 #include <memory>
 
@@ -11,7 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "chromeos/chromeos_export.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -60,4 +60,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_NETWORK_DHCP_PROXY_SCRIPT_FETCHER_CHROMEOS_H_
+#endif  // CHROMEOS_NETWORK_DHCP_PAC_FILE_FETCHER_CHROMEOS_H_
diff --git a/chromeos/network/dhcp_proxy_script_fetcher_factory_chromeos.cc b/chromeos/network/dhcp_pac_file_fetcher_factory_chromeos.cc
similarity index 82%
rename from chromeos/network/dhcp_proxy_script_fetcher_factory_chromeos.cc
rename to chromeos/network/dhcp_pac_file_fetcher_factory_chromeos.cc
index 96aeef0a..dc5a89c 100644
--- a/chromeos/network/dhcp_proxy_script_fetcher_factory_chromeos.cc
+++ b/chromeos/network/dhcp_pac_file_fetcher_factory_chromeos.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/network/dhcp_proxy_script_fetcher_factory_chromeos.h"
+#include "chromeos/network/dhcp_pac_file_fetcher_factory_chromeos.h"
 
 #include <memory>
 
-#include "chromeos/network/dhcp_proxy_script_fetcher_chromeos.h"
+#include "chromeos/network/dhcp_pac_file_fetcher_chromeos.h"
 
 namespace chromeos {
 
diff --git a/chromeos/network/dhcp_proxy_script_fetcher_factory_chromeos.h b/chromeos/network/dhcp_pac_file_fetcher_factory_chromeos.h
similarity index 79%
rename from chromeos/network/dhcp_proxy_script_fetcher_factory_chromeos.h
rename to chromeos/network/dhcp_pac_file_fetcher_factory_chromeos.h
index 9265c96c..ef57f68 100644
--- a/chromeos/network/dhcp_proxy_script_fetcher_factory_chromeos.h
+++ b/chromeos/network/dhcp_pac_file_fetcher_factory_chromeos.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_DHCP_PROXY_SCRIPT_FETCHER_FACTORY_CHROMEOS_H_
-#define CHROMEOS_NETWORK_DHCP_PROXY_SCRIPT_FETCHER_FACTORY_CHROMEOS_H_
+#ifndef CHROMEOS_NETWORK_DHCP_PAC_FILE_FETCHER_FACTORY_CHROMEOS_H_
+#define CHROMEOS_NETWORK_DHCP_PAC_FILE_FETCHER_FACTORY_CHROMEOS_H_
 
 #include <memory>
 
 #include "base/macros.h"
 #include "chromeos/chromeos_export.h"
-#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
+#include "net/proxy/dhcp_pac_file_fetcher_factory.h"
 
 namespace net {
 class DhcpProxyScriptFetcher;
@@ -37,4 +37,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_NETWORK_DHCP_PROXY_SCRIPT_FETCHER_FACTORY_CHROMEOS_H_
+#endif  // CHROMEOS_NETWORK_DHCP_PAC_FILE_FETCHER_FACTORY_CHROMEOS_H_
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index 939dbaa..c3ab9331 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -1338,5 +1338,56 @@
   return policy != NULL;
 }
 
+bool HasUserPasswordSubsitutionVariable(const OncValueSignature& signature,
+                                        base::DictionaryValue* onc_object) {
+  if (&signature == &kEAPSignature) {
+    std::string password_field;
+    if (!onc_object->GetStringWithoutPathExpansion(::onc::eap::kPassword,
+                                                   &password_field)) {
+      return false;
+    }
+
+    if (password_field == ::onc::substitutes::kPasswordField) {
+      return true;
+    }
+  }
+
+  // Recurse into nested objects.
+  for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd();
+       it.Advance()) {
+    base::DictionaryValue* inner_object = nullptr;
+    if (!onc_object->GetDictionaryWithoutPathExpansion(it.key(), &inner_object))
+      continue;
+
+    const OncFieldSignature* field_signature =
+        GetFieldSignature(signature, it.key());
+    if (!field_signature)
+      continue;
+
+    bool result = HasUserPasswordSubsitutionVariable(
+        *field_signature->value_signature, inner_object);
+    if (result) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool HasUserPasswordSubsitutionVariable(base::ListValue* network_configs) {
+  for (auto& entry : *network_configs) {
+    base::DictionaryValue* network = nullptr;
+    entry.GetAsDictionary(&network);
+    DCHECK(network);
+
+    bool result = HasUserPasswordSubsitutionVariable(
+        kNetworkConfigurationSignature, network);
+    if (result) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace onc
 }  // namespace chromeos
diff --git a/chromeos/network/onc/onc_utils.h b/chromeos/network/onc/onc_utils.h
index d64613e1..65ffe84 100644
--- a/chromeos/network/onc/onc_utils.h
+++ b/chromeos/network/onc/onc_utils.h
@@ -206,6 +206,17 @@
                                          const PrefService* local_state_prefs,
                                          const NetworkState& network);
 
+// Checks whether a WiFi dictionary object has the ${PASSWORD} substitution
+// variable set as the password.
+CHROMEOS_EXPORT bool HasUserPasswordSubsitutionVariable(
+    const OncValueSignature& signature,
+    base::DictionaryValue* onc_object);
+
+// Checks whether a list of network objects has at least one network with the
+// ${PASSWORD} substitution variable set as the password.
+CHROMEOS_EXPORT bool HasUserPasswordSubsitutionVariable(
+    base::ListValue* network_configs);
+
 }  // namespace onc
 }  // namespace chromeos
 
diff --git a/chromeos/network/onc/onc_utils_unittest.cc b/chromeos/network/onc/onc_utils_unittest.cc
index 63407c5..548877d 100644
--- a/chromeos/network/onc/onc_utils_unittest.cc
+++ b/chromeos/network/onc/onc_utils_unittest.cc
@@ -232,5 +232,48 @@
   }
 }
 
+TEST(ONCPasswordVariable, PasswordAvailable) {
+  const auto wifi_onc = test_utils::ReadTestDictionary(
+      "wifi_eap_ttls_with_password_variable.onc");
+
+  EXPECT_TRUE(HasUserPasswordSubsitutionVariable(kNetworkConfigurationSignature,
+                                                 wifi_onc.get()));
+}
+
+TEST(ONCPasswordVariable, PasswordNotAvailable) {
+  const auto wifi_onc = test_utils::ReadTestDictionary("wifi_eap_ttls.onc");
+
+  EXPECT_FALSE(HasUserPasswordSubsitutionVariable(
+      kNetworkConfigurationSignature, wifi_onc.get()));
+}
+
+TEST(ONCPasswordVariable, PasswordHarcdoded) {
+  const auto wifi_onc = test_utils::ReadTestDictionary(
+      "wifi_eap_ttls_with_hardcoded_password.onc");
+
+  EXPECT_FALSE(HasUserPasswordSubsitutionVariable(
+      kNetworkConfigurationSignature, wifi_onc.get()));
+}
+
+TEST(ONCPasswordVariable, MultipleNetworksPasswordAvailable) {
+  const auto network_dictionary = test_utils::ReadTestDictionary(
+      "managed_toplevel_with_password_variable.onc");
+
+  const auto network_list = std::make_unique<base::ListValue>(base::ListValue(
+      network_dictionary->FindKey("NetworkConfigurations")->GetList()));
+
+  EXPECT_TRUE(HasUserPasswordSubsitutionVariable(network_list.get()));
+}
+
+TEST(ONCPasswordVariable, MultipleNetworksPasswordNotAvailable) {
+  const auto network_dictionary = test_utils::ReadTestDictionary(
+      "managed_toplevel_with_no_password_variable.onc");
+
+  const auto network_list = std::make_unique<base::ListValue>(base::ListValue(
+      network_dictionary->FindKey("NetworkConfigurations")->GetList()));
+
+  EXPECT_FALSE(HasUserPasswordSubsitutionVariable(network_list.get()));
+}
+
 }  // namespace onc
 }  // namespace chromeos
diff --git a/chromeos/network/proxy/proxy_config_service_impl_unittest.cc b/chromeos/network/proxy/proxy_config_service_impl_unittest.cc
index 6bd5088..a0e1ddf 100644
--- a/chromeos/network/proxy/proxy_config_service_impl_unittest.cc
+++ b/chromeos/network/proxy/proxy_config_service_impl_unittest.cc
@@ -78,17 +78,17 @@
   ProxyConfigServiceImpl proxy_tracker(&profile_prefs, &local_state_prefs,
                                        base::ThreadTaskRunnerHandle::Get());
 
-  std::unique_ptr<net::ProxyConfigService> proxy_service =
+  std::unique_ptr<net::ProxyConfigService> proxy_resolution_service =
       proxy_tracker.CreateTrackingProxyConfigService(std::move(nested_service));
 
   net::ProxyConfig config;
   EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID,
-            proxy_service->GetLatestProxyConfig(&config));
+            proxy_resolution_service->GetLatestProxyConfig(&config));
   EXPECT_TRUE(config.Equals(net::ProxyConfig::CreateDirect()));
 
   environment_.RunUntilIdle();
   EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID,
-            proxy_service->GetLatestProxyConfig(&config));
+            proxy_resolution_service->GetLatestProxyConfig(&config));
   EXPECT_TRUE(config.Equals(net::ProxyConfig::CreateDirect()));
 
   proxy_tracker.DetachFromPrefService();
@@ -112,17 +112,17 @@
   ProxyConfigServiceImpl proxy_tracker(&profile_prefs, &local_state_prefs,
                                        base::ThreadTaskRunnerHandle::Get());
 
-  std::unique_ptr<net::ProxyConfigService> proxy_service =
+  std::unique_ptr<net::ProxyConfigService> proxy_resolution_service =
       proxy_tracker.CreateTrackingProxyConfigService(std::move(nested_service));
 
   net::ProxyConfig config;
   EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID,
-            proxy_service->GetLatestProxyConfig(&config));
+            proxy_resolution_service->GetLatestProxyConfig(&config));
   EXPECT_TRUE(config.Equals(fixed_config));
 
   environment_.RunUntilIdle();
   EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID,
-            proxy_service->GetLatestProxyConfig(&config));
+            proxy_resolution_service->GetLatestProxyConfig(&config));
   EXPECT_TRUE(config.Equals(fixed_config));
 
   proxy_tracker.DetachFromPrefService();
diff --git a/chromeos/test/data/network/managed_toplevel_with_no_password_variable.onc b/chromeos/test/data/network/managed_toplevel_with_no_password_variable.onc
new file mode 100644
index 0000000..af446bec
--- /dev/null
+++ b/chromeos/test/data/network/managed_toplevel_with_no_password_variable.onc
@@ -0,0 +1,59 @@
+{
+  "NetworkConfigurations": [
+    {
+      "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
+      "Type": "WiFi",
+      "Name": "MyWifi1",
+      "WiFi": {
+        "SSID": "MyWifi1",
+        "Security": "WPA-EAP",
+        "Recommended": [ "AutoConnect" ],
+        "EAP": {
+          "Outer": "EAP-TLS",
+          "Identity": "${LOGIN_ID}@my.domain.com",
+          "UseSystemCAs": true,
+          "ClientCertType": "Pattern",
+          "ClientCertPattern": {
+            "IssuerCARef": [
+              "{58ac1967-a0e7-49e9-be68-123abc}",
+              "{42cb13cd-140c-4941-9fb6-456def}"
+            ],
+            "EnrollmentURI": [ "chrome-extension://delkjfjibodjclmdijflfnimdmgdagfk/generate-cert.html" ]
+          },
+          "Recommended": [ "Identity" ],
+          "SaveCredentials": true
+        }
+      },
+      "ProxySettings": {
+        "Type": "PAC",
+        "PAC": "https://proxycfg.my.domain.com/proxy.dat"
+      }
+    },
+    {
+      "GUID": "{77db0089-0bc8-4358-929c-123xca}",
+      "Type": "WiFi",
+      "Name": "MyWifi2",
+      "WiFi": {
+        "SSID": "MyWifi2",
+        "Security": "WPA-EAP",
+        "Recommended": [ "AutoConnect" ],
+        "EAP": {
+          "Outer": "EAP-TTLS",
+          "Identity": "${LOGIN_ID}@my.domain.com",
+          "Password": "mypassword",
+          "UseSystemCAs": true,
+          "ClientCertType": "Pattern",
+          "ClientCertPattern": {
+            "IssuerCARef": [
+              "{58ac1967-a0e7-49e9-be68-123abc}",
+              "{42cb13cd-140c-4941-9fb6-456def}"
+            ],
+            "EnrollmentURI": [ "chrome-extension://delkjfjibodjclmdijflfnimdmgdagfk/generate-cert.html" ]
+          },
+          "Recommended": [ "Identity" ],
+          "SaveCredentials": true
+        }
+      },
+    },
+  ]
+}
diff --git a/chromeos/test/data/network/managed_toplevel_with_password_variable.onc b/chromeos/test/data/network/managed_toplevel_with_password_variable.onc
new file mode 100644
index 0000000..15c22335
--- /dev/null
+++ b/chromeos/test/data/network/managed_toplevel_with_password_variable.onc
@@ -0,0 +1,59 @@
+{
+  "NetworkConfigurations": [
+  {
+    "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
+    "Type": "WiFi",
+    "Name": "MyWifi1",
+    "WiFi": {
+      "SSID": "MyWifi1",
+      "Security": "WPA-EAP",
+      "Recommended": [ "AutoConnect" ],
+      "EAP": {
+        "Outer": "EAP-TLS",
+        "Identity": "${LOGIN_ID}@my.domain.com",
+        "UseSystemCAs": true,
+        "ClientCertType": "Pattern",
+        "ClientCertPattern": {
+          "IssuerCARef": [
+            "{58ac1967-a0e7-49e9-be68-123abc}",
+            "{42cb13cd-140c-4941-9fb6-456def}"
+          ],
+          "EnrollmentURI": [ "chrome-extension://delkjfjibodjclmdijflfnimdmgdagfk/generate-cert.html" ]
+        },
+        "Recommended": [ "Identity" ],
+        "SaveCredentials": true
+      }
+    },
+    "ProxySettings": {
+      "Type": "PAC",
+      "PAC": "https://proxycfg.my.domain.com/proxy.dat"
+    }
+  },
+  {
+    "GUID": "{77db0089-0bc8-4358-929c-123xca}",
+    "Type": "WiFi",
+    "Name": "MyWifi2",
+    "WiFi": {
+      "SSID": "MyWifi2",
+      "Security": "WPA-EAP",
+      "Recommended": [ "AutoConnect" ],
+      "EAP": {
+        "Outer": "EAP-TTLS",
+        "Identity": "${LOGIN_ID}@my.domain.com",
+        "Password": "${PASSWORD}",
+        "UseSystemCAs": true,
+        "ClientCertType": "Pattern",
+        "ClientCertPattern": {
+          "IssuerCARef": [
+            "{58ac1967-a0e7-49e9-be68-123abc}",
+            "{42cb13cd-140c-4941-9fb6-456def}"
+          ],
+          "EnrollmentURI": [ "chrome-extension://delkjfjibodjclmdijflfnimdmgdagfk/generate-cert.html" ]
+        },
+        "Recommended": [ "Identity" ],
+        "SaveCredentials": true
+      }
+    },
+  },
+  ]
+}
diff --git a/chromeos/test/data/network/wifi_eap_ttls_with_hardcoded_password.onc b/chromeos/test/data/network/wifi_eap_ttls_with_hardcoded_password.onc
new file mode 100644
index 0000000..4bba849
--- /dev/null
+++ b/chromeos/test/data/network/wifi_eap_ttls_with_hardcoded_password.onc
@@ -0,0 +1,18 @@
+{
+  "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
+  "Type": "WiFi",
+  "Name": "WifiEapTtls",
+  "WiFi": {
+    "Security": "WPA-EAP",
+    "EAP": {
+      "Outer": "EAP-TTLS",
+      "Inner": "MSCHAPv2",
+      "Identity": "my_identity",
+      "Password": "my_password",
+      "UseSystemCAs": true,
+      "ClientCertType": "Ref",
+      "ClientCertRef": "{58ac1967-a0e7-49e9-be68-123abc}",
+      "SaveCredentials": true
+    }
+  },
+}
diff --git a/chromeos/test/data/network/wifi_eap_ttls_with_password_variable.onc b/chromeos/test/data/network/wifi_eap_ttls_with_password_variable.onc
new file mode 100644
index 0000000..c864198
--- /dev/null
+++ b/chromeos/test/data/network/wifi_eap_ttls_with_password_variable.onc
@@ -0,0 +1,18 @@
+{
+  "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
+  "Type": "WiFi",
+  "Name": "WifiEapTtls",
+  "WiFi": {
+    "Security": "WPA-EAP",
+    "EAP": {
+      "Outer": "EAP-TTLS",
+      "Inner": "MSCHAPv2",
+      "Identity": "my_identity",
+      "Password": "${PASSWORD}",
+      "UseSystemCAs": true,
+      "ClientCertType": "Ref",
+      "ClientCertRef": "{58ac1967-a0e7-49e9-be68-123abc}",
+      "SaveCredentials": true
+    }
+  },
+}
diff --git a/components/BUILD.gn b/components/BUILD.gn
index edcca1e3..982c25b 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -6,6 +6,7 @@
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
 import("//components/nacl/features.gni")
+import("//media/media_options.gni")
 import("//printing/features/features.gni")
 import("//rlz/features/features.gni")
 import("//testing/test.gni")
@@ -323,6 +324,13 @@
     deps += [ "//components/safe_browsing/android:unit_tests_mobile" ]
   }
 
+  if (enable_webrtc && !is_ios) {
+    deps += [
+      "//components/webrtc_logging/browser:unit_tests",
+      "//components/webrtc_logging/common:unit_tests",
+    ]
+  }
+
   # No components should depend on Chrome.
   assert_no_deps = [ "//chrome/*" ]
 
diff --git a/components/cronet/android/cronet_library_loader.cc b/components/cronet/android/cronet_library_loader.cc
index 1e5549a..f2ea77b 100644
--- a/components/cronet/android/cronet_library_loader.cc
+++ b/components/cronet/android/cronet_library_loader.cc
@@ -116,7 +116,7 @@
 std::unique_ptr<net::ProxyConfigService> CreateProxyConfigService(
     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
   std::unique_ptr<net::ProxyConfigService> service =
-      net::ProxyService::CreateSystemProxyConfigService(io_task_runner);
+      net::ProxyResolutionService::CreateSystemProxyConfigService(io_task_runner);
   // If a PAC URL is present, ignore it and use the address and port of
   // Android system's local HTTP proxy server. See: crbug.com/432539.
   // TODO(csharrison) Architect the wrapper better so we don't need to cast for
@@ -128,13 +128,13 @@
 }
 
 // Creates a proxy service appropriate for this platform.
-std::unique_ptr<net::ProxyService> CreateProxyService(
+std::unique_ptr<net::ProxyResolutionService> CreateProxyService(
     std::unique_ptr<net::ProxyConfigService> proxy_config_service,
     net::NetLog* net_log) {
   // Android provides a local HTTP proxy server that handles proxying when a PAC
   // URL is present. Create a proxy service without a resolver and rely on this
   // local HTTP proxy. See: crbug.com/432539.
-  return net::ProxyService::CreateWithoutProxyResolver(
+  return net::ProxyResolutionService::CreateWithoutProxyResolver(
       std::move(proxy_config_service), net_log);
 }
 
diff --git a/components/cronet/cronet_global_state.h b/components/cronet/cronet_global_state.h
index 48546e12..7c070f49 100644
--- a/components/cronet/cronet_global_state.h
+++ b/components/cronet/cronet_global_state.h
@@ -13,7 +13,7 @@
 namespace net {
 class NetLog;
 class ProxyConfigService;
-class ProxyService;
+class ProxyResolutionService;
 }  // namespace net
 
 namespace cronet {
@@ -29,7 +29,7 @@
 
 // Creates a proxy service appropriate for this platform that fetches the
 // system proxy settings.
-std::unique_ptr<net::ProxyService> CreateProxyService(
+std::unique_ptr<net::ProxyResolutionService> CreateProxyService(
     std::unique_ptr<net::ProxyConfigService> proxy_config_service,
     net::NetLog* net_log);
 
diff --git a/components/cronet/cronet_url_request_context.cc b/components/cronet/cronet_url_request_context.cc
index 540cb98f..cd11ad6 100644
--- a/components/cronet/cronet_url_request_context.cc
+++ b/components/cronet/cronet_url_request_context.cc
@@ -320,7 +320,7 @@
       std::make_unique<BasicNetworkDelegate>());
   context_builder.set_net_log(g_net_log.Get().net_log());
 
-  context_builder.set_proxy_service(cronet::CreateProxyService(
+  context_builder.set_proxy_resolution_service(cronet::CreateProxyService(
       std::move(proxy_config_service), g_net_log.Get().net_log()));
 
   config->ConfigureURLRequestContextBuilder(&context_builder,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
index 58e17ba..2dddf208 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
@@ -60,10 +60,11 @@
   net::ProxyInfo proxy_info;
   proxy_info.UseProxyList(proxy_list);
   DCHECK(request->context());
-  net::ProxyService* proxy_service = request->context()->proxy_service();
-  DCHECK(proxy_service);
+  net::ProxyResolutionService* proxy_resolution_service =
+      request->context()->proxy_resolution_service();
+  DCHECK(proxy_resolution_service);
 
-  proxy_service->MarkProxiesAsBadUntil(
+  proxy_resolution_service->MarkProxiesAsBadUntil(
       proxy_info, bypass_duration, additional_bad_proxies, request->net_log());
 }
 
@@ -250,13 +251,13 @@
     return false;
 
   DCHECK(request.context());
-  DCHECK(request.context()->proxy_service());
+  DCHECK(request.context()->proxy_resolution_service());
   net::ProxyServer proxy_server =
       data_reduction_proxy_type_info->proxy_servers.front();
 
   // Only record UMA if the proxy isn't already on the retry list.
   if (!config_->IsProxyBypassed(
-          request.context()->proxy_service()->proxy_retry_info(), proxy_server,
+          request.context()->proxy_resolution_service()->proxy_retry_info(), proxy_server,
           nullptr)) {
     DataReductionProxyBypassStats::RecordDataReductionProxyBypassInfo(
         data_reduction_proxy_type_info->proxy_index == 0,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h
index b8e1800..40aaf09 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h
@@ -42,10 +42,11 @@
   ~DataReductionProxyBypassProtocol();
 
   // Decides whether to mark the data reduction proxy as temporarily bad and
-  // put it on the proxy retry map, which is maintained by the ProxyService of
-  // the URLRequestContext. Returns true if the request should be retried.
-  // Updates the load flags in |request| for some bypass types, e.g.,
-  // "block-once". Returns the DataReductionProxyBypassType (if not NULL).
+  // put it on the proxy retry map, which is maintained by the
+  // ProxyResolutionService of the URLRequestContext. Returns true if the
+  // request should be retried. Updates the load flags in |request| for some
+  // bypass types, e.g., "block-once". Returns the DataReductionProxyBypassType
+  // (if not NULL).
   bool MaybeBypassProxyAndPrepareToRetry(
       net::URLRequest* request,
       DataReductionProxyBypassType* proxy_bypass_type,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
index fa0b804..8d44693 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -60,7 +60,7 @@
 using net::MockRead;
 using net::MockWrite;
 using net::ProxyRetryInfoMap;
-using net::ProxyService;
+using net::ProxyResolutionService;
 using net::StaticSocketDataProvider;
 using net::TestDelegate;
 using net::TestURLRequestContext;
@@ -109,13 +109,15 @@
     test_context_->RunUntilIdle();
   }
 
-  // Sets up the |TestURLRequestContext| with the provided |ProxyService|.
-  void ConfigureTestDependencies(std::unique_ptr<ProxyService> proxy_service) {
+  // Sets up the |TestURLRequestContext| with the provided
+  // |ProxyResolutionService|.
+  void ConfigureTestDependencies(
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service) {
     // Create a context with delayed initialization.
     context_.reset(new TestURLRequestContext(true));
 
-    proxy_service_ = std::move(proxy_service);
-    context_->set_proxy_service(proxy_service_.get());
+    proxy_resolution_service_ = std::move(proxy_resolution_service);
+    context_->set_proxy_resolution_service(proxy_resolution_service_.get());
 
     DataReductionProxyInterceptor* interceptor =
         new DataReductionProxyInterceptor(
@@ -140,7 +142,7 @@
   base::MessageLoopForIO message_loop_;
   net::EmbeddedTestServer embedded_test_server_;
 
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<DataReductionProxyTestContext> test_context_;
 
   std::unique_ptr<net::URLRequestInterceptingJobFactory> job_factory_;
@@ -169,7 +171,8 @@
   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
       switches::kDataReductionProxy, proxy_server.host_port_pair().ToString());
   test_context_->config()->ResetParamFlagsForTest();
-  ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult("DIRECT"));
+  ConfigureTestDependencies(
+      ProxyResolutionService::CreateFixedFromPacResult("DIRECT"));
 
   test_context_->RunUntilIdle();
   base::RunLoop().RunUntilIdle();
@@ -187,11 +190,12 @@
     }
     EXPECT_FALSE(url_request->proxy_server().is_http());
     // The proxy should have been marked as bad.
-    ProxyRetryInfoMap retry_info = proxy_service_->proxy_retry_info();
+    ProxyRetryInfoMap retry_info =
+        proxy_resolution_service_->proxy_retry_info();
     while (retry_info.size() != 1) {
       test_context_->RunUntilIdle();
       base::RunLoop().RunUntilIdle();
-      retry_info = proxy_service_->proxy_retry_info();
+      retry_info = proxy_resolution_service_->proxy_retry_info();
     }
 
     EXPECT_LE(base::TimeDelta::FromMinutes(4),
@@ -217,11 +221,12 @@
     EXPECT_TRUE(!url_request->proxy_server().is_valid() ||
                 url_request->proxy_server().is_direct());
     // The proxy should still be marked as bad.
-    ProxyRetryInfoMap retry_info = proxy_service_->proxy_retry_info();
+    ProxyRetryInfoMap retry_info =
+        proxy_resolution_service_->proxy_retry_info();
     while (retry_info.size() != 1) {
       test_context_->RunUntilIdle();
       base::RunLoop().RunUntilIdle();
-      retry_info = proxy_service_->proxy_retry_info();
+      retry_info = proxy_resolution_service_->proxy_retry_info();
     }
 
     EXPECT_LE(base::TimeDelta::FromMinutes(4),
@@ -253,19 +258,21 @@
     test_context_->RunUntilIdle();
   }
 
-  // Sets up the |TestURLRequestContext| with the provided |ProxyService|.
-  void ConfigureTestDependencies(std::unique_ptr<ProxyService> proxy_service,
-                                 bool use_mock_socket_factory,
-                                 bool use_drp_proxy_delegate,
-                                 bool use_test_network_delegate) {
+  // Sets up the |TestURLRequestContext| with the provided
+  // |ProxyResolutionService|.
+  void ConfigureTestDependencies(
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service,
+      bool use_mock_socket_factory,
+      bool use_drp_proxy_delegate,
+      bool use_test_network_delegate) {
     // Create a context with delayed initialization.
     context_.reset(new TestURLRequestContext(true));
 
-    proxy_service_ = std::move(proxy_service);
+    proxy_resolution_service_ = std::move(proxy_resolution_service);
     if (use_mock_socket_factory) {
       context_->set_client_socket_factory(&mock_socket_factory_);
     }
-    context_->set_proxy_service(proxy_service_.get());
+    context_->set_proxy_resolution_service(proxy_resolution_service_.get());
     if (use_test_network_delegate) {
       network_delegate_.reset(new net::TestNetworkDelegate());
       context_->set_network_delegate(network_delegate_.get());
@@ -465,7 +472,8 @@
                       int duration_seconds,
                       const std::string& bad_proxy,
                       const std::string& bad_proxy2) {
-    const ProxyRetryInfoMap& retry_info = proxy_service_->proxy_retry_info();
+    const ProxyRetryInfoMap& retry_info =
+        proxy_resolution_service_->proxy_retry_info();
     ASSERT_EQ(expected_num_bad_proxies, retry_info.size());
 
     base::TimeDelta expected_min_duration;
@@ -501,7 +509,7 @@
   std::unique_ptr<net::URLRequestInterceptor> simple_interceptor_;
   net::MockClientSocketFactory mock_socket_factory_;
   std::unique_ptr<net::TestNetworkDelegate> network_delegate_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<DataReductionProxyTestContext> test_context_;
   std::unique_ptr<DataReductionProxyBypassStats> bypass_stats_;
   net::StaticHttpUserAgentSettings http_user_agent_settings_;
@@ -574,7 +582,7 @@
     base::HistogramTester histogram_tester;
 
     ConfigureTestDependencies(
-        ProxyService::CreateFixedFromPacResult(
+        ProxyResolutionService::CreateFixedFromPacResult(
             net::ProxyServer::FromURI(primary, net::ProxyServer::SCHEME_HTTP)
                 .ToPacString() +
             "; " +
@@ -594,11 +602,12 @@
     TestBadProxies(tests[i].expected_bad_proxy_count,
                    tests[i].expected_duration, primary, fallback);
 
-    ProxyRetryInfoMap retry_info = proxy_service_->proxy_retry_info();
+    ProxyRetryInfoMap retry_info =
+        proxy_resolution_service_->proxy_retry_info();
     while (retry_info.size() != 1) {
       test_context_->RunUntilIdle();
       base::RunLoop().RunUntilIdle();
-      retry_info = proxy_service_->proxy_retry_info();
+      retry_info = proxy_resolution_service_->proxy_retry_info();
     }
 
     EXPECT_LE(base::TimeDelta::FromMinutes(4),
@@ -1019,7 +1028,7 @@
                              .ToString();
   for (size_t i = 0; i < arraysize(tests); ++i) {
     ConfigureTestDependencies(
-        ProxyService::CreateFixedFromPacResult(
+        ProxyResolutionService::CreateFixedFromPacResult(
             net::ProxyServer::FromURI(primary, net::ProxyServer::SCHEME_HTTP)
                 .ToPacString() +
             "; " +
@@ -1129,8 +1138,8 @@
     const std::string kPrimary = "https://unrecognized-drp.net:443";
 
     ResetDependencies();
-    storage()->set_proxy_service(
-        ProxyService::CreateFixed(kPrimary + ",direct://"));
+    storage()->set_proxy_resolution_service(
+        ProxyResolutionService::CreateFixed(kPrimary + ",direct://"));
     AttachToContextAndInit();
 
     // The proxy is an HTTPS proxy, so set up the fake SSL socket data.
@@ -1162,9 +1171,9 @@
     EXPECT_EQ(test.expected_bypass_type,
               drp_test_context()->io_data()->bypass_stats()->GetBypassType());
     // Check the bad proxy list.
-    EXPECT_EQ(test.expected_bad_proxy,
-              base::ContainsKey(context()->proxy_service()->proxy_retry_info(),
-                                kPrimary));
+    EXPECT_EQ(test.expected_bad_proxy, base::ContainsKey(
+        context()->proxy_resolution_service()->proxy_retry_info(),
+        kPrimary));
   }
 }
 
@@ -1199,8 +1208,8 @@
 
   for (const auto& test : test_cases) {
     ResetDependencies();
-    storage()->set_proxy_service(
-        net::ProxyService::CreateFixed(test.proxy_rules));
+    storage()->set_proxy_resolution_service(
+        net::ProxyResolutionService::CreateFixed(test.proxy_rules));
     AttachToContextAndInit();
     if (test.enable_data_reduction_proxy) {
       drp_test_context()->DisableWarmupURLFetch();
@@ -1232,10 +1241,10 @@
        ProxyBypassIgnoredOnDirectConnection) {
   // Verify that a Chrome-Proxy header is ignored when returned from a directly
   // connected origin server.
-  ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult("DIRECT"),
-                            true /* use_mock_socket_factory */,
-                            false /* use_drp_proxy_delegate */,
-                            true /* use_test_network_delegate */);
+  ConfigureTestDependencies(
+      ProxyResolutionService::CreateFixedFromPacResult("DIRECT"),
+      true /* use_mock_socket_factory */, false /* use_drp_proxy_delegate */,
+      true /* use_test_network_delegate */);
 
   MockRead data_reads[] = {
     MockRead("HTTP/1.1 200 OK\r\n"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
index f86c341..7211148 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
@@ -395,8 +395,8 @@
     return request;
   }
 
-  void set_proxy_service(net::ProxyService* proxy_service) {
-    context_.set_proxy_service(proxy_service);
+  void set_proxy_resolution_service(net::ProxyResolutionService* proxy_resolution_service) {
+    context_.set_proxy_resolution_service(proxy_resolution_service);
   }
 
   void set_host_resolver(net::HostResolver* host_resolver) {
@@ -416,7 +416,7 @@
   }
 
   void ClearBadProxies() {
-    context_.proxy_service()->ClearBadProxiesCache();
+    context_.proxy_resolution_service()->ClearBadProxiesCache();
   }
 
   void InitializeContext() {
@@ -597,9 +597,9 @@
 
 TEST_F(DataReductionProxyBypassStatsEndToEndTest,
        BypassedBytesProxyOverridden) {
-  std::unique_ptr<net::ProxyService> proxy_service(
-      net::ProxyService::CreateFixed("http://test.com:80"));
-  set_proxy_service(proxy_service.get());
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+      net::ProxyResolutionService::CreateFixed("http://test.com:80"));
+  set_proxy_resolution_service(proxy_resolution_service.get());
   InitializeContext();
 
   base::HistogramTester histogram_tester;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
index 5e2dfd4..f13d6f99 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -274,7 +274,7 @@
     const net::ProxyConfig& data_reduction_proxy_config) const {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(request.context());
-  DCHECK(request.context()->proxy_service());
+  DCHECK(request.context()->proxy_resolution_service());
   net::ProxyInfo result;
   data_reduction_proxy_config.proxy_rules().Apply(
       request.url(), &result);
@@ -291,9 +291,9 @@
     base::TimeDelta* min_retry_delay) const {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (request.context() != nullptr &&
-      request.context()->proxy_service() != nullptr) {
+      request.context()->proxy_resolution_service() != nullptr) {
     return AreProxiesBypassed(
-        request.context()->proxy_service()->proxy_retry_info(),
+        request.context()->proxy_resolution_service()->proxy_retry_info(),
         data_reduction_proxy_config.proxy_rules(),
         request.url().SchemeIsCryptographic(), min_retry_delay);
   }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
index 9563aba..98eac81f 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
@@ -90,7 +90,6 @@
       configurator_(configurator),
       event_creator_(event_creator),
       bypass_stats_(bypass_stats),
-      alternative_proxies_broken_(false),
       tick_clock_(base::DefaultTickClock::GetInstance()),
       first_data_saver_request_recorded_(false),
       io_data_(nullptr),
@@ -181,8 +180,10 @@
 
   if (!result->is_empty()) {
     net::ProxyServer alternative_proxy_server;
-    GetAlternativeProxy(url, result->proxy_server(), &alternative_proxy_server);
-    result->SetAlternativeProxy(alternative_proxy_server);
+    if (GetAlternativeProxy(url, result->proxy_server(), proxy_retry_info,
+                            &alternative_proxy_server)) {
+      result->SetAlternativeProxy(alternative_proxy_server);
+    }
   }
 
   if (!first_data_saver_request_recorded_ && !result->is_empty() &&
@@ -222,59 +223,49 @@
   last_network_change_time_ = tick_clock_->NowTicks();
 }
 
-void DataReductionProxyDelegate::GetAlternativeProxy(
+bool DataReductionProxyDelegate::GetAlternativeProxy(
     const GURL& url,
     const net::ProxyServer& resolved_proxy_server,
+    const net::ProxyRetryInfoMap& proxy_retry_info,
     net::ProxyServer* alternative_proxy_server) const {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!alternative_proxy_server->is_valid());
 
   if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS() ||
       url.SchemeIsCryptographic()) {
-    return;
+    return false;
   }
 
   if (!params::IsIncludedInQuicFieldTrial()) {
     RecordQuicProxyStatus(QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL);
-    return;
+    return false;
   }
 
   if (!resolved_proxy_server.is_valid() || !resolved_proxy_server.is_https())
-    return;
+    return false;
 
   if (!config_ ||
       !config_->IsDataReductionProxy(resolved_proxy_server, nullptr)) {
-    return;
-  }
-
-  if (alternative_proxies_broken_) {
-    RecordQuicProxyStatus(QUIC_PROXY_STATUS_MARKED_AS_BROKEN);
-    return;
+    return false;
   }
 
   if (!SupportsQUIC(resolved_proxy_server)) {
     RecordQuicProxyStatus(QUIC_PROXY_NOT_SUPPORTED);
-    return;
+    return false;
   }
 
-  *alternative_proxy_server = net::ProxyServer(
-      net::ProxyServer::SCHEME_QUIC, resolved_proxy_server.host_port_pair());
-  DCHECK(alternative_proxy_server->is_valid());
-  RecordQuicProxyStatus(QUIC_PROXY_STATUS_AVAILABLE);
-  return;
-}
+  net::ProxyInfo alternative_proxy_info;
+  alternative_proxy_info.UseProxyServer(net::ProxyServer(
+      net::ProxyServer::SCHEME_QUIC, resolved_proxy_server.host_port_pair()));
+  alternative_proxy_info.DeprioritizeBadProxies(proxy_retry_info);
 
-void DataReductionProxyDelegate::OnAlternativeProxyBroken(
-    const net::ProxyServer& alternative_proxy_server) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  // TODO(tbansal): Reset this on connection change events.
-  // Currently, DataReductionProxyDelegate does not maintain a list of broken
-  // proxies. If one alternative proxy is broken, use of all alternative proxies
-  // is disabled because it is likely that other QUIC proxies would be
-  // broken   too.
-  alternative_proxies_broken_ = true;
-  UMA_HISTOGRAM_COUNTS_100("DataReductionProxy.Quic.OnAlternativeProxyBroken",
-                           1);
+  if (alternative_proxy_info.is_empty()) {
+    RecordQuicProxyStatus(QUIC_PROXY_STATUS_MARKED_AS_BROKEN);
+    return false;
+  }
+
+  RecordQuicProxyStatus(QUIC_PROXY_STATUS_AVAILABLE);
+  *alternative_proxy_server = alternative_proxy_info.proxy_server();
+  return true;
 }
 
 bool DataReductionProxyDelegate::SupportsQUIC(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
index 78cddc6e..eb84ef4f 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
@@ -60,11 +60,6 @@
   void SetTickClockForTesting(base::TickClock* tick_clock);
 
  protected:
-  // Protected so that this method is accessible for testing.
-  // net::ProxyDelegate implementation:
-  void OnAlternativeProxyBroken(
-      const net::ProxyServer& alternative_proxy_server) override;
-
   // Protected so that it can be overridden during testing.
   // Returns true if |proxy_server| supports QUIC.
   virtual bool SupportsQUIC(const net::ProxyServer& proxy_server) const;
@@ -86,8 +81,9 @@
   // NetworkChangeNotifier::IPAddressObserver:
   void OnIPAddressChanged() override;
 
-  void GetAlternativeProxy(const GURL& url,
+  bool GetAlternativeProxy(const GURL& url,
                            const net::ProxyServer& resolved_proxy_server,
+                           const net::ProxyRetryInfoMap& proxy_retry_info,
                            net::ProxyServer* alternative_proxy_server) const;
 
   const DataReductionProxyConfig* config_;
@@ -95,9 +91,6 @@
   DataReductionProxyEventCreator* event_creator_;
   DataReductionProxyBypassStats* bypass_stats_;
 
-  // True if the use of alternate proxies is disabled.
-  bool alternative_proxies_broken_;
-
   // Tick clock used for obtaining the current time.
   base::TickClock* tick_clock_;
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
index dc519c3f..2d63b09 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
@@ -130,7 +130,6 @@
     }
   }
 
-  using DataReductionProxyDelegate::OnAlternativeProxyBroken;
   using DataReductionProxyDelegate::QuicProxyStatus;
 
  private:
@@ -519,30 +518,30 @@
   const struct {
     bool is_in_quic_field_trial;
     bool proxy_supports_quic;
-    GURL gurl;
     net::ProxyServer::Scheme first_proxy_scheme;
     net::ProxyServer::Scheme second_proxy_scheme;
-  } tests[] = {{false, true, GURL("http://www.example.com"),
-                net::ProxyServer::SCHEME_HTTPS, net::ProxyServer::SCHEME_HTTP},
-               {true, true, GURL("http://www.example.com"),
-                net::ProxyServer::SCHEME_HTTPS, net::ProxyServer::SCHEME_HTTP},
-               {true, true, GURL("http://www.example.com"),
-                net::ProxyServer::SCHEME_HTTP, net::ProxyServer::SCHEME_HTTPS},
-               {true, true, GURL("http://www.example.com"),
-                net::ProxyServer::SCHEME_QUIC, net::ProxyServer::SCHEME_HTTP},
-               {true, true, GURL("http://www.example.com"),
-                net::ProxyServer::SCHEME_QUIC, net::ProxyServer::SCHEME_HTTPS},
-               {true, false, GURL("http://www.example.com"),
-                net::ProxyServer::SCHEME_HTTPS, net::ProxyServer::SCHEME_HTTP},
-               {true, false, GURL("http://www.example.com"),
-                net::ProxyServer::SCHEME_HTTP, net::ProxyServer::SCHEME_HTTPS}};
+  } tests[] = {{false, true, net::ProxyServer::SCHEME_HTTPS,
+                net::ProxyServer::SCHEME_HTTP},
+               {true, true, net::ProxyServer::SCHEME_HTTPS,
+                net::ProxyServer::SCHEME_HTTP},
+               {true, true, net::ProxyServer::SCHEME_HTTP,
+                net::ProxyServer::SCHEME_HTTPS},
+               {true, true, net::ProxyServer::SCHEME_QUIC,
+                net::ProxyServer::SCHEME_HTTP},
+               {true, true, net::ProxyServer::SCHEME_QUIC,
+                net::ProxyServer::SCHEME_HTTPS},
+               {true, false, net::ProxyServer::SCHEME_HTTPS,
+                net::ProxyServer::SCHEME_HTTP},
+               {true, false, net::ProxyServer::SCHEME_HTTP,
+                net::ProxyServer::SCHEME_HTTPS}};
+  GURL url("http://www.example.com");
+
   for (const auto test : tests) {
     // True if there should exist a valid alternative proxy server corresponding
     // to the first proxy in the list of proxies available to the data reduction
     // proxy.
     const bool expect_alternative_proxy_server_to_first_proxy =
         test.is_in_quic_field_trial && test.proxy_supports_quic &&
-        !test.gurl.SchemeIsCryptographic() &&
         test.first_proxy_scheme == net::ProxyServer::SCHEME_HTTPS;
 
     // True if there should exist a valid alternative proxy server corresponding
@@ -550,7 +549,6 @@
     // reduction proxy.
     const bool expect_alternative_proxy_server_to_second_proxy =
         test.is_in_quic_field_trial && test.proxy_supports_quic &&
-        !test.gurl.SchemeIsCryptographic() &&
         test.second_proxy_scheme == net::ProxyServer::SCHEME_HTTPS;
 
     std::vector<DataReductionProxyServer> proxies_for_http;
@@ -587,22 +585,20 @@
       // Test if the alternative proxy is correctly set if the resolved proxy is
       // |first_proxy|.
       base::HistogramTester histogram_tester;
-      delegate.OnResolveProxy(test.gurl, "GET", empty_proxy_retry_info,
-                              &proxy_info);
+      delegate.OnResolveProxy(url, "GET", empty_proxy_retry_info, &proxy_info);
       ASSERT_EQ(first_proxy, proxy_info.proxy_server());
       alternative_proxy_server_to_first_proxy = proxy_info.alternative_proxy();
       EXPECT_EQ(expect_alternative_proxy_server_to_first_proxy,
                 alternative_proxy_server_to_first_proxy.is_valid());
 
       // Verify that the metrics are recorded correctly.
-      if (test.is_in_quic_field_trial && !test.gurl.SchemeIsCryptographic() &&
+      if (test.is_in_quic_field_trial &&
           test.first_proxy_scheme == net::ProxyServer::SCHEME_HTTPS) {
         delegate.VerifyQuicHistogramCounts(
             histogram_tester, expect_alternative_proxy_server_to_first_proxy,
             test.proxy_supports_quic, false);
       } else {
-        if (!test.is_in_quic_field_trial &&
-            !test.gurl.SchemeIsCryptographic()) {
+        if (!test.is_in_quic_field_trial) {
           histogram_tester.ExpectUniqueSample(
               "DataReductionProxy.Quic.ProxyStatus",
               3 /* QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL */, 1);
@@ -611,8 +607,6 @@
               "DataReductionProxy.Quic.ProxyStatus", 0);
         }
       }
-      histogram_tester.ExpectTotalCount(
-          "DataReductionProxy.Quic.OnAlternativeProxyBroken", 0);
     }
 
     {
@@ -626,8 +620,8 @@
       proxy_retry_info[first_proxy.ToURI()] = bad_proxy_info;
 
       base::HistogramTester histogram_tester;
-      delegate.OnResolveProxy(test.gurl, "GET", proxy_retry_info, &proxy_info);
-      ASSERT_EQ(second_proxy, proxy_info.proxy_server());
+      delegate.OnResolveProxy(url, "GET", proxy_retry_info, &proxy_info);
+      EXPECT_EQ(second_proxy, proxy_info.proxy_server());
       alternative_proxy_server_to_second_proxy = proxy_info.alternative_proxy();
       EXPECT_EQ(expect_alternative_proxy_server_to_first_proxy,
                 alternative_proxy_server_to_first_proxy.is_valid());
@@ -635,14 +629,13 @@
                 alternative_proxy_server_to_second_proxy.is_valid());
 
       // Verify that the metrics are recorded correctly.
-      if (test.is_in_quic_field_trial && !test.gurl.SchemeIsCryptographic() &&
+      if (test.is_in_quic_field_trial &&
           test.second_proxy_scheme == net::ProxyServer::SCHEME_HTTPS) {
         delegate.VerifyQuicHistogramCounts(
             histogram_tester, expect_alternative_proxy_server_to_second_proxy,
             test.proxy_supports_quic, false);
       } else {
-        if (!test.is_in_quic_field_trial &&
-            !test.gurl.SchemeIsCryptographic()) {
+        if (!test.is_in_quic_field_trial) {
           histogram_tester.ExpectUniqueSample(
               "DataReductionProxy.Quic.ProxyStatus",
               3 /* QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL */, 1);
@@ -651,8 +644,6 @@
               "DataReductionProxy.Quic.ProxyStatus", 0);
         }
       }
-      histogram_tester.ExpectTotalCount(
-          "DataReductionProxy.Quic.OnAlternativeProxyBroken", 0);
     }
 
     {
@@ -663,13 +654,12 @@
       proxy_info.UseProxyServer(non_drp_proxy_server);
 
       base::HistogramTester histogram_tester;
-      delegate.OnResolveProxy(test.gurl, "GET", empty_proxy_retry_info,
-                              &proxy_info);
-      ASSERT_EQ(non_drp_proxy_server, proxy_info.proxy_server());
+      delegate.OnResolveProxy(url, "GET", empty_proxy_retry_info, &proxy_info);
+      EXPECT_EQ(non_drp_proxy_server, proxy_info.proxy_server());
       EXPECT_FALSE(proxy_info.alternative_proxy().is_valid());
 
       // Verify that the metrics are recorded correctly.
-      if (!test.is_in_quic_field_trial && !test.gurl.SchemeIsCryptographic()) {
+      if (!test.is_in_quic_field_trial) {
         histogram_tester.ExpectUniqueSample(
             "DataReductionProxy.Quic.ProxyStatus",
             3 /* QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL */, 1);
@@ -677,38 +667,30 @@
         histogram_tester.ExpectTotalCount("DataReductionProxy.Quic.ProxyStatus",
                                           0);
       }
-
-      histogram_tester.ExpectTotalCount(
-          "DataReductionProxy.Quic.OnAlternativeProxyBroken", 0);
     }
 
     // Test if the alternative proxy is correctly marked as broken.
     if (expect_alternative_proxy_server_to_first_proxy) {
+      base::HistogramTester histogram_tester;
       proxy_info.UseDirect();
 
-      base::HistogramTester histogram_tester;
       // Verify that when the alternative proxy server is reported as broken,
       // then it is no longer returned when OnResolveProxy is called.
-      EXPECT_EQ(
-          first_proxy.host_port_pair().host(),
-          alternative_proxy_server_to_first_proxy.host_port_pair().host());
-      EXPECT_EQ(
-          first_proxy.host_port_pair().port(),
-          alternative_proxy_server_to_first_proxy.host_port_pair().port());
-      EXPECT_EQ(net::ProxyServer::SCHEME_QUIC,
-                alternative_proxy_server_to_first_proxy.scheme());
+      net::ProxyRetryInfoMap proxy_retry_info;
+      net::ProxyRetryInfo bad_proxy_info;
+      bad_proxy_info.bad_until = base::TimeTicks() + base::TimeDelta::Max();
+      bad_proxy_info.try_while_bad = false;
+      net::ProxyServer bad_proxy_server(net::ProxyServer::SCHEME_QUIC,
+                                        first_proxy.host_port_pair());
+      proxy_retry_info[bad_proxy_server.ToURI()] = bad_proxy_info;
 
-      delegate.OnAlternativeProxyBroken(first_proxy);
-      delegate.OnResolveProxy(test.gurl, "GET", empty_proxy_retry_info,
-                              &proxy_info);
+      delegate.OnResolveProxy(url, "GET", proxy_retry_info, &proxy_info);
       ASSERT_EQ(first_proxy, proxy_info.proxy_server());
+      EXPECT_FALSE(proxy_info.alternative_proxy().is_valid());
 
       delegate.VerifyQuicHistogramCounts(
           histogram_tester, expect_alternative_proxy_server_to_first_proxy,
           test.proxy_supports_quic, true);
-      histogram_tester.ExpectTotalCount(
-          "DataReductionProxy.Quic.OnAlternativeProxyBroken", 1);
-      EXPECT_FALSE(proxy_info.alternative_proxy().is_valid());
     }
   }
 }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
index 27520ed..b1fdde2 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
@@ -103,8 +103,8 @@
   TestURLRequestContextWithDataReductionProxy(const net::ProxyServer& origin,
                                               net::NetworkDelegate* delegate)
       : net::TestURLRequestContext(true) {
-    context_storage_.set_proxy_service(
-        net::ProxyService::CreateFixed(origin.ToURI()));
+    context_storage_.set_proxy_resolution_service(
+        net::ProxyResolutionService::CreateFixed(origin.ToURI()));
     set_network_delegate(delegate);
   }
 
@@ -231,10 +231,11 @@
         DataReductionProxyServer(origin, ProxyServer::UNSPECIFIED_TYPE));
     test_context_->config()->test_params()->SetProxiesForHttp(proxies_for_http);
     std::string proxy_name = origin.ToURI();
-    proxy_service_ = net::ProxyService::CreateFixedFromPacResult(
-        "PROXY " + proxy_name + "; DIRECT");
+    proxy_resolution_service_ =
+        net::ProxyResolutionService::CreateFixedFromPacResult(
+            "PROXY " + proxy_name + "; DIRECT");
 
-    context_.set_proxy_service(proxy_service_.get());
+    context_.set_proxy_resolution_service(proxy_resolution_service_.get());
 
     std::unique_ptr<net::URLRequestJobFactoryImpl> job_factory_impl(
         new net::URLRequestJobFactoryImpl());
@@ -260,7 +261,7 @@
   net::TestURLRequestContext context_;
   net::EmbeddedTestServer proxy_;
   net::EmbeddedTestServer direct_;
-  std::unique_ptr<net::ProxyService> proxy_service_;
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<net::URLRequestJobFactory> job_factory_;
   std::unique_ptr<DataReductionProxyTestContext> test_context_;
 };
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
index be824254..4d11e358 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -75,7 +75,7 @@
 BasicHTTPURLRequestContextGetter::GetURLRequestContext() {
   if (!url_request_context_) {
     net::URLRequestContextBuilder builder;
-    builder.set_proxy_service(net::ProxyService::CreateDirect());
+    builder.set_proxy_resolution_service(net::ProxyResolutionService::CreateDirect());
     builder.SetSpdyAndQuicEnabled(false, false);
     url_request_context_ = builder.Build();
   }
@@ -282,7 +282,7 @@
 // Bug http://crbug/488190.
 void DataReductionProxyIOData::SetProxyPrefs(bool enabled, bool at_startup) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-  DCHECK(url_request_context_getter_->GetURLRequestContext()->proxy_service());
+  DCHECK(url_request_context_getter_->GetURLRequestContext()->proxy_resolution_service());
   enabled_ = enabled;
   config_->SetProxyConfig(enabled, at_startup);
   if (config_client_) {
@@ -293,9 +293,9 @@
 
   // If Data Saver is disabled, reset data reduction proxy state.
   if (!enabled) {
-    net::ProxyService* proxy_service =
-        url_request_context_getter_->GetURLRequestContext()->proxy_service();
-    proxy_service->ClearBadProxiesCache();
+    net::ProxyResolutionService* proxy_resolution_service =
+        url_request_context_getter_->GetURLRequestContext()->proxy_resolution_service();
+    proxy_resolution_service->ClearBadProxiesCache();
     bypass_stats_->ClearRequestCounts();
     bypass_stats_->NotifyUnavailabilityIfChanged();
   }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
index f102d9c..e758e893 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -167,17 +167,17 @@
   std::vector<net::ProxyServer> proxies;
   proxies.push_back(net::ProxyServer::FromURI("http://foo1.com",
                                               net::ProxyServer::SCHEME_HTTP));
-  net::ProxyService* proxy_service =
+  net::ProxyResolutionService* proxy_resolution_service =
       io_data->url_request_context_getter_->GetURLRequestContext()
-          ->proxy_service();
+          ->proxy_resolution_service();
   net::ProxyInfo proxy_info;
   proxy_info.UseNamedProxy("http://foo2.com");
   net::NetLogWithSource net_log_with_source;
   const net::ProxyRetryInfoMap& bad_proxy_list =
-      proxy_service->proxy_retry_info();
+      proxy_resolution_service->proxy_retry_info();
 
   // Simulate network error to add proxies to the bad proxy list.
-  proxy_service->MarkProxiesAsBadUntil(proxy_info, base::TimeDelta::FromDays(1),
+  proxy_resolution_service->MarkProxiesAsBadUntil(proxy_info, base::TimeDelta::FromDays(1),
                                        proxies, net_log_with_source);
   base::RunLoop().RunUntilIdle();
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
index 3eaf9e5b..5860fde 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
@@ -171,11 +171,11 @@
     net::TestURLRequestContext context(true);
     net::MockClientSocketFactory mock_socket_factory;
     context.set_client_socket_factory(&mock_socket_factory);
-    // Set the |proxy_service| to use |test_case.proxy_server| for requests.
-    std::unique_ptr<net::ProxyService> proxy_service(
-        net::ProxyService::CreateFixedFromPacResult(
+    // Set the |proxy_resolution_service| to use |test_case.proxy_server| for requests.
+    std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+        net::ProxyResolutionService::CreateFixedFromPacResult(
             test_case.proxy_server.ToPacString()));
-    context.set_proxy_service(proxy_service.get());
+    context.set_proxy_resolution_service(proxy_resolution_service.get());
     context.Init();
 
     // Create a fake URLRequest and fill it with the appropriate response
@@ -204,7 +204,7 @@
       net::ProxyInfo proxy_info;
       proxy_info.UseProxyList(
           data_reduction_proxy_config.proxy_rules().proxies_for_http);
-      EXPECT_TRUE(context.proxy_service()->MarkProxiesAsBadUntil(
+      EXPECT_TRUE(context.proxy_resolution_service()->MarkProxiesAsBadUntil(
           proxy_info, test_case.bypass_duration,
           std::vector<net::ProxyServer>(),
           net::NetLogWithSource::Make(context.net_log(),
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
index 33c20c1e..4724c138 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -365,9 +365,9 @@
     }
     context_.reset(new net::TestURLRequestContext(true));
     context_storage_.reset(new net::URLRequestContextStorage(context_.get()));
-    proxy_service_ =
-        net::ProxyService::CreateFixedFromPacResult(proxy_server.ToPacString());
-    context_->set_proxy_service(proxy_service_.get());
+    proxy_resolution_service_ = net::ProxyResolutionService::CreateFixedFromPacResult(
+        proxy_server.ToPacString());
+    context_->set_proxy_resolution_service(proxy_resolution_service_.get());
     context_->set_network_quality_estimator(&test_network_quality_estimator_);
 
     mock_socket_factory_.reset(new net::MockClientSocketFactory());
@@ -868,7 +868,7 @@
  private:
   base::MessageLoopForIO message_loop_;
   std::unique_ptr<net::MockClientSocketFactory> mock_socket_factory_;
-  std::unique_ptr<net::ProxyService> proxy_service_;
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<net::TestURLRequestContext> context_;
   std::unique_ptr<net::URLRequestContextStorage> context_storage_;
 
diff --git a/components/domain_reliability/google_configs.cc b/components/domain_reliability/google_configs.cc
index b7bea47b..36018a2 100644
--- a/components/domain_reliability/google_configs.cc
+++ b/components/domain_reliability/google_configs.cc
@@ -308,6 +308,7 @@
     {"chromeexperiments.com", true, false, false},
     {"chromestatus.com", true, false, false},
     {"chromium.org", true, false, false},
+    {"clients6.google.com", true, false, false},
     {"cloudendpointsapis.com", true, false, false},
     {"dartmotif.com", true, false, false},
     {"dartsearch.net", true, false, false},
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index ce9643b..cfe4708 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -1554,6 +1554,7 @@
       AddState(&states, ZXDG_TOPLEVEL_V6_STATE_ACTIVATED);
     zxdg_toplevel_v6_send_configure(resource_, size.width(), size.height(),
                                     &states);
+    wl_array_release(&states);
   }
 
   wl_resource* const resource_;
diff --git a/components/onc/onc_constants.cc b/components/onc/onc_constants.cc
index 41d3142..43be1619 100644
--- a/components/onc/onc_constants.cc
+++ b/components/onc/onc_constants.cc
@@ -440,6 +440,7 @@
 
 namespace substitutes {
 const char kLoginIDField[] = "${LOGIN_ID}";
+const char kPasswordField[] = "${PASSWORD}";
 const char kEmailField[] = "${LOGIN_EMAIL}";
 const char kCertSANEmail[] = "${CERT_SAN_EMAIL}";
 const char kCertSANUPN[] = "${CERT_SAN_UPN}";
diff --git a/components/onc/onc_constants.h b/components/onc/onc_constants.h
index 9b16a55..6091e2b 100644
--- a/components/onc/onc_constants.h
+++ b/components/onc/onc_constants.h
@@ -438,6 +438,7 @@
 
 namespace substitutes {
 ONC_EXPORT extern const char kEmailField[];
+ONC_EXPORT extern const char kPasswordField[];
 ONC_EXPORT extern const char kLoginIDField[];
 ONC_EXPORT extern const char kCertSANEmail[];
 ONC_EXPORT extern const char kCertSANUPN[];
diff --git a/components/prefs/pref_registry_simple.cc b/components/prefs/pref_registry_simple.cc
index f7d1ef3..670a4b44 100644
--- a/components/prefs/pref_registry_simple.cc
+++ b/components/prefs/pref_registry_simple.cc
@@ -10,84 +10,8 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 
-PrefRegistrySimple::PrefRegistrySimple() {
-}
-
-PrefRegistrySimple::~PrefRegistrySimple() {
-}
-
-void PrefRegistrySimple::RegisterBooleanPref(const std::string& path,
-                                             bool default_value) {
-  RegisterPreference(path, std::make_unique<base::Value>(default_value),
-                     NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterIntegerPref(const std::string& path,
-                                             int default_value) {
-  RegisterPreference(path, std::make_unique<base::Value>(default_value),
-                     NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterDoublePref(const std::string& path,
-                                            double default_value) {
-  RegisterPreference(path, std::make_unique<base::Value>(default_value),
-                     NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterStringPref(const std::string& path,
-                                            const std::string& default_value) {
-  RegisterPreference(path, std::make_unique<base::Value>(default_value),
-                     NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterFilePathPref(
-    const std::string& path,
-    const base::FilePath& default_value) {
-  RegisterPreference(path, std::make_unique<base::Value>(default_value.value()),
-                     NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterListPref(const std::string& path) {
-  RegisterPreference(path, std::make_unique<base::ListValue>(),
-                     NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterListPref(
-    const std::string& path,
-    std::unique_ptr<base::ListValue> default_value) {
-  RegisterPreference(path, std::move(default_value), NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterDictionaryPref(const std::string& path) {
-  RegisterPreference(path, std::make_unique<base::DictionaryValue>(),
-                     NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterDictionaryPref(
-    const std::string& path,
-    std::unique_ptr<base::DictionaryValue> default_value) {
-  RegisterPreference(path, std::move(default_value), NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterInt64Pref(const std::string& path,
-                                           int64_t default_value) {
-  RegisterPreference(
-      path, std::make_unique<base::Value>(base::Int64ToString(default_value)),
-      NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterUint64Pref(const std::string& path,
-                                            uint64_t default_value) {
-  RegisterPreference(
-      path, std::make_unique<base::Value>(base::NumberToString(default_value)),
-      NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterTimePref(const std::string& path,
-                                          base::Time default_value) {
-  RegisterInt64Pref(path,
-                    default_value.ToDeltaSinceWindowsEpoch().InMicroseconds());
-}
+PrefRegistrySimple::PrefRegistrySimple() = default;
+PrefRegistrySimple::~PrefRegistrySimple() = default;
 
 void PrefRegistrySimple::RegisterBooleanPref(const std::string& path,
                                              bool default_value,
diff --git a/components/prefs/pref_registry_simple.h b/components/prefs/pref_registry_simple.h
index e68301c4..5e01cc4e 100644
--- a/components/prefs/pref_registry_simple.h
+++ b/components/prefs/pref_registry_simple.h
@@ -26,59 +26,54 @@
  public:
   PrefRegistrySimple();
 
-  void RegisterBooleanPref(const std::string& path, bool default_value);
-  void RegisterIntegerPref(const std::string& path, int default_value);
-  void RegisterDoublePref(const std::string& path, double default_value);
+  // For each of these registration methods, |flags| is an optional bitmask of
+  // PrefRegistrationFlags.
+  void RegisterBooleanPref(const std::string& path,
+                           bool default_value,
+                           uint32_t flags = NO_REGISTRATION_FLAGS);
+
+  void RegisterIntegerPref(const std::string& path,
+                           int default_value,
+                           uint32_t flags = NO_REGISTRATION_FLAGS);
+
+  void RegisterDoublePref(const std::string& path,
+                          double default_value,
+                          uint32_t flags = NO_REGISTRATION_FLAGS);
+
   void RegisterStringPref(const std::string& path,
-                          const std::string& default_value);
+                          const std::string& default_value,
+                          uint32_t flags = NO_REGISTRATION_FLAGS);
+
   void RegisterFilePathPref(const std::string& path,
-                            const base::FilePath& default_value);
-  void RegisterListPref(const std::string& path);
-  void RegisterDictionaryPref(const std::string& path);
+                            const base::FilePath& default_value,
+                            uint32_t flags = NO_REGISTRATION_FLAGS);
+
   void RegisterListPref(const std::string& path,
-                        std::unique_ptr<base::ListValue> default_value);
+                        uint32_t flags = NO_REGISTRATION_FLAGS);
+
+  void RegisterListPref(const std::string& path,
+                        std::unique_ptr<base::ListValue> default_value,
+                        uint32_t flags = NO_REGISTRATION_FLAGS);
+
+  void RegisterDictionaryPref(const std::string& path,
+                              uint32_t flags = NO_REGISTRATION_FLAGS);
+
   void RegisterDictionaryPref(
       const std::string& path,
-      std::unique_ptr<base::DictionaryValue> default_value);
-  void RegisterInt64Pref(const std::string& path, int64_t default_value);
-  void RegisterUint64Pref(const std::string&, uint64_t default_value);
-  void RegisterTimePref(const std::string& path, base::Time default_value);
-
-  // Versions of registration functions that accept PrefRegistrationFlags.
-  // |flags| is a bitmask of PrefRegistrationFlags.
-  void RegisterBooleanPref(const std::string&,
-                           bool default_value,
-                           uint32_t flags);
-  void RegisterIntegerPref(const std::string&,
-                           int default_value,
-                           uint32_t flags);
-  void RegisterDoublePref(const std::string&,
-                          double default_value,
-                          uint32_t flags);
-  void RegisterStringPref(const std::string&,
-                          const std::string& default_value,
-                          uint32_t flags);
-  void RegisterFilePathPref(const std::string&,
-                            const base::FilePath& default_value,
-                            uint32_t flags);
-  void RegisterListPref(const std::string&, uint32_t flags);
-  void RegisterDictionaryPref(const std::string&, uint32_t flags);
-  void RegisterListPref(const std::string&,
-                        std::unique_ptr<base::ListValue> default_value,
-                        uint32_t flags);
-  void RegisterDictionaryPref(
-      const std::string&,
       std::unique_ptr<base::DictionaryValue> default_value,
-      uint32_t flags);
-  void RegisterInt64Pref(const std::string&,
+      uint32_t flags = NO_REGISTRATION_FLAGS);
+
+  void RegisterInt64Pref(const std::string& path,
                          int64_t default_value,
-                         uint32_t flags);
-  void RegisterUint64Pref(const std::string&,
+                         uint32_t flags = NO_REGISTRATION_FLAGS);
+
+  void RegisterUint64Pref(const std::string& path,
                           uint64_t default_value,
-                          uint32_t flags);
-  void RegisterTimePref(const std::string&,
+                          uint32_t flags = NO_REGISTRATION_FLAGS);
+
+  void RegisterTimePref(const std::string& path,
                         base::Time default_value,
-                        uint32_t flags);
+                        uint32_t flags = NO_REGISTRATION_FLAGS);
 
  protected:
   ~PrefRegistrySimple() override;
diff --git a/components/proxy_config/ios/proxy_service_factory.cc b/components/proxy_config/ios/proxy_service_factory.cc
index e0e0775a..b65b044 100644
--- a/components/proxy_config/ios/proxy_service_factory.cc
+++ b/components/proxy_config/ios/proxy_service_factory.cc
@@ -16,7 +16,7 @@
 std::unique_ptr<net::ProxyConfigService>
 ProxyServiceFactory::CreateProxyConfigService(PrefProxyConfigTracker* tracker) {
   std::unique_ptr<net::ProxyConfigService> base_service(
-      net::ProxyService::CreateSystemProxyConfigService(
+      net::ProxyResolutionService::CreateSystemProxyConfigService(
           web::WebThread::GetTaskRunnerForThread(web::WebThread::IO)));
   return tracker->CreateTrackingProxyConfigService(std::move(base_service));
 }
@@ -41,16 +41,17 @@
 }
 
 // static
-std::unique_ptr<net::ProxyService> ProxyServiceFactory::CreateProxyService(
+std::unique_ptr<net::ProxyResolutionService>
+ProxyServiceFactory::CreateProxyService(
     net::NetLog* net_log,
     net::URLRequestContext* context,
     net::NetworkDelegate* network_delegate,
     std::unique_ptr<net::ProxyConfigService> proxy_config_service,
     bool quick_check_enabled) {
   DCHECK_CURRENTLY_ON(web::WebThread::IO);
-  std::unique_ptr<net::ProxyService> proxy_service(
-      net::ProxyService::CreateUsingSystemProxyResolver(
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+      net::ProxyResolutionService::CreateUsingSystemProxyResolver(
           std::move(proxy_config_service), net_log));
-  proxy_service->set_quick_check_enabled(quick_check_enabled);
-  return proxy_service;
+  proxy_resolution_service->set_quick_check_enabled(quick_check_enabled);
+  return proxy_resolution_service;
 }
diff --git a/components/proxy_config/ios/proxy_service_factory.h b/components/proxy_config/ios/proxy_service_factory.h
index dfa00ca5..77e112e 100644
--- a/components/proxy_config/ios/proxy_service_factory.h
+++ b/components/proxy_config/ios/proxy_service_factory.h
@@ -17,7 +17,7 @@
 class NetLog;
 class NetworkDelegate;
 class ProxyConfigService;
-class ProxyService;
+class ProxyResolutionService;
 class URLRequestContext;
 }
 
@@ -38,7 +38,7 @@
   CreatePrefProxyConfigTrackerOfLocalState(PrefService* local_state_prefs);
 
   // Create a proxy service.
-  static std::unique_ptr<net::ProxyService> CreateProxyService(
+  static std::unique_ptr<net::ProxyResolutionService> CreateProxyService(
       net::NetLog* net_log,
       net::URLRequestContext* context,
       net::NetworkDelegate* network_delegate,
diff --git a/components/variations/metrics.cc b/components/variations/metrics.cc
index a59d3d6..05cd56a 100644
--- a/components/variations/metrics.cc
+++ b/components/variations/metrics.cc
@@ -20,6 +20,11 @@
                             LoadSeedResult::ENUM_SIZE);
 }
 
+void RecordLoadSafeSeedResult(LoadSeedResult state) {
+  UMA_HISTOGRAM_ENUMERATION("Variations.SafeMode.LoadSafeSeed.Result", state,
+                            LoadSeedResult::ENUM_SIZE);
+}
+
 void RecordStoreSeedResult(StoreSeedResult result) {
   UMA_HISTOGRAM_ENUMERATION("Variations.SeedStoreResult", result,
                             StoreSeedResult::ENUM_SIZE);
diff --git a/components/variations/metrics.h b/components/variations/metrics.h
index 28e846d..832f39b 100644
--- a/components/variations/metrics.h
+++ b/components/variations/metrics.h
@@ -83,9 +83,13 @@
 void RecordFirstRunSeedImportResult(FirstRunSeedImportResult result);
 #endif  // OS_ANDROID
 
-// Records the result of attempting to load a variations seed on startup.
+// Records the result of attempting to load the latest variations seed on
+// startup.
 void RecordLoadSeedResult(LoadSeedResult state);
 
+// Records the result of attempting to load the safe variations seed on startup.
+void RecordLoadSafeSeedResult(LoadSeedResult state);
+
 // Records the result of attempting to store a variations seed received from the
 // server.
 void RecordStoreSeedResult(StoreSeedResult result);
diff --git a/components/variations/service/safe_seed_manager_unittest.cc b/components/variations/service/safe_seed_manager_unittest.cc
index 289de528..723bd6a 100644
--- a/components/variations/service/safe_seed_manager_unittest.cc
+++ b/components/variations/service/safe_seed_manager_unittest.cc
@@ -41,8 +41,6 @@
     return true;
   }
 
-  // TODO(isherman): Replace these with a LoadSafeSeed() function once that's
-  // implemented on the seed store.
   const std::string& seed_data() const { return seed_data_; }
   const std::string& signature() const { return signature_; }
   const base::Time& date() const { return date_; }
diff --git a/components/variations/variations_seed_store.cc b/components/variations/variations_seed_store.cc
index d0b7e7c..7358eb2 100644
--- a/components/variations/variations_seed_store.cc
+++ b/components/variations/variations_seed_store.cc
@@ -120,34 +120,13 @@
     ImportFirstRunJavaSeed();
 #endif  // OS_ANDROID
 
-  LoadSeedResult read_result = ReadSeedData(seed_data);
-  if (read_result != LoadSeedResult::SUCCESS) {
-    RecordLoadSeedResult(read_result);
+  LoadSeedResult result =
+      LoadSeedImpl(SeedType::LATEST, seed, seed_data, base64_seed_signature);
+  RecordLoadSeedResult(result);
+  if (result != LoadSeedResult::SUCCESS)
     return false;
-  }
-
-  *base64_seed_signature =
-      local_state_->GetString(prefs::kVariationsSeedSignature);
-  if (SignatureVerificationEnabled()) {
-    const VerifySignatureResult result =
-        VerifySeedSignature(*seed_data, *base64_seed_signature);
-    UMA_HISTOGRAM_ENUMERATION("Variations.LoadSeedSignature", result,
-                              VerifySignatureResult::ENUM_SIZE);
-    if (result != VerifySignatureResult::VALID_SIGNATURE) {
-      ClearPrefs();
-      RecordLoadSeedResult(LoadSeedResult::INVALID_SIGNATURE);
-      return false;
-    }
-  }
-
-  if (!seed->ParseFromString(*seed_data)) {
-    ClearPrefs();
-    RecordLoadSeedResult(LoadSeedResult::CORRUPT_PROTOBUF);
-    return false;
-  }
 
   latest_serial_number_ = seed->serial_number();
-  RecordLoadSeedResult(LoadSeedResult::SUCCESS);
   return true;
 }
 
@@ -201,7 +180,8 @@
 
   std::string existing_seed_data;
   std::string updated_seed_data;
-  LoadSeedResult read_result = ReadSeedData(&existing_seed_data);
+  LoadSeedResult read_result =
+      ReadSeedData(SeedType::LATEST, &existing_seed_data);
   if (read_result != LoadSeedResult::SUCCESS) {
     RecordStoreSeedResult(StoreSeedResult::FAILED_DELTA_READ_SEED);
     return false;
@@ -229,6 +209,27 @@
   return result;
 }
 
+bool VariationsSeedStore::LoadSafeSeed(VariationsSeed* seed,
+                                       ClientFilterableState* client_state) {
+  std::string unused_seed_data;
+  std::string unused_base64_seed_signature;
+  LoadSeedResult result = LoadSeedImpl(SeedType::SAFE, seed, &unused_seed_data,
+                                       &unused_base64_seed_signature);
+  RecordLoadSafeSeedResult(result);
+  if (result != LoadSeedResult::SUCCESS)
+    return false;
+
+  client_state->reference_date =
+      local_state_->GetTime(prefs::kVariationsSafeSeedDate);
+  client_state->locale =
+      local_state_->GetString(prefs::kVariationsSafeSeedLocale);
+  client_state->permanent_consistency_country = local_state_->GetString(
+      prefs::kVariationsSafeSeedPermanentConsistencyCountry);
+  client_state->session_consistency_country = local_state_->GetString(
+      prefs::kVariationsSafeSeedSessionConsistencyCountry);
+  return true;
+}
+
 bool VariationsSeedStore::StoreSafeSeed(
     const std::string& seed_data,
     const std::string& base64_seed_signature,
@@ -284,7 +285,7 @@
     // when running in safe mode.
     std::string seed_data;
     VariationsSeed seed;
-    if (ReadSeedData(&seed_data) == LoadSeedResult::SUCCESS &&
+    if (ReadSeedData(SeedType::LATEST, &seed_data) == LoadSeedResult::SUCCESS &&
         seed.ParseFromString(seed_data)) {
       latest_serial_number_ = seed.serial_number();
     }
@@ -323,10 +324,22 @@
 #endif
 }
 
-void VariationsSeedStore::ClearPrefs() {
-  local_state_->ClearPref(prefs::kVariationsCompressedSeed);
-  local_state_->ClearPref(prefs::kVariationsSeedDate);
-  local_state_->ClearPref(prefs::kVariationsSeedSignature);
+void VariationsSeedStore::ClearPrefs(SeedType seed_type) {
+  if (seed_type == SeedType::LATEST) {
+    local_state_->ClearPref(prefs::kVariationsCompressedSeed);
+    local_state_->ClearPref(prefs::kVariationsSeedDate);
+    local_state_->ClearPref(prefs::kVariationsSeedSignature);
+    return;
+  }
+
+  DCHECK_EQ(seed_type, SeedType::SAFE);
+  local_state_->ClearPref(prefs::kVariationsSafeCompressedSeed);
+  local_state_->ClearPref(prefs::kVariationsSafeSeedDate);
+  local_state_->ClearPref(prefs::kVariationsSafeSeedLocale);
+  local_state_->ClearPref(
+      prefs::kVariationsSafeSeedPermanentConsistencyCountry);
+  local_state_->ClearPref(prefs::kVariationsSafeSeedSessionConsistencyCountry);
+  local_state_->ClearPref(prefs::kVariationsSafeSeedSignature);
 }
 
 #if defined(OS_ANDROID)
@@ -365,21 +378,60 @@
 }
 #endif  // OS_ANDROID
 
-LoadSeedResult VariationsSeedStore::ReadSeedData(std::string* seed_data) {
-  std::string base64_seed_data =
-      local_state_->GetString(prefs::kVariationsCompressedSeed);
+LoadSeedResult VariationsSeedStore::LoadSeedImpl(
+    SeedType seed_type,
+    VariationsSeed* seed,
+    std::string* seed_data,
+    std::string* base64_seed_signature) {
+  LoadSeedResult read_result = ReadSeedData(seed_type, seed_data);
+  if (read_result != LoadSeedResult::SUCCESS)
+    return read_result;
+
+  *base64_seed_signature = local_state_->GetString(
+      seed_type == SeedType::LATEST ? prefs::kVariationsSeedSignature
+                                    : prefs::kVariationsSafeSeedSignature);
+  if (SignatureVerificationEnabled()) {
+    const VerifySignatureResult result =
+        VerifySeedSignature(*seed_data, *base64_seed_signature);
+    if (seed_type == SeedType::LATEST) {
+      UMA_HISTOGRAM_ENUMERATION("Variations.LoadSeedSignature", result,
+                                VerifySignatureResult::ENUM_SIZE);
+    } else {
+      UMA_HISTOGRAM_ENUMERATION(
+          "Variations.SafeMode.LoadSafeSeed.SignatureValidity", result,
+          VerifySignatureResult::ENUM_SIZE);
+    }
+    if (result != VerifySignatureResult::VALID_SIGNATURE) {
+      ClearPrefs(seed_type);
+      return LoadSeedResult::INVALID_SIGNATURE;
+    }
+  }
+
+  if (!seed->ParseFromString(*seed_data)) {
+    ClearPrefs(seed_type);
+    return LoadSeedResult::CORRUPT_PROTOBUF;
+  }
+
+  return LoadSeedResult::SUCCESS;
+}
+
+LoadSeedResult VariationsSeedStore::ReadSeedData(SeedType seed_type,
+                                                 std::string* seed_data) {
+  std::string base64_seed_data = local_state_->GetString(
+      seed_type == SeedType::LATEST ? prefs::kVariationsCompressedSeed
+                                    : prefs::kVariationsSafeCompressedSeed);
   if (base64_seed_data.empty())
     return LoadSeedResult::EMPTY;
 
   // If the decode process fails, assume the pref value is corrupt and clear it.
   std::string decoded_data;
   if (!base::Base64Decode(base64_seed_data, &decoded_data)) {
-    ClearPrefs();
+    ClearPrefs(seed_type);
     return LoadSeedResult::CORRUPT_BASE64;
   }
 
   if (!compression::GzipUncompress(decoded_data, seed_data)) {
-    ClearPrefs();
+    ClearPrefs(seed_type);
     return LoadSeedResult::CORRUPT_GZIP;
   }
 
diff --git a/components/variations/variations_seed_store.h b/components/variations/variations_seed_store.h
index 2af9b8d..fff7bcb 100644
--- a/components/variations/variations_seed_store.h
+++ b/components/variations/variations_seed_store.h
@@ -57,6 +57,15 @@
                      bool fetched_insecurely,
                      VariationsSeed* parsed_seed) WARN_UNUSED_RESULT;
 
+  // Loads the safe variations seed data from local state into |seed| and
+  // updates any relevant fields in |client_state|. Returns true iff the safe
+  // seed was read successfully from prefs. If the safe seed could not be
+  // loaded, it is guaranteed that no fields in |client_state| are modified.
+  // Side-effect: Upon any failure to read or validate the safe seed, clears all
+  // of the safe seed pref values. This occurs iff the method returns false.
+  bool LoadSafeSeed(VariationsSeed* seed,
+                    ClientFilterableState* client_state) WARN_UNUSED_RESULT;
+
   // Stores the given |seed_data| (a serialized protobuf) to local state as a
   // safe seed, along with a base64-encoded digital signature for seed and any
   // additional client metadata relevant to the safe seed. Returns true on
@@ -108,8 +117,9 @@
     SAFE,
   };
 
-  // Clears all prefs related to variations seed storage.
-  void ClearPrefs();
+  // Clears all prefs related to variations seed storage for the specified seed
+  // type.
+  void ClearPrefs(SeedType seed_type);
 
 #if defined(OS_ANDROID)
   // Imports the variations seed data from Java side during the first
@@ -117,11 +127,25 @@
   void ImportFirstRunJavaSeed();
 #endif  // OS_ANDROID
 
+  // Loads the variations seed data from local state into |seed|, as well as the
+  // raw pref values into |seed_data| and |base64_signature|. Loads either the
+  // safe seed or the latest seed, according to the |seed_type|. Returns whether
+  // loading the seed was successful.
+  // Side-effect: Upon any failure to read or validate the safe seed, clears all
+  // of the pref values for the seed. This occurs iff the method returns false.
+  LoadSeedResult LoadSeedImpl(SeedType seed_type,
+                              VariationsSeed* seed,
+                              std::string* seed_data,
+                              std::string* base64_seed_signature)
+      WARN_UNUSED_RESULT;
+
   // Reads the variations seed data from prefs into |seed_data|, and returns the
   // result of the load. The value stored into |seed_data| should only be used
-  // if the result is SUCCESS.
+  // if the result is SUCCESS. Reads either the latest or the safe seed,
+  // according to the specified |seed_type|.
   // Side-effect: If the read fails, clears the prefs associated with the seed.
-  LoadSeedResult ReadSeedData(std::string* seed_data) WARN_UNUSED_RESULT;
+  LoadSeedResult ReadSeedData(SeedType seed_type,
+                              std::string* seed_data) WARN_UNUSED_RESULT;
 
   // Internal version of |StoreSeedData()| that assumes |seed_data| is not delta
   // compressed.
diff --git a/components/variations/variations_seed_store_unittest.cc b/components/variations/variations_seed_store_unittest.cc
index f401c99..ce77e3c 100644
--- a/components/variations/variations_seed_store_unittest.cc
+++ b/components/variations/variations_seed_store_unittest.cc
@@ -4,9 +4,14 @@
 
 #include "components/variations/variations_seed_store.h"
 
+#include <memory>
+#include <utility>
+
 #include "base/base64.h"
 #include "base/macros.h"
 #include "base/test/histogram_tester.h"
+#include "base/time/time.h"
+#include "base/version.h"
 #include "build/build_config.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/variations/client_filterable_state.h"
@@ -83,6 +88,25 @@
   return seed;
 }
 
+// Returns a ClientFilterableState with all fields set to "interesting" values
+// for testing.
+std::unique_ptr<ClientFilterableState> CreateTestClientFilterableState() {
+  std::unique_ptr<ClientFilterableState> client_state =
+      std::make_unique<ClientFilterableState>();
+  client_state->locale = "es-MX";
+  client_state->reference_date =
+      base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromDays(12345));
+  client_state->version = base::Version("1.2.3.4");
+  client_state->channel = Study::CANARY;
+  client_state->form_factor = Study::PHONE;
+  client_state->platform = Study::PLATFORM_MAC;
+  client_state->hardware_class = "mario";
+  client_state->is_low_end_device = true;
+  client_state->session_consistency_country = "mx";
+  client_state->permanent_consistency_country = "br";
+  return client_state;
+}
+
 // Serializes |seed| to protobuf binary format.
 std::string SerializeSeed(const VariationsSeed& seed) {
   std::string serialized_seed;
@@ -106,6 +130,20 @@
   return base64_serialized_seed;
 }
 
+// Sets all seed-related prefs to non-default values. Used to verify whether
+// pref values were cleared.
+void SetAllSeedPrefsToNonDefaultValues(PrefService* prefs) {
+  prefs->SetString(prefs::kVariationsCompressedSeed, "a");
+  prefs->SetString(prefs::kVariationsSafeCompressedSeed, "b");
+  prefs->SetString(prefs::kVariationsSafeSeedLocale, "c");
+  prefs->SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "d");
+  prefs->SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "e");
+  prefs->SetString(prefs::kVariationsSafeSeedSignature, "f");
+  prefs->SetString(prefs::kVariationsSeedSignature, "g");
+  prefs->SetTime(prefs::kVariationsSafeSeedDate, base::Time::Now());
+  prefs->SetTime(prefs::kVariationsSeedDate, base::Time::Now());
+}
+
 // Checks whether the pref with name |pref_name| is at its default value in
 // |prefs|.
 bool PrefHasDefaultValue(const TestingPrefServiceSimple& prefs,
@@ -115,11 +153,11 @@
 
 }  // namespace
 
-TEST(VariationsSeedStoreTest, LoadSeed) {
+TEST(VariationsSeedStoreTest, LoadSeed_ValidSeed) {
   // Store good seed data to test if loading from prefs works.
   const VariationsSeed seed = CreateTestSeed();
   const std::string base64_seed = SerializeSeedBase64(seed);
-  const std::string base64_seed_signature = "a test signature, clearly forged.";
+  const std::string base64_seed_signature = "a test signature, ignored.";
 
   TestingPrefServiceSimple prefs;
   VariationsSeedStore::RegisterPrefs(prefs.registry());
@@ -142,18 +180,83 @@
   // Make sure the pref hasn't been changed.
   EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
   EXPECT_EQ(base64_seed, prefs.GetString(prefs::kVariationsCompressedSeed));
+}
 
-  // Check that loading a bad seed returns false and clears the pref.
+TEST(VariationsSeedStoreTest, LoadSeed_InvalidSeed) {
+  TestingPrefServiceSimple prefs;
+  VariationsSeedStore::RegisterPrefs(prefs.registry());
+  SetAllSeedPrefsToNonDefaultValues(&prefs);
   prefs.SetString(prefs::kVariationsCompressedSeed, "this should fail");
-  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
+
+  // Loading an invalid seed should return false and clear all associated prefs.
+  TestVariationsSeedStore seed_store(&prefs);
+  VariationsSeed loaded_seed;
+  std::string loaded_seed_data;
+  std::string loaded_base64_seed_signature;
   EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
                                    &loaded_base64_seed_signature));
   EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
   EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
   EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
 
-  // Check that having no seed in prefs results in a return value of false.
-  prefs.ClearPref(prefs::kVariationsCompressedSeed);
+  // However, only the latest seed prefs should be cleared; the safe seed prefs
+  // should not be modified.
+  EXPECT_FALSE(
+      PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+  EXPECT_FALSE(PrefHasDefaultValue(
+      prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+  EXPECT_FALSE(PrefHasDefaultValue(
+      prefs, prefs::kVariationsSafeSeedSessionConsistencyCountry));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature));
+}
+
+TEST(VariationsSeedStoreTest, LoadSeed_InvalidSignature) {
+  const VariationsSeed seed = CreateTestSeed();
+  const std::string base64_seed = SerializeSeedBase64(seed);
+  const std::string base64_seed_signature = "a deeply compromised signature.";
+
+  TestingPrefServiceSimple prefs;
+  VariationsSeedStore::RegisterPrefs(prefs.registry());
+  SetAllSeedPrefsToNonDefaultValues(&prefs);
+  prefs.SetString(prefs::kVariationsCompressedSeed, base64_seed);
+  prefs.SetString(prefs::kVariationsSeedSignature, base64_seed_signature);
+
+  // Loading a valid seed with an invalid signature should return false and
+  // clear all associated prefs when signature verification is enabled.
+  SignatureVerifyingVariationsSeedStore seed_store(&prefs);
+  VariationsSeed loaded_seed;
+  std::string loaded_seed_data;
+  std::string loaded_base64_seed_signature;
+  EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
+                                   &loaded_base64_seed_signature));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
+
+  // However, only the latest seed prefs should be cleared; the safe seed prefs
+  // should not be modified.
+  EXPECT_FALSE(
+      PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+  EXPECT_FALSE(PrefHasDefaultValue(
+      prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+  EXPECT_FALSE(PrefHasDefaultValue(
+      prefs, prefs::kVariationsSafeSeedSessionConsistencyCountry));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature));
+}
+
+TEST(VariationsSeedStoreTest, LoadSeed_EmptySeed) {
+  TestingPrefServiceSimple prefs;
+  VariationsSeedStore::RegisterPrefs(prefs.registry());
+
+  // Loading an empty seed should return false.
+  TestVariationsSeedStore seed_store(&prefs);
+  VariationsSeed loaded_seed;
+  std::string loaded_seed_data;
+  std::string loaded_base64_seed_signature;
   EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
                                    &loaded_base64_seed_signature));
 }
@@ -236,6 +339,152 @@
   EXPECT_EQ(serialized_seed, SerializeSeed(parsed_seed));
 }
 
+TEST(VariationsSeedStoreTest, LoadSafeSeed_ValidSeed) {
+  // Store good seed data to test if loading from prefs works.
+  const VariationsSeed seed = CreateTestSeed();
+  const std::string base64_seed = SerializeSeedBase64(seed);
+  const std::string base64_seed_signature = "a test signature, ignored.";
+  const base::Time reference_date = base::Time::Now();
+  const std::string locale = "en-US";
+  const std::string permanent_consistency_country = "us";
+  const std::string session_consistency_country = "ca";
+
+  TestingPrefServiceSimple prefs;
+  VariationsSeedStore::RegisterPrefs(prefs.registry());
+  prefs.SetString(prefs::kVariationsSafeCompressedSeed, base64_seed);
+  prefs.SetString(prefs::kVariationsSafeSeedSignature, base64_seed_signature);
+  prefs.SetTime(prefs::kVariationsSafeSeedDate, reference_date);
+  prefs.SetString(prefs::kVariationsSafeSeedLocale, locale);
+  prefs.SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry,
+                  permanent_consistency_country);
+  prefs.SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry,
+                  session_consistency_country);
+
+  TestVariationsSeedStore seed_store(&prefs);
+  VariationsSeed loaded_seed;
+  std::unique_ptr<ClientFilterableState> client_state =
+      CreateTestClientFilterableState();
+  EXPECT_TRUE(seed_store.LoadSafeSeed(&loaded_seed, client_state.get()));
+
+  // Check that the loaded data is the same as the original.
+  EXPECT_EQ(SerializeSeed(seed), SerializeSeed(loaded_seed));
+  EXPECT_EQ(locale, client_state->locale);
+  EXPECT_EQ(reference_date, client_state->reference_date);
+  EXPECT_EQ(permanent_consistency_country,
+            client_state->permanent_consistency_country);
+  EXPECT_EQ(session_consistency_country,
+            client_state->session_consistency_country);
+
+  // Make sure that other data in the |client_state| hasn't been changed.
+  std::unique_ptr<ClientFilterableState> original_state =
+      CreateTestClientFilterableState();
+  EXPECT_EQ(original_state->version, client_state->version);
+  EXPECT_EQ(original_state->channel, client_state->channel);
+  EXPECT_EQ(original_state->form_factor, client_state->form_factor);
+  EXPECT_EQ(original_state->platform, client_state->platform);
+  EXPECT_EQ(original_state->hardware_class, client_state->hardware_class);
+  EXPECT_EQ(original_state->is_low_end_device, client_state->is_low_end_device);
+
+  // Make sure the pref hasn't been changed.
+  EXPECT_FALSE(
+      PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+  EXPECT_EQ(base64_seed, prefs.GetString(prefs::kVariationsSafeCompressedSeed));
+}
+
+TEST(VariationsSeedStoreTest, LoadSafeSeed_InvalidSeed) {
+  TestingPrefServiceSimple prefs;
+  VariationsSeedStore::RegisterPrefs(prefs.registry());
+  SetAllSeedPrefsToNonDefaultValues(&prefs);
+  prefs.SetString(prefs::kVariationsSafeCompressedSeed, "this should fail");
+
+  // Loading an invalid seed should return false and clear all associated prefs.
+  TestVariationsSeedStore seed_store(&prefs);
+  VariationsSeed loaded_seed;
+  std::unique_ptr<ClientFilterableState> client_state =
+      CreateTestClientFilterableState();
+  EXPECT_FALSE(seed_store.LoadSafeSeed(&loaded_seed, client_state.get()));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+  EXPECT_TRUE(PrefHasDefaultValue(
+      prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+  EXPECT_TRUE(PrefHasDefaultValue(
+      prefs, prefs::kVariationsSafeSeedSessionConsistencyCountry));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature));
+
+  // However, only the safe seed prefs should be cleared; the latest seed prefs
+  // should not be modified.
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
+
+  // Moreover, loading an invalid seed should leave the |client_state|
+  // unmodified.
+  std::unique_ptr<ClientFilterableState> original_state =
+      CreateTestClientFilterableState();
+  EXPECT_EQ(original_state->locale, client_state->locale);
+  EXPECT_EQ(original_state->reference_date, client_state->reference_date);
+  EXPECT_EQ(original_state->session_consistency_country,
+            client_state->session_consistency_country);
+  EXPECT_EQ(original_state->permanent_consistency_country,
+            client_state->permanent_consistency_country);
+}
+
+TEST(VariationsSeedStoreTest, LoadSafeSeed_InvalidSignature) {
+  const VariationsSeed seed = CreateTestSeed();
+  const std::string base64_seed = SerializeSeedBase64(seed);
+  const std::string base64_seed_signature = "a deeply compromised signature.";
+
+  TestingPrefServiceSimple prefs;
+  VariationsSeedStore::RegisterPrefs(prefs.registry());
+  SetAllSeedPrefsToNonDefaultValues(&prefs);
+  prefs.SetString(prefs::kVariationsSafeCompressedSeed, base64_seed);
+  prefs.SetString(prefs::kVariationsSafeSeedSignature, base64_seed_signature);
+
+  // Loading a valid seed with an invalid signature should return false and
+  // clear all associated prefs when signature verification is enabled.
+  SignatureVerifyingVariationsSeedStore seed_store(&prefs);
+  VariationsSeed loaded_seed;
+  std::unique_ptr<ClientFilterableState> client_state =
+      CreateTestClientFilterableState();
+  EXPECT_FALSE(seed_store.LoadSafeSeed(&loaded_seed, client_state.get()));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+  EXPECT_TRUE(PrefHasDefaultValue(
+      prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+  EXPECT_TRUE(PrefHasDefaultValue(
+      prefs, prefs::kVariationsSafeSeedSessionConsistencyCountry));
+  EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature));
+
+  // However, only the safe seed prefs should be cleared; the latest seed prefs
+  // should not be modified.
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
+  EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
+
+  // Moreover, the passed-in |client_state| should remain unmodified.
+  std::unique_ptr<ClientFilterableState> original_state =
+      CreateTestClientFilterableState();
+  EXPECT_EQ(original_state->locale, client_state->locale);
+  EXPECT_EQ(original_state->reference_date, client_state->reference_date);
+  EXPECT_EQ(original_state->session_consistency_country,
+            client_state->session_consistency_country);
+  EXPECT_EQ(original_state->permanent_consistency_country,
+            client_state->permanent_consistency_country);
+}
+
+TEST(VariationsSeedStoreTest, LoadSafeSeed_EmptySeed) {
+  TestingPrefServiceSimple prefs;
+  VariationsSeedStore::RegisterPrefs(prefs.registry());
+
+  // Loading an empty seed should return false.
+  TestVariationsSeedStore seed_store(&prefs);
+  VariationsSeed loaded_seed;
+  ClientFilterableState client_state;
+  EXPECT_FALSE(seed_store.LoadSafeSeed(&loaded_seed, &client_state));
+}
+
 TEST(VariationsSeedStoreTest, StoreSafeSeed_ValidSeed) {
   const VariationsSeed seed = CreateTestSeed();
   const std::string serialized_seed = SerializeSeed(seed);
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index a327ba1a..4f94a0e35 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -34,7 +34,6 @@
 #include "third_party/skia/include/core/SkPath.h"
 #include "third_party/skia/include/core/SkPoint.h"
 #include "third_party/skia/include/core/SkShader.h"
-#include "third_party/skia/include/effects/SkLayerRasterizer.h"
 #include "third_party/skia/include/effects/SkOverdrawColorFilter.h"
 #include "third_party/skia/include/gpu/GrBackendSurface.h"
 #include "third_party/skia/include/gpu/GrContext.h"
diff --git a/components/webrtc_logging/OWNERS b/components/webrtc_logging/OWNERS
new file mode 100644
index 0000000..aa82f4f
--- /dev/null
+++ b/components/webrtc_logging/OWNERS
@@ -0,0 +1,4 @@
+grunell@chromium.org
+tommi@chromium.org
+
+# COMPONENT: Blink>WebRTC>Tools
diff --git a/components/webrtc_logging/README.md b/components/webrtc_logging/README.md
new file mode 100644
index 0000000..bfd5dc3
--- /dev/null
+++ b/components/webrtc_logging/README.md
@@ -0,0 +1,4 @@
+# WebRTC Logging
+
+This component provides helpers for uploading WebRTC message logs for diagnostic
+purposes.
diff --git a/components/webrtc_logging/browser/BUILD.gn b/components/webrtc_logging/browser/BUILD.gn
new file mode 100644
index 0000000..b1f22936
--- /dev/null
+++ b/components/webrtc_logging/browser/BUILD.gn
@@ -0,0 +1,35 @@
+# 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.
+
+import("//media/media_options.gni")
+
+assert(enable_webrtc)
+
+source_set("browser") {
+  sources = [
+    "log_cleanup.cc",
+    "log_cleanup.h",
+    "log_list.cc",
+    "log_list.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/upload_list",
+    "//content/public/browser",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "log_cleanup_unittest.cc",
+  ]
+  deps = [
+    ":browser",
+    "//base",
+    "//content/test:test_support",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/webrtc_logging/browser/DEPS b/components/webrtc_logging/browser/DEPS
new file mode 100644
index 0000000..9d7ae7d8
--- /dev/null
+++ b/components/webrtc_logging/browser/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+  "+components/upload_list",
+  "+content/public/browser",
+]
+
+specific_include_rules = {
+  ".*test\.cc": [
+    "+content/public/test",
+  ]
+}
diff --git a/components/webrtc_logging/browser/log_cleanup.cc b/components/webrtc_logging/browser/log_cleanup.cc
new file mode 100644
index 0000000..2f3fc805
--- /dev/null
+++ b/components/webrtc_logging/browser/log_cleanup.cc
@@ -0,0 +1,104 @@
+// 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 "components/webrtc_logging/browser/log_cleanup.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
+#include "components/webrtc_logging/browser/log_list.h"
+
+namespace webrtc_logging {
+
+namespace {
+
+const int kDaysToKeepLogs = 5;
+
+// Remove any empty entries from the log list. One line is one log entry, see
+// WebRtcLogUploader::AddLocallyStoredLogInfoToUploadListFile for more
+// information about the format.
+void RemoveEmptyEntriesInLogList(std::string* log_list) {
+  static const char kEmptyLine[] = ",,\n";
+  size_t pos = 0;
+  do {
+    pos = log_list->find(kEmptyLine, pos);
+    if (pos == std::string::npos)
+      break;
+    DCHECK(pos == 0 || (*log_list)[pos - 1] == '\n');
+    log_list->erase(pos, arraysize(kEmptyLine) - 1);
+  } while (true);
+}
+
+}  // namespace
+
+void DeleteOldWebRtcLogFiles(const base::FilePath& log_dir) {
+  DeleteOldAndRecentWebRtcLogFiles(log_dir, base::Time::Max());
+}
+
+void DeleteOldAndRecentWebRtcLogFiles(const base::FilePath& log_dir,
+                                      const base::Time& delete_begin_time) {
+  base::AssertBlockingAllowed();
+
+  if (!base::PathExists(log_dir)) {
+    // This will happen if no logs have been stored or uploaded.
+    DVLOG(3) << "Could not find directory: " << log_dir.value();
+    return;
+  }
+
+  const base::Time now = base::Time::Now();
+  const base::TimeDelta time_to_keep_logs =
+      base::TimeDelta::FromDays(kDaysToKeepLogs);
+
+  base::FilePath log_list_path =
+      LogList::GetWebRtcLogListFileForDirectory(log_dir);
+  std::string log_list;
+  const bool update_log_list = base::PathExists(log_list_path);
+  if (update_log_list) {
+    bool read_ok = base::ReadFileToString(log_list_path, &log_list);
+    DPCHECK(read_ok);
+  }
+
+  base::FileEnumerator log_files(log_dir, false, base::FileEnumerator::FILES);
+  bool delete_ok = true;
+  for (base::FilePath name = log_files.Next(); !name.empty();
+       name = log_files.Next()) {
+    if (name == log_list_path)
+      continue;
+    base::FileEnumerator::FileInfo file_info(log_files.GetInfo());
+    base::TimeDelta file_age = now - file_info.GetLastModifiedTime();
+    if (file_age > time_to_keep_logs ||
+        (!delete_begin_time.is_max() &&
+         file_info.GetLastModifiedTime() > delete_begin_time)) {
+      if (!base::DeleteFile(name, false))
+        delete_ok = false;
+
+      // Remove the local ID from the log list file. The ID is guaranteed to be
+      // unique.
+      std::string id = file_info.GetName().RemoveExtension().MaybeAsASCII();
+      size_t id_pos = log_list.find(id);
+      if (id_pos == std::string::npos)
+        continue;
+      log_list.erase(id_pos, id.size());
+    }
+  }
+
+  if (!delete_ok)
+    LOG(WARNING) << "Could not delete all old WebRTC logs.";
+
+  RemoveEmptyEntriesInLogList(&log_list);
+
+  if (update_log_list) {
+    int written = base::WriteFile(log_list_path, &log_list[0], log_list.size());
+    DPCHECK(written == static_cast<int>(log_list.size()));
+  }
+}
+
+}  // namespace webrtc_logging
diff --git a/components/webrtc_logging/browser/log_cleanup.h b/components/webrtc_logging/browser/log_cleanup.h
new file mode 100644
index 0000000..dc8fdd9
--- /dev/null
+++ b/components/webrtc_logging/browser/log_cleanup.h
@@ -0,0 +1,28 @@
+// 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 COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_CLEANUP_H_
+#define COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_CLEANUP_H_
+
+namespace base {
+class FilePath;
+class Time;
+}  // namespace base
+
+namespace webrtc_logging {
+
+// Deletes logs files older that 5 days. Updates the log file list. Must be
+// called on the FILE thread.
+void DeleteOldWebRtcLogFiles(const base::FilePath& log_dir);
+
+// Deletes logs files older that 5 days and logs younger than
+// |delete_begin_time|. Updates the log file list. If |delete_begin_time| is
+// base::time::Max(), no recent logs will be deleted, and the function is
+// equal to DeleteOldWebRtcLogFiles(). Must be called on the FILE thread.
+void DeleteOldAndRecentWebRtcLogFiles(const base::FilePath& log_dir,
+                                      const base::Time& delete_begin_time);
+
+}  // namespace webrtc_logging
+
+#endif  // COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_CLEANUP_H_
diff --git a/chrome/browser/media/webrtc/webrtc_log_util_unittest.cc b/components/webrtc_logging/browser/log_cleanup_unittest.cc
similarity index 81%
rename from chrome/browser/media/webrtc/webrtc_log_util_unittest.cc
rename to components/webrtc_logging/browser/log_cleanup_unittest.cc
index 521a3d6..5d6ec15 100644
--- a/chrome/browser/media/webrtc/webrtc_log_util_unittest.cc
+++ b/components/webrtc_logging/browser/log_cleanup_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/media/webrtc/webrtc_log_util.h"
+#include "components/webrtc_logging/browser/log_cleanup.h"
 
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
@@ -12,11 +12,17 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace webrtc_logging {
+
+namespace {
+
 const int kExpectedDaysToKeepLogFiles = 5;
 
-class WebRtcLogUtilTest : public testing::Test {
+}  // namespace
+
+class WebRtcLogCleanupTest : public testing::Test {
  public:
-  WebRtcLogUtilTest() = default;
+  WebRtcLogCleanupTest() = default;
 
   void SetUp() override {
     // Create three files. One with modified date as of now, one with date one
@@ -55,15 +61,16 @@
   base::ScopedTempDir dir_;
 };
 
-TEST_F(WebRtcLogUtilTest, DeleteOldWebRtcLogFiles) {
-  WebRtcLogUtil::DeleteOldWebRtcLogFiles(dir_.GetPath());
+TEST_F(WebRtcLogCleanupTest, DeleteOldWebRtcLogFiles) {
+  DeleteOldWebRtcLogFiles(dir_.GetPath());
   VerifyFiles(2);
 }
 
-TEST_F(WebRtcLogUtilTest, DeleteOldAndRecentWebRtcLogFiles) {
+TEST_F(WebRtcLogCleanupTest, DeleteOldAndRecentWebRtcLogFiles) {
   base::Time time_begin_delete =
       base::Time::Now() - base::TimeDelta::FromDays(1);
-  WebRtcLogUtil::DeleteOldAndRecentWebRtcLogFiles(dir_.GetPath(),
-                                                  time_begin_delete);
+  DeleteOldAndRecentWebRtcLogFiles(dir_.GetPath(), time_begin_delete);
   VerifyFiles(1);
 }
+
+}  // namespace webrtc_logging
diff --git a/chrome/browser/media/webrtc/webrtc_log_list.cc b/components/webrtc_logging/browser/log_list.cc
similarity index 78%
rename from chrome/browser/media/webrtc/webrtc_log_list.cc
rename to components/webrtc_logging/browser/log_list.cc
index 295c87ae..4d25b27 100644
--- a/chrome/browser/media/webrtc/webrtc_log_list.cc
+++ b/components/webrtc_logging/browser/log_list.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/media/webrtc/webrtc_log_list.h"
+#include "components/webrtc_logging/browser/log_list.h"
 
 #include "base/files/file.h"
 #include "base/files/file_util.h"
@@ -10,6 +10,8 @@
 #include "components/upload_list/text_log_upload_list.h"
 #include "content/public/browser/browser_context.h"
 
+namespace webrtc_logging {
+
 namespace {
 
 const char kWebRtcLogDirectory[] = "WebRTC Logs";
@@ -18,7 +20,7 @@
 }  // namespace
 
 // static
-UploadList* WebRtcLogList::CreateWebRtcLogList(
+UploadList* LogList::CreateWebRtcLogList(
     content::BrowserContext* browser_context) {
   base::FilePath log_list_path = GetWebRtcLogListFileForDirectory(
       GetWebRtcLogDirectoryForBrowserContextPath(browser_context->GetPath()));
@@ -26,15 +28,17 @@
 }
 
 // static
-base::FilePath WebRtcLogList::GetWebRtcLogDirectoryForBrowserContextPath(
+base::FilePath LogList::GetWebRtcLogDirectoryForBrowserContextPath(
     const base::FilePath& browser_context_path) {
   DCHECK(!browser_context_path.empty());
   return browser_context_path.AppendASCII(kWebRtcLogDirectory);
 }
 
 // static
-base::FilePath WebRtcLogList::GetWebRtcLogListFileForDirectory(
+base::FilePath LogList::GetWebRtcLogListFileForDirectory(
     const base::FilePath& dir) {
   DCHECK(!dir.empty());
   return dir.AppendASCII(kWebRtcLogListFilename);
 }
+
+}  // namespace webrtc_logging
diff --git a/chrome/browser/media/webrtc/webrtc_log_list.h b/components/webrtc_logging/browser/log_list.h
similarity index 81%
rename from chrome/browser/media/webrtc/webrtc_log_list.h
rename to components/webrtc_logging/browser/log_list.h
index 2f4b5c3..6a4b00a9 100644
--- a/chrome/browser/media/webrtc/webrtc_log_list.h
+++ b/components/webrtc_logging/browser/log_list.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_LOG_LIST_H_
-#define CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_LOG_LIST_H_
+#ifndef COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_LIST_H_
+#define COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_LIST_H_
 
 #include "base/files/file_path.h"
 
@@ -13,7 +13,9 @@
 class BrowserContext;
 }  // namespace content
 
-class WebRtcLogList {
+namespace webrtc_logging {
+
+class LogList {
  public:
   // Creates the upload list with the given callback delegate for a
   // browser context. The upload list loads and parses a text file list of
@@ -32,4 +34,6 @@
       const base::FilePath& dir);
 };
 
-#endif  // CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_LOG_LIST_H_
+}  // namespace webrtc_logging
+
+#endif  // COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_LIST_H_
diff --git a/components/webrtc_logging/common/BUILD.gn b/components/webrtc_logging/common/BUILD.gn
new file mode 100644
index 0000000..9df6f3b6
--- /dev/null
+++ b/components/webrtc_logging/common/BUILD.gn
@@ -0,0 +1,30 @@
+# 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.
+
+import("//media/media_options.gni")
+
+assert(enable_webrtc)
+
+source_set("common") {
+  sources = [
+    "partial_circular_buffer.cc",
+    "partial_circular_buffer.h",
+  ]
+
+  deps = [
+    "//base",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "partial_circular_buffer_unittest.cc",
+  ]
+  deps = [
+    ":common",
+    "//base",
+    "//testing/gtest",
+  ]
+}
diff --git a/chrome/common/partial_circular_buffer.cc b/components/webrtc_logging/common/partial_circular_buffer.cc
similarity index 97%
rename from chrome/common/partial_circular_buffer.cc
rename to components/webrtc_logging/common/partial_circular_buffer.cc
index c93a4b3..9a35d865 100644
--- a/chrome/common/partial_circular_buffer.cc
+++ b/components/webrtc_logging/common/partial_circular_buffer.cc
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/common/partial_circular_buffer.h"
+#include "components/webrtc_logging/common/partial_circular_buffer.h"
 
 #include <algorithm>
 
 #include "base/logging.h"
 
+namespace webrtc_logging {
+
 namespace {
 
 inline uint32_t Min3(uint32_t a, uint32_t b, uint32_t c) {
@@ -184,3 +186,5 @@
 
   buffer_data_->end_position = position_;
 }
+
+}  // namespace webrtc_logging
diff --git a/chrome/common/partial_circular_buffer.h b/components/webrtc_logging/common/partial_circular_buffer.h
similarity index 89%
rename from chrome/common/partial_circular_buffer.h
rename to components/webrtc_logging/common/partial_circular_buffer.h
index dca31b3..e78411a 100644
--- a/chrome/common/partial_circular_buffer.h
+++ b/components/webrtc_logging/common/partial_circular_buffer.h
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
-#define CHROME_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
+#ifndef COMPONENTS_WEBRTC_LOGGING_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
+#define COMPONENTS_WEBRTC_LOGGING_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
 
 #include <stdint.h>
 
+namespace webrtc_logging {
+
 // A wrapper around a memory buffer that allows circular read and write with a
 // selectable wrapping position. Buffer layout (after wrap; H is header):
 // -----------------------------------------------------------
@@ -63,4 +65,6 @@
   uint32_t total_read_;
 };
 
-#endif  // CHROME_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
+}  // namespace webrtc_logging
+
+#endif  // COMPONENTS_WEBRTC_LOGGING_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
diff --git a/chrome/common/partial_circular_buffer_unittest.cc b/components/webrtc_logging/common/partial_circular_buffer_unittest.cc
similarity index 95%
rename from chrome/common/partial_circular_buffer_unittest.cc
rename to components/webrtc_logging/common/partial_circular_buffer_unittest.cc
index f58e24b..a01e074 100644
--- a/chrome/common/partial_circular_buffer_unittest.cc
+++ b/components/webrtc_logging/common/partial_circular_buffer_unittest.cc
@@ -12,7 +12,7 @@
 // Note that desipte the number of wraps (if one or more), the reference output
 // data is the same since the offset at each wrap is always the same.
 
-#include "chrome/common/partial_circular_buffer.h"
+#include "components/webrtc_logging/common/partial_circular_buffer.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -22,6 +22,10 @@
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace webrtc_logging {
+
+namespace {
+
 const uint32_t kWrapPosition = 20;
 const uint8_t kInputData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
 const uint8_t kOutputRefDataWrap[] =
@@ -31,6 +35,8 @@
      11, 12, 13, 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4,
      5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
 
+}  // namespace
+
 class PartialCircularBufferTest : public testing::Test {
  public:
   PartialCircularBufferTest() {
@@ -44,10 +50,8 @@
 
   void InitWriteBuffer(bool append) {
     pcb_write_.reset(new PartialCircularBuffer(
-        buffer_.get(),
-        buffer_header_size_ + sizeof(kOutputRefDataWrap),
-        kWrapPosition,
-        append));
+        buffer_.get(), buffer_header_size_ + sizeof(kOutputRefDataWrap),
+        kWrapPosition, append));
   }
 
   void WriteToBuffer(int num) {
@@ -216,3 +220,4 @@
   EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
 }
 
+}  // namespace webrtc_logging
diff --git a/content/browser/android/synchronous_compositor_host.cc b/content/browser/android/synchronous_compositor_host.cc
index b3f08f79..13f22a22 100644
--- a/content/browser/android/synchronous_compositor_host.cc
+++ b/content/browser/android/synchronous_compositor_host.cc
@@ -76,6 +76,8 @@
     IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_LayerTreeFrameSinkCreated,
                         LayerTreeFrameSinkCreated)
     IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
+    IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_SetNeedsBeginFrames,
+                        SetNeedsBeginFrames)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -371,13 +373,24 @@
                          over_scroll_params.current_fling_velocity);
 }
 
-void SynchronousCompositorHost::DidSendBeginFrame(
-    ui::WindowAndroid* window_android) {
+void SynchronousCompositorHost::SendBeginFrame(
+    ui::WindowAndroid* window_android,
+    const viz::BeginFrameArgs& args) {
   compute_scroll_needs_synchronous_draw_ = false;
+  sender_->Send(new SyncCompositorMsg_BeginFrame(routing_id_, args));
+
   if (SynchronousCompositorBrowserFilter* filter = GetFilter())
     filter->SyncStateAfterVSync(window_android, this);
 }
 
+void SynchronousCompositorHost::SetBeginFramePaused(bool paused) {
+  sender_->Send(new SyncCompositorMsg_SetBeginFramePaused(routing_id_, paused));
+}
+
+void SynchronousCompositorHost::SetNeedsBeginFrames(bool needs_begin_frames) {
+  rwhva_->GetRenderWidgetHostImpl()->SetNeedsBeginFrame(needs_begin_frames);
+}
+
 void SynchronousCompositorHost::LayerTreeFrameSinkCreated() {
   // New LayerTreeFrameSink is not aware of state from Browser side. So need to
   // re-send all browser side state here.
diff --git a/content/browser/android/synchronous_compositor_host.h b/content/browser/android/synchronous_compositor_host.h
index 0bd21d8..b6fe882 100644
--- a/content/browser/android/synchronous_compositor_host.h
+++ b/content/browser/android/synchronous_compositor_host.h
@@ -64,7 +64,10 @@
   void OnComputeScroll(base::TimeTicks animation_time) override;
 
   void DidOverscroll(const ui::DidOverscrollParams& over_scroll_params);
-  void DidSendBeginFrame(ui::WindowAndroid* window_android);
+  void SendBeginFrame(ui::WindowAndroid* window_android,
+                      const viz::BeginFrameArgs& args);
+  void SetBeginFramePaused(bool paused);
+  void SetNeedsBeginFrames(bool needs_begin_frames);
   bool OnMessageReceived(const IPC::Message& message);
 
   // Called by SynchronousCompositorBrowserFilter.
diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc
index 93c6889..612e282b 100644
--- a/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/content/browser/devtools/devtools_agent_host_impl.cc
@@ -371,9 +371,11 @@
     observer.DevToolsAgentHostCreated(this);
 }
 
-void DevToolsAgentHostImpl::NotifyNavigated() {
+void DevToolsAgentHostImpl::NotifyNavigated(DevToolsAgentHostImpl* host) {
+  if (!host)
+    return;
   for (auto& observer : g_devtools_observers.Get())
-    observer.DevToolsAgentHostNavigated(this);
+    observer.DevToolsAgentHostNavigated(host);
 }
 
 void DevToolsAgentHostImpl::NotifyAttached() {
diff --git a/content/browser/devtools/devtools_agent_host_impl.h b/content/browser/devtools/devtools_agent_host_impl.h
index 6105f50b..db91037d 100644
--- a/content/browser/devtools/devtools_agent_host_impl.h
+++ b/content/browser/devtools/devtools_agent_host_impl.h
@@ -71,7 +71,7 @@
   virtual void InspectElement(DevToolsSession* session, int x, int y);
 
   void NotifyCreated();
-  void NotifyNavigated();
+  void NotifyNavigated(DevToolsAgentHostImpl* host);
   void ForceDetachAllClients();
   void ForceDetachSession(DevToolsSession* session);
   DevToolsIOContext* GetIOContext() { return &io_context_; }
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index 0834599..027586e9b 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -179,10 +179,9 @@
 // static
 std::vector<std::unique_ptr<NavigationThrottle>>
 RenderFrameDevToolsAgentHost::CreateNavigationThrottles(
-    NavigationHandle* navigation_handle) {
+    NavigationHandleImpl* navigation_handle) {
   std::vector<std::unique_ptr<NavigationThrottle>> result;
-  FrameTreeNode* frame_tree_node =
-      static_cast<NavigationHandleImpl*>(navigation_handle)->frame_tree_node();
+  FrameTreeNode* frame_tree_node = navigation_handle->frame_tree_node();
 
   // Interception might throttle navigations in inspected frames.
   RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
@@ -399,8 +398,14 @@
     NavigationHandle* navigation_handle) {
   NavigationHandleImpl* handle =
       static_cast<NavigationHandleImpl*>(navigation_handle);
-  if (handle->frame_tree_node() != frame_tree_node_)
+  if (handle->frame_tree_node() != frame_tree_node_) {
+    if (ShouldForceCreation() && handle->GetRenderFrameHost() &&
+        handle->GetRenderFrameHost()->IsCrossProcessSubframe()) {
+      RenderFrameDevToolsAgentHost::GetOrCreateForDangling(
+          handle->frame_tree_node());
+    }
     return;
+  }
 
   UpdateFrameHost(handle->GetRenderFrameHost());
   // UpdateFrameHost may destruct |this|.
@@ -408,10 +413,9 @@
 
 void RenderFrameDevToolsAgentHost::DidFinishNavigation(
     NavigationHandle* navigation_handle) {
-  NotifyNavigated();
-
   NavigationHandleImpl* handle =
       static_cast<NavigationHandleImpl*>(navigation_handle);
+  NotifyNavigated(FindAgentHost(handle->frame_tree_node()));
   if (handle->frame_tree_node() != frame_tree_node_)
     return;
   navigation_handles_.erase(handle);
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h
index a930558..4ae4f609 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -34,7 +34,6 @@
 class BrowserContext;
 class DevToolsFrameTraceRecorder;
 class FrameTreeNode;
-class NavigationHandle;
 class NavigationHandleImpl;
 class NavigationRequest;
 class NavigationThrottle;
@@ -62,7 +61,7 @@
   static void OnResetNavigationRequest(NavigationRequest* navigation_request);
 
   static std::vector<std::unique_ptr<NavigationThrottle>>
-  CreateNavigationThrottles(NavigationHandle* navigation_handle);
+  CreateNavigationThrottles(NavigationHandleImpl* navigation_handle);
   static bool IsNetworkHandlerEnabled(FrameTreeNode* frame_tree_node);
   static void WebContentsCreated(WebContents* web_contents);
 
diff --git a/content/browser/dom_storage/local_storage_context_mojo.cc b/content/browser/dom_storage/local_storage_context_mojo.cc
index ba83170..f7dfc76f9 100644
--- a/content/browser/dom_storage/local_storage_context_mojo.cc
+++ b/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -1013,14 +1013,17 @@
 
 void LocalStorageContextMojo::OnCommitResult(
     leveldb::mojom::DatabaseError error) {
-  DCHECK_EQ(connection_state_, CONNECTION_FINISHED);
+  DCHECK(connection_state_ == CONNECTION_FINISHED ||
+         connection_state_ == CONNECTION_SHUTDOWN)
+      << connection_state_;
   if (error == leveldb::mojom::DatabaseError::OK) {
     commit_error_count_ = 0;
     return;
   }
 
   commit_error_count_++;
-  if (commit_error_count_ > kCommitErrorThreshold) {
+  if (commit_error_count_ > kCommitErrorThreshold &&
+      connection_state_ != CONNECTION_SHUTDOWN) {
     if (tried_to_recover_from_commit_errors_) {
       // We already tried to recover from a high commit error rate before, but
       // are still having problems: there isn't really anything left to try, so
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 11eb1d3..a85896e 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -177,7 +177,6 @@
     std::unique_ptr<DownloadUrlParameters> params,
     std::unique_ptr<network::ResourceRequest> request,
     scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
-    scoped_refptr<storage::FileSystemContext> file_system_context,
     uint32_t download_id,
     base::WeakPtr<DownloadManagerImpl> download_manager,
     const GURL& site_url,
@@ -205,8 +204,8 @@
   return DownloadManagerImpl::UniqueUrlDownloadHandlerPtr(
       ResourceDownloader::BeginDownload(
           download_manager, std::move(params), std::move(request),
-          url_loader_factory_getter, file_system_context, getter, site_url,
-          tab_url, tab_referrer_url, download_id, false)
+          url_loader_factory_getter, getter, site_url, tab_url,
+          tab_referrer_url, download_id, false)
           .release());
 }
 
@@ -1090,8 +1089,7 @@
         BrowserThread::IO, FROM_HERE,
         base::BindOnce(
             &BeginResourceDownload, std::move(params), std::move(request),
-            storage_partition->url_loader_factory_getter(),
-            base::WrapRefCounted(storage_partition->GetFileSystemContext()), id,
+            storage_partition->url_loader_factory_getter(), id,
             weak_factory_.GetWeakPtr(), site_url, tab_url, tab_referrer_url),
         base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler,
                        weak_factory_.GetWeakPtr()));
diff --git a/content/browser/download/resource_downloader.cc b/content/browser/download/resource_downloader.cc
index b3a28d9..1310ed342 100644
--- a/content/browser/download/resource_downloader.cc
+++ b/content/browser/download/resource_downloader.cc
@@ -11,7 +11,6 @@
 #include "content/browser/download/download_utils.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
-#include "storage/browser/fileapi/file_system_context.h"
 
 namespace network {
 struct ResourceResponseHead;
@@ -89,7 +88,6 @@
     std::unique_ptr<DownloadUrlParameters> params,
     std::unique_ptr<network::ResourceRequest> request,
     scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
-    scoped_refptr<storage::FileSystemContext> file_system_context,
     const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
     const GURL& site_url,
     const GURL& tab_url,
@@ -100,8 +98,8 @@
       delegate, std::move(request), web_contents_getter, site_url, tab_url,
       tab_referrer_url, download_id);
 
-  downloader->Start(url_loader_factory_getter, file_system_context,
-                    std::move(params), is_parallel_request);
+  downloader->Start(url_loader_factory_getter, std::move(params),
+                    is_parallel_request);
   return downloader;
 }
 
@@ -146,7 +144,6 @@
 
 void ResourceDownloader::Start(
     scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
-    scoped_refptr<storage::FileSystemContext> file_system_context,
     std::unique_ptr<DownloadUrlParameters> download_url_parameters,
     bool is_parallel_request) {
   callback_ = download_url_parameters->callback();
diff --git a/content/browser/download/resource_downloader.h b/content/browser/download/resource_downloader.h
index 62f4202..d3b5dce 100644
--- a/content/browser/download/resource_downloader.h
+++ b/content/browser/download/resource_downloader.h
@@ -14,10 +14,6 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/interfaces/url_loader.mojom.h"
 
-namespace storage {
-class FileSystemContext;
-}
-
 namespace content {
 
 // Class for handing the download of a url.
@@ -30,7 +26,6 @@
       std::unique_ptr<DownloadUrlParameters> download_url_parameters,
       std::unique_ptr<network::ResourceRequest> request,
       scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
-      scoped_refptr<storage::FileSystemContext> file_system_context,
       const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
       const GURL& site_url,
       const GURL& tab_url,
@@ -70,7 +65,6 @@
  private:
   // Helper method to start the network request.
   void Start(scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
-             scoped_refptr<storage::FileSystemContext> file_system_context,
              std::unique_ptr<DownloadUrlParameters> download_url_parameters,
              bool is_parallel_request);
 
diff --git a/content/browser/renderer_host/input/composited_scrolling_browsertest.cc b/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
index 1bfed52..556aace 100644
--- a/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
+++ b/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
@@ -151,7 +151,8 @@
 // crbug.com/543655 for a case where this was broken.
 // Disabled on MacOS because it doesn't support touch input.
 // Disabled on Android due to flakiness, see https://crbug.com/376668.
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+// Flaky on Windows: crbug.com/804009
+#if defined(OS_MACOSX) || defined(OS_ANDROID) || defined(OS_WIN)
 #define MAYBE_Scroll3DTransformedScroller DISABLED_Scroll3DTransformedScroller
 #else
 #define MAYBE_Scroll3DTransformedScroller Scroll3DTransformedScroller
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
index 776b59cb..056390f 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -112,17 +112,9 @@
   if (!media_stream_manager_->media_devices_manager())
     return;
 
-  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
-    if (!device_change_subscriptions_[i].empty()) {
-      media_stream_manager_->media_devices_manager()
-          ->UnsubscribeDeviceChangeNotifications(
-              static_cast<MediaDeviceType>(i), this);
-    }
-  }
-
-  for (auto& subscription_id : subscription_ids_) {
-    media_stream_manager_->media_devices_manager()->UnsubscribeDeviceChange(
-        subscription_id);
+  for (auto subscription_id : subscription_ids_) {
+    media_stream_manager_->media_devices_manager()
+        ->UnsubscribeDeviceChangeNotifications(subscription_id);
   }
 }
 
@@ -190,47 +182,6 @@
                      base::Passed(&client_callback)));
 }
 
-void MediaDevicesDispatcherHost::SubscribeDeviceChangeNotifications(
-    MediaDeviceType type,
-    uint32_t subscription_id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK(IsValidMediaDeviceType(type));
-  auto it =
-      std::find(device_change_subscriptions_[type].begin(),
-                device_change_subscriptions_[type].end(), subscription_id);
-  if (it != device_change_subscriptions_[type].end()) {
-    bad_message::ReceivedBadMessage(
-        render_process_id_, bad_message::MDDH_INVALID_SUBSCRIPTION_REQUEST);
-    return;
-  }
-
-  if (device_change_subscriptions_[type].empty()) {
-    media_stream_manager_->media_devices_manager()
-        ->SubscribeDeviceChangeNotifications(type, this);
-  }
-
-  device_change_subscriptions_[type].push_back(subscription_id);
-}
-
-void MediaDevicesDispatcherHost::UnsubscribeDeviceChangeNotifications(
-    MediaDeviceType type,
-    uint32_t subscription_id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK(IsValidMediaDeviceType(type));
-  auto it =
-      std::find(device_change_subscriptions_[type].begin(),
-                device_change_subscriptions_[type].end(), subscription_id);
-  // Ignore invalid unsubscription requests.
-  if (it == device_change_subscriptions_[type].end())
-    return;
-
-  device_change_subscriptions_[type].erase(it);
-  if (device_change_subscriptions_[type].empty()) {
-    media_stream_manager_->media_devices_manager()
-        ->UnsubscribeDeviceChangeNotifications(type, this);
-  }
-}
-
 void MediaDevicesDispatcherHost::AddMediaDevicesListener(
     bool subscribe_audio_input,
     bool subscribe_video_input,
@@ -250,70 +201,14 @@
   devices_to_subscribe[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = subscribe_video_input;
   devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = subscribe_audio_output;
 
-  uint32_t subscription_id = media_stream_manager_->media_devices_manager()
-                                 ->SubscribeDeviceChangeNotifications(
-                                     devices_to_subscribe, std::move(listener));
+  uint32_t subscription_id =
+      media_stream_manager_->media_devices_manager()
+          ->SubscribeDeviceChangeNotifications(
+              render_process_id_, render_frame_id_, group_id_salt_base_,
+              devices_to_subscribe, std::move(listener));
   subscription_ids_.push_back(subscription_id);
 }
 
-void MediaDevicesDispatcherHost::OnDevicesChanged(
-    MediaDeviceType type,
-    const MediaDeviceInfoArray& device_infos) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK(IsValidMediaDeviceType(type));
-  std::vector<uint32_t> subscriptions = device_change_subscriptions_[type];
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&MediaDevicesDispatcherHost::NotifyDeviceChangeOnUIThread,
-                     weak_factory_.GetWeakPtr(), std::move(subscriptions), type,
-                     device_infos));
-}
-
-void MediaDevicesDispatcherHost::NotifyDeviceChangeOnUIThread(
-    const std::vector<uint32_t>& subscriptions,
-    MediaDeviceType type,
-    const MediaDeviceInfoArray& device_infos) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(IsValidMediaDeviceType(type));
-
-  blink::mojom::MediaDevicesListenerPtr media_devices_listener;
-  if (device_change_listener_) {
-    media_devices_listener = std::move(device_change_listener_);
-  } else {
-    RenderFrameHost* render_frame_host =
-        RenderFrameHost::FromID(render_process_id_, render_frame_id_);
-    if (!render_frame_host)
-      return;
-
-    render_frame_host->GetRemoteInterfaces()->GetInterface(
-        mojo::MakeRequest(&media_devices_listener));
-    if (!media_devices_listener)
-      return;
-  }
-
-  const auto& salt_and_origin = media_stream_manager_->media_devices_manager()
-                                    ->salt_and_origin_callback()
-                                    .Run(render_process_id_, render_frame_id_);
-  std::string group_id_salt = group_id_salt_base_ + salt_and_origin.first;
-  for (uint32_t subscription_id : subscriptions) {
-    bool has_permission = media_stream_manager_->media_devices_manager()
-                              ->media_devices_permission_checker()
-                              ->CheckPermissionOnUIThread(
-                                  type, render_process_id_, render_frame_id_);
-    media_devices_listener->OnDevicesChanged(
-        type, subscription_id,
-        TranslateMediaDeviceInfoArray(has_permission, salt_and_origin.first,
-                                      group_id_salt, salt_and_origin.second,
-                                      device_infos));
-  }
-}
-
-void MediaDevicesDispatcherHost::SetDeviceChangeListenerForTesting(
-    blink::mojom::MediaDevicesListenerPtr listener) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  device_change_listener_ = std::move(listener);
-}
-
 void MediaDevicesDispatcherHost::GetDefaultVideoInputDeviceID(
     GetVideoInputCapabilitiesCallback client_callback,
     const std::pair<std::string, url::Origin>& salt_and_origin) {
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.h b/content/browser/renderer_host/media/media_devices_dispatcher_host.h
index b85891b..a605b18 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host.h
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.h
@@ -25,8 +25,7 @@
 class MediaStreamManager;
 
 class CONTENT_EXPORT MediaDevicesDispatcherHost
-    : public blink::mojom::MediaDevicesDispatcherHost,
-      public MediaDeviceChangeSubscriber {
+    : public blink::mojom::MediaDevicesDispatcherHost {
  public:
   MediaDevicesDispatcherHost(int render_process_id,
                              int render_frame_id,
@@ -53,23 +52,12 @@
       GetAvailableVideoInputDeviceFormatsCallback client_callback) override;
   void GetAudioInputCapabilities(
       GetAudioInputCapabilitiesCallback client_callback) override;
-  void SubscribeDeviceChangeNotifications(MediaDeviceType type,
-                                          uint32_t subscription_id) override;
-  void UnsubscribeDeviceChangeNotifications(MediaDeviceType type,
-                                            uint32_t subscription_id) override;
   void AddMediaDevicesListener(
       bool subscribe_audio_input,
       bool subscribe_video_input,
       bool subscribe_audio_output,
       blink::mojom::MediaDevicesListenerPtr listener) override;
 
-  // MediaDeviceChangeSubscriber implementation.
-  void OnDevicesChanged(MediaDeviceType type,
-                        const MediaDeviceInfoArray& device_infos) override;
-
-  void SetDeviceChangeListenerForTesting(
-      blink::mojom::MediaDevicesListenerPtr listener);
-
  private:
   using GetVideoInputDeviceFormatsCallback =
       GetAllVideoInputDeviceFormatsCallback;
@@ -130,10 +118,6 @@
   media::VideoCaptureFormats GetVideoInputFormats(const std::string& device_id,
                                                   bool try_in_use_first);
 
-  void NotifyDeviceChangeOnUIThread(const std::vector<uint32_t>& subscriptions,
-                                    MediaDeviceType type,
-                                    const MediaDeviceInfoArray& device_infos);
-
   // The following const fields can be accessed on any thread.
   const int render_process_id_;
   const int render_frame_id_;
@@ -145,12 +129,6 @@
 
   // The following fields can only be accessed on the IO thread.
   MediaStreamManager* media_stream_manager_;
-  std::vector<uint32_t> device_change_subscriptions_[NUM_MEDIA_DEVICE_TYPES];
-
-  // TODO(c.padhi): Remove this field once device change migration to blink is
-  // complete, see https://crbug.com/793297.
-  // This field can only be accessed on the UI thread.
-  blink::mojom::MediaDevicesListenerPtr device_change_listener_;
 
   struct AudioInputCapabilitiesRequest;
   // Queued requests for audio-input capabilities.
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
index 0d46aec8..231c783 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
@@ -32,7 +32,7 @@
 #include "media/base/media_switches.h"
 #include "media/capture/video/fake_video_capture_device_factory.h"
 #include "media/capture/video/video_capture_system_impl.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/origin.h"
@@ -65,19 +65,19 @@
 
 class MockMediaDevicesListener : public blink::mojom::MediaDevicesListener {
  public:
-  MockMediaDevicesListener() : binding_(this) {}
+  MockMediaDevicesListener() {}
 
-  MOCK_METHOD3(OnDevicesChanged,
-               void(MediaDeviceType, uint32_t, const MediaDeviceInfoArray&));
+  MOCK_METHOD2(OnDevicesChanged,
+               void(MediaDeviceType, const MediaDeviceInfoArray&));
 
   blink::mojom::MediaDevicesListenerPtr CreateInterfacePtrAndBind() {
     blink::mojom::MediaDevicesListenerPtr listener;
-    binding_.Bind(mojo::MakeRequest(&listener));
+    bindings_.AddBinding(this, mojo::MakeRequest(&listener));
     return listener;
   }
 
  private:
-  mojo::Binding<blink::mojom::MediaDevicesListener> binding_;
+  mojo::BindingSet<blink::mojom::MediaDevicesListener> bindings_;
 };
 
 }  // namespace
@@ -346,24 +346,24 @@
   void SubscribeAndWaitForResult(bool has_permission) {
     media_stream_manager_->media_devices_manager()->SetPermissionChecker(
         std::make_unique<MediaDevicesPermissionChecker>(has_permission));
-    uint32_t subscription_id = 0u;
+    MockMediaDevicesListener device_change_listener;
     for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
       MediaDeviceType type = static_cast<MediaDeviceType>(i);
-      host_->SubscribeDeviceChangeNotifications(type, subscription_id);
-      MockMediaDevicesListener device_change_listener;
-      host_->SetDeviceChangeListenerForTesting(
+      host_->AddMediaDevicesListener(
+          type == MEDIA_DEVICE_TYPE_AUDIO_INPUT,
+          type == MEDIA_DEVICE_TYPE_VIDEO_INPUT,
+          type == MEDIA_DEVICE_TYPE_AUDIO_OUTPUT,
           device_change_listener.CreateInterfacePtrAndBind());
       MediaDeviceInfoArray changed_devices;
-      EXPECT_CALL(device_change_listener,
-                  OnDevicesChanged(type, subscription_id, testing::_))
-          .WillRepeatedly(SaveArg<2>(&changed_devices));
+      EXPECT_CALL(device_change_listener, OnDevicesChanged(type, _))
+          .WillRepeatedly(SaveArg<1>(&changed_devices));
 
       // Simulate device-change notification
-      MediaDeviceInfoArray updated_devices = {
-          {"fake_device_id", "fake_label", "fake_group"}};
-      host_->OnDevicesChanged(type, updated_devices);
+      media_stream_manager_->media_devices_manager()->OnDevicesChanged(
+          base::SystemMonitor::DEVTYPE_AUDIO);
+      media_stream_manager_->media_devices_manager()->OnDevicesChanged(
+          base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
       base::RunLoop().RunUntilIdle();
-      host_->UnsubscribeDeviceChangeNotifications(type, subscription_id);
 
       if (has_permission)
         EXPECT_TRUE(DoesContainLabels(changed_devices));
diff --git a/content/browser/renderer_host/media/media_devices_manager.cc b/content/browser/renderer_host/media/media_devices_manager.cc
index 57ee40f0..cfb50f7 100644
--- a/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/content/browser/renderer_host/media/media_devices_manager.cc
@@ -147,9 +147,16 @@
 };
 
 MediaDevicesManager::SubscriptionRequest::SubscriptionRequest(
+    int render_process_id,
+    int render_frame_id,
+    const std::string& group_id_salt_base,
     const BoolDeviceTypes& subscribe_types,
     blink::mojom::MediaDevicesListenerPtr listener)
-    : subscribe_types(subscribe_types), listener(std::move(listener)) {}
+    : render_process_id(render_process_id),
+      render_frame_id(render_frame_id),
+      group_id_salt_base(group_id_salt_base),
+      subscribe_types(subscribe_types),
+      listener(std::move(listener)) {}
 
 MediaDevicesManager::SubscriptionRequest::SubscriptionRequest(
     SubscriptionRequest&&) = default;
@@ -223,45 +230,29 @@
                      base::Passed(&callback)));
 }
 
-void MediaDevicesManager::SubscribeDeviceChangeNotifications(
-    MediaDeviceType type,
-    MediaDeviceChangeSubscriber* subscriber) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  auto it = std::find(device_change_subscribers_[type].begin(),
-                      device_change_subscribers_[type].end(), subscriber);
-  if (it == device_change_subscribers_[type].end())
-    device_change_subscribers_[type].push_back(subscriber);
-}
-
-void MediaDevicesManager::UnsubscribeDeviceChangeNotifications(
-    MediaDeviceType type,
-    MediaDeviceChangeSubscriber* subscriber) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  auto it = std::find(device_change_subscribers_[type].begin(),
-                      device_change_subscribers_[type].end(), subscriber);
-  if (it != device_change_subscribers_[type].end())
-    device_change_subscribers_[type].erase(it);
-}
-
 uint32_t MediaDevicesManager::SubscribeDeviceChangeNotifications(
+    int render_process_id,
+    int render_frame_id,
+    const std::string& group_id_salt_base,
     const BoolDeviceTypes& subscribe_types,
     blink::mojom::MediaDevicesListenerPtr listener) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  uint32_t subscription_id = ++current_subscription_id_;
+  uint32_t subscription_id = ++last_subscription_id_;
   blink::mojom::MediaDevicesListenerPtr media_devices_listener =
       std::move(listener);
   media_devices_listener.set_connection_error_handler(
-      base::BindOnce(&MediaDevicesManager::UnsubscribeDeviceChange,
+      base::BindOnce(&MediaDevicesManager::UnsubscribeDeviceChangeNotifications,
                      weak_factory_.GetWeakPtr(), subscription_id));
   subscriptions_.emplace(
-      subscription_id,
-      SubscriptionRequest(subscribe_types, std::move(media_devices_listener)));
+      subscription_id, SubscriptionRequest(render_process_id, render_frame_id,
+                                           group_id_salt_base, subscribe_types,
+                                           std::move(media_devices_listener)));
 
   return subscription_id;
 }
 
-void MediaDevicesManager::UnsubscribeDeviceChange(uint32_t subscription_id) {
+void MediaDevicesManager::UnsubscribeDeviceChangeNotifications(
+    uint32_t subscription_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   subscriptions_.erase(subscription_id);
 }
@@ -624,17 +615,47 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(IsValidMediaDeviceType(type));
 
-  for (auto* subscriber : device_change_subscribers_[type])
-    subscriber->OnDevicesChanged(type, snapshot);
-
-  // TODO(c.padhi): Check permission for |type| and translate |snapshot|,
-  // see https://crbug.com/793297.
   for (auto& subscription : subscriptions_) {
-    if (subscription.second.subscribe_types[type]) {
-      subscription.second.listener->OnDevicesChanged(type, subscription.first,
-                                                     MediaDeviceInfoArray());
+    SubscriptionRequest* request = &subscription.second;
+    if (request->subscribe_types[type]) {
+      base::PostTaskAndReplyWithResult(
+          BrowserThread::GetTaskRunnerForThread(BrowserThread::UI).get(),
+          FROM_HERE,
+          base::BindOnce(salt_and_origin_callback_, request->render_process_id,
+                         request->render_frame_id),
+          base::BindOnce(&MediaDevicesManager::CheckPermissionForDeviceChange,
+                         weak_factory_.GetWeakPtr(), request, type, snapshot));
     }
   }
 }
 
+void MediaDevicesManager::CheckPermissionForDeviceChange(
+    SubscriptionRequest* request,
+    MediaDeviceType type,
+    const MediaDeviceInfoArray& device_infos,
+    const std::pair<std::string, url::Origin>& salt_and_origin) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  permission_checker_->CheckPermission(
+      type, request->render_process_id, request->render_frame_id,
+      base::BindOnce(&MediaDevicesManager::NotifyDeviceChange,
+                     weak_factory_.GetWeakPtr(), request, type, device_infos,
+                     salt_and_origin.first, salt_and_origin.second));
+}
+
+void MediaDevicesManager::NotifyDeviceChange(
+    SubscriptionRequest* request,
+    MediaDeviceType type,
+    const MediaDeviceInfoArray& device_infos,
+    std::string device_id_salt,
+    const url::Origin& security_origin,
+    bool has_permission) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(IsValidMediaDeviceType(type));
+  std::string group_id_salt = request->group_id_salt_base + device_id_salt;
+  request->listener->OnDevicesChanged(
+      type, TranslateMediaDeviceInfoArray(has_permission, device_id_salt,
+                                          group_id_salt, security_origin,
+                                          device_infos));
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/media/media_devices_manager.h b/content/browser/renderer_host/media/media_devices_manager.h
index bcf3055d..638d11b8 100644
--- a/content/browser/renderer_host/media/media_devices_manager.h
+++ b/content/browser/renderer_host/media/media_devices_manager.h
@@ -34,18 +34,6 @@
 using MediaDeviceEnumeration =
     std::array<MediaDeviceInfoArray, NUM_MEDIA_DEVICE_TYPES>;
 
-// MediaDeviceChangeSubscriber is an interface to be implemented by classes
-// that can register with MediaDevicesManager to get notifications about changes
-// in the set of media devices.
-class CONTENT_EXPORT MediaDeviceChangeSubscriber {
- public:
-  // This function is invoked to notify about changes in the set of media
-  // devices of type |type|. |device_infos| contains the updated list of
-  // devices of type |type|.
-  virtual void OnDevicesChanged(MediaDeviceType type,
-                                const MediaDeviceInfoArray& device_infos) = 0;
-};
-
 // MediaDevicesManager is responsible for doing media-device enumerations.
 // In addition it implements caching for enumeration results and device
 // monitoring in order to keep caches consistent.
@@ -94,26 +82,13 @@
                         const BoolDeviceTypes& requested_types,
                         EnumerateDevicesCallback callback);
 
-  // Subscribes |subscriber| to receive device-change notifications for devices
-  // of type |type|. If |subscriber| is already subscribed, this function has
-  // no side effects. MediaDevicesManager does not own |subscriber|. It is the
-  // responsibility of the caller to ensure that all registered subscribers
-  // remain valid while the they are subscribed.
-  void SubscribeDeviceChangeNotifications(
-      MediaDeviceType type,
-      MediaDeviceChangeSubscriber* subscriber);
-
-  // Unubscribes |subscriber| from device-change notifications for the devices
-  // of type |type|. If |subscriber| is not subscribed, this function has no
-  // side effects.
-  void UnsubscribeDeviceChangeNotifications(
-      MediaDeviceType type,
-      MediaDeviceChangeSubscriber* subscriber);
-
   uint32_t SubscribeDeviceChangeNotifications(
+      int render_process_id,
+      int render_frame_id,
+      const std::string& group_id_salt_base,
       const BoolDeviceTypes& subscribe_types,
       blink::mojom::MediaDevicesListenerPtr listener);
-  void UnsubscribeDeviceChange(uint32_t subscription_id);
+  void UnsubscribeDeviceChangeNotifications(uint32_t subscription_id);
 
   // Tries to start device monitoring. If successful, enables caching of
   // enumeration results for the device types supported by the monitor.
@@ -153,6 +128,24 @@
   friend class MediaDevicesManagerTest;
   struct EnumerationRequest;
 
+  struct SubscriptionRequest {
+    SubscriptionRequest(int render_process_id,
+                        int render_frame_id,
+                        const std::string& group_id_salt_base,
+                        const BoolDeviceTypes& subscribe_types,
+                        blink::mojom::MediaDevicesListenerPtr listener);
+    SubscriptionRequest(SubscriptionRequest&&);
+    ~SubscriptionRequest();
+
+    SubscriptionRequest& operator=(SubscriptionRequest&&);
+
+    int render_process_id;
+    int render_frame_id;
+    std::string group_id_salt_base;
+    BoolDeviceTypes subscribe_types;
+    blink::mojom::MediaDevicesListenerPtr listener;
+  };
+
   // The NO_CACHE policy is such that no previous results are used when
   // EnumerateDevices is called. The results of a new or in-progress low-level
   // device enumeration are used.
@@ -218,6 +211,17 @@
                                 const MediaDeviceInfoArray& new_snapshot);
   void NotifyDeviceChangeSubscribers(MediaDeviceType type,
                                      const MediaDeviceInfoArray& snapshot);
+  void CheckPermissionForDeviceChange(
+      SubscriptionRequest* request,
+      MediaDeviceType type,
+      const MediaDeviceInfoArray& device_infos,
+      const std::pair<std::string, url::Origin>& salt_and_origin);
+  void NotifyDeviceChange(SubscriptionRequest* request,
+                          MediaDeviceType type,
+                          const MediaDeviceInfoArray& device_infos,
+                          std::string device_id_salt,
+                          const url::Origin& security_origin,
+                          bool has_permission);
 
 #if defined(OS_MACOSX)
   void StartMonitoringOnUIThread();
@@ -242,22 +246,7 @@
   MediaDeviceEnumeration current_snapshot_;
   bool monitoring_started_;
 
-  std::vector<MediaDeviceChangeSubscriber*>
-      device_change_subscribers_[NUM_MEDIA_DEVICE_TYPES];
-
-  struct SubscriptionRequest {
-    SubscriptionRequest(const BoolDeviceTypes& subscribe_types,
-                        blink::mojom::MediaDevicesListenerPtr listener);
-    SubscriptionRequest(SubscriptionRequest&&);
-    ~SubscriptionRequest();
-
-    SubscriptionRequest& operator=(SubscriptionRequest&&);
-
-    BoolDeviceTypes subscribe_types;
-    blink::mojom::MediaDevicesListenerPtr listener;
-  };
-
-  uint32_t current_subscription_id_ = 0u;
+  uint32_t last_subscription_id_ = 0u;
   base::flat_map<uint32_t, SubscriptionRequest> subscriptions_;
 
   // Callback used to obtain the current device ID salt and security origin.
diff --git a/content/browser/renderer_host/media/media_devices_manager_unittest.cc b/content/browser/renderer_host/media/media_devices_manager_unittest.cc
index f3a858d..08599f4 100644
--- a/content/browser/renderer_host/media/media_devices_manager_unittest.cc
+++ b/content/browser/renderer_host/media/media_devices_manager_unittest.cc
@@ -23,8 +23,11 @@
 #include "media/audio/test_audio_thread.h"
 #include "media/capture/video/fake_video_capture_device_factory.h"
 #include "media/capture/video/video_capture_system_impl.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
 
 using testing::_;
 using testing::SaveArg;
@@ -33,12 +36,22 @@
 
 namespace {
 
+const int kRenderProcessId = 1;
+const int kRenderFrameId = 3;
+
 // Number of client enumerations to simulate on each test run.
 // This allows testing that a single call to low-level enumeration functions
 // is performed when cache is enabled, regardless of the number of client calls.
 const int kNumCalls = 3;
 
 const auto kIgnoreLogMessageCB = base::BindRepeating([](const std::string&) {});
+
+std::pair<std::string, url::Origin> GetSaltAndOrigin(int /* process_id */,
+                                                     int /* frame_id */) {
+  return std::make_pair(std::string("fake_media_device_salt"),
+                        url::Origin::Create(GURL("https://test.com")));
+}
+
 // This class mocks the audio manager and overrides some methods to ensure that
 // we can run simulate device changes.
 class MockAudioManager : public media::FakeAudioManager {
@@ -118,10 +131,21 @@
   }
 };
 
-class MockMediaDeviceChangeSubscriber : public MediaDeviceChangeSubscriber {
+class MockMediaDevicesListener : public blink::mojom::MediaDevicesListener {
  public:
+  MockMediaDevicesListener() {}
+
   MOCK_METHOD2(OnDevicesChanged,
                void(MediaDeviceType, const MediaDeviceInfoArray&));
+
+  blink::mojom::MediaDevicesListenerPtr CreateInterfacePtrAndBind() {
+    blink::mojom::MediaDevicesListenerPtr listener;
+    bindings_.AddBinding(this, mojo::MakeRequest(&listener));
+    return listener;
+  }
+
+ private:
+  mojo::BindingSet<blink::mojom::MediaDevicesListener> bindings_;
 };
 
 }  // namespace
@@ -159,6 +183,8 @@
         std::move(video_capture_provider), kIgnoreLogMessageCB);
     media_devices_manager_.reset(new MediaDevicesManager(
         audio_system_.get(), video_capture_manager_, nullptr));
+    media_devices_manager_->set_salt_and_origin_callback_for_testing(
+        base::BindRepeating(&GetSaltAndOrigin));
   }
 
   void EnableCache(MediaDeviceType type) {
@@ -490,24 +516,45 @@
                  base::Unretained(this), &run_loop));
   run_loop.Run();
 
-  // Add device-change event subscribers.
-  MockMediaDeviceChangeSubscriber subscriber_audio_input;
-  MockMediaDeviceChangeSubscriber subscriber_video_input;
-  MockMediaDeviceChangeSubscriber subscriber_audio_output;
-  MockMediaDeviceChangeSubscriber subscriber_all;
+  // Add device-change event listeners.
+  MockMediaDevicesListener listener_audio_input;
+  MediaDevicesManager::BoolDeviceTypes audio_input_devices_to_subscribe;
+  audio_input_devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
+  uint32_t audio_input_subscription_id =
+      media_devices_manager_->SubscribeDeviceChangeNotifications(
+          kRenderProcessId, kRenderFrameId,
+          std::string("fake_group_id_salt_base"),
+          audio_input_devices_to_subscribe,
+          listener_audio_input.CreateInterfacePtrAndBind());
 
+  MockMediaDevicesListener listener_video_input;
+  MediaDevicesManager::BoolDeviceTypes video_input_devices_to_subscribe;
+  video_input_devices_to_subscribe[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
+  uint32_t video_input_subscription_id =
+      media_devices_manager_->SubscribeDeviceChangeNotifications(
+          kRenderProcessId, kRenderFrameId,
+          std::string("fake_group_id_salt_base"),
+          video_input_devices_to_subscribe,
+          listener_video_input.CreateInterfacePtrAndBind());
+
+  MockMediaDevicesListener listener_audio_output;
+  MediaDevicesManager::BoolDeviceTypes audio_output_devices_to_subscribe;
+  audio_output_devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
+  uint32_t audio_output_subscription_id =
+      media_devices_manager_->SubscribeDeviceChangeNotifications(
+          kRenderProcessId, kRenderFrameId,
+          std::string("fake_group_id_salt_base"),
+          audio_output_devices_to_subscribe,
+          listener_audio_output.CreateInterfacePtrAndBind());
+
+  MockMediaDevicesListener listener_all;
+  MediaDevicesManager::BoolDeviceTypes all_devices_to_subscribe;
+  all_devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
+  all_devices_to_subscribe[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
+  all_devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
   media_devices_manager_->SubscribeDeviceChangeNotifications(
-      MEDIA_DEVICE_TYPE_AUDIO_INPUT, &subscriber_audio_input);
-  media_devices_manager_->SubscribeDeviceChangeNotifications(
-      MEDIA_DEVICE_TYPE_VIDEO_INPUT, &subscriber_video_input);
-  media_devices_manager_->SubscribeDeviceChangeNotifications(
-      MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, &subscriber_audio_output);
-  media_devices_manager_->SubscribeDeviceChangeNotifications(
-      MEDIA_DEVICE_TYPE_AUDIO_INPUT, &subscriber_all);
-  media_devices_manager_->SubscribeDeviceChangeNotifications(
-      MEDIA_DEVICE_TYPE_VIDEO_INPUT, &subscriber_all);
-  media_devices_manager_->SubscribeDeviceChangeNotifications(
-      MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, &subscriber_all);
+      kRenderProcessId, kRenderFrameId, std::string("fake_group_id_salt_base"),
+      all_devices_to_subscribe, listener_all.CreateInterfacePtrAndBind());
 
   MediaDeviceInfoArray notification_audio_input;
   MediaDeviceInfoArray notification_video_input;
@@ -515,28 +562,25 @@
   MediaDeviceInfoArray notification_all_audio_input;
   MediaDeviceInfoArray notification_all_video_input;
   MediaDeviceInfoArray notification_all_audio_output;
-  EXPECT_CALL(subscriber_audio_input,
+  EXPECT_CALL(listener_audio_input,
               OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_INPUT, _))
       .Times(1)
       .WillOnce(SaveArg<1>(&notification_audio_input));
-  EXPECT_CALL(subscriber_video_input,
+  EXPECT_CALL(listener_video_input,
               OnDevicesChanged(MEDIA_DEVICE_TYPE_VIDEO_INPUT, _))
       .Times(1)
       .WillOnce(SaveArg<1>(&notification_video_input));
-  EXPECT_CALL(subscriber_audio_output,
+  EXPECT_CALL(listener_audio_output,
               OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, _))
       .Times(1)
       .WillOnce(SaveArg<1>(&notification_audio_output));
-  EXPECT_CALL(subscriber_all,
-              OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_INPUT, _))
+  EXPECT_CALL(listener_all, OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_INPUT, _))
       .Times(2)
       .WillRepeatedly(SaveArg<1>(&notification_all_audio_input));
-  EXPECT_CALL(subscriber_all,
-              OnDevicesChanged(MEDIA_DEVICE_TYPE_VIDEO_INPUT, _))
+  EXPECT_CALL(listener_all, OnDevicesChanged(MEDIA_DEVICE_TYPE_VIDEO_INPUT, _))
       .Times(2)
       .WillRepeatedly(SaveArg<1>(&notification_all_video_input));
-  EXPECT_CALL(subscriber_all,
-              OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, _))
+  EXPECT_CALL(listener_all, OnDevicesChanged(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, _))
       .Times(2)
       .WillRepeatedly(SaveArg<1>(&notification_all_audio_output));
 
@@ -560,11 +604,11 @@
   EXPECT_EQ(num_audio_output_devices, notification_all_audio_output.size());
 
   media_devices_manager_->UnsubscribeDeviceChangeNotifications(
-      MEDIA_DEVICE_TYPE_AUDIO_INPUT, &subscriber_audio_input);
+      audio_input_subscription_id);
   media_devices_manager_->UnsubscribeDeviceChangeNotifications(
-      MEDIA_DEVICE_TYPE_VIDEO_INPUT, &subscriber_video_input);
+      video_input_subscription_id);
   media_devices_manager_->UnsubscribeDeviceChangeNotifications(
-      MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, &subscriber_audio_output);
+      audio_output_subscription_id);
 
   // Simulate further device changes. Only the objects still subscribed to the
   // device-change events will receive notifications.
diff --git a/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc b/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
index 46ee756..b8e2d15 100644
--- a/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
@@ -28,7 +28,7 @@
                                                PP_Instance instance,
                                                PP_Resource resource)
     : ResourceHost(host->GetPpapiHost(), instance, resource),
-      proxy_service_(nullptr),
+      proxy_resolution_service_(nullptr),
       is_allowed_(false),
       waiting_for_ui_thread_data_(true),
       weak_factory_(this) {
@@ -48,11 +48,11 @@
 
 PepperNetworkProxyHost::~PepperNetworkProxyHost() {
   while (!pending_requests_.empty()) {
-    // If the proxy_service_ is NULL, we shouldn't have any outstanding
+    // If the proxy_resolution_service_ is NULL, we shouldn't have any outstanding
     // requests.
-    DCHECK(proxy_service_);
-    net::ProxyService::Request* request = pending_requests_.front();
-    proxy_service_->CancelRequest(request);
+    DCHECK(proxy_resolution_service_);
+    net::ProxyResolutionService::Request* request = pending_requests_.front();
+    proxy_resolution_service_->CancelRequest(request);
     pending_requests_.pop();
   }
 }
@@ -91,13 +91,13 @@
   is_allowed_ = ui_thread_data.is_allowed;
   if (ui_thread_data.context_getter.get() &&
       ui_thread_data.context_getter->GetURLRequestContext()) {
-    proxy_service_ =
-        ui_thread_data.context_getter->GetURLRequestContext()->proxy_service();
+    proxy_resolution_service_ =
+        ui_thread_data.context_getter->GetURLRequestContext()->proxy_resolution_service();
   }
   waiting_for_ui_thread_data_ = false;
-  if (!proxy_service_) {
-    DLOG_IF(WARNING, proxy_service_)
-        << "Failed to find a ProxyService for Pepper plugin.";
+  if (!proxy_resolution_service_) {
+    DLOG_IF(WARNING, proxy_resolution_service_)
+        << "Failed to find a ProxyResolutionService for Pepper plugin.";
   }
   TryToSendUnsentRequests();
 }
@@ -132,25 +132,25 @@
 
   while (!unsent_requests_.empty()) {
     const UnsentRequest& request = unsent_requests_.front();
-    if (!proxy_service_) {
+    if (!proxy_resolution_service_) {
       SendFailureReply(PP_ERROR_FAILED, request.reply_context);
     } else if (!is_allowed_) {
       SendFailureReply(PP_ERROR_NOACCESS, request.reply_context);
     } else {
       // Everything looks valid, so try to resolve the proxy.
       net::ProxyInfo* proxy_info = new net::ProxyInfo;
-      net::ProxyService::Request* pending_request = nullptr;
+      net::ProxyResolutionService::Request* pending_request = nullptr;
       base::Callback<void(int)> callback =
           base::Bind(&PepperNetworkProxyHost::OnResolveProxyCompleted,
                      weak_factory_.GetWeakPtr(),
                      request.reply_context,
                      base::Owned(proxy_info));
-      int result = proxy_service_->ResolveProxy(
+      int result = proxy_resolution_service_->ResolveProxy(
           request.url, std::string(), proxy_info, callback, &pending_request,
           nullptr, net::NetLogWithSource());
       pending_requests_.push(pending_request);
       // If it was handled synchronously, we must run the callback now;
-      // proxy_service_ won't run it for us in this case.
+      // proxy_resolution_service_ won't run it for us in this case.
       if (result != net::ERR_IO_PENDING)
         callback.Run(result);
     }
diff --git a/content/browser/renderer_host/pepper/pepper_network_proxy_host.h b/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
index 011417f..3182f5bcd 100644
--- a/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
+++ b/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
@@ -46,7 +46,7 @@
  private:
   // We retrieve the appropriate URLRequestContextGetter and whether this API
   // is allowed for the instance on the UI thread and pass those to
-  // DidGetUIThreadData, which sets allowed_ and proxy_service_.
+  // DidGetUIThreadData, which sets allowed_ and proxy_resolution_service_.
   struct UIThreadData {
     UIThreadData();
     UIThreadData(const UIThreadData& other);
@@ -67,7 +67,8 @@
   int32_t OnMsgGetProxyForURL(ppapi::host::HostMessageContext* context,
                               const std::string& url);
 
-  // If we have a valid proxy_service_, send all messages in unsent_requests_.
+  // If we have a valid proxy_resolution_service_, send all messages in
+  // unsent_requests_.
   void TryToSendUnsentRequests();
 
   void OnResolveProxyCompleted(ppapi::host::ReplyMessageContext context,
@@ -79,25 +80,26 @@
   // The following two members are invalid until we get some information from
   // the UI thread. However, these are only ever set or accessed on the IO
   // thread.
-  net::ProxyService* proxy_service_;
+  net::ProxyResolutionService* proxy_resolution_service_;
   bool is_allowed_;
 
-  // True initially, but set to false once the values for proxy_service_ and
-  // is_allowed_ have been set.
+  // True initially, but set to false once the values for
+  // proxy_resolution_service_ and is_allowed_ have been set.
   bool waiting_for_ui_thread_data_;
 
   // We have to get the URLRequestContextGetter from the UI thread before we
-  // can retrieve proxy_service_. If we receive any calls for GetProxyForURL
-  // before proxy_service_ is available, we save them in unsent_requests_.
+  // can retrieve proxy_resolution_service_. If we receive any calls for
+  // GetProxyForURL before proxy_resolution_service_ is available, we save them
+  // in unsent_requests_.
   struct UnsentRequest {
     GURL url;
     ppapi::host::ReplyMessageContext reply_context;
   };
   base::queue<UnsentRequest> unsent_requests_;
 
-  // Requests awaiting a response from ProxyService. We need to store these so
-  // that we can cancel them if we get destroyed.
-  base::queue<net::ProxyService::Request*> pending_requests_;
+  // Requests awaiting a response from ProxyResolutionService. We need to store
+  // these so that we can cancel them if we get destroyed.
+  base::queue<net::ProxyResolutionService::Request*> pending_requests_;
 
   base::WeakPtrFactory<PepperNetworkProxyHost> weak_factory_;
 
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 2ee0858b..9e9bba8 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -67,6 +67,7 @@
 #include "content/common/cursors/webcursor.h"
 #include "content/common/drag_messages.h"
 #include "content/common/frame_messages.h"
+#include "content/common/input/sync_compositor_messages.h"
 #include "content/common/input_messages.h"
 #include "content/common/resize_params.h"
 #include "content/common/text_input_state.h"
@@ -581,13 +582,9 @@
   if (!renderer_initialized()) {
     // SetNeedsBeginFrame messages are only sent by the renderer once and so
     // should never be dropped.
-    bool handled = true;
-    IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostImpl, msg)
-      IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames,
-                          OnSetNeedsBeginFrames)
-      IPC_MESSAGE_UNHANDLED(handled = false)
-    IPC_END_MESSAGE_MAP()
-    return handled;
+    if (msg.type() == SyncCompositorHostMsg_SetNeedsBeginFrames::ID && view_)
+      return view_->OnMessageReceived(msg);
+    return false;
   }
 
   if (owner_delegate_ && owner_delegate_->OnMessageReceived(msg))
@@ -620,7 +617,6 @@
                         OnSelectionBoundsChanged)
     IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
                         OnImeCompositionRangeChanged)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames, OnSetNeedsBeginFrames)
     IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
     IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
     IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
@@ -1642,15 +1638,6 @@
     view_->SelectionBoundsChanged(params);
 }
 
-void RenderWidgetHostImpl::OnSetNeedsBeginFrames(bool needs_begin_frames) {
-  if (needs_begin_frames_ == needs_begin_frames)
-    return;
-
-  needs_begin_frames_ = needs_begin_frames;
-  if (view_)
-    view_->SetNeedsBeginFrames(needs_begin_frames);
-}
-
 void RenderWidgetHostImpl::OnFocusedNodeTouched(bool editable) {
   if (delegate_)
     delegate_->FocusedNodeTouched(editable);
@@ -2675,8 +2662,13 @@
   return !input_router_->HasPendingEvents();
 }
 
-void RenderWidgetHostImpl::SetNeedsBeginFrame(bool needs_begin_frame) {
-  OnSetNeedsBeginFrames(needs_begin_frame);
+void RenderWidgetHostImpl::SetNeedsBeginFrame(bool needs_begin_frames) {
+  if (needs_begin_frames_ == needs_begin_frames)
+    return;
+
+  needs_begin_frames_ = needs_begin_frames;
+  if (view_)
+    view_->SetNeedsBeginFrames(needs_begin_frames);
 }
 
 void RenderWidgetHostImpl::SetWantsAnimateOnlyBeginFrames() {
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 d1b93ef..9a8a5ec 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1697,8 +1697,7 @@
   args.deadline = sync_compositor_ ? base::TimeTicks()
   : args.frame_time + (args.interval * 0.6);
   if (sync_compositor_) {
-    host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args));
-    sync_compositor_->DidSendBeginFrame(view_.GetWindowAndroid());
+    sync_compositor_->SendBeginFrame(view_.GetWindowAndroid(), args);
   } else if (renderer_compositor_frame_sink_) {
     renderer_compositor_frame_sink_->OnBeginFrame(args);
   }
@@ -2300,10 +2299,8 @@
   bool paused = begin_frame_paused_ || !observing_root_window_;
 
   if (!using_browser_compositor_) {
-    if (host_) {
-      host_->Send(
-          new ViewMsg_SetBeginFramePaused(host_->GetRoutingID(), paused));
-    }
+    if (sync_compositor_)
+      sync_compositor_->SetBeginFramePaused(paused);
   } else if (renderer_compositor_frame_sink_) {
     renderer_compositor_frame_sink_->OnBeginFramePausedChanged(paused);
   }
diff --git a/content/browser/resolve_proxy_msg_helper.cc b/content/browser/resolve_proxy_msg_helper.cc
index 2bc88b5..08885d8 100644
--- a/content/browser/resolve_proxy_msg_helper.cc
+++ b/content/browser/resolve_proxy_msg_helper.cc
@@ -19,12 +19,11 @@
     net::URLRequestContextGetter* getter)
     : BrowserMessageFilter(ViewMsgStart),
       context_getter_(getter),
-      proxy_service_(nullptr) {}
+      proxy_resolution_service_(nullptr) {}
 
-ResolveProxyMsgHelper::ResolveProxyMsgHelper(net::ProxyService* proxy_service)
-    : BrowserMessageFilter(ViewMsgStart),
-      proxy_service_(proxy_service) {
-}
+ResolveProxyMsgHelper::ResolveProxyMsgHelper(
+    net::ProxyResolutionService* proxy_resolution_service)
+    : BrowserMessageFilter(ViewMsgStart), proxy_resolution_service_(proxy_resolution_service) {}
 
 bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
@@ -46,11 +45,11 @@
 }
 
 ResolveProxyMsgHelper::~ResolveProxyMsgHelper() {
-  // Clear all pending requests if the ProxyService is still alive (if we have a
-  // default request context or override).
+  // Clear all pending requests if the ProxyResolutionService is still alive (if
+  // we have a default request context or override).
   if (!pending_requests_.empty()) {
     PendingRequest req = pending_requests_.front();
-    proxy_service_->CancelRequest(req.request);
+    proxy_resolution_service_->CancelRequest(req.request);
   }
 
   for (PendingRequestList::iterator it = pending_requests_.begin();
@@ -85,12 +84,12 @@
   DCHECK(nullptr == req.request);
 
   if (context_getter_.get()) {
-    proxy_service_ = context_getter_->GetURLRequestContext()->proxy_service();
+    proxy_resolution_service_ = context_getter_->GetURLRequestContext()->proxy_resolution_service();
     context_getter_ = nullptr;
   }
 
   // Start the request.
-  int result = proxy_service_->ResolveProxy(
+  int result = proxy_resolution_service_->ResolveProxy(
       req.url, std::string(), &proxy_info_,
       base::Bind(&ResolveProxyMsgHelper::OnResolveProxyCompleted,
                  base::Unretained(this)),
diff --git a/content/browser/resolve_proxy_msg_helper.h b/content/browser/resolve_proxy_msg_helper.h
index 115e4ea..6312ff2 100644
--- a/content/browser/resolve_proxy_msg_helper.h
+++ b/content/browser/resolve_proxy_msg_helper.h
@@ -35,7 +35,8 @@
  public:
   explicit ResolveProxyMsgHelper(net::URLRequestContextGetter* getter);
   // Constructor used by unittests.
-  explicit ResolveProxyMsgHelper(net::ProxyService* proxy_service);
+  explicit ResolveProxyMsgHelper(
+      net::ProxyResolutionService* proxy_resolution_service);
 
   // BrowserMessageFilter implementation
   bool OnMessageReceived(const IPC::Message& message) override;
@@ -48,7 +49,7 @@
   ~ResolveProxyMsgHelper() override;
 
  private:
-  // Callback for the ProxyService (bound to |callback_|).
+  // Callback for the ProxyResolutionService (bound to |callback_|).
   void OnResolveProxyCompleted(int result);
 
   // Starts the first pending request.
@@ -67,7 +68,7 @@
     IPC::Message* reply_msg;
 
     // Handle for cancelling the current request if it has started (else NULL).
-    net::ProxyService::Request* request;
+    net::ProxyResolutionService::Request* request;
   };
 
   // Info about the current outstanding proxy request.
@@ -78,7 +79,7 @@
   PendingRequestList pending_requests_;
 
   scoped_refptr<net::URLRequestContextGetter> context_getter_;
-  net::ProxyService* proxy_service_;
+  net::ProxyResolutionService* proxy_resolution_service_;
 };
 
 }  // namespace content
diff --git a/content/browser/resolve_proxy_msg_helper_unittest.cc b/content/browser/resolve_proxy_msg_helper_unittest.cc
index 9a6ae81..5058702 100644
--- a/content/browser/resolve_proxy_msg_helper_unittest.cc
+++ b/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -31,11 +31,9 @@
 
 class TestResolveProxyMsgHelper : public ResolveProxyMsgHelper {
  public:
-  TestResolveProxyMsgHelper(
-      net::ProxyService* proxy_service,
-      IPC::Listener* listener)
-      : ResolveProxyMsgHelper(proxy_service),
-        listener_(listener) {}
+  TestResolveProxyMsgHelper(net::ProxyResolutionService* proxy_resolution_service,
+                            IPC::Listener* listener)
+      : ResolveProxyMsgHelper(proxy_resolution_service), listener_(listener) {}
   bool Send(IPC::Message* message) override {
     listener_->OnMessageReceived(*message);
     delete message;
@@ -62,10 +60,10 @@
 
   ResolveProxyMsgHelperTest()
       : resolver_factory_(new net::MockAsyncProxyResolverFactory(false)),
-        service_(
-            new net::ProxyService(base::WrapUnique(new MockProxyConfigService),
-                                  base::WrapUnique(resolver_factory_),
-                                  nullptr)),
+        service_(new net::ProxyResolutionService(
+            base::WrapUnique(new MockProxyConfigService),
+            base::WrapUnique(resolver_factory_),
+            nullptr)),
         helper_(new TestResolveProxyMsgHelper(service_.get(), this)) {
     test_sink_.AddFilter(this);
   }
@@ -86,7 +84,7 @@
 
   net::MockAsyncProxyResolverFactory* resolver_factory_;
   net::MockAsyncProxyResolver resolver_;
-  std::unique_ptr<net::ProxyService> service_;
+  std::unique_ptr<net::ProxyResolutionService> service_;
   scoped_refptr<ResolveProxyMsgHelper> helper_;
   std::unique_ptr<PendingResult> pending_result_;
 
@@ -121,7 +119,7 @@
 
   helper_->OnResolveProxy(url1, msg1);
 
-  // Finish ProxyService's initialization.
+  // Finish ProxyResolutionService's initialization.
   ASSERT_EQ(1u, resolver_factory_->pending_requests().size());
   resolver_factory_->pending_requests()[0]->CompleteNowWithForwarder(
       net::OK, &resolver_);
@@ -176,7 +174,7 @@
 
   helper_->OnResolveProxy(url1, msg1);
 
-  // Finish ProxyService's initialization.
+  // Finish ProxyResolutionService's initialization.
   ASSERT_EQ(1u, resolver_factory_->pending_requests().size());
   resolver_factory_->pending_requests()[0]->CompleteNowWithForwarder(
       net::OK, &resolver_);
@@ -184,8 +182,8 @@
   helper_->OnResolveProxy(url2, msg2);
   helper_->OnResolveProxy(url3, msg3);
 
-  // ResolveProxyHelper only keeps 1 request outstanding in ProxyService
-  // at a time.
+  // ResolveProxyHelper only keeps 1 request outstanding in
+  // ProxyResolutionService at a time.
   ASSERT_EQ(1u, resolver_.pending_jobs().size());
   EXPECT_EQ(url1, resolver_.pending_jobs()[0]->url());
 
@@ -236,7 +234,7 @@
 
   helper_->OnResolveProxy(url1, msg1);
 
-  // Finish ProxyService's initialization.
+  // Finish ProxyResolutionService's initialization.
   ASSERT_EQ(1u, resolver_factory_->pending_requests().size());
   resolver_factory_->pending_requests()[0]->CompleteNowWithForwarder(
       net::OK, &resolver_);
@@ -244,8 +242,8 @@
   helper_->OnResolveProxy(url2, msg2);
   helper_->OnResolveProxy(url3, msg3);
 
-  // ResolveProxyHelper only keeps 1 request outstanding in ProxyService
-  // at a time.
+  // ResolveProxyHelper only keeps 1 request outstanding in
+  // ProxyResolutionService at a time.
   ASSERT_EQ(1u, resolver_.pending_jobs().size());
   EXPECT_EQ(url1, resolver_.pending_jobs()[0]->url());
 
diff --git a/content/browser/service_manager/service_manager_context_browsertest.cc b/content/browser/service_manager/service_manager_context_browsertest.cc
index b049756d..80982c2 100644
--- a/content/browser/service_manager/service_manager_context_browsertest.cc
+++ b/content/browser/service_manager/service_manager_context_browsertest.cc
@@ -112,8 +112,9 @@
   loop.Run();
 }
 
-// Flaky timeout on Linux and Chrome OS ASAN: http://crbug.com/803814
-#if defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER)
+// Flaky timeout on Linux and Chrome OS ASAN: http://crbug.com/803814,
+// crbug.com/804113.
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(ADDRESS_SANITIZER)
 #define MAYBE_TerminateOnServiceQuit DISABLED_TerminateOnServiceQuit
 #else
 #define MAYBE_TerminateOnServiceQuit TerminateOnServiceQuit
diff --git a/content/browser/shared_worker/shared_worker_connector_impl.cc b/content/browser/shared_worker/shared_worker_connector_impl.cc
index 1e95910e..adcc28c 100644
--- a/content/browser/shared_worker/shared_worker_connector_impl.cc
+++ b/content/browser/shared_worker/shared_worker_connector_impl.cc
@@ -34,9 +34,14 @@
     mojom::SharedWorkerClientPtr client,
     blink::mojom::SharedWorkerCreationContextType creation_context_type,
     mojo::ScopedMessagePipeHandle message_port) {
+  RenderProcessHost* host = RenderProcessHost::FromID(process_id_);
+  // The render process was already terminated.
+  if (!host) {
+    client->OnScriptLoadFailed();
+    return;
+  }
   SharedWorkerServiceImpl* service =
-      static_cast<StoragePartitionImpl*>(
-          RenderProcessHost::FromID(process_id_)->GetStoragePartition())
+      static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
           ->GetSharedWorkerService();
   service->ConnectToWorker(process_id_, frame_id_, std::move(info),
                            std::move(client), creation_context_type,
diff --git a/content/common/input/sync_compositor_messages.h b/content/common/input/sync_compositor_messages.h
index 77c534a..e0fd66b 100644
--- a/content/common/input/sync_compositor_messages.h
+++ b/content/common/input/sync_compositor_messages.h
@@ -160,6 +160,13 @@
 
 IPC_MESSAGE_ROUTED1(SyncCompositorMsg_SetScroll, gfx::ScrollOffset)
 
+// Let renderer know begin frame messages won't be sent even if requested.
+IPC_MESSAGE_ROUTED1(SyncCompositorMsg_SetBeginFramePaused, bool /* paused */)
+
+// Sent by the browser when the renderer should generate a new frame.
+IPC_MESSAGE_ROUTED1(SyncCompositorMsg_BeginFrame,
+                    viz::BeginFrameArgs /* args */)
+
 // -----------------------------------------------------------------------------
 // Messages sent from the renderer to the browser.
 
@@ -172,4 +179,10 @@
                     uint32_t /* layer_tree_frame_sink_id */,
                     base::Optional<viz::CompositorFrame>)
 
+// Sent by renderer to request a SyncCompositorMsg_BeginFrame message for
+// upcoming display events. If |enabled| is true, the BeginFrame message will
+// continue to be be delivered until the notification is disabled.
+IPC_MESSAGE_ROUTED1(SyncCompositorHostMsg_SetNeedsBeginFrames,
+                    bool /* enabled */)
+
 #endif  // CONTENT_COMMON_SYNC_COMPOSITOR_MESSAGES_H_
diff --git a/content/common/sandbox_init_mac.cc b/content/common/sandbox_init_mac.cc
index 92b49c5..06c9ead 100644
--- a/content/common/sandbox_init_mac.cc
+++ b/content/common/sandbox_init_mac.cc
@@ -53,7 +53,8 @@
         gpu::GpuFeatureInfo gpu_feature_info = gpu::ComputeGpuFeatureInfo(
             gpu_info, gpu_preferences.ignore_gpu_blacklist,
             gpu_preferences.disable_gpu_driver_bug_workarounds,
-            gpu_preferences.log_gpu_control_list_decisions, command_line);
+            gpu_preferences.log_gpu_control_list_decisions, command_line,
+            nullptr);
         gpu::CacheGpuFeatureInfo(gpu_feature_info);
         // Preload either the desktop GL or the osmesa so, depending on the
         // --use-gl flag.
diff --git a/content/common/swapped_out_messages.cc b/content/common/swapped_out_messages.cc
index 74b51ac..b3efd1f 100644
--- a/content/common/swapped_out_messages.cc
+++ b/content/common/swapped_out_messages.cc
@@ -20,8 +20,6 @@
     // Handled by RenderWidgetHost.
     case InputHostMsg_HandleInputEvent_ACK::ID:
     case ViewHostMsg_ResizeOrRepaint_ACK::ID:
-    // Handled by RenderWidgetHostView.
-    case ViewHostMsg_SetNeedsBeginFrames::ID:
     // Handled by RenderViewHost.
     case FrameHostMsg_RenderProcessGone::ID:
     case ViewHostMsg_ClosePage_ACK::ID:
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index e7aea70..72668127 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -541,12 +541,6 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_ForceRedraw,
                     ui::LatencyInfo /* latency_info */)
 
-// Let renderer know begin frame messages won't be sent even if requested.
-IPC_MESSAGE_ROUTED1(ViewMsg_SetBeginFramePaused, bool /* paused */)
-
-// Sent by the browser when the renderer should generate a new frame.
-IPC_MESSAGE_ROUTED1(ViewMsg_BeginFrame, viz::BeginFrameArgs /* args */)
-
 // Sets the viewport intersection on the widget for an out-of-process iframe.
 IPC_MESSAGE_ROUTED1(ViewMsg_SetViewportIntersection,
                     gfx::Rect /* viewport_intersection */)
@@ -562,12 +556,6 @@
 // -----------------------------------------------------------------------------
 // Messages sent from the renderer to the browser.
 
-// Sent by renderer to request a ViewMsg_BeginFrame message for upcoming
-// display events. If |enabled| is true, the BeginFrame message will continue
-// to be be delivered until the notification is disabled.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_SetNeedsBeginFrames,
-                    bool /* enabled */)
-
 // These two messages are sent to the parent RenderViewHost to display a widget
 // that was created by CreateWidget/CreateFullscreenWidget. |route_id| refers
 // to the id that was returned from the corresponding Create message above.
diff --git a/content/network/network_context_unittest.cc b/content/network/network_context_unittest.cc
index 62bebf3..16bddd2 100644
--- a/content/network/network_context_unittest.cc
+++ b/content/network/network_context_unittest.cc
@@ -596,8 +596,9 @@
 TEST_F(NetworkContextTest, ProxyConfig) {
   // Create a bunch of proxy rules to switch between. All that matters is that
   // they're all different. It's important that none of these configs require
-  // fetching a PAC scripts, as this test checks ProxyService::config(), which
-  // is only updated after fetching PAC scripts (if applicable).
+  // fetching a PAC scripts, as this test checks
+  // ProxyResolutionService::config(), which is only updated after fetching PAC
+  // scripts (if applicable).
   net::ProxyConfig proxy_configs[3];
   proxy_configs[0].proxy_rules().ParseFromString("http=foopy:80");
   proxy_configs[1].proxy_rules().ParseFromString("http=foopy:80;ftp=foopy2");
@@ -620,13 +621,13 @@
     std::unique_ptr<NetworkContext> network_context =
         CreateContextWithParams(std::move(context_params));
 
-    net::ProxyService* proxy_service =
-        network_context->url_request_context()->proxy_service();
-    // Kick the ProxyService into action, as it doesn't start updating its
-    // config until it's first used.
-    proxy_service->ForceReloadProxyConfig();
-    EXPECT_TRUE(proxy_service->config().is_valid());
-    EXPECT_TRUE(proxy_service->config().Equals(initial_proxy_config));
+    net::ProxyResolutionService* proxy_resolution_service =
+        network_context->url_request_context()->proxy_resolution_service();
+    // Kick the ProxyResolutionService into action, as it doesn't start updating
+    // its config until it's first used.
+    proxy_resolution_service->ForceReloadProxyConfig();
+    EXPECT_TRUE(proxy_resolution_service->config().is_valid());
+    EXPECT_TRUE(proxy_resolution_service->config().Equals(initial_proxy_config));
 
     // Always go through the other configs in the same order. This has the
     // advantage of testing the case where there's no change, for
@@ -634,8 +635,8 @@
     for (const auto& proxy_config : proxy_configs) {
       config_client->OnProxyConfigUpdated(proxy_config);
       scoped_task_environment_.RunUntilIdle();
-      EXPECT_TRUE(proxy_service->config().is_valid());
-      EXPECT_TRUE(proxy_service->config().Equals(proxy_config));
+      EXPECT_TRUE(proxy_resolution_service->config().is_valid());
+      EXPECT_TRUE(proxy_resolution_service->config().Equals(proxy_config));
     }
   }
 }
@@ -651,13 +652,13 @@
   std::unique_ptr<NetworkContext> network_context =
       CreateContextWithParams(std::move(context_params));
 
-  net::ProxyService* proxy_service =
-      network_context->url_request_context()->proxy_service();
-  // Kick the ProxyService into action, as it doesn't start updating its
-  // config until it's first used.
-  proxy_service->ForceReloadProxyConfig();
-  EXPECT_TRUE(proxy_service->config().is_valid());
-  EXPECT_TRUE(proxy_service->config().Equals(proxy_config));
+  net::ProxyResolutionService* proxy_resolution_service =
+      network_context->url_request_context()->proxy_resolution_service();
+  // Kick the ProxyResolutionService into action, as it doesn't start updating
+  // its config until it's first used.
+  proxy_resolution_service->ForceReloadProxyConfig();
+  EXPECT_TRUE(proxy_resolution_service->config().is_valid());
+  EXPECT_TRUE(proxy_resolution_service->config().Equals(proxy_config));
 }
 
 TEST_F(NetworkContextTest, NoInitialProxyConfig) {
@@ -670,22 +671,22 @@
   std::unique_ptr<NetworkContext> network_context =
       CreateContextWithParams(std::move(context_params));
 
-  net::ProxyService* proxy_service =
-      network_context->url_request_context()->proxy_service();
-  EXPECT_FALSE(proxy_service->config().is_valid());
-  EXPECT_FALSE(proxy_service->fetched_config().is_valid());
+  net::ProxyResolutionService* proxy_resolution_service =
+      network_context->url_request_context()->proxy_resolution_service();
+  EXPECT_FALSE(proxy_resolution_service->config().is_valid());
+  EXPECT_FALSE(proxy_resolution_service->fetched_config().is_valid());
 
   // Before there's a proxy configuration, proxy requests should hang.
   net::ProxyInfo proxy_info;
   net::TestCompletionCallback test_callback;
-  net::ProxyService::Request* request = nullptr;
+  net::ProxyResolutionService::Request* request = nullptr;
   ASSERT_EQ(net::ERR_IO_PENDING,
-            proxy_service->ResolveProxy(GURL("http://bar/"), "GET", &proxy_info,
+            proxy_resolution_service->ResolveProxy(GURL("http://bar/"), "GET", &proxy_info,
                                         test_callback.callback(), &request,
                                         nullptr, net::NetLogWithSource()));
   scoped_task_environment_.RunUntilIdle();
-  EXPECT_FALSE(proxy_service->config().is_valid());
-  EXPECT_FALSE(proxy_service->fetched_config().is_valid());
+  EXPECT_FALSE(proxy_resolution_service->config().is_valid());
+  EXPECT_FALSE(proxy_resolution_service->fetched_config().is_valid());
   ASSERT_FALSE(test_callback.have_result());
 
   net::ProxyConfig proxy_config;
diff --git a/content/network/proxy_resolver_factory_mojo.cc b/content/network/proxy_resolver_factory_mojo.cc
index 2ed821e..f92ba955 100644
--- a/content/network/proxy_resolver_factory_mojo.cc
+++ b/content/network/proxy_resolver_factory_mojo.cc
@@ -25,10 +25,10 @@
 #include "net/log/net_log_capture_mode.h"
 #include "net/log/net_log_event_type.h"
 #include "net/log/net_log_with_source.h"
+#include "net/proxy/pac_file_data.h"
 #include "net/proxy/proxy_info.h"
 #include "net/proxy/proxy_resolver.h"
 #include "net/proxy/proxy_resolver_error_observer.h"
-#include "net/proxy/proxy_resolver_script_data.h"
 #include "services/proxy_resolver/public/interfaces/proxy_resolver.mojom.h"
 
 namespace content {
diff --git a/content/network/proxy_resolver_factory_mojo_unittest.cc b/content/network/proxy_resolver_factory_mojo_unittest.cc
index f7763d2..477f28c 100644
--- a/content/network/proxy_resolver_factory_mojo_unittest.cc
+++ b/content/network/proxy_resolver_factory_mojo_unittest.cc
@@ -26,11 +26,11 @@
 #include "net/log/net_log_event_type.h"
 #include "net/log/net_log_with_source.h"
 #include "net/log/test_net_log.h"
+#include "net/proxy/pac_file_data.h"
 #include "net/proxy/proxy_info.h"
 #include "net/proxy/proxy_resolver.h"
 #include "net/proxy/proxy_resolver_error_observer.h"
 #include "net/proxy/proxy_resolver_factory.h"
-#include "net/proxy/proxy_resolver_script_data.h"
 #include "net/test/event_waiter.h"
 #include "net/test/gtest_util.h"
 #include "services/proxy_resolver/public/interfaces/proxy_resolver.mojom.h"
diff --git a/content/network/proxy_service_mojo.cc b/content/network/proxy_service_mojo.cc
index 49012c33..4b4ec79 100644
--- a/content/network/proxy_service_mojo.cc
+++ b/content/network/proxy_service_mojo.cc
@@ -18,7 +18,7 @@
 
 namespace content {
 
-std::unique_ptr<net::ProxyService> CreateProxyServiceUsingMojoFactory(
+std::unique_ptr<net::ProxyResolutionService> CreateProxyServiceUsingMojoFactory(
     proxy_resolver::mojom::ProxyResolverFactoryPtr mojo_proxy_factory,
     std::unique_ptr<net::ProxyConfigService> proxy_config_service,
     std::unique_ptr<net::ProxyScriptFetcher> proxy_script_fetcher,
@@ -31,20 +31,22 @@
   DCHECK(dhcp_proxy_script_fetcher);
   DCHECK(host_resolver);
 
-  std::unique_ptr<net::ProxyService> proxy_service(new net::ProxyService(
-      std::move(proxy_config_service),
-      std::make_unique<ProxyResolverFactoryMojo>(
-          std::move(mojo_proxy_factory), host_resolver,
-          base::Bind(&net::NetworkDelegateErrorObserver::Create,
-                     network_delegate, base::ThreadTaskRunnerHandle::Get()),
-          net_log),
-      net_log));
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+      new net::ProxyResolutionService(
+          std::move(proxy_config_service),
+          std::make_unique<ProxyResolverFactoryMojo>(
+              std::move(mojo_proxy_factory), host_resolver,
+              base::Bind(&net::NetworkDelegateErrorObserver::Create,
+                         network_delegate, base::ThreadTaskRunnerHandle::Get()),
+              net_log),
+          net_log));
 
   // Configure fetchers to use for PAC script downloads and auto-detect.
-  proxy_service->SetProxyScriptFetchers(std::move(proxy_script_fetcher),
-                                        std::move(dhcp_proxy_script_fetcher));
+  proxy_resolution_service->SetProxyScriptFetchers(
+      std::move(proxy_script_fetcher),
+      std::move(dhcp_proxy_script_fetcher));
 
-  return proxy_service;
+  return proxy_resolution_service;
 }
 
 }  // namespace content
diff --git a/content/network/proxy_service_mojo.h b/content/network/proxy_service_mojo.h
index 729ea71..82fefcf 100644
--- a/content/network/proxy_service_mojo.h
+++ b/content/network/proxy_service_mojo.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "content/common/content_export.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
 #include "services/proxy_resolver/public/interfaces/proxy_resolver.mojom.h"
 
 namespace net {
@@ -17,7 +17,7 @@
 class NetworkDelegate;
 class ProxyConfigService;
 class ProxyScriptFetcher;
-class ProxyService;
+class ProxyResolutionService;
 }  // namespace net
 
 namespace content {
@@ -34,8 +34,8 @@
 //
 // |host_resolver| points to the host resolving dependency the PAC script
 // should use for any DNS queries. It must remain valid throughout the
-// lifetime of the ProxyService.
-std::unique_ptr<net::ProxyService> CONTENT_EXPORT
+// lifetime of the ProxyResolutionService.
+std::unique_ptr<net::ProxyResolutionService> CONTENT_EXPORT
 CreateProxyServiceUsingMojoFactory(
     proxy_resolver::mojom::ProxyResolverFactoryPtr mojo_proxy_factory,
     std::unique_ptr<net::ProxyConfigService> proxy_config_service,
diff --git a/content/network/url_request_context_builder_mojo.cc b/content/network/url_request_context_builder_mojo.cc
index c388e69..e55302e 100644
--- a/content/network/url_request_context_builder_mojo.cc
+++ b/content/network/url_request_context_builder_mojo.cc
@@ -8,8 +8,8 @@
 #include "build/build_config.h"
 #include "content/network/network_context.h"
 #include "content/network/proxy_service_mojo.h"
+#include "net/proxy/pac_file_fetcher_impl.h"
 #include "net/proxy/proxy_config_service.h"
-#include "net/proxy/proxy_script_fetcher_impl.h"
 
 namespace content {
 
@@ -37,7 +37,7 @@
                                                      quic_disabled, net_log);
 }
 
-std::unique_ptr<net::ProxyService>
+std::unique_ptr<net::ProxyResolutionService>
 URLRequestContextBuilderMojo::CreateProxyService(
     std::unique_ptr<net::ProxyConfigService> proxy_config_service,
     net::URLRequestContext* url_request_context,
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 55313048..8e3728a46 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -152,6 +152,7 @@
     "java/src/org/chromium/content/browser/ViewPositionObserver.java",
     "java/src/org/chromium/content/browser/WindowAndroidProvider.java",
     "java/src/org/chromium/content/browser/WindowAndroidChangedObserver.java",
+    "java/src/org/chromium/content/browser/WindowEventObserver.java",
     "java/src/org/chromium/content/browser/accessibility/KitKatWebContentsAccessibility.java",
     "java/src/org/chromium/content/browser/accessibility/LollipopWebContentsAccessibility.java",
     "java/src/org/chromium/content/browser/accessibility/OWebContentsAccessibility.java",
@@ -491,6 +492,7 @@
     "javatests/src/org/chromium/content/browser/input/ImeLollipopTest.java",
     "javatests/src/org/chromium/content/browser/input/ImeTest.java",
     "javatests/src/org/chromium/content/browser/input/ImeActivityTestRule.java",
+    "javatests/src/org/chromium/content/browser/input/ImeAutocapitalizeTest.java",
     "javatests/src/org/chromium/content/browser/input/ImePasswordTest.java",
     "javatests/src/org/chromium/content/browser/input/ImeTestUtils.java",
     "javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
index 709c9d6..033a4ed0 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
@@ -147,6 +147,8 @@
 
     private final Context mContext;
     private final String mProductVersion;
+    private final ObserverList<WindowEventObserver> mWindowEventObservers = new ObserverList<>();
+
     private ViewGroup mContainerView;
     private InternalAccessDelegate mContainerViewInternals;
     private WebContentsImpl mWebContents;
@@ -329,6 +331,12 @@
                 && ContentFeatureList.isEnabled(ContentFeatureList.REQUEST_UNBUFFERED_DISPATCH)
                 && !nativeUsingSynchronousCompositing(mNativeContentViewCore);
         getGestureListenerManager().addListener(new ContentGestureStateListener());
+
+        mWindowEventObservers.addObserver(controller);
+        mWindowEventObservers.addObserver(getGestureListenerManager());
+        mWindowEventObservers.addObserver(mTextSuggestionHost);
+        mWindowEventObservers.addObserver(imeAdapter);
+        mWindowEventObservers.addObserver(mWebContentsAccessibility);
     }
 
     @Override
@@ -426,6 +434,7 @@
         mWebContentsObserver.destroy();
         mWebContentsObserver = null;
         getImeAdapter().resetAndHideKeyboard();
+        mWindowEventObservers.clear();
         hidePopupsAndPreserveSelection();
         mWebContents = null;
         mNativeContentViewCore = 0;
@@ -587,14 +596,13 @@
     @Override
     public void onAttachedToWindow() {
         mAttachedToWindow = true;
+        for (WindowEventObserver observer : mWindowEventObservers) observer.onAttachedToWindow();
         addDisplayAndroidObserverIfNeeded();
         if (mWebContents != null) {
             updateTextSelectionUI(true);
-            getImeAdapter().onViewAttachedToWindow();
         }
         GamepadList.onAttachedToWindow(mContext);
         mSystemCaptioningBridge.addListener(this);
-        mWebContentsAccessibility.onAttachedToWindow();
     }
 
     @Override
@@ -612,6 +620,7 @@
     @Override
     public void onDetachedFromWindow() {
         mAttachedToWindow = false;
+        for (WindowEventObserver observer : mWindowEventObservers) observer.onDetachedFromWindow();
         removeDisplayAndroidObserver();
         GamepadList.onDetachedFromWindow();
 
@@ -622,10 +631,8 @@
             // preserve the underlying selection for detachment cases like screen
             // locking and app switching.
             updateTextSelectionUI(false);
-            getImeAdapter().onViewDetachedFromWindow();
         }
         mSystemCaptioningBridge.removeListener(this);
-        mWebContentsAccessibility.onDetachedFromWindow();
     }
 
     @SuppressWarnings("javadoc")
@@ -669,10 +676,8 @@
     @Override
     public void onWindowFocusChanged(boolean hasWindowFocus) {
         if (!hasWindowFocus) resetGestureDetection();
-        if (isAlive()) {
-            getImeAdapter().onWindowFocusChanged(hasWindowFocus);
-            getSelectionPopupController().onWindowFocusChanged(hasWindowFocus);
-            getGestureListenerManager().updateOnWindowFocusChanged(hasWindowFocus);
+        for (WindowEventObserver observer : mWindowEventObservers) {
+            observer.onWindowFocusChanged(hasWindowFocus);
         }
     }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
index ef7590b..7268a872 100644
--- a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
@@ -23,7 +23,7 @@
  * managed by {@link WebContents}.
  */
 @JNINamespace("content")
-public class GestureListenerManagerImpl implements GestureListenerManager {
+public class GestureListenerManagerImpl implements GestureListenerManager, WindowEventObserver {
     private static final class UserDataFactoryLazyHolder {
         private static final UserDataFactory<GestureListenerManagerImpl> INSTANCE =
                 GestureListenerManagerImpl::new;
@@ -65,13 +65,12 @@
         for (mIterator.rewind(); mIterator.hasNext();) mIterator.next().onTouchDown();
     }
 
-    /**
-     * Update all the listeners after window focus has changed.
-     * @param hasFocus {@code true} if we're gaining focus.
-     */
-    public void updateOnWindowFocusChanged(boolean hasFocus) {
+    // WindowEventObserver
+
+    @Override
+    public void onWindowFocusChanged(boolean gainFocus) {
         for (mIterator.rewind(); mIterator.hasNext();) {
-            mIterator.next().onWindowFocusChanged(hasFocus);
+            mIterator.next().onWindowFocusChanged(gainFocus);
         }
     }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/WindowEventObserver.java b/content/public/android/java/src/org/chromium/content/browser/WindowEventObserver.java
new file mode 100644
index 0000000..323b5d5
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/WindowEventObserver.java
@@ -0,0 +1,25 @@
+// 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.
+
+package org.chromium.content.browser;
+
+/**
+ * Interface to implement if Window-related events are needed.
+ */
+public interface WindowEventObserver {
+    /**
+     * This is called when the container view is attached to a window.
+     */
+    default void onAttachedToWindow() {}
+
+    /**
+     * This is called when the container view is detached from a window.
+     */
+    default void onDetachedFromWindow() {}
+
+    /**
+     * @param gainFocus {@code true} if we're gaining focus.
+     */
+    default void onWindowFocusChanged(boolean gainFocus) {}
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibility.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibility.java
index 34193f2..7be124f 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibility.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibility.java
@@ -30,6 +30,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.content.browser.RenderCoordinates;
+import org.chromium.content.browser.WindowEventObserver;
 import org.chromium.content.browser.webcontents.WebContentsImpl;
 import org.chromium.content_public.browser.AccessibilitySnapshotCallback;
 import org.chromium.content_public.browser.AccessibilitySnapshotNode;
@@ -45,8 +46,8 @@
  *{@link AccessibilityNodeProvider}, and shares the lifetime with {@link WebContents}.
  */
 @JNINamespace("content")
-public class WebContentsAccessibility
-        extends AccessibilityNodeProvider implements AccessibilityStateChangeListener {
+public class WebContentsAccessibility extends AccessibilityNodeProvider
+        implements AccessibilityStateChangeListener, WindowEventObserver {
     // Constants from AccessibilityNodeInfo defined in the K SDK.
     private static final int ACTION_COLLAPSE = 0x00080000;
     private static final int ACTION_EXPAND = 0x00040000;
@@ -1398,16 +1399,14 @@
         viewNode.asyncCommit();
     }
 
-    /**
-     * @see View#onDetachedFromWindow()
-     */
+    // WindowEventObserver
+
+    @Override
     public void onDetachedFromWindow() {
         mAccessibilityManager.removeAccessibilityStateChangeListener(this);
     }
 
-    /**
-     * @see View#onAttachedToWindow()
-     */
+    @Override
     public void onAttachedToWindow() {
         mAccessibilityManager.addAccessibilityStateChangeListener(this);
         refreshState();
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
index aac7e73..9500d875 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
@@ -37,6 +37,7 @@
 import org.chromium.blink_public.web.WebInputEventModifier;
 import org.chromium.blink_public.web.WebInputEventType;
 import org.chromium.blink_public.web.WebTextInputMode;
+import org.chromium.content.browser.WindowEventObserver;
 import org.chromium.content.browser.picker.InputDialogContainer;
 import org.chromium.content.browser.webcontents.WebContentsUserData;
 import org.chromium.content.browser.webcontents.WebContentsUserData.UserDataFactory;
@@ -75,7 +76,7 @@
  * lifetime of the object.
  */
 @JNINamespace("content")
-public class ImeAdapterImpl implements ImeAdapter {
+public class ImeAdapterImpl implements ImeAdapter, WindowEventObserver {
     private static final String TAG = "cr_Ime";
     private static final boolean DEBUG_LOGS = false;
 
@@ -573,29 +574,24 @@
         }
     }
 
-    /**
-     * Call this when window's focus has changed.
-     * @param gainFocus True if we're gaining focus.
-     */
+    // WindowEventObserver
+
+    @Override
     public void onWindowFocusChanged(boolean gainFocus) {
         if (mInputConnectionFactory != null) {
             mInputConnectionFactory.onWindowFocusChanged(gainFocus);
         }
     }
 
-    /**
-     * Call this when view is attached to window.
-     */
-    public void onViewAttachedToWindow() {
+    @Override
+    public void onAttachedToWindow() {
         if (mInputConnectionFactory != null) {
             mInputConnectionFactory.onViewAttachedToWindow();
         }
     }
 
-    /**
-     * Call this when view is detached from window.
-     */
-    public void onViewDetachedFromWindow() {
+    @Override
+    public void onDetachedFromWindow() {
         resetAndHideKeyboard();
         if (mInputConnectionFactory != null) {
             mInputConnectionFactory.onViewDetachedFromWindow();
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java
index 9eea36a..0897a23a 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java
@@ -123,10 +123,6 @@
         } else if ((inputFlags & WebTextInputFlags.AUTOCAPITALIZE_SENTENCES) != 0) {
             outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
         }
-        // Content editable doesn't use autocapitalize so we need to set it manually.
-        if (inputType == TextInputType.CONTENT_EDITABLE) {
-            outAttrs.inputType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
-        }
 
         if ((inputFlags & WebTextInputFlags.HAS_BEEN_PASSWORD_FIELD) != 0) {
             outAttrs.inputType =
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionHost.java b/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionHost.java
index 357a9e1c..9f37ce4 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionHost.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionHost.java
@@ -8,6 +8,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.content.browser.ContentViewCoreImpl;
+import org.chromium.content.browser.WindowEventObserver;
 import org.chromium.content.browser.webcontents.WebContentsImpl;
 import org.chromium.content_public.browser.WebContents;
 
@@ -17,9 +18,10 @@
  * the commands in that menu (by calling back to the C++ class).
  */
 @JNINamespace("content")
-public class TextSuggestionHost {
+public class TextSuggestionHost implements WindowEventObserver {
     private long mNativeTextSuggestionHost;
     private final ContentViewCoreImpl mContentViewCore;
+    private boolean mIsAttachedToWindow;
 
     private SpellCheckPopupWindow mSpellCheckPopupWindow;
     private TextSuggestionsPopupWindow mTextSuggestionsPopupWindow;
@@ -33,10 +35,22 @@
         return ((WebContentsImpl) webContents).getRenderCoordinates().getContentOffsetYPix();
     }
 
+    // WindowEventObserver
+
+    @Override
+    public void onAttachedToWindow() {
+        mIsAttachedToWindow = true;
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        mIsAttachedToWindow = false;
+    }
+
     @CalledByNative
     private void showSpellCheckSuggestionMenu(
             double caretXPx, double caretYPx, String markedText, String[] suggestions) {
-        if (!mContentViewCore.isAttachedToWindow()) {
+        if (!mIsAttachedToWindow) {
             // This can happen if a new browser window is opened immediately after tapping a spell
             // check underline, before the timer to open the menu fires.
             onSuggestionMenuClosed(false);
@@ -55,7 +69,7 @@
     @CalledByNative
     private void showTextSuggestionMenu(
             double caretXPx, double caretYPx, String markedText, SuggestionInfo[] suggestions) {
-        if (!mContentViewCore.isAttachedToWindow()) {
+        if (!mIsAttachedToWindow) {
             // This can happen if a new browser window is opened immediately after tapping a spell
             // check underline, before the timer to open the menu fires.
             onSuggestionMenuClosed(false);
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
index ca593be5..6f5f284 100644
--- a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
@@ -41,6 +41,7 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.content.R;
 import org.chromium.content.browser.ContentClassFactory;
+import org.chromium.content.browser.WindowEventObserver;
 import org.chromium.content.browser.webcontents.WebContentsImpl;
 import org.chromium.content.browser.webcontents.WebContentsUserData;
 import org.chromium.content.browser.webcontents.WebContentsUserData.UserDataFactory;
@@ -61,7 +62,7 @@
 @JNINamespace("content")
 @TargetApi(Build.VERSION_CODES.M)
 public class SelectionPopupControllerImpl
-        extends ActionModeCallbackHelper implements SelectionPopupController {
+        extends ActionModeCallbackHelper implements SelectionPopupController, WindowEventObserver {
     private static final String TAG = "SelectionPopupCtlr"; // 20 char limit
 
     /**
@@ -524,12 +525,12 @@
         }
     }
 
-    /**
-     * @see ActionMode#onWindowFocusChanged()
-     */
-    public void onWindowFocusChanged(boolean hasWindowFocus) {
+    // WindowEventObserver
+
+    @Override
+    public void onWindowFocusChanged(boolean gainFocus) {
         if (supportsFloatingActionMode() && isActionModeValid()) {
-            mActionMode.onWindowFocusChanged(hasWindowFocus);
+            mActionMode.onWindowFocusChanged(gainFocus);
         }
     }
 
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeAutocapitalizeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeAutocapitalizeTest.java
new file mode 100644
index 0000000..4ca97bd94
--- /dev/null
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeAutocapitalizeTest.java
@@ -0,0 +1,72 @@
+// 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.
+
+package org.chromium.content.browser.input;
+
+import android.support.test.filters.SmallTest;
+import android.view.inputmethod.EditorInfo;
+
+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.test.util.Feature;
+import org.chromium.content.browser.test.ContentJUnit4ClassRunner;
+
+/**
+ * IME (input method editor) and text input tests.
+ */
+@RunWith(ContentJUnit4ClassRunner.class)
+public class ImeAutocapitalizeTest {
+    static final String AUTOCAPITALIZE_HTML = "content/test/data/android/input/autocapitalize.html";
+
+    @Rule
+    public ImeActivityTestRule mRule = new ImeActivityTestRule();
+
+    @Before
+    public void setUp() throws Exception {
+        mRule.setUpForUrl(AUTOCAPITALIZE_HTML);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"TextInput"})
+    public void testAutocapitalizeAttribute() throws Throwable {
+        final int autocapitalizeFlagMask = EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS
+                | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
+
+        // <input> element without autocapitalize attribute set. Should enable sentences
+        // autocapitalization as the default behavior.
+        mRule.focusElement("input_text");
+        Assert.assertEquals(EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES,
+                mRule.getConnectionFactory().getOutAttrs().inputType & autocapitalizeFlagMask);
+
+        // <input> element that has autocapitalize="none" set.
+        mRule.focusElement("input_autocapitalize_none");
+        Assert.assertEquals(
+                0, mRule.getConnectionFactory().getOutAttrs().inputType & autocapitalizeFlagMask);
+
+        // <input> element that has autocapitalize="characters" set.
+        mRule.focusElement("input_autocapitalize_characters");
+        Assert.assertEquals(EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS,
+                mRule.getConnectionFactory().getOutAttrs().inputType & autocapitalizeFlagMask);
+
+        // <input> element that has autocapitalize="words" set.
+        mRule.focusElement("input_autocapitalize_words");
+        Assert.assertEquals(EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS,
+                mRule.getConnectionFactory().getOutAttrs().inputType & autocapitalizeFlagMask);
+
+        // <input> element that has autocapitalize="sentences" set.
+        mRule.focusElement("input_autocapitalize_sentences");
+        Assert.assertEquals(EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES,
+                mRule.getConnectionFactory().getOutAttrs().inputType & autocapitalizeFlagMask);
+
+        // contenteditable <div> element with autocapitalize="characters".
+        mRule.focusElement("div_autocapitalize_characters");
+        Assert.assertEquals(EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS,
+                mRule.getConnectionFactory().getOutAttrs().inputType & autocapitalizeFlagMask);
+    }
+}
diff --git a/content/public/network/url_request_context_builder_mojo.h b/content/public/network/url_request_context_builder_mojo.h
index 98f2a4b..577ddb3 100644
--- a/content/public/network/url_request_context_builder_mojo.h
+++ b/content/public/network/url_request_context_builder_mojo.h
@@ -11,7 +11,7 @@
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/public/network/url_request_context_owner.h"
-#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
+#include "net/proxy/dhcp_pac_file_fetcher_factory.h"
 #include "net/url_request/url_request_context_builder.h"
 #include "services/network/public/interfaces/network_service.mojom.h"
 #include "services/proxy_resolver/public/interfaces/proxy_resolver.mojom.h"
@@ -20,16 +20,17 @@
 class HostResolver;
 class NetLog;
 class NetworkDelegate;
-class ProxyService;
+class ProxyResolutionService;
 class URLRequestContext;
 }  // namespace net
 
 namespace content {
 
-// Specialization of URLRequestContextBuilder that can create a ProxyService
-// that uses a Mojo ProxyResolver. The consumer is responsible for providing
-// the proxy_resolver::mojom::ProxyResolverFactory.  If a ProxyService is set
-// directly via the URLRequestContextBuilder API, it will be used instead.
+// Specialization of URLRequestContextBuilder that can create a
+// ProxyResolutionService that uses a Mojo ProxyResolver. The consumer is
+// responsible for providing the proxy_resolver::mojom::ProxyResolverFactory.
+// If a ProxyResolutionService is set directly via the URLRequestContextBuilder
+// API, it will be used instead.
 class CONTENT_EXPORT URLRequestContextBuilderMojo
     : public net::URLRequestContextBuilder {
  public:
@@ -59,7 +60,7 @@
                                 net::NetLog* net_log);
 
  private:
-  std::unique_ptr<net::ProxyService> CreateProxyService(
+  std::unique_ptr<net::ProxyResolutionService> CreateProxyService(
       std::unique_ptr<net::ProxyConfigService> proxy_config_service,
       net::URLRequestContext* url_request_context,
       net::HostResolver* host_resolver,
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index f19f139..b8e28a1 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -141,10 +141,6 @@
     "gpu/actions_parser.cc",
     "gpu/actions_parser.h",
     "gpu/compositor_dependencies.h",
-    "gpu/compositor_external_begin_frame_source.cc",
-    "gpu/compositor_external_begin_frame_source.h",
-    "gpu/compositor_forwarding_message_filter.cc",
-    "gpu/compositor_forwarding_message_filter.h",
     "gpu/frame_swap_message_queue.cc",
     "gpu/frame_swap_message_queue.h",
     "gpu/gpu_benchmarking_extension.cc",
@@ -700,10 +696,6 @@
       "media/gpu/rtc_video_encoder_factory.h",
       "media/local_media_stream_audio_source.cc",
       "media/local_media_stream_audio_source.h",
-      "media/media_devices_event_dispatcher.cc",
-      "media/media_devices_event_dispatcher.h",
-      "media/media_devices_listener_impl.cc",
-      "media/media_devices_listener_impl.h",
       "media/media_stream_audio_deliverer.h",
       "media/media_stream_audio_level_calculator.cc",
       "media/media_stream_audio_level_calculator.h",
diff --git a/content/renderer/android/synchronous_compositor_proxy.cc b/content/renderer/android/synchronous_compositor_proxy.cc
index 2242dd4e..83b44f43 100644
--- a/content/renderer/android/synchronous_compositor_proxy.cc
+++ b/content/renderer/android/synchronous_compositor_proxy.cc
@@ -63,6 +63,8 @@
   layer_tree_frame_sink_ = layer_tree_frame_sink;
   if (layer_tree_frame_sink_) {
     layer_tree_frame_sink_->SetSyncClient(this);
+    if (begin_frame_paused_)
+      layer_tree_frame_sink_->SetBeginFrameSourcePaused(true);
   }
 }
 
@@ -144,6 +146,9 @@
                                     DemandDrawSw)
     IPC_MESSAGE_HANDLER(SyncCompositorMsg_ZoomBy, SynchronouslyZoomBy)
     IPC_MESSAGE_HANDLER(SyncCompositorMsg_SetScroll, SetScroll)
+    IPC_MESSAGE_HANDLER(SyncCompositorMsg_SetBeginFramePaused,
+                        OnSetBeginFrameSourcePaused)
+    IPC_MESSAGE_HANDLER(SyncCompositorMsg_BeginFrame, OnBeginFrame)
   IPC_END_MESSAGE_MAP()
 }
 
@@ -355,6 +360,11 @@
   }
 }
 
+void SynchronousCompositorProxy::SetNeedsBeginFrames(bool needs_begin_frames) {
+  Send(new SyncCompositorHostMsg_SetNeedsBeginFrames(routing_id_,
+                                                     needs_begin_frames));
+}
+
 void SynchronousCompositorProxy::OnComputeScroll(
     base::TimeTicks animation_time) {
   if (need_animate_scroll_) {
@@ -363,6 +373,17 @@
   }
 }
 
+void SynchronousCompositorProxy::OnSetBeginFrameSourcePaused(bool paused) {
+  begin_frame_paused_ = paused;
+  if (layer_tree_frame_sink_)
+    layer_tree_frame_sink_->SetBeginFrameSourcePaused(paused);
+}
+
+void SynchronousCompositorProxy::OnBeginFrame(const viz::BeginFrameArgs& args) {
+  if (layer_tree_frame_sink_)
+    layer_tree_frame_sink_->BeginFrame(args);
+}
+
 void SynchronousCompositorProxy::SynchronouslyZoomBy(
     float zoom_delta,
     const gfx::Point& anchor,
diff --git a/content/renderer/android/synchronous_compositor_proxy.h b/content/renderer/android/synchronous_compositor_proxy.h
index af52f80..032d64af 100644
--- a/content/renderer/android/synchronous_compositor_proxy.h
+++ b/content/renderer/android/synchronous_compositor_proxy.h
@@ -56,6 +56,7 @@
   void Invalidate() override;
   void SubmitCompositorFrame(uint32_t layer_tree_frame_sink_id,
                              viz::CompositorFrame frame) override;
+  void SetNeedsBeginFrames(bool needs_begin_frames) override;
 
   void SetLayerTreeFrameSink(
       SynchronousLayerTreeFrameSink* layer_tree_frame_sink);
@@ -68,6 +69,8 @@
 
   // IPC handlers.
   void OnComputeScroll(base::TimeTicks animation_time);
+  void OnSetBeginFrameSourcePaused(bool paused);
+  void OnBeginFrame(const viz::BeginFrameArgs& args);
   void DemandDrawHwAsync(const SyncCompositorDemandDrawHwParams& params);
   void DemandDrawHw(const SyncCompositorDemandDrawHwParams& params,
                     IPC::Message* reply_message);
@@ -111,6 +114,7 @@
   IPC::Message* hardware_draw_reply_;
   IPC::Message* software_draw_reply_;
   bool hardware_draw_reply_async_;
+  bool begin_frame_paused_ = false;
 
   // From browser.
   std::unique_ptr<SharedMemoryWithSize> software_draw_shm_;
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
index d02b13d..7cbeb2e 100644
--- a/content/renderer/android/synchronous_layer_tree_frame_sink.cc
+++ b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -116,7 +116,7 @@
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     int routing_id,
     uint32_t layer_tree_frame_sink_id,
-    std::unique_ptr<viz::BeginFrameSource> begin_frame_source,
+    std::unique_ptr<viz::BeginFrameSource> synthetic_begin_frame_source,
     SynchronousCompositorRegistry* registry,
     scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
     : cc::LayerTreeFrameSink(std::move(context_provider),
@@ -132,10 +132,13 @@
       frame_swap_message_queue_(frame_swap_message_queue),
       parent_local_surface_id_allocator_(
           new viz::ParentLocalSurfaceIdAllocator),
-      begin_frame_source_(std::move(begin_frame_source)) {
+      synthetic_begin_frame_source_(std::move(synthetic_begin_frame_source)) {
   DCHECK(registry_);
   DCHECK(sender_);
-  DCHECK(begin_frame_source_);
+  if (!synthetic_begin_frame_source_) {
+    external_begin_frame_source_ =
+        std::make_unique<viz::ExternalBeginFrameSource>(this);
+  }
   thread_checker_.DetachFromThread();
   memory_policy_.priority_cutoff_when_visible =
       gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
@@ -170,8 +173,9 @@
 
   frame_sink_manager_ = std::make_unique<viz::FrameSinkManagerImpl>();
 
-  DCHECK(begin_frame_source_);
-  client_->SetBeginFrameSource(begin_frame_source_.get());
+  client_->SetBeginFrameSource(synthetic_begin_frame_source_
+                                   ? synthetic_begin_frame_source_.get()
+                                   : external_begin_frame_source_.get());
   client_->SetMemoryPolicy(memory_policy_);
   client_->SetTreeActivationCallback(
       base::Bind(&SynchronousLayerTreeFrameSink::DidActivatePendingTree,
@@ -215,7 +219,8 @@
   DCHECK(CalledOnValidThread());
   client_->SetBeginFrameSource(nullptr);
   // Destroy the begin frame source on the same thread it was bound on.
-  begin_frame_source_ = nullptr;
+  synthetic_begin_frame_source_ = nullptr;
+  external_begin_frame_source_ = nullptr;
   registry_->UnregisterLayerTreeFrameSink(routing_id_, this);
   client_->SetTreeActivationCallback(base::Closure());
   root_support_.reset();
@@ -518,4 +523,22 @@
 
 void SynchronousLayerTreeFrameSink::OnBeginFramePausedChanged(bool paused) {}
 
+void SynchronousLayerTreeFrameSink::OnNeedsBeginFrames(
+    bool needs_begin_frames) {
+  if (sync_client_) {
+    sync_client_->SetNeedsBeginFrames(needs_begin_frames);
+  }
+}
+
+void SynchronousLayerTreeFrameSink::BeginFrame(
+    const viz::BeginFrameArgs& args) {
+  if (external_begin_frame_source_)
+    external_begin_frame_source_->OnBeginFrame(args);
+}
+
+void SynchronousLayerTreeFrameSink::SetBeginFrameSourcePaused(bool paused) {
+  if (external_begin_frame_source_)
+    external_begin_frame_source_->OnSetBeginFrameSourcePaused(paused);
+}
+
 }  // namespace content
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.h b/content/renderer/android/synchronous_layer_tree_frame_sink.h
index a273d304..e81ec13 100644
--- a/content/renderer/android/synchronous_layer_tree_frame_sink.h
+++ b/content/renderer/android/synchronous_layer_tree_frame_sink.h
@@ -17,6 +17,7 @@
 #include "base/threading/thread_checker.h"
 #include "cc/trees/layer_tree_frame_sink.h"
 #include "cc/trees/managed_memory_policy.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/service/display/display_client.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
@@ -51,6 +52,7 @@
   virtual void Invalidate() = 0;
   virtual void SubmitCompositorFrame(uint32_t layer_tree_frame_sink_id,
                                      viz::CompositorFrame frame) = 0;
+  virtual void SetNeedsBeginFrames(bool needs_begin_frames) = 0;
 
  protected:
   virtual ~SynchronousLayerTreeFrameSinkClient() {}
@@ -66,7 +68,8 @@
 // to a fixed thread when BindToClient is called.
 class SynchronousLayerTreeFrameSink
     : public cc::LayerTreeFrameSink,
-      public viz::mojom::CompositorFrameSinkClient {
+      public viz::mojom::CompositorFrameSinkClient,
+      public viz::ExternalBeginFrameSourceClient {
  public:
   SynchronousLayerTreeFrameSink(
       scoped_refptr<viz::ContextProvider> context_provider,
@@ -109,6 +112,12 @@
       const std::vector<viz::ReturnedResource>& resources) override;
   void OnBeginFramePausedChanged(bool paused) override;
 
+  // viz::ExternalBeginFrameSourceClient overrides.
+  void OnNeedsBeginFrames(bool needs_begin_frames) override;
+
+  void BeginFrame(const viz::BeginFrameArgs& args);
+  void SetBeginFrameSourcePaused(bool paused);
+
  private:
   class SoftwareOutputSurface;
 
@@ -181,7 +190,8 @@
   std::unique_ptr<viz::Display> display_;
   // Owned by |display_|.
   SoftwareOutputSurface* software_output_surface_ = nullptr;
-  std::unique_ptr<viz::BeginFrameSource> begin_frame_source_;
+  std::unique_ptr<viz::BeginFrameSource> synthetic_begin_frame_source_;
+  std::unique_ptr<viz::ExternalBeginFrameSource> external_begin_frame_source_;
 
   gfx::Rect sw_viewport_for_current_draw_;
 
diff --git a/content/renderer/gpu/compositor_external_begin_frame_source.cc b/content/renderer/gpu/compositor_external_begin_frame_source.cc
deleted file mode 100644
index 867179b6..0000000
--- a/content/renderer/gpu/compositor_external_begin_frame_source.cc
+++ /dev/null
@@ -1,98 +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/renderer/gpu/compositor_external_begin_frame_source.h"
-
-#include "content/common/view_messages.h"
-#include "ipc/ipc_sync_channel.h"
-#include "ipc/ipc_sync_message_filter.h"
-
-namespace content {
-
-CompositorExternalBeginFrameSource::CompositorExternalBeginFrameSource(
-    CompositorForwardingMessageFilter* filter,
-    IPC::SyncMessageFilter* sync_message_filter,
-    int routing_id)
-    : BeginFrameSource(kNotRestartableId),
-      external_begin_frame_source_(this),
-      begin_frame_source_filter_(filter),
-      message_sender_(sync_message_filter),
-      routing_id_(routing_id) {
-  DCHECK(begin_frame_source_filter_);
-  DCHECK(message_sender_);
-  DETACH_FROM_THREAD(thread_checker_);
-}
-
-CompositorExternalBeginFrameSource::~CompositorExternalBeginFrameSource() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  if (begin_frame_source_proxy_) {
-    begin_frame_source_proxy_->ClearBeginFrameSource();
-    begin_frame_source_filter_->RemoveHandlerOnCompositorThread(
-                                    routing_id_,
-                                    begin_frame_source_filter_handler_);
-  }
-}
-
-void CompositorExternalBeginFrameSource::AddObserver(
-    viz::BeginFrameObserver* obs) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  if (!begin_frame_source_proxy_) {
-    begin_frame_source_proxy_ =
-        new CompositorExternalBeginFrameSourceProxy(this);
-    begin_frame_source_filter_handler_ =
-        base::Bind(&CompositorExternalBeginFrameSourceProxy::OnMessageReceived,
-                   begin_frame_source_proxy_);
-    begin_frame_source_filter_->AddHandlerOnCompositorThread(
-        routing_id_, begin_frame_source_filter_handler_);
-  }
-
-  external_begin_frame_source_.AddObserver(obs);
-}
-
-void CompositorExternalBeginFrameSource::RemoveObserver(
-    viz::BeginFrameObserver* obs) {
-  external_begin_frame_source_.RemoveObserver(obs);
-}
-
-void CompositorExternalBeginFrameSource::DidFinishFrame(
-    viz::BeginFrameObserver* obs) {
-  external_begin_frame_source_.DidFinishFrame(obs);
-}
-
-bool CompositorExternalBeginFrameSource::IsThrottled() const {
-  return true;
-}
-
-void CompositorExternalBeginFrameSource::OnNeedsBeginFrames(
-    bool needs_begin_frames) {
-  Send(new ViewHostMsg_SetNeedsBeginFrames(routing_id_, needs_begin_frames));
-}
-
-void CompositorExternalBeginFrameSource::OnMessageReceived(
-    const IPC::Message& message) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  DCHECK(begin_frame_source_proxy_);
-  IPC_BEGIN_MESSAGE_MAP(CompositorExternalBeginFrameSource, message)
-    IPC_MESSAGE_HANDLER(ViewMsg_SetBeginFramePaused,
-                        OnSetBeginFrameSourcePaused)
-    IPC_MESSAGE_HANDLER(ViewMsg_BeginFrame, OnBeginFrame)
-  IPC_END_MESSAGE_MAP()
-}
-
-void CompositorExternalBeginFrameSource::OnSetBeginFrameSourcePaused(
-    bool paused) {
-  external_begin_frame_source_.OnSetBeginFrameSourcePaused(paused);
-}
-
-void CompositorExternalBeginFrameSource::OnBeginFrame(
-    const viz::BeginFrameArgs& args) {
-  external_begin_frame_source_.OnBeginFrame(args);
-}
-
-bool CompositorExternalBeginFrameSource::Send(IPC::Message* message) {
-  return message_sender_->Send(message);
-}
-
-}  // namespace content
diff --git a/content/renderer/gpu/compositor_external_begin_frame_source.h b/content/renderer/gpu/compositor_external_begin_frame_source.h
deleted file mode 100644
index b9e7ac2..0000000
--- a/content/renderer/gpu/compositor_external_begin_frame_source.h
+++ /dev/null
@@ -1,97 +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.
-
-#ifndef CONTENT_RENDERER_GPU_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_
-#define CONTENT_RENDERER_GPU_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_
-
-#include <unordered_set>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "components/viz/common/frame_sinks/begin_frame_source.h"
-#include "content/renderer/gpu/compositor_forwarding_message_filter.h"
-
-namespace IPC {
-class Message;
-class SyncMessageFilter;
-}
-
-namespace content {
-
-// This class can be created only on the main thread, but then becomes pinned
-// to a fixed thread where cc::Scheduler is running.
-//
-// TODO(enne): This only implements the BeginFrameSource interface to
-// make it easier to give to cc as an external begin frame source.  In the
-// future, if this is owned by an output surface, then the internal
-// viz::ExternalBeginFrameSource can be the BeginFrameSource passed to cc
-// directly rather than proxied by this class.
-class CompositorExternalBeginFrameSource
-    : public viz::BeginFrameSource,
-      public viz::ExternalBeginFrameSourceClient {
- public:
-  explicit CompositorExternalBeginFrameSource(
-      CompositorForwardingMessageFilter* filter,
-      IPC::SyncMessageFilter* sync_message_filter,
-      int routing_id);
-  ~CompositorExternalBeginFrameSource() override;
-
-  // viz::BeginFrameSource implementation.
-  void AddObserver(viz::BeginFrameObserver* obs) override;
-  void RemoveObserver(viz::BeginFrameObserver* obs) override;
-  void DidFinishFrame(viz::BeginFrameObserver* obs) override;
-  bool IsThrottled() const override;
-
-  // viz::ExternalBeginFrameSourceClient implementation.
-  void OnNeedsBeginFrames(bool need_begin_frames) override;
-
- private:
-  class CompositorExternalBeginFrameSourceProxy
-      : public base::RefCountedThreadSafe<
-                   CompositorExternalBeginFrameSourceProxy> {
-   public:
-    explicit CompositorExternalBeginFrameSourceProxy(
-        CompositorExternalBeginFrameSource* begin_frame_source)
-        : begin_frame_source_(begin_frame_source) {}
-    void ClearBeginFrameSource() { begin_frame_source_ = NULL; }
-    void OnMessageReceived(const IPC::Message& message) {
-      if (begin_frame_source_)
-        begin_frame_source_->OnMessageReceived(message);
-    }
-
-   private:
-    friend class base::RefCountedThreadSafe<
-                     CompositorExternalBeginFrameSourceProxy>;
-    virtual ~CompositorExternalBeginFrameSourceProxy() {}
-
-    CompositorExternalBeginFrameSource* begin_frame_source_;
-
-    DISALLOW_COPY_AND_ASSIGN(CompositorExternalBeginFrameSourceProxy);
-  };
-
-  void OnMessageReceived(const IPC::Message& message);
-  void OnSetBeginFrameSourcePaused(bool paused);
-  void OnBeginFrame(const viz::BeginFrameArgs& args);
-  bool Send(IPC::Message* message);
-
-  // Shared helper implementation.
-  viz::ExternalBeginFrameSource external_begin_frame_source_;
-
-  scoped_refptr<CompositorForwardingMessageFilter> begin_frame_source_filter_;
-  scoped_refptr<CompositorExternalBeginFrameSourceProxy>
-      begin_frame_source_proxy_;
-  scoped_refptr<IPC::SyncMessageFilter> message_sender_;
-  int routing_id_;
-  CompositorForwardingMessageFilter::Handler begin_frame_source_filter_handler_;
-
-  THREAD_CHECKER(thread_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(CompositorExternalBeginFrameSource);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_GPU_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_
diff --git a/content/renderer/gpu/compositor_forwarding_message_filter.cc b/content/renderer/gpu/compositor_forwarding_message_filter.cc
deleted file mode 100644
index 16e02e0..0000000
--- a/content/renderer/gpu/compositor_forwarding_message_filter.cc
+++ /dev/null
@@ -1,76 +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/renderer/gpu/compositor_forwarding_message_filter.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "content/common/view_messages.h"
-#include "ipc/ipc_message.h"
-
-namespace content {
-
-CompositorForwardingMessageFilter::CompositorForwardingMessageFilter(
-    base::TaskRunner* compositor_task_runner)
-    : compositor_task_runner_(compositor_task_runner) {
-  DCHECK(compositor_task_runner_.get());
-  // This check will only be used by functions running on compositor thread.
-  compositor_thread_checker_.DetachFromThread();
-}
-
-CompositorForwardingMessageFilter::~CompositorForwardingMessageFilter() {
-}
-
-void CompositorForwardingMessageFilter::AddHandlerOnCompositorThread(
-    int routing_id,
-    const Handler& handler) {
-  DCHECK(compositor_thread_checker_.CalledOnValidThread());
-  DCHECK(!handler.is_null());
-  multi_handlers_.insert(std::make_pair(routing_id, handler));
-}
-
-void CompositorForwardingMessageFilter::RemoveHandlerOnCompositorThread(
-    int routing_id,
-    const Handler& handler) {
-  DCHECK(compositor_thread_checker_.CalledOnValidThread());
-  auto handlers = multi_handlers_.equal_range(routing_id);
-  for (auto it = handlers.first; it != handlers.second; ++it) {
-    if (it->second.Equals(handler)) {
-      multi_handlers_.erase(it);
-      return;
-    }
-  }
-  NOTREACHED();
-}
-
-bool CompositorForwardingMessageFilter::OnMessageReceived(
-    const IPC::Message& message) {
-  switch (message.type()) {
-    case ViewMsg_SetBeginFramePaused::ID:
-    case ViewMsg_BeginFrame::ID:
-      break;
-    default:
-      return false;
-  }
-
-  compositor_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &CompositorForwardingMessageFilter::ProcessMessageOnCompositorThread,
-          this, message));
-  return true;
-}
-
-void CompositorForwardingMessageFilter::ProcessMessageOnCompositorThread(
-    const IPC::Message& message) {
-  DCHECK(compositor_thread_checker_.CalledOnValidThread());
-  auto handlers = multi_handlers_.equal_range(message.routing_id());
-  if (handlers.first == handlers.second)
-    return;
-
-  for (auto it = handlers.first; it != handlers.second; ++it)
-    it->second.Run(message);
-}
-
-}  // namespace content
diff --git a/content/renderer/gpu/compositor_forwarding_message_filter.h b/content/renderer/gpu/compositor_forwarding_message_filter.h
deleted file mode 100644
index 92527cc..0000000
--- a/content/renderer/gpu/compositor_forwarding_message_filter.h
+++ /dev/null
@@ -1,75 +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.
-
-#ifndef CONTENT_RENDERER_GPU_COMPOSITOR_FORWARDING_MESSAGE_FILTER_H_
-#define CONTENT_RENDERER_GPU_COMPOSITOR_FORWARDING_MESSAGE_FILTER_H_
-
-#include <map>
-#include <set>
-
-#include "base/bind.h"
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "base/task_runner.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/content_export.h"
-#include "ipc/message_filter.h"
-
-namespace content {
-
-// This class can be used to intercept routed messages and
-// deliver them to a compositor task runner than they would otherwise
-// be sent. Messages are filtered based on type. To route these messages,
-// add a Handler to the filter.
-//
-// The user of this class implements CompositorForwardingMessageFilter::Handler,
-// which will receive the intercepted messages, on the compositor thread.
-// The caller must ensure that each handler in |multi_handlers_| outlives the
-// lifetime of the filter.
-// User can add multiple handlers for specific routing id. When messages have
-// arrived, all handlers in |multi_handlers_| for routing id will be executed.
-//
-// Note: When we want to add new message, add a new switch case in
-// OnMessageReceived() then add a new Handler for it.
-class CONTENT_EXPORT CompositorForwardingMessageFilter
-    : public IPC::MessageFilter {
- public:
-  // The handler is invoked on the compositor thread with messages that were
-  // intercepted by this filter.
-  typedef base::Callback<void(const IPC::Message&)> Handler;
-
-  // This filter will intercept messages defined in OnMessageReceived() and run
-  // them by ProcessMessageOnCompositorThread on compositor thread.
-  CompositorForwardingMessageFilter(base::TaskRunner* compositor_task_runner);
-
-  void AddHandlerOnCompositorThread(int routing_id, const Handler& handler);
-  void RemoveHandlerOnCompositorThread(int routing_id, const Handler& handler);
-
-  // MessageFilter methods:
-  bool OnMessageReceived(const IPC::Message& message) override;
-
- protected:
-  ~CompositorForwardingMessageFilter() override;
-
- private:
-  void ProcessMessageOnCompositorThread(const IPC::Message& message);
-
-  // The handler only gets run on the compositor thread.
-  scoped_refptr<base::TaskRunner> compositor_task_runner_;
-
-  // This is used to check some functions that are only running on compositor
-  // thread.
-  base::ThreadChecker compositor_thread_checker_;
-
-  // Maps the routing_id for which messages should be filtered and handlers
-  // which will be routed.
-  std::multimap<int, Handler> multi_handlers_;
-
-  DISALLOW_COPY_AND_ASSIGN(CompositorForwardingMessageFilter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_GPU_COMPOSITOR_FORWARDING_MESSAGE_FILTER_H_
diff --git a/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc b/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc
deleted file mode 100644
index 851837e..0000000
--- a/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc
+++ /dev/null
@@ -1,82 +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/renderer/gpu/compositor_forwarding_message_filter.h"
-
-#include "base/bind.h"
-#include "base/test/test_simple_task_runner.h"
-#include "components/viz/test/begin_frame_args_test.h"
-#include "content/common/view_messages.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class CompositorForwardingMessageFilterTestHandler
-    : public base::RefCounted<CompositorForwardingMessageFilterTestHandler> {
- public:
-  CompositorForwardingMessageFilterTestHandler() : count_(0) {
-  }
-
-  void OnPlusMethod(const IPC::Message& msg) {
-    count_++;
-  }
-
-  void OnMinusMethod(const IPC::Message& msg) {
-    count_--;
-  }
-
-  int count() { return count_; }
-
-  void ResetCount() { count_ = 0; }
-
- private:
-  friend class base::RefCounted<CompositorForwardingMessageFilterTestHandler>;
-  ~CompositorForwardingMessageFilterTestHandler() {}
-
-  int count_;
-};
-
-TEST(CompositorForwardingMessageFilterTest, BasicTest) {
-  scoped_refptr<CompositorForwardingMessageFilterTestHandler> handler =
-      new CompositorForwardingMessageFilterTestHandler;
-  scoped_refptr<base::TestSimpleTaskRunner> task_runner(
-      new base::TestSimpleTaskRunner);
-  int route_id = 0;
-
-  ViewMsg_BeginFrame msg(route_id, viz::CreateBeginFrameArgsForTesting(
-                                       BEGINFRAME_FROM_HERE, 0, 1));
-
-  CompositorForwardingMessageFilter::Handler plus_handler =
-      base::Bind(&CompositorForwardingMessageFilterTestHandler::OnPlusMethod,
-                 handler);
-  CompositorForwardingMessageFilter::Handler minus_handler =
-      base::Bind(&CompositorForwardingMessageFilterTestHandler::OnMinusMethod,
-                 handler);
-
-  scoped_refptr<CompositorForwardingMessageFilter> filter =
-      new CompositorForwardingMessageFilter(task_runner.get());
-
-  filter->AddHandlerOnCompositorThread(route_id, plus_handler);
-  filter->OnMessageReceived(msg);
-  task_runner->RunPendingTasks();
-  EXPECT_EQ(1, handler->count());
-
-  handler->ResetCount();
-  EXPECT_EQ(0, handler->count());
-
-  filter->AddHandlerOnCompositorThread(route_id, minus_handler);
-  filter->OnMessageReceived(msg);
-  task_runner->RunPendingTasks();
-  EXPECT_EQ(0, handler->count());
-
-  handler->ResetCount();
-  EXPECT_EQ(0, handler->count());
-
-  filter->RemoveHandlerOnCompositorThread(route_id, plus_handler);
-  filter->OnMessageReceived(msg);
-  task_runner->RunPendingTasks();
-  EXPECT_EQ(-1, handler->count());
-}
-
-}  // namespace content
diff --git a/content/renderer/media/media_devices_event_dispatcher.cc b/content/renderer/media/media_devices_event_dispatcher.cc
deleted file mode 100644
index 9c4a323d..0000000
--- a/content/renderer/media/media_devices_event_dispatcher.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/media_devices_event_dispatcher.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "content/public/renderer/render_frame.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "url/origin.h"
-
-namespace content {
-
-base::WeakPtr<MediaDevicesEventDispatcher>
-MediaDevicesEventDispatcher::GetForRenderFrame(RenderFrame* render_frame) {
-  MediaDevicesEventDispatcher* dispatcher =
-      MediaDevicesEventDispatcher::Get(render_frame);
-  if (!dispatcher)
-    dispatcher = new MediaDevicesEventDispatcher(render_frame);
-
-  return dispatcher->AsWeakPtr();
-}
-
-MediaDevicesEventDispatcher::MediaDevicesEventDispatcher(
-    RenderFrame* render_frame)
-    : RenderFrameObserver(render_frame),
-      RenderFrameObserverTracker<MediaDevicesEventDispatcher>(render_frame),
-      current_id_(0) {}
-
-MediaDevicesEventDispatcher::~MediaDevicesEventDispatcher() {}
-
-MediaDevicesEventDispatcher::SubscriptionId
-MediaDevicesEventDispatcher::SubscribeDeviceChangeNotifications(
-    MediaDeviceType type,
-    const MediaDevicesEventDispatcher::DevicesChangedCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsValidMediaDeviceType(type));
-
-  SubscriptionId subscription_id = ++current_id_;
-  GetMediaDevicesDispatcher()->SubscribeDeviceChangeNotifications(
-      type, subscription_id);
-  SubscriptionList& subscriptions = device_change_subscriptions_[type];
-  subscriptions.push_back(Subscription{subscription_id, callback});
-
-  return current_id_;
-}
-
-void MediaDevicesEventDispatcher::UnsubscribeDeviceChangeNotifications(
-    MediaDeviceType type,
-    SubscriptionId subscription_id) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsValidMediaDeviceType(type));
-
-  SubscriptionList& subscriptions = device_change_subscriptions_[type];
-  auto it = std::find_if(subscriptions.begin(), subscriptions.end(),
-                         [subscription_id](const Subscription& subscription) {
-                           return subscription.first == subscription_id;
-                         });
-  if (it == subscriptions.end())
-    return;
-
-  GetMediaDevicesDispatcher()->UnsubscribeDeviceChangeNotifications(type,
-                                                                    it->first);
-  subscriptions.erase(it);
-}
-
-MediaDevicesEventDispatcher::SubscriptionIdList
-MediaDevicesEventDispatcher::SubscribeDeviceChangeNotifications(
-    const DevicesChangedCallback& callback) {
-  SubscriptionIdList list;
-  SubscriptionId id;
-  id = SubscribeDeviceChangeNotifications(MEDIA_DEVICE_TYPE_AUDIO_INPUT,
-                                          callback);
-  list.push_back(id);
-  id = SubscribeDeviceChangeNotifications(MEDIA_DEVICE_TYPE_VIDEO_INPUT,
-                                          callback);
-  list.push_back(id);
-  id = SubscribeDeviceChangeNotifications(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT,
-                                          callback);
-  list.push_back(id);
-
-  return list;
-}
-
-void MediaDevicesEventDispatcher::UnsubscribeDeviceChangeNotifications(
-    const SubscriptionIdList& subscription_ids) {
-  DCHECK_EQ(static_cast<size_t>(NUM_MEDIA_DEVICE_TYPES),
-            subscription_ids.size());
-  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i)
-    UnsubscribeDeviceChangeNotifications(static_cast<MediaDeviceType>(i),
-                                         subscription_ids[i]);
-}
-
-void MediaDevicesEventDispatcher::DispatchDevicesChangedEvent(
-    MediaDeviceType type,
-    const MediaDeviceInfoArray& device_infos) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(IsValidMediaDeviceType(type));
-  SubscriptionList& subscriptions = device_change_subscriptions_[type];
-  for (auto& subscription : subscriptions)
-    subscription.second.Run(type, device_infos);
-}
-
-void MediaDevicesEventDispatcher::OnDestruct() {
-  delete this;
-}
-
-void MediaDevicesEventDispatcher::SetMediaDevicesDispatcherForTesting(
-    blink::mojom::MediaDevicesDispatcherHostPtr media_devices_dispatcher) {
-  media_devices_dispatcher_ = std::move(media_devices_dispatcher);
-}
-
-const blink::mojom::MediaDevicesDispatcherHostPtr&
-MediaDevicesEventDispatcher::GetMediaDevicesDispatcher() {
-  if (!media_devices_dispatcher_) {
-    render_frame()->GetRemoteInterfaces()->GetInterface(
-        mojo::MakeRequest(&media_devices_dispatcher_));
-  }
-
-  return media_devices_dispatcher_;
-}
-
-}  // namespace content
diff --git a/content/renderer/media/media_devices_event_dispatcher.h b/content/renderer/media/media_devices_event_dispatcher.h
deleted file mode 100644
index 806105d..0000000
--- a/content/renderer/media/media_devices_event_dispatcher.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_MEDIA_DEVICES_EVENT_DISPATCHER_H_
-#define CONTENT_RENDERER_MEDIA_MEDIA_DEVICES_EVENT_DISPATCHER_H_
-
-#include <stdint.h>
-
-#include <utility>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/content_export.h"
-#include "content/common/media/media_devices.h"
-#include "content/public/renderer/render_frame_observer.h"
-#include "content/public/renderer/render_frame_observer_tracker.h"
-#include "third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom.h"
-
-namespace content {
-
-// This class implements the logic for managing media device-change
-// subscriptions on the renderer process. It manages the generation of
-// subscription IDs and  handles the interaction with the Mojo objects that
-// communicate with the  browser process. There is at most one instance of this
-// class per frame.
-class CONTENT_EXPORT MediaDevicesEventDispatcher
-    : public RenderFrameObserver,
-      public RenderFrameObserverTracker<MediaDevicesEventDispatcher>,
-      public base::SupportsWeakPtr<MediaDevicesEventDispatcher> {
- public:
-  using SubscriptionId = uint32_t;
-  using SubscriptionIdList = std::vector<SubscriptionId>;
-  using DevicesChangedCallback =
-      base::Callback<void(MediaDeviceType, const MediaDeviceInfoArray&)>;
-
-  // Returns a weak pointer to the MediaDevicesEventDispatcher for the given
-  // |render_frame|.
-  static base::WeakPtr<MediaDevicesEventDispatcher> GetForRenderFrame(
-      RenderFrame* render_frame);
-
-  ~MediaDevicesEventDispatcher() override;
-
-  // Register a callback for device-change notifications for a given device
-  // type. Returns a subscription ID that can be used to cancel the
-  // subscription.
-  SubscriptionId SubscribeDeviceChangeNotifications(
-      MediaDeviceType type,
-      const DevicesChangedCallback& callback);
-
-  // Cancels a subscription identified with |subscription_id| to device-change
-  // notifications for device type |type|. If no subscription identified with
-  // |subscription_id| exists for device type |type|, this function returns
-  // without side effects.
-  void UnsubscribeDeviceChangeNotifications(MediaDeviceType type,
-                                            SubscriptionId subscription_id);
-
-  // Register a callback for device-change notifications for any device type.
-  // Returns a list of subscription IDs that can be used to cancel the
-  // subscriptions.
-  SubscriptionIdList SubscribeDeviceChangeNotifications(
-      const DevicesChangedCallback& callback);
-
-  // Cancels subscriptions identified by |subscription_ids| to device-change
-  // notifications for all device types. This is implemented by invoking the
-  // single-parameter version of UnsubscribeDeviceChangeNotifications() for all
-  // device types.
-  void UnsubscribeDeviceChangeNotifications(
-      const SubscriptionIdList& subscription_ids);
-
-  // Dispatches an event notification to all registered callbacks for device
-  // type |type|. Should be invoked only by an object that detects changes in
-  // the set of media devices.
-  void DispatchDevicesChangedEvent(MediaDeviceType type,
-                                   const MediaDeviceInfoArray& device_infos);
-
-  // RenderFrameObserver override.
-  void OnDestruct() override;
-
-  void SetMediaDevicesDispatcherForTesting(
-      blink::mojom::MediaDevicesDispatcherHostPtr media_devices_dispatcher);
-
- private:
-  explicit MediaDevicesEventDispatcher(RenderFrame* render_frame);
-
-  const blink::mojom::MediaDevicesDispatcherHostPtr&
-  GetMediaDevicesDispatcher();
-
-  SubscriptionId current_id_;
-
-  using Subscription = std::pair<SubscriptionId, DevicesChangedCallback>;
-  using SubscriptionList = std::vector<Subscription>;
-  SubscriptionList device_change_subscriptions_[NUM_MEDIA_DEVICE_TYPES];
-
-  blink::mojom::MediaDevicesDispatcherHostPtr media_devices_dispatcher_;
-
-  base::ThreadChecker thread_checker_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaDevicesEventDispatcher);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MEDIA_MEDIA_DEVICES_EVENT_DISPATCHER_H_
diff --git a/content/renderer/media/media_devices_event_dispatcher_unittest.cc b/content/renderer/media/media_devices_event_dispatcher_unittest.cc
deleted file mode 100644
index eb34cd27..0000000
--- a/content/renderer/media/media_devices_event_dispatcher_unittest.cc
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/media_devices_event_dispatcher.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <string>
-
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-using testing::_;
-
-namespace content {
-namespace {
-
-class MockMediaDevicesEventSubscriber {
- public:
-  MOCK_METHOD2(EventDispatched,
-               void(MediaDeviceType, const MediaDeviceInfoArray&));
-};
-
-class MockMediaDevicesDispatcherHost
-    : public blink::mojom::MediaDevicesDispatcherHost {
- public:
-  MockMediaDevicesDispatcherHost() : binding_(this) {}
-
-  MOCK_METHOD2(SubscribeDeviceChangeNotifications,
-               void(MediaDeviceType type, uint32_t subscription_id));
-  MOCK_METHOD2(UnsubscribeDeviceChangeNotifications,
-               void(MediaDeviceType type, uint32_t subscription_id));
-
-  void EnumerateDevices(bool request_audio_input,
-                        bool request_video_input,
-                        bool request_audio_output,
-                        EnumerateDevicesCallback) override {
-    NOTREACHED();
-  }
-
-  void GetVideoInputCapabilities(
-      GetVideoInputCapabilitiesCallback client_callback) override {
-    NOTREACHED();
-  }
-
-  void GetAudioInputCapabilities(
-      GetAudioInputCapabilitiesCallback client_callback) override {
-    NOTREACHED();
-  }
-
-  void GetAllVideoInputDeviceFormats(
-      const std::string&,
-      GetAllVideoInputDeviceFormatsCallback) override {
-    NOTREACHED();
-  }
-
-  void GetAvailableVideoInputDeviceFormats(
-      const std::string&,
-      GetAvailableVideoInputDeviceFormatsCallback) override {
-    NOTREACHED();
-  }
-
-  void AddMediaDevicesListener(
-      bool subscribe_audio_input,
-      bool subscribe_video_input,
-      bool subscribe_audio_output,
-      blink::mojom::MediaDevicesListenerPtr listener) override {
-    NOTREACHED();
-  }
-
-  blink::mojom::MediaDevicesDispatcherHostPtr CreateInterfacePtrAndBind() {
-    blink::mojom::MediaDevicesDispatcherHostPtr ptr;
-    binding_.Bind(mojo::MakeRequest(&ptr));
-    return ptr;
-  }
-
- private:
-  mojo::Binding<blink::mojom::MediaDevicesDispatcherHost> binding_;
-};
-
-class MediaDevicesEventDispatcherTest : public ::testing::Test {
- public:
-  MediaDevicesEventDispatcherTest() {}
-
-  void SetUp() override {
-    event_dispatcher_ = MediaDevicesEventDispatcher::GetForRenderFrame(nullptr);
-    blink::mojom::MediaDevicesDispatcherHostPtr ptr =
-        media_devices_dispatcher_.CreateInterfacePtrAndBind();
-    event_dispatcher_->SetMediaDevicesDispatcherForTesting(std::move(ptr));
-  }
-
-  void TearDown() override { event_dispatcher_->OnDestruct(); }
-
- protected:
-  base::MessageLoop message_loop_;
-  base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher_;
-  MockMediaDevicesDispatcherHost media_devices_dispatcher_;
-};
-
-}  // namespace
-
-TEST_F(MediaDevicesEventDispatcherTest, SubscribeUnsubscribeSingleType) {
-  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
-    MediaDeviceType type = static_cast<MediaDeviceType>(i);
-    MediaDeviceInfoArray device_infos;
-    MockMediaDevicesEventSubscriber subscriber1, subscriber2;
-    EXPECT_CALL(media_devices_dispatcher_,
-                SubscribeDeviceChangeNotifications(type, _))
-        .Times(2);
-    auto subscription_id1 =
-        event_dispatcher_->SubscribeDeviceChangeNotifications(
-            type, base::Bind(&MockMediaDevicesEventSubscriber::EventDispatched,
-                             base::Unretained(&subscriber1)));
-    auto subscription_id2 =
-        event_dispatcher_->SubscribeDeviceChangeNotifications(
-            type, base::Bind(&MockMediaDevicesEventSubscriber::EventDispatched,
-                             base::Unretained(&subscriber2)));
-
-    // Simulate a device change.
-    EXPECT_CALL(subscriber1, EventDispatched(type, _));
-    EXPECT_CALL(subscriber2, EventDispatched(type, _));
-    event_dispatcher_->DispatchDevicesChangedEvent(type, device_infos);
-    base::RunLoop().RunUntilIdle();
-
-    // Unsubscribe one of the subscribers.
-    EXPECT_CALL(media_devices_dispatcher_,
-                UnsubscribeDeviceChangeNotifications(type, subscription_id1));
-    event_dispatcher_->UnsubscribeDeviceChangeNotifications(type,
-                                                            subscription_id1);
-
-    // Simulate another device change.
-    EXPECT_CALL(subscriber1, EventDispatched(_, _)).Times(0);
-    EXPECT_CALL(subscriber2, EventDispatched(type, _));
-    event_dispatcher_->DispatchDevicesChangedEvent(type, device_infos);
-    base::RunLoop().RunUntilIdle();
-
-    // Unsubscribe the other subscriber.
-    EXPECT_CALL(media_devices_dispatcher_,
-                UnsubscribeDeviceChangeNotifications(type, subscription_id2));
-    event_dispatcher_->UnsubscribeDeviceChangeNotifications(type,
-                                                            subscription_id2);
-    base::RunLoop().RunUntilIdle();
-  }
-}
-
-TEST_F(MediaDevicesEventDispatcherTest, SubscribeUnsubscribeAllTypes) {
-  MediaDeviceInfoArray device_infos;
-  MockMediaDevicesEventSubscriber subscriber1, subscriber2;
-  EXPECT_CALL(media_devices_dispatcher_, SubscribeDeviceChangeNotifications(
-                                             MEDIA_DEVICE_TYPE_AUDIO_INPUT, _))
-      .Times(2);
-  EXPECT_CALL(media_devices_dispatcher_, SubscribeDeviceChangeNotifications(
-                                             MEDIA_DEVICE_TYPE_VIDEO_INPUT, _))
-      .Times(2);
-  EXPECT_CALL(media_devices_dispatcher_, SubscribeDeviceChangeNotifications(
-                                             MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, _))
-      .Times(2);
-  auto subscription_list_1 =
-      event_dispatcher_->SubscribeDeviceChangeNotifications(
-          base::Bind(&MockMediaDevicesEventSubscriber::EventDispatched,
-                     base::Unretained(&subscriber1)));
-  auto subscription_list_2 =
-      event_dispatcher_->SubscribeDeviceChangeNotifications(
-          base::Bind(&MockMediaDevicesEventSubscriber::EventDispatched,
-                     base::Unretained(&subscriber2)));
-
-  // Simulate a device changes for all types.
-  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
-    MediaDeviceType type = static_cast<MediaDeviceType>(i);
-    EXPECT_CALL(subscriber1, EventDispatched(type, _));
-    EXPECT_CALL(subscriber2, EventDispatched(type, _));
-    event_dispatcher_->DispatchDevicesChangedEvent(type, device_infos);
-    base::RunLoop().RunUntilIdle();
-  }
-
-  // Unsubscribe one of the subscribers.
-  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
-    MediaDeviceType type = static_cast<MediaDeviceType>(i);
-    EXPECT_CALL(
-        media_devices_dispatcher_,
-        UnsubscribeDeviceChangeNotifications(type, subscription_list_1[type]));
-  }
-  event_dispatcher_->UnsubscribeDeviceChangeNotifications(subscription_list_1);
-  base::RunLoop().RunUntilIdle();
-
-  // Simulate more device changes.
-  EXPECT_CALL(subscriber1, EventDispatched(_, _)).Times(0);
-  EXPECT_CALL(subscriber2, EventDispatched(_, _)).Times(NUM_MEDIA_DEVICE_TYPES);
-  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
-    MediaDeviceType type = static_cast<MediaDeviceType>(i);
-    event_dispatcher_->DispatchDevicesChangedEvent(type, device_infos);
-    base::RunLoop().RunUntilIdle();
-  }
-
-  // Unsubscribe the other subscriber.
-  for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
-    MediaDeviceType type = static_cast<MediaDeviceType>(i);
-    EXPECT_CALL(
-        media_devices_dispatcher_,
-        UnsubscribeDeviceChangeNotifications(type, subscription_list_2[type]));
-  }
-  event_dispatcher_->UnsubscribeDeviceChangeNotifications(subscription_list_2);
-  base::RunLoop().RunUntilIdle();
-}
-
-}  // namespace content
diff --git a/content/renderer/media/media_devices_listener_impl.cc b/content/renderer/media/media_devices_listener_impl.cc
deleted file mode 100644
index 019fbeb..0000000
--- a/content/renderer/media/media_devices_listener_impl.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/media_devices_listener_impl.h"
-
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "content/public/renderer/render_frame.h"
-#include "content/renderer/media/media_devices_event_dispatcher.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace content {
-
-// static
-void MediaDevicesListenerImpl::Create(
-    int render_frame_id,
-    blink::mojom::MediaDevicesListenerRequest request) {
-  mojo::MakeStrongBinding(
-      std::make_unique<MediaDevicesListenerImpl>(render_frame_id),
-      std::move(request));
-}
-
-MediaDevicesListenerImpl::MediaDevicesListenerImpl(int render_frame_id)
-    : render_frame_id_(render_frame_id) {}
-
-MediaDevicesListenerImpl::~MediaDevicesListenerImpl() = default;
-
-void MediaDevicesListenerImpl::OnDevicesChanged(
-    MediaDeviceType type,
-    uint32_t subscription_id,
-    const MediaDeviceInfoArray& device_infos) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher =
-      MediaDevicesEventDispatcher::GetForRenderFrame(
-          RenderFrame::FromRoutingID(render_frame_id_));
-  if (event_dispatcher)
-    event_dispatcher->DispatchDevicesChangedEvent(type, device_infos);
-}
-
-}  // namespace content
diff --git a/content/renderer/media/media_devices_listener_impl.h b/content/renderer/media/media_devices_listener_impl.h
deleted file mode 100644
index 7e24ebf..0000000
--- a/content/renderer/media/media_devices_listener_impl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_MEDIA_DEVICES_LISTENER_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_MEDIA_DEVICES_LISTENER_IMPL_H_
-
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/content_export.h"
-#include "content/common/media/media_devices.h"
-#include "third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom.h"
-
-namespace content {
-
-// This class implements a Mojo object that receives notifications about changes
-// in the set of media devices for a given frame.
-class CONTENT_EXPORT MediaDevicesListenerImpl
-    : public blink::mojom::MediaDevicesListener {
- public:
-  static void Create(int render_frame_id,
-                     blink::mojom::MediaDevicesListenerRequest request);
-  explicit MediaDevicesListenerImpl(int render_frame_id);
-  ~MediaDevicesListenerImpl() override;
-
-  // blink::mojom::MediaDevicesListener implementation.
-  void OnDevicesChanged(MediaDeviceType type,
-                        uint32_t subscription_id,
-                        const MediaDeviceInfoArray& device_infos) override;
-
- private:
-  // Used for DCHECKs so methods calls won't execute in the wrong thread.
-  base::ThreadChecker thread_checker_;
-
-  int render_frame_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaDevicesListenerImpl);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MEDIA_MEDIA_DEVICES_LISTENER_IMPL_H_
diff --git a/content/renderer/media/user_media_client_impl_unittest.cc b/content/renderer/media/user_media_client_impl_unittest.cc
index b1a6c3ac..388bb90 100644
--- a/content/renderer/media/user_media_client_impl_unittest.cc
+++ b/content/renderer/media/user_media_client_impl_unittest.cc
@@ -237,11 +237,6 @@
     audio_parameters_ = media::AudioParameters::UnavailableDeviceParams();
   }
 
-  MOCK_METHOD2(SubscribeDeviceChangeNotifications,
-               void(MediaDeviceType type, uint32_t subscription_id));
-  MOCK_METHOD2(UnsubscribeDeviceChangeNotifications,
-               void(MediaDeviceType type, uint32_t subscription_id));
-
   void AddMediaDevicesListener(
       bool subscribe_audio_input,
       bool subscribe_video_input,
diff --git a/content/renderer/pepper/pepper_device_enumeration_host_helper.cc b/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
index 02a3158c..b6e43a6 100644
--- a/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
+++ b/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
@@ -93,7 +93,7 @@
       : owner_(owner),
         callback_(callback),
         requested_(false),
-        subscription_id_(0) {
+        subscription_id_(0u) {
     DCHECK(owner_);
     if (!owner->delegate_) {
       return;
@@ -120,7 +120,7 @@
   PepperDeviceEnumerationHostHelper* const owner_;
   PepperDeviceEnumerationHostHelper::Delegate::DevicesCallback callback_;
   bool requested_;
-  int subscription_id_;
+  size_t subscription_id_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedMonitoringRequest);
 };
diff --git a/content/renderer/pepper/pepper_device_enumeration_host_helper.h b/content/renderer/pepper/pepper_device_enumeration_host_helper.h
index a322a9a..98c746a 100644
--- a/content/renderer/pepper/pepper_device_enumeration_host_helper.h
+++ b/content/renderer/pepper/pepper_device_enumeration_host_helper.h
@@ -55,14 +55,13 @@
     // subscription ID that must be used to stop monitoring for the device
     // |type|. Does not invoke |callback| synchronously. |callback| is invoked
     // when device changes of the specified |type| occur.
-    virtual uint32_t StartMonitoringDevices(
-        PP_DeviceType_Dev type,
-        const DevicesCallback& callback) = 0;
+    virtual size_t StartMonitoringDevices(PP_DeviceType_Dev type,
+                                          const DevicesCallback& callback) = 0;
 
     // Stops monitoring devices of the specified |type|. The
     // |subscription_id| is the return value of StartMonitoringDevices.
     virtual void StopMonitoringDevices(PP_DeviceType_Dev type,
-                                       uint32_t subscription_id) = 0;
+                                       size_t subscription_id) = 0;
   };
 
   // |resource_host| and |delegate| must outlive this object.
diff --git a/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc b/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
index caaf6984..6c2d52e 100644
--- a/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
+++ b/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
@@ -48,7 +48,7 @@
 class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate,
                      public base::SupportsWeakPtr<TestDelegate> {
  public:
-  TestDelegate() : last_used_id_(0) {}
+  TestDelegate() : last_used_id_(0u) {}
 
   ~TestDelegate() override { CHECK(monitoring_callbacks_.empty()); }
 
@@ -57,15 +57,15 @@
     callback.Run(TestEnumerationData());
   }
 
-  uint32_t StartMonitoringDevices(PP_DeviceType_Dev /* type */,
-                                  const DevicesCallback& callback) override {
+  size_t StartMonitoringDevices(PP_DeviceType_Dev /* type */,
+                                const DevicesCallback& callback) override {
     last_used_id_++;
     monitoring_callbacks_[last_used_id_] = callback;
     return last_used_id_;
   }
 
   void StopMonitoringDevices(PP_DeviceType_Dev /* type */,
-                             uint32_t subscription_id) override {
+                             size_t subscription_id) override {
     auto iter = monitoring_callbacks_.find(subscription_id);
     CHECK(iter != monitoring_callbacks_.end());
     monitoring_callbacks_.erase(iter);
@@ -73,7 +73,7 @@
 
   // Returns false if |request_id| is not found.
   bool SimulateDevicesChanged(
-      uint32_t subscription_id,
+      size_t subscription_id,
       const std::vector<ppapi::DeviceRefData>& devices) {
     auto iter = monitoring_callbacks_.find(subscription_id);
     if (iter == monitoring_callbacks_.end())
@@ -87,11 +87,11 @@
     return monitoring_callbacks_.size();
   }
 
-  int last_used_id() const { return last_used_id_; }
+  size_t last_used_id() const { return last_used_id_; }
 
  private:
-  std::map<uint32_t, DevicesCallback> monitoring_callbacks_;
-  int last_used_id_;
+  std::map<size_t, DevicesCallback> monitoring_callbacks_;
+  size_t last_used_id_;
 
   DISALLOW_COPY_AND_ASSIGN(TestDelegate);
 };
@@ -188,7 +188,7 @@
   SimulateMonitorDeviceChangeReceived(callback_id);
 
   EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount());
-  int request_id = delegate_.last_used_id();
+  size_t request_id = delegate_.last_used_id();
 
   std::vector<ppapi::DeviceRefData> data;
   ASSERT_TRUE(delegate_.SimulateDevicesChanged(request_id, data));
@@ -218,7 +218,7 @@
 
   // StopEnumerateDevice() should have been called for the previous request.
   EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount());
-  int request_id2 = delegate_.last_used_id();
+  size_t request_id2 = delegate_.last_used_id();
 
   data_item.type = PP_DEVICETYPE_DEV_AUDIOCAPTURE;
   data_item.name = "name_3";
diff --git a/content/renderer/pepper/pepper_media_device_manager.cc b/content/renderer/pepper/pepper_media_device_manager.cc
index db0bd30b..4e3f384 100644
--- a/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/content/renderer/pepper/pepper_media_device_manager.cc
@@ -8,12 +8,12 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/child/child_thread_impl.h"
 #include "content/public/common/console_message_level.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/service_names.mojom.h"
-#include "content/renderer/media/media_devices_event_dispatcher.h"
 #include "content/renderer/media/media_stream_device_observer.h"
 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
 #include "content/renderer/render_frame_impl.h"
@@ -71,6 +71,17 @@
   return data;
 }
 
+std::vector<ppapi::DeviceRefData> FromMediaDeviceInfoArray(
+    MediaDeviceType type,
+    const MediaDeviceInfoArray& device_infos) {
+  std::vector<ppapi::DeviceRefData> devices;
+  devices.reserve(device_infos.size());
+  for (const auto& device_info : device_infos)
+    devices.push_back(FromMediaDeviceInfo(type, device_info));
+
+  return devices;
+}
+
 }  // namespace
 
 base::WeakPtr<PepperMediaDeviceManager>
@@ -85,8 +96,7 @@
 
 PepperMediaDeviceManager::PepperMediaDeviceManager(RenderFrame* render_frame)
     : RenderFrameObserver(render_frame),
-      RenderFrameObserverTracker<PepperMediaDeviceManager>(render_frame),
-      next_id_(1) {}
+      RenderFrameObserverTracker<PepperMediaDeviceManager>(render_frame) {}
 
 PepperMediaDeviceManager::~PepperMediaDeviceManager() {
   DCHECK(open_callbacks_.empty());
@@ -112,28 +122,41 @@
 #endif
 }
 
-uint32_t PepperMediaDeviceManager::StartMonitoringDevices(
+size_t PepperMediaDeviceManager::StartMonitoringDevices(
     PP_DeviceType_Dev type,
     const DevicesCallback& callback) {
 #if BUILDFLAG(ENABLE_WEBRTC)
-  base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher =
-      MediaDevicesEventDispatcher::GetForRenderFrame(render_frame());
-  return event_dispatcher->SubscribeDeviceChangeNotifications(
-      ToMediaDeviceType(type),
-      base::Bind(&PepperMediaDeviceManager::DevicesChanged, AsWeakPtr(),
-                 callback));
+  bool subscribe_audio_input = type == PP_DEVICETYPE_DEV_AUDIOCAPTURE;
+  bool subscribe_video_input = type == PP_DEVICETYPE_DEV_VIDEOCAPTURE;
+  bool subscribe_audio_output = type == PP_DEVICETYPE_DEV_AUDIOOUTPUT;
+  CHECK(subscribe_audio_input || subscribe_video_input ||
+        subscribe_audio_output);
+  blink::mojom::MediaDevicesListenerPtr listener;
+  size_t subscription_id =
+      bindings_.AddBinding(this, mojo::MakeRequest(&listener));
+  GetMediaDevicesDispatcher()->AddMediaDevicesListener(
+      subscribe_audio_input, subscribe_video_input, subscribe_audio_output,
+      std::move(listener));
+  SubscriptionList& subscriptions =
+      device_change_subscriptions_[ToMediaDeviceType(type)];
+  subscriptions.push_back(Subscription{subscription_id, callback});
+
+  return subscription_id;
 #else
-  return 0;
+  return 0u;
 #endif
 }
 
 void PepperMediaDeviceManager::StopMonitoringDevices(PP_DeviceType_Dev type,
-                                                     uint32_t subscription_id) {
+                                                     size_t subscription_id) {
 #if BUILDFLAG(ENABLE_WEBRTC)
-  base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher =
-      MediaDevicesEventDispatcher::GetForRenderFrame(render_frame());
-  event_dispatcher->UnsubscribeDeviceChangeNotifications(
-      ToMediaDeviceType(type), subscription_id);
+  SubscriptionList& subscriptions =
+      device_change_subscriptions_[ToMediaDeviceType(type)];
+  base::EraseIf(subscriptions,
+                [subscription_id](const Subscription& subscription) {
+                  return subscription.first == subscription_id;
+                });
+  bindings_.RemoveBinding(subscription_id);
 #endif
 }
 
@@ -225,6 +248,16 @@
   }
 }
 
+void PepperMediaDeviceManager::OnDevicesChanged(
+    MediaDeviceType type,
+    const MediaDeviceInfoArray& device_infos) {
+  std::vector<ppapi::DeviceRefData> devices =
+      FromMediaDeviceInfoArray(type, device_infos);
+  SubscriptionList& subscriptions = device_change_subscriptions_[type];
+  for (auto& subscription : subscriptions)
+    subscription.second.Run(devices);
+}
+
 void PepperMediaDeviceManager::OnDeviceOpened(int request_id,
                                               bool success,
                                               const std::string& label,
@@ -248,19 +281,7 @@
     const DevicesCallback& client_callback,
     MediaDeviceType type,
     const std::vector<MediaDeviceInfoArray>& enumeration) {
-  DevicesChanged(client_callback, type, enumeration[type]);
-}
-
-void PepperMediaDeviceManager::DevicesChanged(
-    const DevicesCallback& client_callback,
-    MediaDeviceType type,
-    const MediaDeviceInfoArray& device_infos) {
-  std::vector<ppapi::DeviceRefData> devices;
-  devices.reserve(device_infos.size());
-  for (const auto& device_info : device_infos)
-    devices.push_back(FromMediaDeviceInfo(type, device_info));
-
-  client_callback.Run(devices);
+  client_callback.Run(FromMediaDeviceInfoArray(type, enumeration[type]));
 }
 
 const mojom::MediaStreamDispatcherHostPtr&
diff --git a/content/renderer/pepper/pepper_media_device_manager.h b/content/renderer/pepper/pepper_media_device_manager.h
index 329cd56..1367d35 100644
--- a/content/renderer/pepper/pepper_media_device_manager.h
+++ b/content/renderer/pepper/pepper_media_device_manager.h
@@ -7,6 +7,7 @@
 
 #include <map>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/macros.h"
@@ -16,6 +17,7 @@
 #include "content/public/renderer/render_frame_observer.h"
 #include "content/public/renderer/render_frame_observer_tracker.h"
 #include "content/renderer/pepper/pepper_device_enumeration_host_helper.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
 #include "ppapi/c/pp_instance.h"
 #include "third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom.h"
 
@@ -24,6 +26,7 @@
 
 class PepperMediaDeviceManager
     : public PepperDeviceEnumerationHostHelper::Delegate,
+      public blink::mojom::MediaDevicesListener,
       public RenderFrameObserver,
       public RenderFrameObserverTracker<PepperMediaDeviceManager>,
       public base::SupportsWeakPtr<PepperMediaDeviceManager> {
@@ -35,10 +38,14 @@
   // PepperDeviceEnumerationHostHelper::Delegate implementation:
   void EnumerateDevices(PP_DeviceType_Dev type,
                         const DevicesCallback& callback) override;
-  uint32_t StartMonitoringDevices(PP_DeviceType_Dev type,
-                                  const DevicesCallback& callback) override;
+  size_t StartMonitoringDevices(PP_DeviceType_Dev type,
+                                const DevicesCallback& callback) override;
   void StopMonitoringDevices(PP_DeviceType_Dev type,
-                             uint32_t subscription_id) override;
+                             size_t subscription_id) override;
+
+  // blink::mojom::MediaDevicesListener implementation.
+  void OnDevicesChanged(MediaDeviceType type,
+                        const MediaDeviceInfoArray& device_infos) override;
 
   typedef base::Callback<void(int /* request_id */,
                               bool /* succeeded */,
@@ -83,23 +90,24 @@
                          MediaDeviceType type,
                          const std::vector<MediaDeviceInfoArray>& enumeration);
 
-  void DevicesChanged(const DevicesCallback& callback,
-                      MediaDeviceType type,
-                      const MediaDeviceInfoArray& enumeration);
-
   const mojom::MediaStreamDispatcherHostPtr& GetMediaStreamDispatcherHost();
   MediaStreamDeviceObserver* GetMediaStreamDeviceObserver() const;
   const blink::mojom::MediaDevicesDispatcherHostPtr&
   GetMediaDevicesDispatcher();
 
-  int next_id_;
-
-  typedef std::map<int, OpenDeviceCallback> OpenCallbackMap;
+  int next_id_ = 1;
+  using OpenCallbackMap = std::map<int, OpenDeviceCallback>;
   OpenCallbackMap open_callbacks_;
 
+  using Subscription = std::pair<size_t, DevicesCallback>;
+  using SubscriptionList = std::vector<Subscription>;
+  SubscriptionList device_change_subscriptions_[NUM_MEDIA_DEVICE_TYPES];
+
   mojom::MediaStreamDispatcherHostPtr dispatcher_host_;
   blink::mojom::MediaDevicesDispatcherHostPtr media_devices_dispatcher_;
 
+  mojo::BindingSet<blink::mojom::MediaDevicesListener> bindings_;
+
   DISALLOW_COPY_AND_ASSIGN(PepperMediaDeviceManager);
 };
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index f341fb4a..4ff4df9 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -117,7 +117,6 @@
 #include "content/renderer/manifest/manifest_manager.h"
 #include "content/renderer/media/audio_device_factory.h"
 #include "content/renderer/media/audio_output_ipc_factory.h"
-#include "content/renderer/media/media_devices_listener_impl.h"
 #include "content/renderer/media/media_permission_dispatcher.h"
 #include "content/renderer/media/media_stream_device_observer.h"
 #include "content/renderer/media/user_media_client_impl.h"
@@ -6633,8 +6632,6 @@
   web_user_media_client_ = new UserMediaClientImpl(
       this, RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(),
       std::make_unique<MediaStreamDeviceObserver>(this));
-  registry_.AddInterface(
-      base::Bind(&MediaDevicesListenerImpl::Create, GetRoutingID()));
 #endif
 }
 
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 0df9eb3..1dfa7eb 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -92,8 +92,6 @@
 #include "content/renderer/effective_connection_type_helper.h"
 #include "content/renderer/fileapi/file_system_dispatcher.h"
 #include "content/renderer/fileapi/webfilesystem_impl.h"
-#include "content/renderer/gpu/compositor_external_begin_frame_source.h"
-#include "content/renderer/gpu/compositor_forwarding_message_filter.h"
 #include "content/renderer/gpu/frame_swap_message_queue.h"
 #include "content/renderer/indexed_db/indexed_db_dispatcher.h"
 #include "content/renderer/input/input_event_filter.h"
@@ -1268,10 +1266,6 @@
   else
     compositor_impl_side_task_runner = base::ThreadTaskRunnerHandle::Get();
 
-  compositor_message_filter_ = new CompositorForwardingMessageFilter(
-      compositor_impl_side_task_runner.get());
-  AddFilter(compositor_message_filter_.get());
-
   RenderThreadImpl::RegisterSchemes();
 
   RenderMediaClient::Initialize();
@@ -1651,12 +1645,6 @@
   return renderer_scheduler_.get();
 }
 
-std::unique_ptr<viz::BeginFrameSource>
-RenderThreadImpl::CreateExternalBeginFrameSource(int routing_id) {
-  return std::make_unique<CompositorExternalBeginFrameSource>(
-      compositor_message_filter_.get(), sync_message_filter(), routing_id);
-}
-
 std::unique_ptr<viz::SyntheticBeginFrameSource>
 RenderThreadImpl::CreateSyntheticBeginFrameSource() {
   base::SingleThreadTaskRunner* compositor_impl_side_task_runner =
@@ -2102,14 +2090,11 @@
 
 #if defined(OS_ANDROID)
   if (sync_compositor_message_filter_) {
-    std::unique_ptr<viz::BeginFrameSource> begin_frame_source =
-        params.synthetic_begin_frame_source
-            ? std::move(params.synthetic_begin_frame_source)
-            : CreateExternalBeginFrameSource(routing_id);
     callback.Run(std::make_unique<SynchronousLayerTreeFrameSink>(
         std::move(context_provider), std::move(worker_context_provider),
         compositor_task_runner_, GetGpuMemoryBufferManager(), routing_id,
-        g_next_layer_tree_frame_sink_id++, std::move(begin_frame_source),
+        g_next_layer_tree_frame_sink_id++,
+        std::move(params.synthetic_begin_frame_source),
         sync_compositor_message_filter_.get(),
         std::move(frame_swap_message_queue)));
     return;
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 8ceb3f27..4c762f4c 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -134,7 +134,6 @@
 class BrowserPluginManager;
 class CacheStorageDispatcher;
 class CategorizedWorkerPool;
-class CompositorForwardingMessageFilter;
 class DomStorageDispatcher;
 class FileSystemDispatcher;
 class FrameSwapMessageQueue;
@@ -318,10 +317,6 @@
     return blink_platform_impl_.get();
   }
 
-  CompositorForwardingMessageFilter* compositor_message_filter() const {
-    return compositor_message_filter_.get();
-  }
-
   InputHandlerManager* input_handler_manager() const {
     return input_handler_manager_.get();
   }
@@ -630,9 +625,6 @@
   void OnSyncMemoryPressure(
       base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
 
-  std::unique_ptr<viz::BeginFrameSource> CreateExternalBeginFrameSource(
-      int routing_id);
-
   std::unique_ptr<viz::SyntheticBeginFrameSource>
   CreateSyntheticBeginFrameSource();
 
@@ -746,7 +738,6 @@
   base::CancelableCallback<void(const IPC::Message&)> main_input_callback_;
   scoped_refptr<IPC::MessageFilter> input_event_filter_;
   std::unique_ptr<InputHandlerManager> input_handler_manager_;
-  scoped_refptr<CompositorForwardingMessageFilter> compositor_message_filter_;
 
 #if defined(OS_ANDROID)
   scoped_refptr<SynchronousCompositorFilter> sync_compositor_message_filter_;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index b50da9c..a6ee8c5 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1885,29 +1885,24 @@
 
 void RenderWidget::OnSetViewportIntersection(
     const gfx::Rect& viewport_intersection) {
-  if (GetWebWidget()) {
-    DCHECK(GetWebWidget()->IsWebFrameWidget());
+  if (auto* frame_widget = GetFrameWidget()) {
     DCHECK_EQ(popup_type_, WebPopupType::kWebPopupTypeNone);
-    static_cast<WebFrameWidget*>(GetWebWidget())
-        ->SetRemoteViewportIntersection(viewport_intersection);
+    frame_widget->SetRemoteViewportIntersection(viewport_intersection);
   }
 }
 
 void RenderWidget::OnSetIsInert(bool inert) {
-  if (GetWebWidget()) {
-    DCHECK(GetWebWidget()->IsWebFrameWidget());
+  if (auto* frame_widget = GetFrameWidget()) {
     DCHECK_EQ(popup_type_, WebPopupType::kWebPopupTypeNone);
-    static_cast<WebFrameWidget*>(GetWebWidget())->SetIsInert(inert);
+    frame_widget->SetIsInert(inert);
   }
 }
 
 void RenderWidget::OnUpdateRenderThrottlingStatus(bool is_throttled,
                                                   bool subtree_throttled) {
-  if (GetWebWidget()) {
-    DCHECK(GetWebWidget()->IsWebFrameWidget());
+  if (auto* frame_widget = GetFrameWidget()) {
     DCHECK_EQ(popup_type_, WebPopupType::kWebPopupTypeNone);
-    static_cast<WebFrameWidget*>(GetWebWidget())
-        ->UpdateRenderThrottlingStatus(is_throttled, subtree_throttled);
+    frame_widget->UpdateRenderThrottlingStatus(is_throttled, subtree_throttled);
   }
 }
 
@@ -1917,14 +1912,13 @@
     const gfx::PointF& screen_point,
     WebDragOperationsMask ops,
     int key_modifiers) {
-  if (!GetWebWidget())
+  blink::WebFrameWidget* frame_widget = GetFrameWidget();
+  if (!frame_widget)
     return;
 
-  DCHECK(GetWebWidget()->IsWebFrameWidget());
-  WebDragOperation operation =
-      static_cast<WebFrameWidget*>(GetWebWidget())
-          ->DragTargetDragEnter(DropMetaDataToWebDragData(drop_meta_data),
-                                client_point, screen_point, ops, key_modifiers);
+  WebDragOperation operation = frame_widget->DragTargetDragEnter(
+      DropMetaDataToWebDragData(drop_meta_data), client_point, screen_point,
+      ops, key_modifiers);
 
   Send(new DragHostMsg_UpdateDragCursor(routing_id(), operation));
 }
@@ -1933,24 +1927,25 @@
                                         const gfx::PointF& screen_point,
                                         WebDragOperationsMask ops,
                                         int key_modifiers) {
-  if (!GetWebWidget())
+  blink::WebFrameWidget* frame_widget = GetFrameWidget();
+  if (!frame_widget)
     return;
 
-  DCHECK(GetWebWidget()->IsWebFrameWidget());
-  WebDragOperation operation =
-      static_cast<WebFrameWidget*>(GetWebWidget())
-          ->DragTargetDragOver(ConvertWindowPointToViewport(client_point),
-                               screen_point, ops, key_modifiers);
+  WebDragOperation operation = frame_widget->DragTargetDragOver(
+      ConvertWindowPointToViewport(client_point), screen_point, ops,
+      key_modifiers);
 
   Send(new DragHostMsg_UpdateDragCursor(routing_id(), operation));
 }
 
 void RenderWidget::OnDragTargetDragLeave(const gfx::PointF& client_point,
                                          const gfx::PointF& screen_point) {
-  if (!GetWebWidget())
+  blink::WebFrameWidget* frame_widget = GetFrameWidget();
+  if (!frame_widget)
     return;
-  DCHECK(GetWebWidget()->IsWebFrameWidget());
-  static_cast<WebFrameWidget*>(GetWebWidget())
+
+  frame_widget
+
       ->DragTargetDragLeave(ConvertWindowPointToViewport(client_point),
                             screen_point);
 }
@@ -1959,25 +1954,24 @@
                                     const gfx::PointF& client_point,
                                     const gfx::PointF& screen_point,
                                     int key_modifiers) {
-  if (!GetWebWidget())
+  blink::WebFrameWidget* frame_widget = GetFrameWidget();
+  if (!frame_widget)
     return;
 
-  DCHECK(GetWebWidget()->IsWebFrameWidget());
-  static_cast<WebFrameWidget*>(GetWebWidget())
-      ->DragTargetDrop(DropDataToWebDragData(drop_data),
-                       ConvertWindowPointToViewport(client_point), screen_point,
-                       key_modifiers);
+  frame_widget->DragTargetDrop(DropDataToWebDragData(drop_data),
+                               ConvertWindowPointToViewport(client_point),
+                               screen_point, key_modifiers);
 }
 
 void RenderWidget::OnDragSourceEnded(const gfx::PointF& client_point,
                                      const gfx::PointF& screen_point,
                                      WebDragOperation op) {
-  if (!GetWebWidget())
+  blink::WebFrameWidget* frame_widget = GetFrameWidget();
+  if (!frame_widget)
     return;
 
-  static_cast<WebFrameWidget*>(GetWebWidget())
-      ->DragSourceEndedAt(ConvertWindowPointToViewport(client_point),
-                          screen_point, op);
+  frame_widget->DragSourceEndedAt(ConvertWindowPointToViewport(client_point),
+                                  screen_point, op);
 }
 
 void RenderWidget::OnDragSourceSystemDragEnded() {
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 72d9fb1..82468087 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -338,36 +338,19 @@
 
 // Creates a callback which takes an |event_id|, which calls the given event's
 // callback with ABORTED status and removes it from |map|.
-template <typename MapType>
-base::OnceCallback<void(int /* event_id */)> CreateAbortCallback(MapType* map) {
+template <typename MapType, typename... Args>
+base::OnceCallback<void(int /* event_id */)> CreateAbortCallback(MapType* map,
+                                                                 Args... args) {
   return base::BindOnce(
-      [](MapType* map, base::Time dispatched_time, int event_id) {
+      [](MapType* map, Args... args, base::Time dispatched_time, int event_id) {
         auto iter = map->find(event_id);
         DCHECK(iter != map->end());
         std::move(iter->second)
             .Run(blink::mojom::ServiceWorkerEventStatus::ABORTED,
-                 dispatched_time);
+                 std::forward<Args>(args)..., dispatched_time);
         map->erase(iter);
       },
-      map, base::Time::Now());
-}
-
-// Same as CreateAbortCallback() for InstallEvent only.
-// DispatchInstallEventCallback has an additional parameter, so this is
-// separately defined.
-template <typename MapType>
-base::OnceCallback<void(int /* event_id */)> CreateInstallEventAbortCallback(
-    MapType* map) {
-  return base::BindOnce(
-      [](MapType* map, base::Time dispatched_time, int event_id) {
-        auto iter = map->find(event_id);
-        DCHECK(iter != map->end());
-        std::move(iter->second)
-            .Run(blink::mojom::ServiceWorkerEventStatus::ABORTED,
-                 false /* has_fetch_handler */, dispatched_time);
-        map->erase(iter);
-      },
-      map, base::Time::Now());
+      map, std::forward<Args>(args)..., base::Time::Now());
 }
 
 void OnResponseBlobDispatchDone(
@@ -1465,8 +1448,8 @@
   TRACE_EVENT0("ServiceWorker",
                "ServiceWorkerContextClient::DispatchInstallEvent");
 
-  int event_id = context_->timeout_timer->StartEvent(
-      CreateInstallEventAbortCallback(&context_->install_event_callbacks));
+  int event_id = context_->timeout_timer->StartEvent(CreateAbortCallback(
+      &context_->install_event_callbacks, false /* has_fetch_handler */));
   context_->install_event_callbacks.emplace(event_id, std::move(callback));
   proxy_->DispatchInstallEvent(event_id);
 }
diff --git a/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc b/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc
index eb91433..dffc3ba 100644
--- a/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc
+++ b/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc
@@ -58,9 +58,9 @@
   return nullptr;
 }
 
-std::unique_ptr<net::ProxyService>
+std::unique_ptr<net::ProxyResolutionService>
 LayoutTestURLRequestContextGetter::GetProxyService() {
-  return net::ProxyService::CreateDirect();
+  return net::ProxyResolutionService::CreateDirect();
 }
 
 }  // namespace content
diff --git a/content/shell/browser/layout_test/layout_test_url_request_context_getter.h b/content/shell/browser/layout_test/layout_test_url_request_context_getter.h
index 6f4ddd70..7df184c 100644
--- a/content/shell/browser/layout_test/layout_test_url_request_context_getter.h
+++ b/content/shell/browser/layout_test/layout_test_url_request_context_getter.h
@@ -42,7 +42,7 @@
   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::ProxyService> GetProxyService() override;
+  std::unique_ptr<net::ProxyResolutionService> GetProxyService() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LayoutTestURLRequestContextGetter);
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc
index 60cb2243..6afa9c8e 100644
--- a/content/shell/browser/shell_url_request_context_getter.cc
+++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -112,10 +112,11 @@
 
 std::unique_ptr<net::ProxyConfigService>
 ShellURLRequestContextGetter::GetProxyConfigService() {
-  return net::ProxyService::CreateSystemProxyConfigService(io_task_runner_);
+  return net::ProxyResolutionService::CreateSystemProxyConfigService(
+      io_task_runner_);
 }
 
-std::unique_ptr<net::ProxyService>
+std::unique_ptr<net::ProxyResolutionService>
 ShellURLRequestContextGetter::GetProxyService() {
   // TODO(jam): use v8 if possible, look at chrome code.
   return nullptr;
@@ -150,9 +151,10 @@
     builder.set_ct_policy_enforcer(
         base::WrapUnique(new IgnoresCTPolicyEnforcer));
 
-    std::unique_ptr<net::ProxyService> proxy_service = GetProxyService();
-    if (proxy_service) {
-      builder.set_proxy_service(std::move(proxy_service));
+    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_));
     }
diff --git a/content/shell/browser/shell_url_request_context_getter.h b/content/shell/browser/shell_url_request_context_getter.h
index 62f162a1..3b592a2 100644
--- a/content/shell/browser/shell_url_request_context_getter.h
+++ b/content/shell/browser/shell_url_request_context_getter.h
@@ -24,7 +24,7 @@
 class NetLog;
 class NetworkDelegate;
 class ProxyConfigService;
-class ProxyService;
+class ProxyResolutionService;
 class URLRequestContext;
 }
 
@@ -54,7 +54,7 @@
   ~ShellURLRequestContextGetter() override;
 
   // Used by subclasses to create their own implementation of NetworkDelegate
-  // and net::ProxyService.
+  // and net::ProxyResolutionService.
   virtual std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate();
   virtual std::unique_ptr<net::CertVerifier> GetCertVerifier();
   // GetProxyConfigService() and GetProxyService() are mutually exclusive.
@@ -64,7 +64,7 @@
   virtual std::unique_ptr<net::ProxyConfigService> GetProxyConfigService();
   // If this returns nullptr, the URLRequestContextBuilder will create the
   // service.
-  virtual std::unique_ptr<net::ProxyService> GetProxyService();
+  virtual std::unique_ptr<net::ProxyResolutionService> GetProxyService();
 
  private:
   bool ignore_certificate_errors_;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index b6283f7..a41393f 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1546,7 +1546,6 @@
     "../renderer/dom_storage/mock_leveldb_wrapper.cc",
     "../renderer/dom_storage/mock_leveldb_wrapper.h",
     "../renderer/fileapi/webfilewriter_base_unittest.cc",
-    "../renderer/gpu/compositor_forwarding_message_filter_unittest.cc",
     "../renderer/gpu/frame_swap_message_queue_unittest.cc",
     "../renderer/gpu/queue_message_swap_promise_unittest.cc",
     "../renderer/gpu/render_widget_compositor_unittest.cc",
@@ -1808,7 +1807,6 @@
       "../browser/webrtc/webrtc_internals_unittest.cc",
       "../renderer/media/gpu/rtc_video_decoder_unittest.cc",
       "../renderer/media/gpu/rtc_video_encoder_unittest.cc",
-      "../renderer/media/media_devices_event_dispatcher_unittest.cc",
       "../renderer/media/media_stream_audio_processor_unittest.cc",
       "../renderer/media/media_stream_audio_unittest.cc",
       "../renderer/media/media_stream_constraints_util_audio_unittest.cc",
diff --git a/content/test/content_test_suite.cc b/content/test/content_test_suite.cc
index 54b69fc..56d19f4 100644
--- a/content/test/content_test_suite.cc
+++ b/content/test/content_test_suite.cc
@@ -94,7 +94,7 @@
                                    false,  // ignore_gpu_blacklist
                                    false,  // disable_gpu_driver_bug_workarounds
                                    false,  // log_gpu_control_list_decisions
-                                   command_line);
+                                   command_line, nullptr);
     gpu::InProcessCommandBuffer::InitializeDefaultServiceForTesting(
         gpu_feature_info);
     gl::GLSurfaceTestSupport::InitializeNoExtensionsOneOff();
diff --git a/content/test/data/android/input/autocapitalize.html b/content/test/data/android/input/autocapitalize.html
new file mode 100644
index 0000000..6b462a6
--- /dev/null
+++ b/content/test/data/android/input/autocapitalize.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta name="viewport" content="width=device-width">
+  </head>
+  <body>
+    <input id="input_text">
+    <input id="input_autocapitalize_none" autocapitalize="none">
+    <input id="input_autocapitalize_characters" autocapitalize="characters">
+    <input id="input_autocapitalize_words" autocapitalize="words">
+    <input id="input_autocapitalize_sentences" autocapitalize="sentences">
+
+    <div id="div_autocapitalize_characters" contenteditable autocapitalize="characters">
+    </div>
+  </body>
+
+  <script>
+    var selectionChangeEventLog = "";
+    var otherEventLog = "";
+    var mutationObserver = new MutationObserver(function(mutations) {
+      mutations.forEach(function(mutation) {
+        addEventLog(mutation.type, mutation.detail);
+      });
+    })
+
+    var mutationConfig = { attributes: false, childList: false, characterData: true };
+
+    function addOtherEventLog(type, detail) {
+      if (otherEventLog.length > 0) {
+        otherEventLog += ',';
+      }
+      if (detail == null) {
+        otherEventLog += type;
+      } else {
+        otherEventLog += type + '(' + detail + ')';
+      }
+    }
+
+    function addSelectionChangeEventLog(type, detail) {
+      if (selectionChangeEventLog.length > 0) {
+        selectionChangeEventLog += ',';
+      }
+      if (detail == null) {
+        selectionChangeEventLog += type;
+      } else {
+        selectionChangeEventLog += type + '(' + detail + ')';
+      }
+    }
+
+    // selectionchange event is queued, so it races with the other events.
+    // crbug.com/628964
+    function getEventLogs() {
+      if (otherEventLog.length > 0 && selectionChangeEventLog.length > 0)
+        return otherEventLog + ',' + selectionChangeEventLog;
+      return otherEventLog + selectionChangeEventLog;
+    }
+
+    function clearEventLogs() {
+      selectionChangeEventLog = '';
+      otherEventLog = '';
+    }
+
+    function addEventListener(element, event_name) {
+      element.addEventListener(event_name, function (e) { addOtherEventLog(event_name, e.data); });
+    }
+
+    function addKeyEventListener(element, event_name) {
+      element.addEventListener(event_name, function (e) { addOtherEventLog(event_name, e.keyCode); });
+    }
+
+    function addSelectionEventListener(event_name) {
+      // Note that listeners added to the element are not effective for now.
+      document.addEventListener(event_name, function (e) { addSelectionChangeEventLog(event_name, e.data); });
+    }
+
+    function registerListenersAndObserver(element) {
+      addKeyEventListener(element, "keydown");
+      addKeyEventListener(element, "keypress");
+      addKeyEventListener(element, "keyup");
+      addEventListener(element, "compositionstart");
+      addEventListener(element, "compositionupdate");
+      addEventListener(element, "compositionend");
+      addEventListener(element, "beforeedit");
+      addEventListener(element, "edit");
+      addEventListener(element, "select");
+      addEventListener(element, "change");
+      addEventListener(element, "input");
+      mutationObserver.observe(element, mutationConfig);
+    }
+
+    var inputText = document.getElementById("input_text");
+    var contenteditableEvent = document.getElementById("contenteditable_event");
+
+    // SelectionEventListener should be outside registerListenersAndObserver() to avoid duplication.
+    addSelectionEventListener("selectionchange");
+
+    registerListenersAndObserver(inputText);
+    registerListenersAndObserver(contenteditableEvent);
+  </script>
+</html>
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn
index 3907fe2..63b6a59 100644
--- a/content/test/fuzzer/BUILD.gn
+++ b/content/test/fuzzer/BUILD.gn
@@ -22,7 +22,9 @@
     "//content/shell:content_shell_lib",
     "//content/test:test_support",
     "//gin",
+    "//tools/v8_context_snapshot",
   ]
+  configs += [ "//tools/v8_context_snapshot:use_v8_context_snapshot" ]
   testonly = true
 }
 
diff --git a/content/test/fuzzer/fuzzer_support.cc b/content/test/fuzzer/fuzzer_support.cc
index 8b8ed62..bbc3be1 100644
--- a/content/test/fuzzer/fuzzer_support.cc
+++ b/content/test/fuzzer/fuzzer_support.cc
@@ -14,6 +14,18 @@
 
 namespace content {
 
+namespace {
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
+#if defined(USE_V8_CONTEXT_SNAPSHOT)
+constexpr gin::V8Initializer::V8SnapshotFileType kSnapshotType =
+    gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext;
+#else
+constexpr gin::V8Initializer::V8SnapshotFileType kSnapshotType =
+    gin::V8Initializer::V8SnapshotFileType::kDefault;
+#endif
+#endif
+}
+
 void RenderViewTestAdapter::SetUp() {
   RenderViewTest::SetUp();
 }
@@ -27,7 +39,7 @@
   blink::WebRuntimeFeatures::EnableTestOnlyFeatures(true);
 
 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
-  gin::V8Initializer::LoadV8Snapshot();
+  gin::V8Initializer::LoadV8Snapshot(kSnapshotType);
   gin::V8Initializer::LoadV8Natives();
 #endif
   gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode,
diff --git a/content/test/proxy_service_mojo_unittest.cc b/content/test/proxy_service_mojo_unittest.cc
index 940fd2b..d055fcc 100644
--- a/content/test/proxy_service_mojo_unittest.cc
+++ b/content/test/proxy_service_mojo_unittest.cc
@@ -22,8 +22,8 @@
 #include "net/log/net_log_with_source.h"
 #include "net/log/test_net_log.h"
 #include "net/log/test_net_log_entry.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
-#include "net/proxy/mock_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
+#include "net/proxy/mock_pac_file_fetcher.h"
 #include "net/proxy/proxy_config_service_fixed.h"
 #include "net/proxy/proxy_service.h"
 #include "net/test/event_waiter.h"
@@ -85,8 +85,8 @@
 void CheckCapturedNetLogEntries(const net::TestNetLogEntry::List& entries) {
   ASSERT_GT(entries.size(), 2u);
   size_t i = 0;
-  // ProxyService records its own NetLog entries, so skip forward until the
-  // expected event type.
+  // ProxyResolutionService records its own NetLog entries, so skip forward
+  // until the expected event type.
   while (i < entries.size() &&
          entries[i].type != net::NetLogEventType::PAC_JAVASCRIPT_ALERT) {
     i++;
@@ -131,7 +131,7 @@
     mock_host_resolver_.rules()->AddRule("example.com", "1.2.3.4");
 
     fetcher_ = new net::MockProxyScriptFetcher;
-    proxy_service_ = CreateProxyServiceUsingMojoFactory(
+    proxy_resolution_service_ = CreateProxyServiceUsingMojoFactory(
         test_mojo_proxy_resolver_factory_.CreateFactoryInterface(),
         std::make_unique<net::ProxyConfigServiceFixed>(
             net::ProxyConfig::CreateFromCustomPacURL(GURL(kPacUrl))),
@@ -144,18 +144,21 @@
   content::TestMojoProxyResolverFactory test_mojo_proxy_resolver_factory_;
   TestNetworkDelegate network_delegate_;
   LoggingMockHostResolver mock_host_resolver_;
-  net::MockProxyScriptFetcher* fetcher_;  // Owned by |proxy_service_|.
+  // Owned by |proxy_resolution_service_|.
+  net::MockProxyScriptFetcher* fetcher_;
   net::TestNetLog net_log_;
-  std::unique_ptr<net::ProxyService> proxy_service_;
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service_;
 };
 
 TEST_F(ProxyServiceMojoTest, Basic) {
   net::ProxyInfo info;
   net::TestCompletionCallback callback;
   EXPECT_EQ(net::ERR_IO_PENDING,
-            proxy_service_->ResolveProxy(GURL("http://foo"), std::string(),
-                                         &info, callback.callback(), nullptr,
-                                         nullptr, net::NetLogWithSource()));
+            proxy_resolution_service_->ResolveProxy(
+                GURL("http://foo"),
+                std::string(),
+                &info, callback.callback(), nullptr,
+                nullptr, net::NetLogWithSource()));
 
   // Proxy script fetcher should have a fetch triggered by the first
   // |ResolveProxy()| request.
@@ -166,7 +169,7 @@
   EXPECT_THAT(callback.WaitForResult(), IsOk());
   EXPECT_EQ("PROXY foo:1234", info.ToPacString());
   EXPECT_EQ(0u, mock_host_resolver_.num_resolve());
-  proxy_service_.reset();
+  proxy_resolution_service_.reset();
 }
 
 TEST_F(ProxyServiceMojoTest, DnsResolution) {
@@ -174,9 +177,10 @@
   net::TestCompletionCallback callback;
   net::BoundTestNetLog test_net_log;
   EXPECT_EQ(net::ERR_IO_PENDING,
-            proxy_service_->ResolveProxy(GURL("http://foo"), std::string(),
-                                         &info, callback.callback(), nullptr,
-                                         nullptr, test_net_log.bound()));
+            proxy_resolution_service_->ResolveProxy(
+                GURL("http://foo"), std::string(),
+                &info, callback.callback(), nullptr,
+                nullptr, test_net_log.bound()));
 
   // Proxy script fetcher should have a fetch triggered by the first
   // |ResolveProxy()| request.
@@ -188,7 +192,7 @@
   EXPECT_THAT(callback.WaitForResult(), IsOk());
   EXPECT_EQ("QUIC bar:4321", info.ToPacString());
   EXPECT_EQ(1u, mock_host_resolver_.num_resolve());
-  proxy_service_.reset();
+  proxy_resolution_service_.reset();
 
   net::TestNetLogEntry::List entries;
   test_net_log.GetEntries(&entries);
@@ -206,9 +210,10 @@
   net::TestCompletionCallback callback;
   net::BoundTestNetLog test_net_log;
   EXPECT_EQ(net::ERR_IO_PENDING,
-            proxy_service_->ResolveProxy(GURL("http://foo"), std::string(),
-                                         &info, callback.callback(), nullptr,
-                                         nullptr, test_net_log.bound()));
+            proxy_resolution_service_->ResolveProxy(
+                GURL("http://foo"), std::string(),
+                &info, callback.callback(), nullptr,
+                nullptr, test_net_log.bound()));
 
   // Proxy script fetcher should have a fetch triggered by the first
   // |ResolveProxy()| request.
@@ -235,9 +240,10 @@
   net::ProxyInfo info;
   net::TestCompletionCallback callback;
   EXPECT_EQ(net::ERR_IO_PENDING,
-            proxy_service_->ResolveProxy(GURL("http://foo"), std::string(),
-                                         &info, callback.callback(), nullptr,
-                                         nullptr, net::NetLogWithSource()));
+            proxy_resolution_service_->ResolveProxy(
+                GURL("http://foo"), std::string(),
+                &info, callback.callback(), nullptr,
+                nullptr, net::NetLogWithSource()));
 
   // Proxy script fetcher should have a fetch triggered by the first
   // |ResolveProxy()| request.
diff --git a/device/test/usb_test_gadget_impl.cc b/device/test/usb_test_gadget_impl.cc
index f100f15c..f7225d65 100644
--- a/device/test/usb_test_gadget_impl.cc
+++ b/device/test/usb_test_gadget_impl.cc
@@ -152,7 +152,8 @@
   net::URLRequestContext* GetURLRequestContext() override {
     if (!context_) {
       net::URLRequestContextBuilder context_builder;
-      context_builder.set_proxy_service(net::ProxyService::CreateDirect());
+      context_builder.set_proxy_resolution_service(
+          net::ProxyResolutionService::CreateDirect());
       context_ = context_builder.Build();
     }
     return context_.get();
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
index 907dbac..23fb544 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
@@ -10,7 +10,6 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/timer/elapsed_timer.h"
 #include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
@@ -23,9 +22,6 @@
 namespace flat_rule = url_pattern_index::flat;
 
 namespace {
-void DeleteRulesetHelper(std::unique_ptr<base::MemoryMappedFile> ruleset) {
-  base::AssertBlockingAllowed();
-}
 
 using FindRuleStrategy =
     url_pattern_index::UrlPatternIndexMatcher::FindRuleStrategy;
@@ -46,16 +42,13 @@
   if (!base::PathExists(indexed_ruleset_path))
     return kLoadErrorInvalidPath;
 
-  // TODO(crbug.com/774271): Revisit mmap-ing the file.
-  auto ruleset = std::make_unique<base::MemoryMappedFile>();
-  if (!ruleset->Initialize(indexed_ruleset_path,
-                           base::MemoryMappedFile::READ_ONLY)) {
-    return kLoadErrorMemoryMap;
-  }
+  std::string ruleset_data;
+  if (!base::ReadFileToString(indexed_ruleset_path, &ruleset_data))
+    return kLoadErrorFileRead;
 
   // This guarantees that no memory access will end up outside the buffer.
-  if (!IsValidRulesetData(ruleset->data(), ruleset->length(),
-                          expected_ruleset_checksum)) {
+  if (!IsValidRulesetData(reinterpret_cast<const uint8_t*>(ruleset_data.data()),
+                          ruleset_data.size(), expected_ruleset_checksum)) {
     return kLoadErrorRulesetVerification;
   }
 
@@ -65,18 +58,11 @@
 
   // Using WrapUnique instead of make_unique since this class has a private
   // constructor.
-  *matcher = base::WrapUnique(new RulesetMatcher(std::move(ruleset)));
+  *matcher = base::WrapUnique(new RulesetMatcher(std::move(ruleset_data)));
   return kLoadSuccess;
 }
 
-RulesetMatcher::~RulesetMatcher() {
-  // |ruleset_| must be destroyed on a sequence which supports file IO.
-  // TODO(crbug.com/696822): Revisit this to ensure that this is safe and causes
-  // no resource leak even if this task fails.
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
-      base::BindOnce(&DeleteRulesetHelper, std::move(ruleset_)));
-}
+RulesetMatcher::~RulesetMatcher() = default;
 
 bool RulesetMatcher::ShouldBlockRequest(const GURL& url,
                                         const url::Origin& first_party_origin,
@@ -141,9 +127,9 @@
   return true;
 }
 
-RulesetMatcher::RulesetMatcher(std::unique_ptr<base::MemoryMappedFile> ruleset)
-    : ruleset_(std::move(ruleset)),
-      root_(flat::GetExtensionIndexedRuleset(ruleset_->data())),
+RulesetMatcher::RulesetMatcher(std::string ruleset_data)
+    : ruleset_data_(std::move(ruleset_data)),
+      root_(flat::GetExtensionIndexedRuleset(ruleset_data_.data())),
       blacklist_matcher_(root_->blacklist_index()),
       whitelist_matcher_(root_->whitelist_index()),
       redirect_matcher_(root_->redirect_index()),
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.h b/extensions/browser/api/declarative_net_request/ruleset_matcher.h
index 9c26f99..0bd6e09 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_matcher.h
+++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.h
@@ -6,8 +6,8 @@
 #define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_RULESET_MATCHER_H_
 
 #include <memory>
+#include <string>
 
-#include "base/files/memory_mapped_file.h"
 #include "components/url_pattern_index/url_pattern_index.h"
 
 namespace base {
@@ -29,11 +29,10 @@
 }  // namespace flat
 
 // RulesetMatcher encapsulates the Declarative Net Request API ruleset
-// corresponding to a single extension. The ruleset file is memory mapped. This
-// uses the url_pattern_index component to achieve fast matching of network
-// requests against declarative rules. Since this class is immutable, it is
-// thread-safe. In practice it is accessed on the IO thread but created on a
-// sequence where file IO is allowed.
+// corresponding to a single extension. This uses the url_pattern_index
+// component to achieve fast matching of network requests against declarative
+// rules. Since this class is immutable, it is thread-safe. In practice it is
+// accessed on the IO thread but created on a sequence where file IO is allowed.
 class RulesetMatcher {
  public:
   // Describes the result of creating a RulesetMatcher instance.
@@ -42,7 +41,7 @@
   enum LoadRulesetResult {
     kLoadSuccess = 0,
     kLoadErrorInvalidPath = 1,
-    kLoadErrorMemoryMap = 2,
+    kLoadErrorFileRead = 2,
     kLoadErrorRulesetVerification = 3,
     kLoadResultMax
   };
@@ -79,10 +78,9 @@
   using ExtensionMetadataList =
       flatbuffers::Vector<flatbuffers::Offset<flat::UrlRuleMetadata>>;
 
-  explicit RulesetMatcher(std::unique_ptr<base::MemoryMappedFile> ruleset_file);
+  explicit RulesetMatcher(std::string ruleset_data);
 
-  // The memory mapped ruleset file.
-  std::unique_ptr<base::MemoryMappedFile> ruleset_;
+  const std::string ruleset_data_;
 
   const flat::ExtensionIndexedRuleset* const root_;
   const UrlPatternIndexMatcher blacklist_matcher_;
diff --git a/google_apis/gcm/engine/connection_factory_impl.cc b/google_apis/gcm/engine/connection_factory_impl.cc
index 79f8f07..691012e2 100644
--- a/google_apis/gcm/engine/connection_factory_impl.cc
+++ b/google_apis/gcm/engine/connection_factory_impl.cc
@@ -79,7 +79,7 @@
   CloseSocket();
   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
   if (proxy_resolve_request_) {
-    gcm_network_session_->proxy_service()->CancelRequest(
+    gcm_network_session_->proxy_resolution_service()->CancelRequest(
         proxy_resolve_request_);
     proxy_resolve_request_ = NULL;
   }
@@ -326,7 +326,7 @@
   GURL current_endpoint = GetCurrentEndpoint();
   recorder_->RecordConnectionInitiated(current_endpoint.host());
   UpdateFromHttpNetworkSession();
-  int status = gcm_network_session_->proxy_service()->ResolveProxy(
+  int status = gcm_network_session_->proxy_resolution_service()->ResolveProxy(
       current_endpoint, std::string(), &proxy_info_,
       base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone,
                  weak_ptr_factory_.GetWeakPtr()),
@@ -548,7 +548,8 @@
         proxy_info_.proxy_server().host_port_pair());
   }
 
-  int status = gcm_network_session_->proxy_service()->ReconsiderProxyAfterError(
+  int status = gcm_network_session_->proxy_resolution_service()
+                                   ->ReconsiderProxyAfterError(
       GetCurrentEndpoint(), std::string(), error, &proxy_info_,
       base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone,
                  weak_ptr_factory_.GetWeakPtr()),
@@ -575,8 +576,9 @@
 }
 
 void ConnectionFactoryImpl::ReportSuccessfulProxyConnection() {
-  if (gcm_network_session_ && gcm_network_session_->proxy_service())
-    gcm_network_session_->proxy_service()->ReportSuccess(proxy_info_, NULL);
+  if (gcm_network_session_ && gcm_network_session_->proxy_resolution_service())
+    gcm_network_session_->proxy_resolution_service()->ReportSuccess(proxy_info_,
+        NULL);
 }
 
 void ConnectionFactoryImpl::CloseSocket() {
diff --git a/google_apis/gcm/engine/connection_factory_impl.h b/google_apis/gcm/engine/connection_factory_impl.h
index 79ed86eb..5f8bda2 100644
--- a/google_apis/gcm/engine/connection_factory_impl.h
+++ b/google_apis/gcm/engine/connection_factory_impl.h
@@ -161,7 +161,7 @@
   net::NetLogWithSource net_log_;
   // The current proxy resolution request, if one exists. Owned by the proxy
   // service.
-  net::ProxyService::Request* proxy_resolve_request_;
+  net::ProxyResolutionService::Request* proxy_resolve_request_;
   // The current proxy info.
   net::ProxyInfo proxy_info_;
   // The handle to the socket for the current connection, if one exists.
diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc
index 13dcdef..35348f6 100644
--- a/google_apis/gcm/tools/mcs_probe.cc
+++ b/google_apis/gcm/tools/mcs_probe.cc
@@ -253,7 +253,7 @@
   std::unique_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory_;
   std::unique_ptr<net::HttpServerPropertiesImpl> http_server_properties_;
   std::unique_ptr<net::HttpNetworkSession> network_session_;
-  std::unique_ptr<net::ProxyService> proxy_service_;
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service_;
 
   FakeGCMStatsRecorder recorder_;
   std::unique_ptr<GCMStore> gcm_store_;
@@ -387,7 +387,8 @@
   http_auth_handler_factory_ = net::HttpAuthHandlerRegistryFactory::Create(
       &http_auth_preferences_, host_resolver_.get());
   http_server_properties_ = std::make_unique<net::HttpServerPropertiesImpl>();
-  proxy_service_ = net::ProxyService::CreateDirectWithNetLog(&net_log_);
+  proxy_resolution_service_ =
+      net::ProxyResolutionService::CreateDirectWithNetLog(&net_log_);
 }
 
 void MCSProbe::BuildNetworkSession() {
@@ -408,7 +409,7 @@
   session_context.http_auth_handler_factory = http_auth_handler_factory_.get();
   session_context.http_server_properties = http_server_properties_.get();
   session_context.net_log = &net_log_;
-  session_context.proxy_service = proxy_service_.get();
+  session_context.proxy_resolution_service = proxy_resolution_service_.get();
 
   network_session_ = std::make_unique<net::HttpNetworkSession>(session_params,
                                                                session_context);
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc
index 39572ee..85fcd32 100644
--- a/gpu/command_buffer/client/raster_implementation_gles.cc
+++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -407,9 +407,9 @@
   // This section duplicates RasterSource::PlaybackToCanvas setup preamble.
   cc::PaintOpBufferSerializer::Preamble preamble;
   preamble.translation = translate;
-  preamble.playback_rect = playback_rect;
+  preamble.playback_rect = gfx::RectF(playback_rect);
   preamble.post_translation = post_translate;
-  preamble.post_scale = post_scale;
+  preamble.post_scale = gfx::SizeF(post_scale, post_scale);
 
   // Wrap the provided provider in a stashing provider so that we can delay
   // unrefing images until we have serialized dependent commands.
diff --git a/gpu/command_buffer/tests/gl_tests_main.cc b/gpu/command_buffer/tests/gl_tests_main.cc
index 6a985ab..e469073 100644
--- a/gpu/command_buffer/tests/gl_tests_main.cc
+++ b/gpu/command_buffer/tests/gl_tests_main.cc
@@ -31,12 +31,12 @@
   base::FeatureList::InitializeInstance(std::string(), std::string());
   gpu::GPUInfo gpu_info;
   gpu::CollectBasicGraphicsInfo(&gpu_info);
-  gpu::GLManager::g_gpu_feature_info =
-      gpu::ComputeGpuFeatureInfo(gpu_info,
-                                 false,  // ignore_gpu_blacklist
-                                 false,  // disable_gpu_driver_bug_workarounds
-                                 false,  // log_gpu_control_list_decisions
-                                 base::CommandLine::ForCurrentProcess());
+  gpu::GLManager::g_gpu_feature_info = gpu::ComputeGpuFeatureInfo(
+      gpu_info,
+      false,  // ignore_gpu_blacklist
+      false,  // disable_gpu_driver_bug_workarounds
+      false,  // log_gpu_control_list_decisions
+      base::CommandLine::ForCurrentProcess(), nullptr);
   gl::init::InitializeGLNoExtensionsOneOff();
   gl::init::SetDisabledExtensionsPlatform(
       gpu::GLManager::g_gpu_feature_info.disabled_extensions);
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
index 2d039f3..f6a1bf6c 100644
--- a/gpu/config/gpu_util.cc
+++ b/gpu/config/gpu_util.cc
@@ -330,7 +330,9 @@
                                      bool ignore_gpu_blacklist,
                                      bool disable_gpu_driver_bug_workarounds,
                                      bool log_gpu_control_list_decisions,
-                                     base::CommandLine* command_line) {
+                                     base::CommandLine* command_line,
+                                     bool* needs_more_info) {
+  DCHECK(!needs_more_info || !(*needs_more_info));
   bool use_swift_shader = false;
   bool use_swift_shader_for_webgl = false;
   if (command_line->HasSwitch(switches::kUseGL)) {
@@ -359,6 +361,9 @@
     blacklisted_features = list->MakeDecision(
         GpuControlList::kOsAny, std::string(), gpu_info, target_test_group);
     gpu_feature_info.applied_gpu_blacklist_entries = list->GetActiveEntries();
+    if (needs_more_info) {
+      *needs_more_info = list->needs_more_info();
+    }
   }
 
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_GPU_RASTERIZATION] =
diff --git a/gpu/config/gpu_util.h b/gpu/config/gpu_util.h
index b4ac30f..95e5ed4 100644
--- a/gpu/config/gpu_util.h
+++ b/gpu/config/gpu_util.h
@@ -45,7 +45,8 @@
                       bool ignore_gpu_blacklist,
                       bool disable_gpu_driver_bug_workarounds,
                       bool log_gpu_control_list_decisions,
-                      base::CommandLine* command_line);
+                      base::CommandLine* command_line,
+                      bool* needs_more_info);
 
 GPU_EXPORT void SetKeysForCrashLogging(const GPUInfo& gpu_info);
 
diff --git a/gpu/config/gpu_util_unittest.cc b/gpu/config/gpu_util_unittest.cc
index 17b3af1..0af924ad 100644
--- a/gpu/config/gpu_util_unittest.cc
+++ b/gpu/config/gpu_util_unittest.cc
@@ -85,8 +85,8 @@
   {
     base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
     GPUInfo gpu_info;
-    GpuFeatureInfo gpu_feature_info =
-        ComputeGpuFeatureInfo(gpu_info, false, false, false, &command_line);
+    GpuFeatureInfo gpu_feature_info = ComputeGpuFeatureInfo(
+        gpu_info, false, false, false, &command_line, nullptr);
     EXPECT_FALSE(gpu_feature_info.IsWorkaroundEnabled(
         USE_GPU_DRIVER_WORKAROUND_FOR_TESTING));
   }
@@ -97,8 +97,8 @@
                                        USE_GPU_DRIVER_WORKAROUND_FOR_TESTING),
                                    "1");
     GPUInfo gpu_info;
-    GpuFeatureInfo gpu_feature_info =
-        ComputeGpuFeatureInfo(gpu_info, false, false, false, &command_line);
+    GpuFeatureInfo gpu_feature_info = ComputeGpuFeatureInfo(
+        gpu_info, false, false, false, &command_line, nullptr);
     EXPECT_TRUE(gpu_feature_info.IsWorkaroundEnabled(
         USE_GPU_DRIVER_WORKAROUND_FOR_TESTING));
   }
@@ -108,8 +108,8 @@
     command_line.AppendSwitchASCII(switches::kGpuDriverBugListTestGroup, "1");
     // See gpu/config/gpu_driver_bug_list.json, test_group 1, entry 215.
     GPUInfo gpu_info;
-    GpuFeatureInfo gpu_feature_info =
-        ComputeGpuFeatureInfo(gpu_info, false, false, false, &command_line);
+    GpuFeatureInfo gpu_feature_info = ComputeGpuFeatureInfo(
+        gpu_info, false, false, false, &command_line, nullptr);
     EXPECT_TRUE(gpu_feature_info.IsWorkaroundEnabled(
         USE_GPU_DRIVER_WORKAROUND_FOR_TESTING));
   }
@@ -122,8 +122,8 @@
                                    "0");
     // See gpu/config/gpu_driver_bug_list.json, test_group 1, entry 215.
     GPUInfo gpu_info;
-    GpuFeatureInfo gpu_feature_info =
-        ComputeGpuFeatureInfo(gpu_info, false, false, false, &command_line);
+    GpuFeatureInfo gpu_feature_info = ComputeGpuFeatureInfo(
+        gpu_info, false, false, false, &command_line, nullptr);
     EXPECT_FALSE(gpu_feature_info.IsWorkaroundEnabled(
         USE_GPU_DRIVER_WORKAROUND_FOR_TESTING));
   }
diff --git a/gpu/gles2_conform_support/egl/thread_state.cc b/gpu/gles2_conform_support/egl/thread_state.cc
index 282ccd6..948f860 100644
--- a/gpu/gles2_conform_support/egl/thread_state.cc
+++ b/gpu/gles2_conform_support/egl/thread_state.cc
@@ -87,7 +87,7 @@
             false,  // ignore_gpu_blacklist
             false,  // disable_gpu_driver_bug_workarounds
             false,  // log_gpu_control_list_decisions
-            command_line);
+            command_line, nullptr);
         Context::SetPlatformGpuFeatureInfo(gpu_feature_info);
       }
 
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc
index 320be451..dcb3f91 100644
--- a/gpu/ipc/service/gpu_init.cc
+++ b/gpu/ipc/service/gpu_init.cc
@@ -110,6 +110,10 @@
     const GPUInfo* gpu_info,
     const GpuFeatureInfo* gpu_feature_info) {
   gpu_preferences_ = gpu_preferences;
+  // Blacklist decisions based on basic GPUInfo may not be final. It might
+  // need more context based GPUInfo. In such situations, switching to
+  // SwiftShader needs to wait until creating a context.
+  bool needs_more_info = false;
 #if !defined(OS_ANDROID)
   if (gpu_info) {
     gpu_info_ = *gpu_info;
@@ -138,7 +142,8 @@
     gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(
         gpu_info_, gpu_preferences.ignore_gpu_blacklist,
         gpu_preferences.disable_gpu_driver_bug_workarounds,
-        gpu_preferences.log_gpu_control_list_decisions, command_line);
+        gpu_preferences.log_gpu_control_list_decisions, command_line,
+        &needs_more_info);
   }
   if (gpu::SwitchableGPUsSupported(gpu_info_, *command_line)) {
     gpu::InitializeSwitchableGPUs(
@@ -207,7 +212,7 @@
   ui::OzonePlatform::InitializeForGPU(params);
 #endif
 
-  bool use_swiftshader = ShouldEnableSwiftShader(command_line);
+  bool use_swiftshader = ShouldEnableSwiftShader(command_line, needs_more_info);
   // Load and initialize the GL implementation and locate the GL entry points if
   // needed. This initialization may have already happened if running in the
   // browser process, for example.
@@ -238,8 +243,8 @@
     gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(
         gpu_info_, gpu_preferences.ignore_gpu_blacklist,
         gpu_preferences.disable_gpu_driver_bug_workarounds,
-        gpu_preferences.log_gpu_control_list_decisions, command_line);
-    use_swiftshader = ShouldEnableSwiftShader(command_line);
+        gpu_preferences.log_gpu_control_list_decisions, command_line, nullptr);
+    use_swiftshader = ShouldEnableSwiftShader(command_line, false);
     if (use_swiftshader) {
       gl::init::ShutdownGL(true);
       gl_initialized = gl::init::InitializeGLNoExtensionsOneOff();
@@ -307,9 +312,6 @@
       gles2::PassthroughCommandDecoderSupported();
 
   init_successful_ = true;
-#if defined(USE_OZONE)
-  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
-#endif
   return true;
 }
 
@@ -323,7 +325,6 @@
   ui::OzonePlatform::InitParams params;
   params.single_process = true;
   ui::OzonePlatform::InitializeForGPU(params);
-  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
 #endif
 
   if (gpu_info) {
@@ -336,6 +337,7 @@
     }
 #endif
   }
+  bool needs_more_info = false;
   if (gpu_feature_info) {
     gpu_feature_info_ = *gpu_feature_info;
   } else {
@@ -344,7 +346,8 @@
       gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(
           gpu_info_, gpu_preferences.ignore_gpu_blacklist,
           gpu_preferences.disable_gpu_driver_bug_workarounds,
-          gpu_preferences.log_gpu_control_list_decisions, command_line);
+          gpu_preferences.log_gpu_control_list_decisions, command_line,
+          &needs_more_info);
     }
 #endif
   }
@@ -353,7 +356,7 @@
         gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
   }
 
-  bool use_swiftshader = ShouldEnableSwiftShader(command_line);
+  bool use_swiftshader = ShouldEnableSwiftShader(command_line, needs_more_info);
   if (!gl::init::InitializeGLNoExtensionsOneOff()) {
     VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
     return;
@@ -364,8 +367,8 @@
     gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(
         gpu_info_, gpu_preferences.ignore_gpu_blacklist,
         gpu_preferences.disable_gpu_driver_bug_workarounds,
-        gpu_preferences.log_gpu_control_list_decisions, command_line);
-    use_swiftshader = ShouldEnableSwiftShader(command_line);
+        gpu_preferences.log_gpu_control_list_decisions, command_line, nullptr);
+    use_swiftshader = ShouldEnableSwiftShader(command_line, false);
     if (use_swiftshader) {
       gl::init::ShutdownGL(true);
       if (!gl::init::InitializeGLNoExtensionsOneOff()) {
@@ -387,15 +390,17 @@
   }
 }
 
-bool GpuInit::ShouldEnableSwiftShader(base::CommandLine* command_line) {
+bool GpuInit::ShouldEnableSwiftShader(base::CommandLine* command_line,
+                                      bool blacklist_needs_more_info) {
 #if BUILDFLAG(ENABLE_SWIFTSHADER)
   if (gpu_preferences_.disable_software_rasterizer)
     return false;
   // Don't overwrite user preference.
   if (command_line->HasSwitch(switches::kUseGL))
     return false;
-  if (gpu_feature_info_.status_values[GPU_FEATURE_TYPE_ACCELERATED_WEBGL] !=
-      kGpuFeatureStatusEnabled) {
+  if (!blacklist_needs_more_info &&
+      gpu_feature_info_.status_values[GPU_FEATURE_TYPE_ACCELERATED_WEBGL] !=
+          kGpuFeatureStatusEnabled) {
     command_line->AppendSwitchASCII(
         switches::kUseGL, gl::kGLImplementationSwiftShaderForWebGLName);
     return true;
diff --git a/gpu/ipc/service/gpu_init.h b/gpu/ipc/service/gpu_init.h
index ee94bed..33e7cbd 100644
--- a/gpu/ipc/service/gpu_init.h
+++ b/gpu/ipc/service/gpu_init.h
@@ -69,7 +69,8 @@
   GpuPreferences gpu_preferences_;
   bool init_successful_ = false;
 
-  bool ShouldEnableSwiftShader(base::CommandLine* command_line);
+  bool ShouldEnableSwiftShader(base::CommandLine* command_line,
+                               bool blacklist_needs_more_info);
   void AdjustInfoToSwiftShader();
   DISALLOW_COPY_AND_ASSIGN(GpuInit);
 };
diff --git a/headless/lib/browser/headless_url_request_context_getter.cc b/headless/lib/browser/headless_url_request_context_getter.cc
index 92ea5b0..92e6bd1 100644
--- a/headless/lib/browser/headless_url_request_context_getter.cc
+++ b/headless/lib/browser/headless_url_request_context_getter.cc
@@ -72,7 +72,8 @@
   // the URLRequestContextStorage on the IO thread in GetURLRequestContext().
   if (!proxy_config_) {
     proxy_config_service_ =
-        net::ProxyService::CreateSystemProxyConfigService(io_task_runner_);
+        net::ProxyResolutionService::CreateSystemProxyConfigService(
+            io_task_runner_);
   }
   base::AutoLock lock(lock_);
   headless_browser_context_->AddObserver(this);
@@ -145,7 +146,8 @@
     builder.set_data_enabled(true);
     builder.set_file_enabled(true);
     if (proxy_config_) {
-      builder.set_proxy_service(net::ProxyService::CreateFixed(*proxy_config_));
+      builder.set_proxy_resolution_service(
+          net::ProxyResolutionService::CreateFixed(*proxy_config_));
     } else {
       builder.set_proxy_config_service(std::move(proxy_config_service_));
     }
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
index c8499eb..20035c6 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
@@ -221,7 +221,7 @@
   main_context->set_http_auth_handler_factory(
       io_thread_globals->http_auth_handler_factory.get());
 
-  main_context->set_proxy_service(proxy_service());
+  main_context->set_proxy_resolution_service(proxy_resolution_service());
 
   net::ChannelIDService* channel_id_service = NULL;
 
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h
index 0803361..f3389d9f 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h
@@ -47,7 +47,7 @@
 class HttpServerProperties;
 class HttpTransactionFactory;
 class ProxyConfigService;
-class ProxyService;
+class ProxyResolutionService;
 class ReportSender;
 class SSLConfigService;
 class SystemCookieStore;
@@ -202,7 +202,9 @@
   // the channel_id_service_ member and transfers ownership to the base class.
   void set_channel_id_service(net::ChannelIDService* channel_id_service) const;
 
-  net::ProxyService* proxy_service() const { return proxy_service_.get(); }
+  net::ProxyResolutionService* proxy_resolution_service() const {
+    return proxy_resolution_service_.get();
+  }
 
   net::HttpServerProperties* http_server_properties() const;
 
@@ -285,7 +287,8 @@
   // Pointed to by URLRequestContext.
   mutable std::unique_ptr<net::ChannelIDService> channel_id_service_;
 
-  mutable std::unique_ptr<net::ProxyService> proxy_service_;
+  mutable std::unique_ptr<net::ProxyResolutionService>
+      proxy_resolution_service_;
   mutable std::unique_ptr<net::TransportSecurityState>
       transport_security_state_;
   mutable std::unique_ptr<net::CTVerifier> cert_transparency_verifier_;
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
index ad3e7e29..5eaf8c3 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
@@ -56,7 +56,7 @@
 #include "net/http/transport_security_persister.h"
 #include "net/nqe/network_quality_estimator.h"
 #include "net/proxy/proxy_config_service_fixed.h"
-#include "net/proxy/proxy_script_fetcher_impl.h"
+#include "net/proxy/pac_file_fetcher_impl.h"
 #include "net/proxy/proxy_service.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -356,7 +356,7 @@
 
   // NOTE: Proxy service uses the default io thread network delegate, not the
   // delegate just created.
-  proxy_service_ = ProxyServiceFactory::CreateProxyService(
+  proxy_resolution_service_ = ProxyServiceFactory::CreateProxyService(
       io_thread->net_log(), nullptr,
       io_thread_globals->system_network_delegate.get(),
       std::move(profile_params_->proxy_config_service),
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
index 4bd67328..1caddc60 100644
--- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
@@ -170,7 +170,7 @@
   main_context->set_host_resolver(io_thread_globals->host_resolver.get());
   main_context->set_http_auth_handler_factory(
       io_thread_globals->http_auth_handler_factory.get());
-  main_context->set_proxy_service(proxy_service());
+  main_context->set_proxy_resolution_service(proxy_resolution_service());
 
   main_context->set_cert_transparency_verifier(
       io_thread_globals->cert_transparency_verifier.get());
diff --git a/ios/components/io_thread/ios_io_thread.h b/ios/components/io_thread/ios_io_thread.h
index ef9f853..feedbbe79c 100644
--- a/ios/components/io_thread/ios_io_thread.h
+++ b/ios/components/io_thread/ios_io_thread.h
@@ -41,7 +41,7 @@
 class HttpUserAgentSettings;
 class NetworkDelegate;
 class ProxyConfigService;
-class ProxyService;
+class ProxyResolutionService;
 class SSLConfigService;
 class TransportSecurityState;
 class URLRequestContext;
@@ -113,7 +113,7 @@
     std::unique_ptr<net::HttpAuthPreferences> http_auth_preferences;
     std::unique_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory;
     std::unique_ptr<net::HttpServerProperties> http_server_properties;
-    std::unique_ptr<net::ProxyService> system_proxy_service;
+    std::unique_ptr<net::ProxyResolutionService> system_proxy_resolution_service;
     std::unique_ptr<net::HttpNetworkSession> system_http_network_session;
     std::unique_ptr<net::HttpTransactionFactory>
         system_http_transaction_factory;
diff --git a/ios/components/io_thread/ios_io_thread.mm b/ios/components/io_thread/ios_io_thread.mm
index ccc265f7..41edc3e 100644
--- a/ios/components/io_thread/ios_io_thread.mm
+++ b/ios/components/io_thread/ios_io_thread.mm
@@ -54,7 +54,7 @@
 #include "net/http/http_server_properties_impl.h"
 #include "net/log/net_log_event_type.h"
 #include "net/proxy/proxy_config_service.h"
-#include "net/proxy/proxy_script_fetcher_impl.h"
+#include "net/proxy/pac_file_fetcher_impl.h"
 #include "net/proxy/proxy_service.h"
 #include "net/socket/tcp_client_socket.h"
 #include "net/spdy/chromium/spdy_session.h"
@@ -357,7 +357,7 @@
       base::CommandLine(base::CommandLine::NO_PROGRAM),
       /*is_quic_force_disabled=*/false, quic_user_agent_id, &params_);
 
-  globals_->system_proxy_service = ProxyServiceFactory::CreateProxyService(
+  globals_->system_proxy_resolution_service = ProxyServiceFactory::CreateProxyService(
       net_log_, nullptr, globals_->system_network_delegate.get(),
       std::move(system_proxy_config_service_), true /* quick_check_enabled */);
 
@@ -437,7 +437,8 @@
   context->set_ssl_config_service(globals->ssl_config_service.get());
   context->set_http_auth_handler_factory(
       globals->http_auth_handler_factory.get());
-  context->set_proxy_service(globals->system_proxy_service.get());
+  context->set_proxy_resolution_service(
+      globals->system_proxy_resolution_service.get());
   context->set_ct_policy_enforcer(globals->ct_policy_enforcer.get());
 
   net::URLRequestJobFactoryImpl* system_job_factory =
diff --git a/ios/web/shell/shell_url_request_context_getter.mm b/ios/web/shell/shell_url_request_context_getter.mm
index ccc66f60..ef54608 100644
--- a/ios/web/shell/shell_url_request_context_getter.mm
+++ b/ios/web/shell/shell_url_request_context_getter.mm
@@ -88,8 +88,8 @@
     storage_->set_http_user_agent_settings(
         std::make_unique<net::StaticHttpUserAgentSettings>("en-us,en",
                                                            user_agent));
-    storage_->set_proxy_service(
-        net::ProxyService::CreateUsingSystemProxyResolver(
+    storage_->set_proxy_resolution_service(
+        net::ProxyResolutionService::CreateUsingSystemProxyResolver(
             std::move(proxy_config_service_), url_request_context_->net_log()));
     storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults);
     storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
@@ -130,8 +130,8 @@
     network_session_context.channel_id_service =
         url_request_context_->channel_id_service();
     network_session_context.net_log = url_request_context_->net_log();
-    network_session_context.proxy_service =
-        url_request_context_->proxy_service();
+    network_session_context.proxy_resolution_service =
+        url_request_context_->proxy_resolution_service();
     network_session_context.ssl_config_service =
         url_request_context_->ssl_config_service();
     network_session_context.http_auth_handler_factory =
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm
index c518507..c65f7210 100644
--- a/ios/web_view/internal/web_view_url_request_context_getter.mm
+++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -88,8 +88,8 @@
     storage_->set_http_user_agent_settings(
         std::make_unique<net::StaticHttpUserAgentSettings>("en-us,en",
                                                            user_agent));
-    storage_->set_proxy_service(
-        net::ProxyService::CreateUsingSystemProxyResolver(
+    storage_->set_proxy_resolution_service(
+        net::ProxyResolutionService::CreateUsingSystemProxyResolver(
             std::move(proxy_config_service_), url_request_context_->net_log()));
     storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults);
     storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
@@ -139,8 +139,8 @@
     network_session_context.channel_id_service =
         url_request_context_->channel_id_service();
     network_session_context.net_log = url_request_context_->net_log();
-    network_session_context.proxy_service =
-        url_request_context_->proxy_service();
+    network_session_context.proxy_resolution_service =
+        url_request_context_->proxy_resolution_service();
     network_session_context.ssl_config_service =
         url_request_context_->ssl_config_service();
     network_session_context.http_auth_handler_factory =
diff --git a/media/cast/sender/performance_metrics_overlay.cc b/media/cast/sender/performance_metrics_overlay.cc
index d132db0..8ef6769 100644
--- a/media/cast/sender/performance_metrics_overlay.cc
+++ b/media/cast/sender/performance_metrics_overlay.cc
@@ -252,8 +252,18 @@
     return source;  // Allocation failure: Return source frame.
   for (size_t plane = 0, num_planes = VideoFrame::NumPlanes(source->format());
        plane < num_planes; ++plane) {
-    memcpy(frame->data(plane), source->data(plane),
-           source->stride(plane) * source->rows(plane));
+    const size_t row_count = VideoFrame::Rows(plane, source->format(),
+                                              source->visible_rect().height());
+    const size_t bytes_per_row = VideoFrame::RowBytes(
+        plane, source->format(), source->visible_rect().width());
+    const uint8_t* src = source->visible_data(plane);
+    const int src_stride = source->stride(plane);
+    uint8_t* dst = frame->visible_data(plane);
+    const int dst_stride = frame->stride(plane);
+    for (size_t row = 0; row < row_count;
+         ++row, src += src_stride, dst += dst_stride) {
+      memcpy(dst, src, bytes_per_row);
+    }
   }
   frame->metadata()->MergeMetadataFrom(source->metadata());
   // Important: After all consumers are done with the frame, copy-back the
diff --git a/net/BUILD.gn b/net/BUILD.gn
index f856881..8557659 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1031,20 +1031,27 @@
       "ntlm/ntlm_client.cc",
       "ntlm/ntlm_client.h",
       "ntlm/ntlm_constants.h",
-      "proxy/dhcp_proxy_script_adapter_fetcher_win.cc",
-      "proxy/dhcp_proxy_script_adapter_fetcher_win.h",
-      "proxy/dhcp_proxy_script_fetcher.cc",
-      "proxy/dhcp_proxy_script_fetcher.h",
-      "proxy/dhcp_proxy_script_fetcher_factory.cc",
-      "proxy/dhcp_proxy_script_fetcher_factory.h",
-      "proxy/dhcp_proxy_script_fetcher_win.cc",
-      "proxy/dhcp_proxy_script_fetcher_win.h",
+      "proxy/dhcp_pac_file_adapter_fetcher_win.cc",
+      "proxy/dhcp_pac_file_adapter_fetcher_win.h",
+      "proxy/dhcp_pac_file_fetcher.cc",
+      "proxy/dhcp_pac_file_fetcher.h",
+      "proxy/dhcp_pac_file_fetcher_factory.cc",
+      "proxy/dhcp_pac_file_fetcher_factory.h",
+      "proxy/dhcp_pac_file_fetcher_win.cc",
+      "proxy/dhcp_pac_file_fetcher_win.h",
       "proxy/dhcpcsvc_init_win.cc",
       "proxy/dhcpcsvc_init_win.h",
       "proxy/multi_threaded_proxy_resolver.cc",
       "proxy/multi_threaded_proxy_resolver.h",
       "proxy/network_delegate_error_observer.cc",
       "proxy/network_delegate_error_observer.h",
+      "proxy/pac_file_data.cc",
+      "proxy/pac_file_data.h",
+      "proxy/pac_file_decider.cc",
+      "proxy/pac_file_decider.h",
+      "proxy/pac_file_fetcher.h",
+      "proxy/pac_file_fetcher_impl.cc",
+      "proxy/pac_file_fetcher_impl.h",
       "proxy/pac_js_library.h",
       "proxy/polling_proxy_config_service.cc",
       "proxy/polling_proxy_config_service.h",
@@ -1077,16 +1084,9 @@
       "proxy/proxy_resolver_factory.h",
       "proxy/proxy_resolver_mac.cc",
       "proxy/proxy_resolver_mac.h",
-      "proxy/proxy_resolver_script_data.cc",
-      "proxy/proxy_resolver_script_data.h",
       "proxy/proxy_resolver_winhttp.cc",
       "proxy/proxy_resolver_winhttp.h",
       "proxy/proxy_retry_info.h",
-      "proxy/proxy_script_decider.cc",
-      "proxy/proxy_script_decider.h",
-      "proxy/proxy_script_fetcher.h",
-      "proxy/proxy_script_fetcher_impl.cc",
-      "proxy/proxy_script_fetcher_impl.h",
       "proxy/proxy_server.cc",
       "proxy/proxy_server.h",
       "proxy/proxy_server_mac.cc",
@@ -2585,8 +2585,8 @@
     "nqe/network_quality_estimator_test_util.h",
     "proxy/mock_proxy_resolver.cc",
     "proxy/mock_proxy_resolver.h",
-    "proxy/mock_proxy_script_fetcher.cc",
-    "proxy/mock_proxy_script_fetcher.h",
+    "proxy/mock_pac_file_fetcher.cc",
+    "proxy/mock_pac_file_fetcher.h",
     "proxy/proxy_config_service_common_unittest.cc",
     "proxy/proxy_config_service_common_unittest.h",
     "socket/socket_test_util.cc",
@@ -4969,9 +4969,9 @@
     "ntlm/ntlm_client_unittest.cc",
     "ntlm/ntlm_test_data.h",
     "ntlm/ntlm_unittest.cc",
-    "proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc",
-    "proxy/dhcp_proxy_script_fetcher_factory_unittest.cc",
-    "proxy/dhcp_proxy_script_fetcher_win_unittest.cc",
+    "proxy/dhcp_pac_file_adapter_fetcher_win_unittest.cc",
+    "proxy/dhcp_pac_file_fetcher_factory_unittest.cc",
+    "proxy/dhcp_pac_file_fetcher_win_unittest.cc",
     "proxy/mojo_proxy_resolver_v8_tracing_bindings_unittest.cc",
     "proxy/multi_threaded_proxy_resolver_unittest.cc",
     "proxy/network_delegate_error_observer_unittest.cc",
@@ -4985,8 +4985,8 @@
     "proxy/proxy_resolver_v8_tracing_unittest.cc",
     "proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc",
     "proxy/proxy_resolver_v8_unittest.cc",
-    "proxy/proxy_script_decider_unittest.cc",
-    "proxy/proxy_script_fetcher_impl_unittest.cc",
+    "proxy/pac_file_decider_unittest.cc",
+    "proxy/pac_file_fetcher_impl_unittest.cc",
     "proxy/proxy_server_unittest.cc",
     "proxy/proxy_service_unittest.cc",
     "quic/chromium/bidirectional_stream_quic_impl_unittest.cc",
@@ -5587,7 +5587,7 @@
 
       # Need TestServer.
       "cert_net/cert_net_fetcher_impl_unittest.cc",
-      "proxy/proxy_script_fetcher_impl_unittest.cc",
+      "proxy/pac_file_fetcher_impl_unittest.cc",
       "socket/ssl_client_socket_unittest.cc",
       "url_request/url_fetcher_impl_unittest.cc",
       "url_request/url_request_context_builder_unittest.cc",
diff --git a/net/base/proxy_delegate.h b/net/base/proxy_delegate.h
index 356717b3..620f619 100644
--- a/net/base/proxy_delegate.h
+++ b/net/base/proxy_delegate.h
@@ -30,8 +30,8 @@
   // Called as the proxy is being resolved for |url| for a |method| request.
   // The caller may pass an empty string to get method agnostic resoulution.
   // Allows the delegate to override the proxy resolution decision made by
-  // ProxyService. The delegate may override the decision by modifying the
-  // ProxyInfo |result|.
+  // ProxyResolutionService. The delegate may override the decision by modifying
+  // the ProxyInfo |result|.
   virtual void OnResolveProxy(const GURL& url,
                               const std::string& method,
                               const ProxyRetryInfoMap& proxy_retry_info,
@@ -48,10 +48,6 @@
   // allowed to push cross-origin resources.
   virtual bool IsTrustedSpdyProxy(const ProxyServer& proxy_server) = 0;
 
-  // Notifies the ProxyDelegate that |alternative_proxy_server| is broken.
-  virtual void OnAlternativeProxyBroken(
-      const ProxyServer& alternative_proxy_server) = 0;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(ProxyDelegate);
 };
diff --git a/net/base/test_proxy_delegate.cc b/net/base/test_proxy_delegate.cc
index 66e98cb..acf5b360 100644
--- a/net/base/test_proxy_delegate.cc
+++ b/net/base/test_proxy_delegate.cc
@@ -18,7 +18,13 @@
     const std::string& method,
     const ProxyRetryInfoMap& proxy_retry_info,
     ProxyInfo* result) {
-  result->SetAlternativeProxy(alternative_proxy_server_);
+  // Only set |alternative_proxy_server_| as the alternative proxy if the
+  // ProxyService has not marked it as bad.
+  ProxyInfo alternative_proxy_info;
+  alternative_proxy_info.UseProxyServer(alternative_proxy_server_);
+  alternative_proxy_info.DeprioritizeBadProxies(proxy_retry_info);
+  if (!alternative_proxy_info.is_empty())
+    result->SetAlternativeProxy(alternative_proxy_info.proxy_server());
 }
 
 void TestProxyDelegate::OnFallback(const ProxyServer& bad_proxy,
@@ -28,11 +34,4 @@
   return proxy_server.is_valid() && trusted_spdy_proxy_ == proxy_server;
 }
 
-void TestProxyDelegate::OnAlternativeProxyBroken(
-    const ProxyServer& alternative_proxy_server) {
-  EXPECT_TRUE(alternative_proxy_server.is_valid());
-  EXPECT_EQ(alternative_proxy_server_, alternative_proxy_server);
-  alternative_proxy_server_ = ProxyServer();
-}
-
 }  // namespace net
diff --git a/net/base/test_proxy_delegate.h b/net/base/test_proxy_delegate.h
index 073e4da..06fe55c 100644
--- a/net/base/test_proxy_delegate.h
+++ b/net/base/test_proxy_delegate.h
@@ -32,8 +32,6 @@
                       ProxyInfo* result) override;
   void OnFallback(const ProxyServer& bad_proxy, int net_error) override;
   bool IsTrustedSpdyProxy(const ProxyServer& proxy_server) override;
-  void OnAlternativeProxyBroken(
-      const ProxyServer& alternative_proxy_server) override;
 
   void set_alternative_proxy_server(
       const ProxyServer& alternative_proxy_server) {
diff --git a/net/cert_net/cert_net_fetcher_impl_unittest.cc b/net/cert_net/cert_net_fetcher_impl_unittest.cc
index 1341f353a..8eec077 100644
--- a/net/cert_net/cert_net_fetcher_impl_unittest.cc
+++ b/net/cert_net/cert_net_fetcher_impl_unittest.cc
@@ -52,7 +52,7 @@
     storage_.set_cert_transparency_verifier(
         std::make_unique<MultiLogCTVerifier>());
     storage_.set_ct_policy_enforcer(std::make_unique<CTPolicyEnforcer>());
-    storage_.set_proxy_service(ProxyService::CreateFixed(no_proxy));
+    storage_.set_proxy_resolution_service(ProxyResolutionService::CreateFixed(no_proxy));
     storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
     storage_.set_http_server_properties(
         std::unique_ptr<HttpServerProperties>(new HttpServerPropertiesImpl()));
@@ -63,7 +63,7 @@
     session_context.transport_security_state = transport_security_state();
     session_context.cert_transparency_verifier = cert_transparency_verifier();
     session_context.ct_policy_enforcer = ct_policy_enforcer();
-    session_context.proxy_service = proxy_service();
+    session_context.proxy_resolution_service = proxy_resolution_service();
     session_context.ssl_config_service = ssl_config_service();
     session_context.http_server_properties = http_server_properties();
     storage_.set_http_network_session(std::make_unique<HttpNetworkSession>(
diff --git a/net/http/http_network_layer.h b/net/http/http_network_layer.h
index c46b50e..1b949badc 100644
--- a/net/http/http_network_layer.h
+++ b/net/http/http_network_layer.h
@@ -24,8 +24,8 @@
                                     public base::PowerObserver {
  public:
   // Construct a HttpNetworkLayer with an existing HttpNetworkSession which
-  // contains a valid ProxyService. The HttpNetworkLayer must be destroyed
-  // before |session|.
+  // contains a valid ProxyResolutionService. The HttpNetworkLayer must be
+  // destroyed before |session|.
   explicit HttpNetworkLayer(HttpNetworkSession* session);
   ~HttpNetworkLayer() override;
 
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
index 2e443a6..8d2a8ff 100644
--- a/net/http/http_network_layer_unittest.cc
+++ b/net/http/http_network_layer_unittest.cc
@@ -37,13 +37,14 @@
   HttpNetworkLayerTest() : ssl_config_service_(new SSLConfigServiceDefaults) {}
 
   void SetUp() override {
-    ConfigureTestDependencies(ProxyService::CreateDirect());
+    ConfigureTestDependencies(ProxyResolutionService::CreateDirect());
   }
 
-  void ConfigureTestDependencies(std::unique_ptr<ProxyService> proxy_service) {
+  void ConfigureTestDependencies(
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service) {
     cert_verifier_.reset(new MockCertVerifier);
     transport_security_state_.reset(new TransportSecurityState);
-    proxy_service_ = std::move(proxy_service);
+    proxy_resolution_service_ = std::move(proxy_resolution_service);
     HttpNetworkSession::Context session_context;
     session_context.client_socket_factory = &mock_socket_factory_;
     session_context.host_resolver = &host_resolver_;
@@ -51,7 +52,7 @@
     session_context.transport_security_state = transport_security_state_.get();
     session_context.cert_transparency_verifier = &ct_verifier_;
     session_context.ct_policy_enforcer = &ct_policy_enforcer_;
-    session_context.proxy_service = proxy_service_.get();
+    session_context.proxy_resolution_service = proxy_resolution_service_.get();
     session_context.ssl_config_service = ssl_config_service_.get();
     session_context.http_server_properties = &http_server_properties_;
     network_session_.reset(
@@ -95,7 +96,8 @@
   // These will be, in order, |bad_proxy| and |bad_proxy2|".
   void TestBadProxies(unsigned int proxy_count, const std::string& bad_proxy,
                       const std::string& bad_proxy2) {
-    const ProxyRetryInfoMap& retry_info = proxy_service_->proxy_retry_info();
+    const ProxyRetryInfoMap& retry_info =
+        proxy_resolution_service_->proxy_retry_info();
     ASSERT_EQ(proxy_count, retry_info.size());
     if (proxy_count > 0)
       ASSERT_TRUE(retry_info.find(bad_proxy) != retry_info.end());
@@ -269,7 +271,7 @@
   std::unique_ptr<TransportSecurityState> transport_security_state_;
   MultiLogCTVerifier ct_verifier_;
   CTPolicyEnforcer ct_policy_enforcer_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   const scoped_refptr<SSLConfigService> ssl_config_service_;
   std::unique_ptr<HttpNetworkSession> network_session_;
   std::unique_ptr<HttpNetworkLayer> factory_;
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 4b1fe0d..051ed32 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -154,7 +154,7 @@
       transport_security_state(nullptr),
       cert_transparency_verifier(nullptr),
       ct_policy_enforcer(nullptr),
-      proxy_service(nullptr),
+      proxy_resolution_service(nullptr),
       ssl_config_service(nullptr),
       http_auth_handler_factory(nullptr),
       net_log(nullptr),
@@ -177,7 +177,7 @@
       http_server_properties_(context.http_server_properties),
       cert_verifier_(context.cert_verifier),
       http_auth_handler_factory_(context.http_auth_handler_factory),
-      proxy_service_(context.proxy_service),
+      proxy_resolution_service_(context.proxy_resolution_service),
       ssl_config_service_(context.ssl_config_service),
       push_delegate_(nullptr),
       quic_stream_factory_(
@@ -236,7 +236,7 @@
       network_stream_throttler_(std::make_unique<NetworkThrottleManagerImpl>()),
       params_(params),
       context_(context) {
-  DCHECK(proxy_service_);
+  DCHECK(proxy_resolution_service_);
   DCHECK(ssl_config_service_.get());
   CHECK(http_server_properties_);
 
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 2a20aad3a..1bdaf82 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -59,7 +59,7 @@
 class NetworkQualityProvider;
 class NetworkThrottleManager;
 class ProxyDelegate;
-class ProxyService;
+class ProxyResolutionService;
 class QuicClock;
 class QuicCryptoClientStreamFactory;
 class SocketPerformanceWatcherFactory;
@@ -227,7 +227,7 @@
     TransportSecurityState* transport_security_state;
     CTVerifier* cert_transparency_verifier;
     CTPolicyEnforcer* ct_policy_enforcer;
-    ProxyService* proxy_service;
+    ProxyResolutionService* proxy_resolution_service;
     SSLConfigService* ssl_config_service;
     HttpAuthHandlerFactory* http_auth_handler_factory;
     HttpServerProperties* http_server_properties;
@@ -277,7 +277,9 @@
       const HostPortPair& proxy_server);
 
   CertVerifier* cert_verifier() { return cert_verifier_; }
-  ProxyService* proxy_service() { return proxy_service_; }
+  ProxyResolutionService* proxy_resolution_service() {
+      return proxy_resolution_service_;
+  }
   SSLConfigService* ssl_config_service() { return ssl_config_service_.get(); }
   SpdySessionPool* spdy_session_pool() { return &spdy_session_pool_; }
   QuicStreamFactory* quic_stream_factory() { return &quic_stream_factory_; }
@@ -357,7 +359,7 @@
   HttpAuthHandlerFactory* const http_auth_handler_factory_;
 
   // Not const since it's modified by HttpNetworkSessionPeer for testing.
-  ProxyService* proxy_service_;
+  ProxyResolutionService* proxy_resolution_service_;
   const scoped_refptr<SSLConfigService> ssl_config_service_;
 
   HttpAuthCache http_auth_cache_;
diff --git a/net/http/http_network_transaction_ssl_unittest.cc b/net/http/http_network_transaction_ssl_unittest.cc
index 76f5e8c8..ae5fa409 100644
--- a/net/http/http_network_transaction_ssl_unittest.cc
+++ b/net/http/http_network_transaction_ssl_unittest.cc
@@ -64,8 +64,9 @@
     auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory());
     session_context_.http_auth_handler_factory = auth_handler_factory_.get();
 
-    proxy_service_ = ProxyService::CreateDirect();
-    session_context_.proxy_service = proxy_service_.get();
+    proxy_resolution_service_ = ProxyResolutionService::CreateDirect();
+    session_context_.proxy_resolution_service =
+        proxy_resolution_service_.get();
 
     session_context_.client_socket_factory = &mock_socket_factory_;
     session_context_.host_resolver = &mock_resolver_;
@@ -86,7 +87,7 @@
 
   scoped_refptr<SSLConfigService> ssl_config_service_;
   std::unique_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
 
   MockClientSocketFactory mock_socket_factory_;
   MockHostResolver mock_resolver_;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index dd24ae5c..9d8e6254 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -679,6 +679,8 @@
     return last_group_name_;
   }
 
+  bool socket_requested() const { return socket_requested_; }
+
   int RequestSocket(const std::string& group_name,
                     const void* socket_params,
                     RequestPriority priority,
@@ -688,6 +690,7 @@
                     const CompletionCallback& callback,
                     const NetLogWithSource& net_log) override {
     last_group_name_ = group_name;
+    socket_requested_ = true;
     return ERR_IO_PENDING;
   }
   void CancelRequest(const std::string& group_name,
@@ -711,6 +714,7 @@
 
  private:
   std::string last_group_name_;
+  bool socket_requested_ = false;
 };
 
 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
@@ -3027,8 +3031,8 @@
   request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -3152,8 +3156,8 @@
   request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -3281,7 +3285,8 @@
     request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
 
     // Configure against proxy server "myproxy:70".
-    session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+    session_deps_.proxy_resolution_service =
+        ProxyResolutionService::CreateFixed("myproxy:70");
     BoundTestNetLog log;
     session_deps_.net_log = log.bound().net_log();
     std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -3391,7 +3396,8 @@
     request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
 
     // Configure against proxy server "myproxy:70".
-    session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+    session_deps_.proxy_resolution_service =
+        ProxyResolutionService::CreateFixed("myproxy:70");
     BoundTestNetLog log;
     session_deps_.net_log = log.bound().net_log();
     std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -3496,8 +3502,8 @@
   request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -3622,7 +3628,8 @@
   request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
   std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
 
   HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
@@ -3709,7 +3716,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
 
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
@@ -3766,7 +3774,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
 
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
@@ -3869,7 +3878,8 @@
   request.method = "GET";
   request.url = GURL("https://www.example.org/");
 
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -3929,8 +3939,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
 
   auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
   auth_handler_factory->set_do_init_from_challenge(true);
@@ -4045,8 +4055,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
 
   auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
   auth_handler_factory->set_do_init_from_challenge(true);
@@ -4166,8 +4176,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
 
   auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
   auth_handler_factory->set_do_init_from_challenge(true);
@@ -4263,8 +4273,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
 
   auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
   auth_handler_factory->set_do_init_from_challenge(true);
@@ -4555,7 +4565,7 @@
 // foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
 // request to foo.com using proxy.com as an HTTP proxy.
 TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
-  session_deps_.proxy_service = std::make_unique<ProxyService>(
+  session_deps_.proxy_resolution_service = std::make_unique<ProxyResolutionService>(
       std::make_unique<ProxyConfigServiceFixed>(
           ProxyConfig::CreateAutoDetect()),
       std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
@@ -4717,7 +4727,8 @@
   request2.url = GURL("https://www.example.org/2");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -4816,8 +4827,8 @@
   request2.url = GURL("https://www.example.org/2");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -4911,7 +4922,8 @@
   request.url = GURL("http://www.example.org/");
 
   // Configure against https proxy server "proxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -4972,7 +4984,8 @@
   request.url = GURL("http://www.example.org/");
 
   // Configure against https proxy server "proxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -5031,7 +5044,8 @@
   request.url = GURL("http://www.example.org/");
 
   // Configure SPDY proxy server "proxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -5098,7 +5112,8 @@
   request.url = GURL("http://www.example.org/");
 
   // Configure against https proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -5190,7 +5205,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against https proxy server "proxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -5272,7 +5288,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against https proxy server "proxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -5358,7 +5375,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against https proxy server "proxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -5408,7 +5426,8 @@
 TEST_F(HttpNetworkTransactionTest,
        HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
   // Configure against https proxy server "proxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(
@@ -5538,7 +5557,8 @@
 TEST_F(HttpNetworkTransactionTest,
        HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
   // Configure against https proxy server "proxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(
@@ -5659,7 +5679,8 @@
 // Proxy to different servers.
 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
   // Configure against https proxy server "proxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(
@@ -5761,7 +5782,8 @@
   request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
 
   // Configure against https proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -5855,7 +5877,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
   // Since we have proxy, should try to establish tunnel.
@@ -6069,7 +6092,8 @@
   request.url = GURL("http://www.example.org/");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
   HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
@@ -6783,7 +6807,8 @@
   request.url = GURL("https://www.example.org/");
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
 
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
@@ -8278,7 +8303,8 @@
 // Test HTTPS connections to a site with a bad certificate, going through a
 // proxy
 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
 
   HttpRequestInfo request;
   request.method = "GET";
@@ -8355,8 +8381,8 @@
 
 // Test HTTPS connections to a site, going through an HTTPS proxy
 TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS proxy:70");
   TestNetLog net_log;
   session_deps_.net_log = &net_log;
 
@@ -8418,8 +8444,8 @@
 
 // Test an HTTPS Proxy's ability to redirect a CONNECT request
 TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS proxy:70");
   TestNetLog net_log;
   session_deps_.net_log = &net_log;
 
@@ -8492,7 +8518,8 @@
 
 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
 TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
 
   HttpRequestInfo request;
   request.method = "GET";
@@ -8547,7 +8574,8 @@
 
 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
 TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
 
   HttpRequestInfo request;
   request.method = "GET";
@@ -8589,7 +8617,8 @@
 
 // Test that a SPDY proxy's response to a CONNECT request is filtered.
 TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
 
   HttpRequestInfo request;
   request.method = "GET";
@@ -8648,8 +8677,8 @@
   request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
 
   // Configure against https proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -8791,8 +8820,8 @@
   push_request.url = GURL("http://www.another-origin.com/foo.dat");
 
   // Configure against https proxy server "myproxy:443".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("HTTPS myproxy:443");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS myproxy:443");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
 
@@ -8905,8 +8934,8 @@
   request.method = "GET";
   request.url = GURL("http://www.example.org/");
 
-  session_deps_.proxy_service =
-      ProxyService::CreateFixed("https://myproxy:443");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://myproxy:443");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
 
@@ -8987,7 +9016,8 @@
   request.url = GURL("http://www.example.org/");
 
   // Configure against https proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
 
@@ -9063,7 +9093,8 @@
 // Test HTTPS connections to a site with a bad certificate, going through an
 // HTTPS proxy
 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
 
   HttpRequestInfo request;
   request.method = "GET";
@@ -9186,7 +9217,8 @@
   request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
                                   "Chromium Ultra Awesome X Edition");
 
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
   HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
 
@@ -9527,8 +9559,8 @@
   request.method = "GET";
   request.url = GURL("http://www.example.org/");
 
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("SOCKS myproxy:1080");
   TestNetLog net_log;
   session_deps_.net_log = &net_log;
 
@@ -9585,8 +9617,8 @@
   request.method = "GET";
   request.url = GURL("https://www.example.org/");
 
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("SOCKS myproxy:1080");
   TestNetLog net_log;
   session_deps_.net_log = &net_log;
 
@@ -9648,8 +9680,8 @@
   request.method = "GET";
   request.url = GURL("http://www.example.org/");
 
-  session_deps_.proxy_service =
-      ProxyService::CreateFixed("socks4://myproxy:1080");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("socks4://myproxy:1080");
   TestNetLog net_log;
   session_deps_.net_log = &net_log;
 
@@ -9705,8 +9737,8 @@
   request.method = "GET";
   request.url = GURL("http://www.example.org/");
 
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
   TestNetLog net_log;
   session_deps_.net_log = &net_log;
 
@@ -9776,8 +9808,8 @@
   request.method = "GET";
   request.url = GURL("https://www.example.org/");
 
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
   TestNetLog net_log;
   session_deps_.net_log = &net_log;
 
@@ -9926,8 +9958,8 @@
   };
 
   for (size_t i = 0; i < arraysize(tests); ++i) {
-    session_deps_.proxy_service =
-        ProxyService::CreateFixed(tests[i].proxy_server);
+    session_deps_.proxy_resolution_service =
+        ProxyResolutionService::CreateFixed(tests[i].proxy_server);
     std::unique_ptr<HttpNetworkSession> session(
         SetupSessionForGroupNameTests(&session_deps_));
 
@@ -9943,12 +9975,18 @@
 
     EXPECT_EQ(ERR_IO_PENDING,
               GroupNameTransactionHelper(tests[i].url, session.get()));
-    if (tests[i].ssl)
+    if (tests[i].ssl) {
       EXPECT_EQ(tests[i].expected_group_name,
                 ssl_conn_pool->last_group_name_received());
-    else
+    } else {
       EXPECT_EQ(tests[i].expected_group_name,
                 transport_conn_pool->last_group_name_received());
+    }
+    // When SSL proxy is in use, socket must be requested from |ssl_conn_pool|.
+    EXPECT_EQ(tests[i].ssl, ssl_conn_pool->socket_requested());
+    // When SSL proxy is not in use, socket must be requested from
+    // |transport_conn_pool|.
+    EXPECT_EQ(!tests[i].ssl, transport_conn_pool->socket_requested());
   }
 }
 
@@ -9977,8 +10015,8 @@
   };
 
   for (size_t i = 0; i < arraysize(tests); ++i) {
-    session_deps_.proxy_service =
-        ProxyService::CreateFixed(tests[i].proxy_server);
+    session_deps_.proxy_resolution_service =
+        ProxyResolutionService::CreateFixed(tests[i].proxy_server);
     std::unique_ptr<HttpNetworkSession> session(
         SetupSessionForGroupNameTests(&session_deps_));
 
@@ -10045,8 +10083,8 @@
   };
 
   for (size_t i = 0; i < arraysize(tests); ++i) {
-    session_deps_.proxy_service =
-        ProxyService::CreateFixed(tests[i].proxy_server);
+    session_deps_.proxy_resolution_service =
+        ProxyResolutionService::CreateFixed(tests[i].proxy_server);
     std::unique_ptr<HttpNetworkSession> session(
         SetupSessionForGroupNameTests(&session_deps_));
 
@@ -10082,8 +10120,8 @@
   request.method = "GET";
   request.url = GURL("http://www.example.org/");
 
-  session_deps_.proxy_service =
-      ProxyService::CreateFixed("myproxy:70;foobar:80");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70;foobar:80");
 
   // This simulates failure resolving all hostnames; that means we will fail
   // connecting to both proxies (myproxy:70 and foobar:80).
@@ -10323,7 +10361,8 @@
 
 // Test HTTPS connections going through a proxy that sends extra data.
 TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
 
   HttpRequestInfo request;
   request.method = "GET";
@@ -11861,7 +11900,7 @@
 
   TestNetLog net_log;
 
-  session_deps_.proxy_service = std::make_unique<ProxyService>(
+  session_deps_.proxy_resolution_service = std::make_unique<ProxyResolutionService>(
       std::move(proxy_config_service), std::move(proxy_resolver_factory),
       &net_log);
 
@@ -11937,7 +11976,7 @@
   proxy_config.set_pac_url(GURL("http://fooproxyurl"));
 
   CapturingProxyResolver capturing_proxy_resolver;
-  session_deps_.proxy_service = std::make_unique<ProxyService>(
+  session_deps_.proxy_resolution_service = std::make_unique<ProxyResolutionService>(
       std::make_unique<ProxyConfigServiceFixed>(proxy_config),
       std::make_unique<CapturingProxyResolverFactory>(
           &capturing_proxy_resolver),
@@ -12976,10 +13015,10 @@
                                    HttpAuth::AUTH_SERVER);
     }
     if (test_config.proxy_url) {
-      session_deps_.proxy_service =
-          ProxyService::CreateFixed(test_config.proxy_url);
+      session_deps_.proxy_resolution_service =
+          ProxyResolutionService::CreateFixed(test_config.proxy_url);
     } else {
-      session_deps_.proxy_service = ProxyService::CreateDirect();
+      session_deps_.proxy_resolution_service = ProxyResolutionService::CreateDirect();
     }
 
     HttpRequestInfo request;
@@ -13070,7 +13109,7 @@
   HttpAuthHandlerMock::Factory* auth_factory(
       new HttpAuthHandlerMock::Factory());
   session_deps_.http_auth_handler_factory.reset(auth_factory);
-  session_deps_.proxy_service = ProxyService::CreateDirect();
+  session_deps_.proxy_resolution_service = ProxyResolutionService::CreateDirect();
   session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
   session_deps_.host_resolver->set_synchronous_mode(true);
 
@@ -13457,8 +13496,8 @@
 
 // Test a basic GET request through a proxy.
 TEST_F(HttpNetworkTransactionTest, ProxyGet) {
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -13522,8 +13561,8 @@
 
 // Test a basic HTTPS GET request through a proxy.
 TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -13605,8 +13644,8 @@
 // Test a basic HTTPS GET request through a proxy, connecting to an IPv6
 // literal host.
 TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -13681,7 +13720,8 @@
 // Test a basic HTTPS GET request through a proxy, but the server hangs up
 // while establishing the tunnel.
 TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("myproxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
@@ -14043,7 +14083,8 @@
 // The test is repeated twice, first for connecting to an HTTPS endpoint,
 // then for connecting to an HTTP endpoint.
 TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
-  session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixed("https://proxy:70");
   BoundTestNetLog log;
   session_deps_.net_log = log.bound().net_log();
 
@@ -15050,8 +15091,8 @@
   MockConnect connect_data1(ASYNC, OK);
   data1.set_connect_data(connect_data1);
 
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS proxy:70");
   TestNetLog log;
   session_deps_.net_log = &log;
   SSLSocketDataProvider ssl1(ASYNC, OK);  // to the proxy
@@ -15170,7 +15211,7 @@
   // all others direct.
   ProxyConfig proxy_config;
   proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
-  session_deps_.proxy_service = std::make_unique<ProxyService>(
+  session_deps_.proxy_resolution_service = std::make_unique<ProxyResolutionService>(
       std::make_unique<ProxyConfigServiceFixed>(proxy_config), nullptr,
       nullptr);
 
@@ -16839,8 +16880,8 @@
   AddWebSocketHeaders(&request.extra_headers);
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
 
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
@@ -16943,8 +16984,8 @@
   AddWebSocketHeaders(&request.extra_headers);
 
   // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
 
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
@@ -17553,7 +17594,7 @@
   proxy_config.set_pac_url(GURL("http://fooproxyurl"));
   proxy_config.set_pac_mandatory(true);
   MockAsyncProxyResolver resolver;
-  session_deps_.proxy_service.reset(new ProxyService(
+  session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
       std::make_unique<ProxyConfigServiceFixed>(proxy_config),
       std::make_unique<FailingProxyResolverFactory>(), nullptr));
 
@@ -17579,9 +17620,9 @@
   MockAsyncProxyResolverFactory* proxy_resolver_factory =
       new MockAsyncProxyResolverFactory(false);
   MockAsyncProxyResolver resolver;
-  session_deps_.proxy_service.reset(
-      new ProxyService(std::make_unique<ProxyConfigServiceFixed>(proxy_config),
-                       base::WrapUnique(proxy_resolver_factory), nullptr));
+  session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
+      std::make_unique<ProxyConfigServiceFixed>(proxy_config),
+      base::WrapUnique(proxy_resolver_factory), nullptr));
   HttpRequestInfo request;
   request.method = "GET";
   request.url = GURL("http://www.example.org/");
@@ -17600,8 +17641,8 @@
 }
 
 TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("QUIC myproxy.org:443");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("QUIC myproxy.org:443");
   session_deps_.enable_quic = false;
   std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc
index 766e35b..1e3ec46 100644
--- a/net/http/http_proxy_client_socket_pool.cc
+++ b/net/http/http_proxy_client_socket_pool.cc
@@ -102,6 +102,9 @@
   DCHECK(quic_version_ == QUIC_VERSION_UNSUPPORTED
              ? (bool)transport_params != (bool)ssl_params
              : !transport_params && ssl_params);
+  // Exactly one of |transport_params_| and |ssl_params_| must be non-null.
+  DCHECK(transport_params_ || ssl_params_);
+  DCHECK(!transport_params_ || !ssl_params_);
 }
 
 const HostResolver::RequestInfo& HttpProxySocketParams::destination() const {
@@ -200,13 +203,16 @@
     : transport_pool_(transport_pool),
       ssl_pool_(ssl_pool),
       network_quality_provider_(network_quality_provider),
-      transport_rtt_multiplier_(GetInt32Param("transport_rtt_multiplier", 5)),
+      ssl_http_rtt_multiplier_(GetInt32Param("ssl_http_rtt_multiplier", 5)),
+      non_ssl_http_rtt_multiplier_(
+          GetInt32Param("non_ssl_http_rtt_multiplier", 5)),
       min_proxy_connection_timeout_(base::TimeDelta::FromSeconds(
           GetInt32Param("min_proxy_connection_timeout_seconds", 8))),
       max_proxy_connection_timeout_(base::TimeDelta::FromSeconds(
           GetInt32Param("max_proxy_connection_timeout_seconds", 60))),
       net_log_(net_log) {
-  DCHECK_LT(0, transport_rtt_multiplier_);
+  DCHECK_LT(0, ssl_http_rtt_multiplier_);
+  DCHECK_LT(0, non_ssl_http_rtt_multiplier_);
   DCHECK_LE(base::TimeDelta(), min_proxy_connection_timeout_);
   DCHECK_LE(base::TimeDelta(), max_proxy_connection_timeout_);
   DCHECK_LE(min_proxy_connection_timeout_, max_proxy_connection_timeout_);
@@ -217,23 +223,35 @@
     const std::string& group_name,
     const PoolBase::Request& request,
     ConnectJob::Delegate* delegate) const {
+  bool is_secure_connection = (request.params()->ssl_params() != nullptr);
+
   return std::unique_ptr<ConnectJob>(new HttpProxyConnectJob(
       group_name, request.priority(), request.socket_tag(),
-      request.respect_limits(), request.params(), ConnectionTimeout(),
+      request.respect_limits(), request.params(),
+      ConnectionTimeoutWithConnectionProperty(is_secure_connection),
       transport_pool_, ssl_pool_, delegate, net_log_));
 }
 
 base::TimeDelta
 HttpProxyClientSocketPool::HttpProxyConnectJobFactory::ConnectionTimeout()
     const {
+  // Take a conservative approach: Return the timeout for the secure proxies
+  // which is higher than the connection timeout for the insecure proxies.
+  return ConnectionTimeoutWithConnectionProperty(
+      true /* is_secure_connection */);
+}
+
+base::TimeDelta HttpProxyClientSocketPool::HttpProxyConnectJobFactory::
+    ConnectionTimeoutWithConnectionProperty(bool is_secure_connection) const {
   if (IsInNetAdaptiveProxyConnectionTimeoutFieldTrial() &&
       network_quality_provider_) {
-    base::Optional<base::TimeDelta> transport_rtt_estimate =
-        network_quality_provider_->GetTransportRTT();
-    if (transport_rtt_estimate) {
-      base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(
-          transport_rtt_multiplier_ *
-          transport_rtt_estimate.value().InMilliseconds());
+    base::Optional<base::TimeDelta> http_rtt_estimate =
+        network_quality_provider_->GetHttpRTT();
+    if (http_rtt_estimate) {
+      int32_t multiplier = is_secure_connection ? ssl_http_rtt_multiplier_
+                                                : non_ssl_http_rtt_multiplier_;
+      base::TimeDelta timeout = base::TimeDelta::FromMicroseconds(
+          multiplier * http_rtt_estimate.value().InMicroseconds());
       // Ensure that connection timeout is between
       // |min_proxy_connection_timeout_| and |max_proxy_connection_timeout_|.
       if (timeout < min_proxy_connection_timeout_)
diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h
index e4bf434..09fa48d 100644
--- a/net/http/http_proxy_client_socket_pool.h
+++ b/net/http/http_proxy_client_socket_pool.h
@@ -213,9 +213,13 @@
   bool CloseOneIdleConnection() override;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(HttpProxyClientSocketPoolTest,
+                           ProxyPoolTimeoutWithConnectionProperty);
+
   typedef ClientSocketPoolBase<HttpProxySocketParams> PoolBase;
 
-  class HttpProxyConnectJobFactory : public PoolBase::ConnectJobFactory {
+  class NET_EXPORT_PRIVATE HttpProxyConnectJobFactory
+      : public PoolBase::ConnectJobFactory {
    public:
     HttpProxyConnectJobFactory(TransportClientSocketPool* transport_pool,
                                SSLClientSocketPool* ssl_pool,
@@ -231,12 +235,30 @@
     base::TimeDelta ConnectionTimeout() const override;
 
    private:
+    FRIEND_TEST_ALL_PREFIXES(HttpProxyClientSocketPoolTest,
+                             ProxyPoolTimeoutWithConnectionProperty);
+
+    // Returns proxy connection timeout for secure proxies if
+    // |is_secure_connection| is true. Otherwise, returns timeout for insecure
+    // proxies.
+    base::TimeDelta ConnectionTimeoutWithConnectionProperty(
+        bool is_secure_connection) const;
+
     TransportClientSocketPool* const transport_pool_;
     SSLClientSocketPool* const ssl_pool_;
-    NetworkQualityProvider* network_quality_provider_;
-    const int32_t transport_rtt_multiplier_;
+    NetworkQualityProvider* const network_quality_provider_;
+
+    // For secure proxies, the connection timeout is set to
+    // |ssl_http_rtt_multiplier_| times the HTTP RTT estimate. For insecure
+    // proxies, the connection timeout is set to |non_ssl_http_rtt_multiplier_|
+    // times the HTTP RTT estimate. In either case, the connection timeout
+    // is clamped to be between |min_proxy_connection_timeout_| and
+    // |max_proxy_connection_timeout_|.
+    const int32_t ssl_http_rtt_multiplier_;
+    const int32_t non_ssl_http_rtt_multiplier_;
     const base::TimeDelta min_proxy_connection_timeout_;
     const base::TimeDelta max_proxy_connection_timeout_;
+
     NetLog* net_log_;
 
     DISALLOW_COPY_AND_ASSIGN(HttpProxyConnectJobFactory);
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 90069d8e..c3c48369 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -98,7 +98,8 @@
   // connection timeout based on the network quality.
   void InitAdaptiveTimeoutFieldTrialWithParams(
       bool use_default_params,
-      int transport_rtt_multiplier,
+      int ssl_http_rtt_multiplier,
+      int non_ssl_http_rtt_multiplier,
       base::TimeDelta min_proxy_connection_timeout,
       base::TimeDelta max_proxy_connection_timeout) {
     std::string trial_name = "NetAdaptiveProxyConnectionTimeout";
@@ -106,8 +107,10 @@
 
     std::map<std::string, std::string> params;
     if (!use_default_params) {
-      params["transport_rtt_multiplier"] =
-          base::IntToString(transport_rtt_multiplier);
+      params["ssl_http_rtt_multiplier"] =
+          base::IntToString(ssl_http_rtt_multiplier);
+      params["non_ssl_http_rtt_multiplier"] =
+          base::IntToString(non_ssl_http_rtt_multiplier);
       params["min_proxy_connection_timeout_seconds"] =
           base::IntToString(min_proxy_connection_timeout.InSeconds());
       params["max_proxy_connection_timeout_seconds"] =
@@ -227,6 +230,11 @@
 
   TestNetworkQualityEstimator* estimator() { return &estimator_; }
 
+  MockTransportClientSocketPool* transport_socket_pool() {
+    return &transport_socket_pool_;
+  }
+  SSLClientSocketPool* ssl_socket_pool() { return &ssl_socket_pool_; }
+
  private:
   MockTaggingClientSocketFactory socket_factory_;
   SpdySessionDependencies session_deps_;
@@ -757,101 +765,116 @@
 // Tests the connection timeout values when the field trial parameters are
 // specified.
 TEST_P(HttpProxyClientSocketPoolTest, ProxyPoolTimeoutWithExperiment) {
-  int transport_rtt_multiplier = 2;
-  base::TimeDelta min_timeout = base::TimeDelta::FromSeconds(8);
-  base::TimeDelta max_timeout = base::TimeDelta::FromSeconds(20);
+  // Timeout should be kMultiplier times the HTTP RTT estimate.
+  const int kMultiplier = 4;
+  const base::TimeDelta kMinTimeout = base::TimeDelta::FromSeconds(8);
+  const base::TimeDelta kMaxTimeout = base::TimeDelta::FromSeconds(20);
 
-  InitAdaptiveTimeoutFieldTrialWithParams(false, transport_rtt_multiplier,
-                                          min_timeout, max_timeout);
+  InitAdaptiveTimeoutFieldTrialWithParams(false, kMultiplier, kMultiplier,
+                                          kMinTimeout, kMaxTimeout);
   EXPECT_LE(base::TimeDelta(), pool_->ConnectionTimeout());
 
-  // Timeout should be |transport_rtt_multiplier| times the transport RTT
-  // estimate.
-  base::TimeDelta rtt_estimate = base::TimeDelta::FromSeconds(7);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  EXPECT_EQ(rtt_estimate + rtt_estimate, pool_->ConnectionTimeout());
+  base::TimeDelta rtt_estimate = base::TimeDelta::FromSeconds(4);
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
+  base::TimeDelta expected_connection_timeout = kMultiplier * rtt_estimate;
+  EXPECT_EQ(expected_connection_timeout, pool_->ConnectionTimeout());
 
-  // A change in RTT estimate should also change the connection timeout.
-  rtt_estimate = base::TimeDelta::FromSeconds(8);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  EXPECT_EQ(rtt_estimate + rtt_estimate, pool_->ConnectionTimeout());
-
-  // Connection timeout should not exceed |max_timeout|.
+  // Connection timeout should not exceed kMaxTimeout.
   rtt_estimate = base::TimeDelta::FromSeconds(25);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  EXPECT_EQ(max_timeout, pool_->ConnectionTimeout());
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
+  EXPECT_EQ(kMaxTimeout, pool_->ConnectionTimeout());
 
-  // Connection timeout should not be less than |min_timeout|.
+  // Connection timeout should not be less than kMinTimeout.
   rtt_estimate = base::TimeDelta::FromSeconds(0);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  EXPECT_EQ(min_timeout, pool_->ConnectionTimeout());
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
+  EXPECT_EQ(kMinTimeout, pool_->ConnectionTimeout());
 }
 
 // Tests the connection timeout values when the field trial parameters are
 // specified.
 TEST_P(HttpProxyClientSocketPoolTest,
        ProxyPoolTimeoutWithExperimentDifferentParams) {
-  int transport_rtt_multiplier = 3;
-  base::TimeDelta min_timeout = base::TimeDelta::FromSeconds(2);
-  base::TimeDelta max_timeout = base::TimeDelta::FromSeconds(30);
+  // Timeout should be kMultiplier times the HTTP RTT estimate.
+  const int kMultiplier = 3;
+  const base::TimeDelta kMinTimeout = base::TimeDelta::FromSeconds(2);
+  const base::TimeDelta kMaxTimeout = base::TimeDelta::FromSeconds(30);
 
-  InitAdaptiveTimeoutFieldTrialWithParams(false, transport_rtt_multiplier,
-                                          min_timeout, max_timeout);
+  InitAdaptiveTimeoutFieldTrialWithParams(false, kMultiplier, kMultiplier,
+                                          kMinTimeout, kMaxTimeout);
   EXPECT_LE(base::TimeDelta(), pool_->ConnectionTimeout());
 
-  // Timeout should be |transport_rtt_multiplier| times the transport RTT
-  // estimate.
   base::TimeDelta rtt_estimate = base::TimeDelta::FromSeconds(2);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  EXPECT_EQ(rtt_estimate + rtt_estimate + rtt_estimate,
-            pool_->ConnectionTimeout());
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
+  EXPECT_EQ(kMultiplier * rtt_estimate, pool_->ConnectionTimeout());
 
   // A change in RTT estimate should also change the connection timeout.
   rtt_estimate = base::TimeDelta::FromSeconds(7);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  EXPECT_EQ(rtt_estimate + rtt_estimate + rtt_estimate,
-            pool_->ConnectionTimeout());
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
+  EXPECT_EQ(kMultiplier * rtt_estimate, pool_->ConnectionTimeout());
 
-  // Connection timeout should not exceed |max_timeout|.
+  // Connection timeout should not exceed kMaxTimeout.
   rtt_estimate = base::TimeDelta::FromSeconds(35);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  EXPECT_EQ(max_timeout, pool_->ConnectionTimeout());
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
+  EXPECT_EQ(kMaxTimeout, pool_->ConnectionTimeout());
 
-  // Connection timeout should not be less than |min_timeout|.
+  // Connection timeout should not be less than kMinTimeout.
   rtt_estimate = base::TimeDelta::FromSeconds(0);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  EXPECT_EQ(min_timeout, pool_->ConnectionTimeout());
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
+  EXPECT_EQ(kMinTimeout, pool_->ConnectionTimeout());
+}
+
+TEST_P(HttpProxyClientSocketPoolTest, ProxyPoolTimeoutWithConnectionProperty) {
+  const int kSecureMultiplier = 3;
+  const int kNonSecureMultiplier = 5;
+  const base::TimeDelta kMinTimeout = base::TimeDelta::FromSeconds(2);
+  const base::TimeDelta kMaxTimeout = base::TimeDelta::FromSeconds(30);
+
+  InitAdaptiveTimeoutFieldTrialWithParams(
+      false, kSecureMultiplier, kNonSecureMultiplier, kMinTimeout, kMaxTimeout);
+
+  HttpProxyClientSocketPool::HttpProxyConnectJobFactory job_factory(
+      transport_socket_pool(), ssl_socket_pool(), estimator(), nullptr);
+
+  const base::TimeDelta kRttEstimate = base::TimeDelta::FromSeconds(2);
+  estimator()->SetStartTimeNullHttpRtt(kRttEstimate);
+  // By default, connection timeout should return the timeout for secure
+  // proxies.
+  EXPECT_EQ(kSecureMultiplier * kRttEstimate, job_factory.ConnectionTimeout());
+  EXPECT_EQ(kSecureMultiplier * kRttEstimate,
+            job_factory.ConnectionTimeoutWithConnectionProperty(true));
+  EXPECT_EQ(kNonSecureMultiplier * kRttEstimate,
+            job_factory.ConnectionTimeoutWithConnectionProperty(false));
 }
 
 // Tests the connection timeout values when the field trial parameters are not
 // specified.
 TEST_P(HttpProxyClientSocketPoolTest,
        ProxyPoolTimeoutWithExperimentDefaultParams) {
-  InitAdaptiveTimeoutFieldTrialWithParams(true, 0, base::TimeDelta(),
+  InitAdaptiveTimeoutFieldTrialWithParams(true, 0, 0, base::TimeDelta(),
                                           base::TimeDelta());
   EXPECT_LE(base::TimeDelta(), pool_->ConnectionTimeout());
 
-  // Timeout should be |transport_rtt_multiplier| times the transport RTT
+  // Timeout should be |http_rtt_multiplier| times the HTTP RTT
   // estimate.
   base::TimeDelta rtt_estimate = base::TimeDelta::FromMilliseconds(10);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  // Connection timeout should not be less than the transport RTT estimate.
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
+  // Connection timeout should not be less than the HTTP RTT estimate.
   EXPECT_LE(rtt_estimate, pool_->ConnectionTimeout());
 
   // A change in RTT estimate should also change the connection timeout.
   rtt_estimate = base::TimeDelta::FromSeconds(10);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
-  // Connection timeout should not be less than the transport RTT estimate.
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
+  // Connection timeout should not be less than the HTTP RTT estimate.
   EXPECT_LE(rtt_estimate, pool_->ConnectionTimeout());
 
   // Set RTT to a very large value.
   rtt_estimate = base::TimeDelta::FromMinutes(60);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
   EXPECT_GT(rtt_estimate, pool_->ConnectionTimeout());
 
   // Set RTT to a very small value.
   rtt_estimate = base::TimeDelta::FromSeconds(0);
-  estimator()->SetStartTimeNullTransportRtt(rtt_estimate);
+  estimator()->SetStartTimeNullHttpRtt(rtt_estimate);
   EXPECT_LT(rtt_estimate, pool_->ConnectionTimeout());
 }
 
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index c3a0fafa..0f89998f 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -237,7 +237,7 @@
 class HttpResponseBodyDrainerTest : public testing::Test {
  protected:
   HttpResponseBodyDrainerTest()
-      : proxy_service_(ProxyService::CreateDirect()),
+      : proxy_resolution_service_(ProxyResolutionService::CreateDirect()),
         ssl_config_service_(new SSLConfigServiceDefaults),
         http_server_properties_(new HttpServerPropertiesImpl()),
         session_(CreateNetworkSession()),
@@ -248,7 +248,7 @@
 
   HttpNetworkSession* CreateNetworkSession() {
     HttpNetworkSession::Context context;
-    context.proxy_service = proxy_service_.get();
+    context.proxy_resolution_service = proxy_resolution_service_.get();
     context.ssl_config_service = ssl_config_service_.get();
     context.http_server_properties = http_server_properties_.get();
     context.cert_verifier = &cert_verifier_;
@@ -258,7 +258,7 @@
     return new HttpNetworkSession(HttpNetworkSession::Params(), context);
   }
 
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   scoped_refptr<SSLConfigService> ssl_config_service_;
   std::unique_ptr<HttpServerPropertiesImpl> http_server_properties_;
   MockCertVerifier cert_verifier_;
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index d7f9acc..661fabc 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -1269,8 +1269,9 @@
   if (result < 0)
     return result;
 
-  session_->proxy_service()->ReportSuccess(proxy_info_,
-                                           session_->context().proxy_delegate);
+  session_->proxy_resolution_service()->ReportSuccess(
+      proxy_info_,
+      session_->context().proxy_delegate);
   next_state_ = STATE_NONE;
   return OK;
 }
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h
index cef6090..d02070e3 100644
--- a/net/http/http_stream_factory_impl_job.h
+++ b/net/http/http_stream_factory_impl_job.h
@@ -172,11 +172,11 @@
   // HttpNetworkSession::Params::origins_to_force_quic_on.
   //
   // If |alternative_proxy_server| is a valid proxy server, then the Job will
-  // use that instead of using ProxyService for proxy resolution.  Further, if
-  // |alternative_proxy_server| is a valid but bad proxy, then fallback proxies
-  // are not used. It is illegal to call this constructor with a valid
-  // |alternative_proxy_server| and an |alternate_protocol| different from
-  // kProtoUnknown.
+  // use that instead of using ProxyResolutionService for proxy resolution.
+  // Further, if |alternative_proxy_server| is a valid but bad proxy, then
+  // fallback proxies are not used. It is illegal to call this constructor with
+  // a valid |alternative_proxy_server| and an |alternate_protocol| different
+  // from kProtoUnknown.
   Job(Delegate* delegate,
       JobType job_type,
       HttpNetworkSession* session,
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc
index 0722a63..14f1c85c 100644
--- a/net/http/http_stream_factory_impl_job_controller.cc
+++ b/net/http/http_stream_factory_impl_job_controller.cc
@@ -15,7 +15,6 @@
 #include "base/trace_event/memory_usage_estimator.h"
 #include "base/values.h"
 #include "net/base/host_mapping_rules.h"
-#include "net/base/proxy_delegate.h"
 #include "net/http/bidirectional_stream_impl.h"
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log_capture_mode.h"
@@ -110,7 +109,7 @@
   bound_job_ = nullptr;
   if (proxy_resolve_request_) {
     DCHECK_EQ(STATE_RESOLVE_PROXY_COMPLETE, next_state_);
-    session_->proxy_service()->CancelRequest(proxy_resolve_request_);
+    session_->proxy_resolution_service()->CancelRequest(proxy_resolve_request_);
   }
   net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER);
 }
@@ -159,7 +158,8 @@
 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const {
   DCHECK(request_);
   if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE)
-    return session_->proxy_service()->GetLoadState(proxy_resolve_request_);
+    return session_->proxy_resolution_service()
+                   ->GetLoadState(proxy_resolve_request_);
   if (bound_job_)
     return bound_job_->GetLoadState();
   if (main_job_)
@@ -750,7 +750,7 @@
   HostPortPair destination(HostPortPair::FromURL(request_info_.url));
   GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
 
-  return session_->proxy_service()->ResolveProxy(
+  return session_->proxy_resolution_service()->ResolveProxy(
       origin_url, request_info_.method, &proxy_info_, io_callback_,
       &proxy_resolve_request_, session_->context().proxy_delegate, net_log_);
 }
@@ -852,18 +852,16 @@
     main_job_is_blocked_ = true;
     alternative_job_->Start(request_->stream_type());
   } else {
-    ProxyServer alternative_proxy_server;
+    ProxyInfo alternative_proxy_info;
     if (ShouldCreateAlternativeProxyServerJob(proxy_info_, request_info_.url,
-                                              &alternative_proxy_server)) {
+                                              &alternative_proxy_info)) {
       DCHECK(!main_job_is_blocked_);
-      ProxyInfo alternative_proxy_info;
-      alternative_proxy_info.UseProxyServer(alternative_proxy_server);
 
       alternative_job_ = job_factory_->CreateAltProxyJob(
           this, ALTERNATIVE, session_, request_info_, priority_,
           alternative_proxy_info, server_ssl_config_, proxy_ssl_config_,
-          destination, origin_url, alternative_proxy_server, is_websocket_,
-          enable_ip_based_pooling_, net_log_.net_log());
+          destination, origin_url, alternative_proxy_info.proxy_server(),
+          is_websocket_, enable_ip_based_pooling_, net_log_.net_log());
 
       can_start_alternative_proxy_job_ = false;
       main_job_is_blocked_ = true;
@@ -974,13 +972,18 @@
   DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE);
   DCHECK_NE(OK, net_error);
   DCHECK(alternative_job_->alternative_proxy_server().is_valid());
+  DCHECK(alternative_job_->alternative_proxy_server() ==
+         alternative_job_->proxy_info().proxy_server());
+
+  base::UmaHistogramSparse("Net.AlternativeProxyFailed", -net_error);
 
   // Need to mark alt proxy as broken regardless of whether the job is bound.
-  ProxyDelegate* proxy_delegate = session_->context().proxy_delegate;
-  if (proxy_delegate && net_error != ERR_NETWORK_CHANGED &&
+  // The proxy will be marked bad until the proxy retry information is cleared
+  // by an event such as a network change.
+  if (net_error != ERR_NETWORK_CHANGED &&
       net_error != ERR_INTERNET_DISCONNECTED) {
-    proxy_delegate->OnAlternativeProxyBroken(
-        alternative_job_->alternative_proxy_server());
+    session_->proxy_resolution_service()->MarkProxiesAsBadUntil(
+        alternative_job_->proxy_info(), base::TimeDelta::Max(), {}, net_log_);
   }
 }
 
@@ -1195,8 +1198,8 @@
     ShouldCreateAlternativeProxyServerJob(
         const ProxyInfo& proxy_info,
         const GURL& url,
-        ProxyServer* alternative_proxy_server) const {
-  DCHECK(!alternative_proxy_server->is_valid());
+        ProxyInfo* alternative_proxy_info) const {
+  DCHECK(alternative_proxy_info->is_empty());
 
   if (!enable_alternative_services_)
     return false;
@@ -1220,19 +1223,19 @@
     return false;
   }
 
-  *alternative_proxy_server = proxy_info.alternative_proxy();
-  if (!alternative_proxy_server->is_valid())
+  alternative_proxy_info->UseProxyServer(proxy_info.alternative_proxy());
+  if (alternative_proxy_info->is_empty())
     return false;
 
-  DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server()));
+  DCHECK(alternative_proxy_info->proxy_server() != proxy_info.proxy_server());
 
-  if (!alternative_proxy_server->is_https() &&
-      !alternative_proxy_server->is_quic()) {
+  if (!alternative_proxy_info->is_https() &&
+      !alternative_proxy_info->is_quic()) {
     // Alternative proxy server should be a secure server.
     return false;
   }
 
-  if (alternative_proxy_server->is_quic()) {
+  if (alternative_proxy_info->is_quic()) {
     // Check that QUIC is enabled globally.
     if (!session_->IsQuicEnabled())
       return false;
@@ -1296,7 +1299,7 @@
   HostPortPair destination(HostPortPair::FromURL(request_info_.url));
   GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
 
-  int rv = session_->proxy_service()->ReconsiderProxyAfterError(
+  int rv = session_->proxy_resolution_service()->ReconsiderProxyAfterError(
       origin_url, request_info_.method, error, &proxy_info_, io_callback_,
       &proxy_resolve_request_, session_->context().proxy_delegate, net_log_);
   if (rv == OK || rv == ERR_IO_PENDING) {
diff --git a/net/http/http_stream_factory_impl_job_controller.h b/net/http/http_stream_factory_impl_job_controller.h
index 48d5cc6..bba5c903 100644
--- a/net/http/http_stream_factory_impl_job_controller.h
+++ b/net/http/http_stream_factory_impl_job_controller.h
@@ -285,13 +285,13 @@
   void RemoveRequestFromSpdySessionRequestMap();
 
   // Returns true if the |request_| can be fetched via an alternative
-  // proxy server, and sets |alternative_proxy_server| to the available
-  // alternative proxy server. |alternative_proxy_server| should not be null,
+  // proxy server, and sets |alternative_proxy_info| to the alternative proxy
+  // server configuration. |alternative_proxy_info| should not be null,
   // and is owned by the caller.
   bool ShouldCreateAlternativeProxyServerJob(
       const ProxyInfo& proxy_info_,
       const GURL& url,
-      ProxyServer* alternative_proxy_server) const;
+      ProxyInfo* alternative_proxy_info) const;
 
   // Records histogram metrics for the usage of alternative protocol. Must be
   // called when |job| has succeeded and the other job will be orphaned.
@@ -371,7 +371,7 @@
   bool can_start_alternative_proxy_job_;
 
   State next_state_;
-  ProxyService::Request* proxy_resolve_request_;
+  ProxyResolutionService::Request* proxy_resolve_request_;
   CompletionCallback io_callback_;
   const HttpRequestInfo request_info_;
   ProxyInfo proxy_info_;
diff --git a/net/http/http_stream_factory_impl_job_controller_unittest.cc b/net/http/http_stream_factory_impl_job_controller_unittest.cc
index 48bfe8c..8a1b549f 100644
--- a/net/http/http_stream_factory_impl_job_controller_unittest.cc
+++ b/net/http/http_stream_factory_impl_job_controller_unittest.cc
@@ -47,7 +47,12 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::testing::_;
+using ::testing::Contains;
+using ::testing::ElementsAre;
 using ::testing::Invoke;
+using ::testing::IsEmpty;
+using ::testing::Key;
+using ::testing::SizeIs;
 
 namespace net {
 
@@ -226,9 +231,10 @@
       session_deps_.socket_factory->AddSocketDataProvider(tcp_data_.get());
 
     if (use_alternative_proxy_) {
-      std::unique_ptr<ProxyService> proxy_service =
-          ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
-      session_deps_.proxy_service = std::move(proxy_service);
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+          ProxyResolutionService::CreateFixedFromPacResult(
+              "HTTPS myproxy.org:443");
+      session_deps_.proxy_resolution_service = std::move(proxy_resolution_service);
     }
     session_deps_.net_log = net_log_.bound().net_log();
     HttpNetworkSession::Params params =
@@ -294,7 +300,7 @@
 
   TestJobFactory job_factory_;
   MockHttpStreamRequestDelegate request_delegate_;
-  SpdySessionDependencies session_deps_{ProxyService::CreateDirect()};
+  SpdySessionDependencies session_deps_{ProxyResolutionService::CreateDirect()};
   std::unique_ptr<HttpNetworkSession> session_;
   HttpStreamFactoryImpl* factory_ = nullptr;
   HttpStreamFactoryImpl::JobController* job_controller_ = nullptr;
@@ -331,7 +337,7 @@
   ProxyConfig proxy_config;
   proxy_config.set_pac_url(GURL("http://fooproxyurl"));
   proxy_config.set_pac_mandatory(true);
-  session_deps_.proxy_service.reset(new ProxyService(
+  session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
       std::make_unique<ProxyConfigServiceFixed>(proxy_config),
       std::make_unique<FailingProxyResolverFactory>(), nullptr));
   HttpRequestInfo request_info;
@@ -366,9 +372,9 @@
   MockAsyncProxyResolverFactory* proxy_resolver_factory =
       new MockAsyncProxyResolverFactory(false);
   MockAsyncProxyResolver resolver;
-  session_deps_.proxy_service.reset(
-      new ProxyService(std::make_unique<ProxyConfigServiceFixed>(proxy_config),
-                       base::WrapUnique(proxy_resolver_factory), nullptr));
+  session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
+      std::make_unique<ProxyConfigServiceFixed>(proxy_config),
+      base::WrapUnique(proxy_resolver_factory), nullptr));
   HttpRequestInfo request_info;
   request_info.method = "GET";
   request_info.url = GURL("http://www.google.com");
@@ -396,8 +402,8 @@
 }
 
 TEST_F(HttpStreamFactoryImplJobControllerTest, NoSupportedProxies) {
-  session_deps_.proxy_service =
-      ProxyService::CreateFixedFromPacResult("QUIC myproxy.org:443");
+  session_deps_.proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("QUIC myproxy.org:443");
   session_deps_.enable_quic = false;
   HttpRequestInfo request_info;
   request_info.method = "GET";
@@ -423,10 +429,10 @@
     : public HttpStreamFactoryImplJobControllerTest,
       public ::testing::WithParamInterface<::testing::tuple<bool, int>> {
  public:
-  void Initialize(std::unique_ptr<ProxyService> proxy_service,
+  void Initialize(std::unique_ptr<ProxyResolutionService> proxy_resolution_service,
                   std::unique_ptr<ProxyDelegate> proxy_delegate) {
     session_deps_.proxy_delegate = std::move(proxy_delegate);
-    session_deps_.proxy_service = std::move(proxy_service);
+    session_deps_.proxy_resolution_service = std::move(proxy_resolution_service);
     session_ = std::make_unique<HttpNetworkSession>(
         SpdySessionDependencies::CreateSessionParams(&session_deps_),
         SpdySessionDependencies::CreateSessionContext(&session_deps_));
@@ -463,14 +469,14 @@
 TEST_P(JobControllerReconsiderProxyAfterErrorTest, ReconsiderProxyAfterError) {
   const bool set_alternative_proxy_server = ::testing::get<0>(GetParam());
   const int mock_error = ::testing::get<1>(GetParam());
-  std::unique_ptr<ProxyService> proxy_service =
-      ProxyService::CreateFixedFromPacResult(
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult(
           "HTTPS badproxy:99; HTTPS badfallbackproxy:98; DIRECT");
   auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
   TestProxyDelegate* test_proxy_delegate_raw = test_proxy_delegate.get();
 
   // Before starting the test, verify that there are no proxies marked as bad.
-  ASSERT_TRUE(proxy_service->proxy_retry_info().empty()) << mock_error;
+  ASSERT_TRUE(proxy_resolution_service->proxy_retry_info().empty()) << mock_error;
 
   StaticSocketDataProvider socket_data_proxy_main_job;
   socket_data_proxy_main_job.set_connect_data(MockConnect(ASYNC, mock_error));
@@ -518,7 +524,7 @@
   request_info.method = "GET";
   request_info.url = GURL("http://www.example.com");
 
-  Initialize(std::move(proxy_service), std::move(test_proxy_delegate));
+  Initialize(std::move(proxy_resolution_service), std::move(test_proxy_delegate));
   EXPECT_EQ(set_alternative_proxy_server,
             test_proxy_delegate_raw->alternative_proxy_server().is_quic());
 
@@ -536,23 +542,21 @@
 
     std::unique_ptr<HttpStreamRequest> request =
         CreateJobController(request_info);
-
     base::RunLoop().RunUntilIdle();
-    // The proxy that failed should now be known to the proxy_service as
-    // bad.
-    const ProxyRetryInfoMap retry_info =
-        session_->proxy_service()->proxy_retry_info();
-    EXPECT_EQ(2u, retry_info.size()) << mock_error;
-    EXPECT_NE(retry_info.end(), retry_info.find("https://badproxy:99"));
-    EXPECT_NE(retry_info.end(), retry_info.find("https://badfallbackproxy:98"));
 
     // Verify that request was fetched without proxy.
     EXPECT_TRUE(used_proxy_info.is_direct());
 
-    // If alternative proxy server was specified, it should have been marked
-    // as invalid so that it is not used for subsequent requests.
-    EXPECT_FALSE(
-        test_proxy_delegate_raw->alternative_proxy_server().is_valid());
+    // The proxies that failed should now be known to the proxy service as
+    // bad.
+    const ProxyRetryInfoMap& retry_info =
+        session_->proxy_resolution_service()->proxy_retry_info();
+    EXPECT_THAT(retry_info, SizeIs(set_alternative_proxy_server ? 3 : 2));
+    EXPECT_THAT(retry_info, Contains(Key("https://badproxy:99")));
+    EXPECT_THAT(retry_info, Contains(Key("https://badfallbackproxy:98")));
+
+    if (set_alternative_proxy_server)
+      EXPECT_THAT(retry_info, Contains(Key("quic://badproxy:99")));
   }
   EXPECT_TRUE(HttpStreamFactoryImplPeer::IsJobControllerDeleted(factory_));
 }
@@ -566,14 +570,15 @@
 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
        SecondMainJobIsStartedAfterAltProxyServerJobFailed) {
   // Configure the proxies and initialize the test.
-  std::unique_ptr<ProxyService> proxy_service =
-      ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443; DIRECT");
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult(
+          "HTTPS myproxy.org:443; DIRECT");
 
   auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
   test_proxy_delegate->set_alternative_proxy_server(
       ProxyServer::FromPacString("QUIC myproxy.org:443"));
 
-  Initialize(std::move(proxy_service), std::move(test_proxy_delegate));
+  Initialize(std::move(proxy_resolution_service), std::move(test_proxy_delegate));
 
   // Enable delayed TCP and set time delay for waiting job.
   QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
@@ -633,9 +638,10 @@
 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
        SecondMainJobIsResumedAfterProxyConfigChange) {
   // Initialize the test with direct connection.
-  std::unique_ptr<ProxyService> proxy_service = ProxyService::CreateDirect();
-  ProxyService* proxy_service_raw = proxy_service.get();
-  session_deps_.proxy_service = std::move(proxy_service);
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+      ProxyResolutionService::CreateDirect();
+  ProxyResolutionService* proxy_resolution_service_raw = proxy_resolution_service.get();
+  session_deps_.proxy_resolution_service = std::move(proxy_resolution_service);
 
   // Create a request.
   HttpRequestInfo request_info;
@@ -688,7 +694,7 @@
   // change. It will still be the direct connection but the configuration
   // version will be bumped. That is enough for the job controller to restart
   // the jobs.
-  proxy_service_raw->ForceReloadProxyConfig();
+  proxy_resolution_service_raw->ForceReloadProxyConfig();
 
   base::RunLoop().RunUntilIdle();
 
@@ -720,14 +726,14 @@
   proxy_config.set_pac_mandatory(true);
   MockAsyncProxyResolverFactory* proxy_resolver_factory =
       new MockAsyncProxyResolverFactory(false);
-  ProxyService* proxy_service =
-      new ProxyService(std::make_unique<ProxyConfigServiceFixed>(proxy_config),
-                       base::WrapUnique(proxy_resolver_factory), nullptr);
+  ProxyResolutionService* proxy_resolution_service = new ProxyResolutionService(
+      std::make_unique<ProxyConfigServiceFixed>(proxy_config),
+      base::WrapUnique(proxy_resolver_factory), nullptr);
   HttpRequestInfo request_info;
   request_info.method = "GET";
   request_info.url = GURL("http://www.example.com");
 
-  Initialize(base::WrapUnique<ProxyService>(proxy_service), nullptr);
+  Initialize(base::WrapUnique<ProxyResolutionService>(proxy_resolution_service), nullptr);
   std::unique_ptr<HttpStreamRequest> request =
       CreateJobController(request_info);
   ASSERT_EQ(1u, proxy_resolver_factory->pending_requests().size());
@@ -751,7 +757,7 @@
   new_proxy_config.set_pac_mandatory(true);
   auto new_proxy_config_service =
       std::make_unique<ProxyConfigServiceFixed>(new_proxy_config);
-  proxy_service->ResetConfigService(std::move(new_proxy_config_service));
+  proxy_resolution_service->ResetConfigService(std::move(new_proxy_config_service));
   base::RunLoop().RunUntilIdle();
   ASSERT_EQ(1u, proxy_resolver_factory->pending_requests().size());
   EXPECT_EQ(
@@ -1526,9 +1532,10 @@
 TEST_F(HttpStreamFactoryImplJobControllerTest, ResumeMainJobLaterCanceled) {
   NetTestSuite::SetScopedTaskEnvironment(
       base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
-  std::unique_ptr<ProxyService> proxy_service = ProxyService::CreateDirect();
-  ProxyService* proxy_service_raw = proxy_service.get();
-  session_deps_.proxy_service = std::move(proxy_service);
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+      ProxyResolutionService::CreateDirect();
+  ProxyResolutionService* proxy_resolution_service_raw = proxy_resolution_service.get();
+  session_deps_.proxy_resolution_service = std::move(proxy_resolution_service);
 
   // Using hanging resolver will cause the alternative job to hang indefinitely.
   session_deps_.host_resolver = std::make_unique<HangingResolver>();
@@ -1574,7 +1581,7 @@
   // change. It will still be the direct connection but the configuration
   // version will be bumped. That is enough for the job controller to restart
   // the jobs.
-  proxy_service_raw->ForceReloadProxyConfig();
+  proxy_resolution_service_raw->ForceReloadProxyConfig();
   HttpStreamFactoryImplJobPeer::SetShouldReconsiderProxy(
       job_factory_.main_job());
   // Now the alt service is marked as broken (e.g. through a different request),
@@ -1891,6 +1898,8 @@
   request_info.url = GURL("http://mail.example.org/");
   Initialize(request_info);
   EXPECT_TRUE(test_proxy_delegate()->alternative_proxy_server().is_quic());
+  EXPECT_THAT(
+      session_->proxy_resolution_service()->proxy_retry_info(), IsEmpty());
 
   // Enable delayed TCP and set time delay for waiting job.
   QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
@@ -1914,7 +1923,8 @@
   EXPECT_TRUE(job_controller_->main_job());
 
   // The alternative proxy server should be marked as bad.
-  EXPECT_FALSE(test_proxy_delegate()->alternative_proxy_server().is_valid());
+  EXPECT_THAT(session_->proxy_resolution_service()->proxy_retry_info(),
+              ElementsAre(Key("quic://myproxy.org:443")));
   request_.reset();
   EXPECT_TRUE(HttpStreamFactoryImplPeer::IsJobControllerDeleted(factory_));
 }
diff --git a/net/http/http_stream_factory_impl_request_unittest.cc b/net/http/http_stream_factory_impl_request_unittest.cc
index 7e96567..632be4ce 100644
--- a/net/http/http_stream_factory_impl_request_unittest.cc
+++ b/net/http/http_stream_factory_impl_request_unittest.cc
@@ -27,7 +27,7 @@
   SequencedSocketData data(nullptr, 0, nullptr, 0);
   data.set_connect_data(MockConnect(ASYNC, OK));
   auto ssl_data = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
   session_deps.socket_factory->AddSocketDataProvider(&data);
   session_deps.socket_factory->AddSSLSocketDataProvider(ssl_data.get());
 
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index ec8f0d87..b62e0cf 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -70,6 +70,12 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::testing::Contains;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::Key;
+using ::testing::SizeIs;
+
 using net::test::IsError;
 using net::test::IsOk;
 
@@ -499,7 +505,8 @@
 
 TEST_F(HttpStreamFactoryTest, PreconnectDirect) {
   for (size_t i = 0; i < arraysize(kTests); ++i) {
-    SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+    SpdySessionDependencies session_deps(
+        ProxyResolutionService::CreateDirect());
     std::unique_ptr<HttpNetworkSession> session(
         SpdySessionDependencies::SpdyCreateSession(&session_deps));
     HttpNetworkSessionPeer peer(session.get());
@@ -530,7 +537,7 @@
 TEST_F(HttpStreamFactoryTest, PreconnectHttpProxy) {
   for (size_t i = 0; i < arraysize(kTests); ++i) {
     SpdySessionDependencies session_deps(
-        ProxyService::CreateFixed("http_proxy"));
+        ProxyResolutionService::CreateFixed("http_proxy"));
     std::unique_ptr<HttpNetworkSession> session(
         SpdySessionDependencies::SpdyCreateSession(&session_deps));
     HttpNetworkSessionPeer peer(session.get());
@@ -564,7 +571,7 @@
 TEST_F(HttpStreamFactoryTest, PreconnectSocksProxy) {
   for (size_t i = 0; i < arraysize(kTests); ++i) {
     SpdySessionDependencies session_deps(
-        ProxyService::CreateFixed("socks4://socks_proxy:1080"));
+        ProxyResolutionService::CreateFixed("socks4://socks_proxy:1080"));
     std::unique_ptr<HttpNetworkSession> session(
         SpdySessionDependencies::SpdyCreateSession(&session_deps));
     HttpNetworkSessionPeer peer(session.get());
@@ -597,7 +604,8 @@
 
 TEST_F(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) {
   for (size_t i = 0; i < arraysize(kTests); ++i) {
-    SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+    SpdySessionDependencies session_deps(
+        ProxyResolutionService::CreateDirect());
     std::unique_ptr<HttpNetworkSession> session(
         SpdySessionDependencies::SpdyCreateSession(&session_deps));
     HttpNetworkSessionPeer peer(session.get());
@@ -640,7 +648,7 @@
 TEST_F(HttpStreamFactoryTest, PreconnectUnsafePort) {
   ASSERT_FALSE(IsPortAllowedForScheme(7, "http"));
 
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
   std::unique_ptr<HttpNetworkSession> session(
       SpdySessionDependencies::SpdyCreateSession(&session_deps));
   HttpNetworkSessionPeer peer(session.get());
@@ -660,7 +668,7 @@
 
 // Verify that preconnects correctly set motivation for the SocketPool.
 TEST_F(HttpStreamFactoryTest, PreconnectSetsMotivation) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
   std::unique_ptr<HttpNetworkSession> session(
       SpdySessionDependencies::SpdyCreateSession(&session_deps));
   HttpNetworkSessionPeer peer(session.get());
@@ -681,7 +689,7 @@
 TEST_F(HttpStreamFactoryTest, JobNotifiesProxy) {
   const char* kProxyString = "PROXY bad:99; PROXY maybe:80; DIRECT";
   SpdySessionDependencies session_deps(
-      ProxyService::CreateFixedFromPacResult(kProxyString));
+      ProxyResolutionService::CreateFixedFromPacResult(kProxyString));
 
   // First connection attempt fails
   StaticSocketDataProvider socket_data1;
@@ -711,9 +719,10 @@
           /* enable_alternative_services = */ true, NetLogWithSource()));
   waiter.WaitForStream();
 
-  // The proxy that failed should now be known to the proxy_service as bad.
+  // The proxy that failed should now be known to the proxy_resolution_service
+  // as bad.
   const ProxyRetryInfoMap& retry_info =
-      session->proxy_service()->proxy_retry_info();
+      session->proxy_resolution_service()->proxy_retry_info();
   EXPECT_EQ(1u, retry_info.size());
   ProxyRetryInfoMap::const_iterator iter = retry_info.find("bad:99");
   EXPECT_TRUE(iter != retry_info.end());
@@ -742,9 +751,9 @@
 // Tests that a bad QUIC proxy is added to the list of bad proxies.
 TEST_F(HttpStreamFactoryTest, QuicProxyMarkedAsBad) {
   for (size_t i = 0; i < arraysize(quic_proxy_test_mock_errors); ++i) {
-    std::unique_ptr<ProxyService> proxy_service;
-    proxy_service =
-        ProxyService::CreateFixedFromPacResult("QUIC bad:99; DIRECT");
+    std::unique_ptr<ProxyResolutionService> proxy_resolution_service;
+    proxy_resolution_service =
+        ProxyResolutionService::CreateFixedFromPacResult("QUIC bad:99; DIRECT");
 
     HttpNetworkSession::Params session_params;
     session_params.enable_quic = true;
@@ -765,7 +774,7 @@
     session_context.cert_transparency_verifier = &ct_verifier;
     CTPolicyEnforcer ct_policy_enforcer;
     session_context.ct_policy_enforcer = &ct_policy_enforcer;
-    session_context.proxy_service = proxy_service.get();
+    session_context.proxy_resolution_service = proxy_resolution_service.get();
     session_context.ssl_config_service = ssl_config_service.get();
     session_context.http_server_properties = &http_server_properties;
 
@@ -798,9 +807,10 @@
             /* enable_alternative_services = */ true, NetLogWithSource()));
     waiter.WaitForStream();
 
-    // The proxy that failed should now be known to the proxy_service as bad.
+    // The proxy that failed should now be known to the
+    // proxy_resolution_service as bad.
     const ProxyRetryInfoMap& retry_info =
-        session->proxy_service()->proxy_retry_info();
+        session->proxy_resolution_service()->proxy_retry_info();
     EXPECT_EQ(1u, retry_info.size()) << quic_proxy_test_mock_errors[i];
     EXPECT_TRUE(waiter.used_proxy_info().is_direct());
 
@@ -877,7 +887,7 @@
     HttpNetworkSession::Params* session_params,
     HttpNetworkSession::Context* session_context,
     MockClientSocketFactory* socket_factory,
-    ProxyService* proxy_service,
+    ProxyResolutionService* proxy_resolution_service,
     TestProxyDelegate* test_proxy_delegate,
     HttpServerPropertiesImpl* http_server_properties,
     MockCertVerifier* cert_verifier,
@@ -892,7 +902,7 @@
   session_context->client_socket_factory = socket_factory;
   session_context->host_resolver = host_resolver;
   session_context->transport_security_state = transport_security_state;
-  session_context->proxy_service = proxy_service;
+  session_context->proxy_resolution_service = proxy_resolution_service;
   session_context->ssl_config_service = ssl_config_service;
   session_context->http_server_properties = http_server_properties;
   session_context->cert_verifier = cert_verifier;
@@ -922,8 +932,8 @@
       HttpNetworkSession::Params session_params;
       HttpNetworkSession::Context session_context;
       MockClientSocketFactory socket_factory;
-      std::unique_ptr<ProxyService> proxy_service =
-          ProxyService::CreateFixedFromPacResult(
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+          ProxyResolutionService::CreateFixedFromPacResult(
               "HTTPS badproxy:99; HTTPS badfallbackproxy:98; DIRECT");
       TestProxyDelegate test_proxy_delegate;
       HttpServerPropertiesImpl http_server_properties;
@@ -936,17 +946,18 @@
       TransportSecurityState transport_security_state;
       SetupForQuicAlternativeProxyTest(
           &session_params, &session_context, &socket_factory,
-          proxy_service.get(), &test_proxy_delegate, &http_server_properties,
-          &cert_verifier, &ct_policy_enforcer, &ct_verifier,
-          ssl_config_service.get(), &host_resolver, &transport_security_state,
-          set_alternative_proxy_server);
+          proxy_resolution_service.get(), &test_proxy_delegate,
+          &http_server_properties, &cert_verifier, &ct_policy_enforcer,
+          &ct_verifier, ssl_config_service.get(), &host_resolver,
+          &transport_security_state, set_alternative_proxy_server);
 
       auto session =
           std::make_unique<HttpNetworkSession>(session_params, session_context);
 
       // Before starting the test, verify that there are no proxies marked as
       // bad.
-      ASSERT_TRUE(session->proxy_service()->proxy_retry_info().empty())
+      ASSERT_TRUE(session->proxy_resolution_service()
+                         ->proxy_retry_info().empty())
           << mock_error;
 
       StaticSocketDataProvider socket_data_proxy_main_job;
@@ -1009,22 +1020,19 @@
                 /* enable_alternative_services = */ true, NetLogWithSource()));
         waiter.WaitForStream();
 
-        // The proxy that failed should now be known to the proxy_service as
-        // bad.
-        const ProxyRetryInfoMap retry_info =
-            session->proxy_service()->proxy_retry_info();
-        EXPECT_EQ(2u, retry_info.size()) << mock_error;
-
         // Verify that request was fetched without proxy.
         EXPECT_TRUE(waiter.used_proxy_info().is_direct());
 
-        EXPECT_NE(retry_info.end(), retry_info.find("https://badproxy:99"));
-        EXPECT_NE(retry_info.end(),
-                  retry_info.find("https://badfallbackproxy:98"));
+        // The proxies that failed should now be known to the proxy service as
+        // bad.
+        const ProxyRetryInfoMap& retry_info =
+            session->proxy_resolution_service()->proxy_retry_info();
+        EXPECT_THAT(retry_info, SizeIs(set_alternative_proxy_server ? 3 : 2));
+        EXPECT_THAT(retry_info, Contains(Key("https://badproxy:99")));
+        EXPECT_THAT(retry_info, Contains(Key("https://badfallbackproxy:98")));
 
-        // If alternative proxy server was specified, it should have been marked
-        // as invalid so that it is not used for subsequent requests.
-        EXPECT_FALSE(test_proxy_delegate.alternative_proxy_server().is_valid());
+        if (set_alternative_proxy_server)
+          EXPECT_THAT(retry_info, Contains(Key("quic://badproxy:99")));
       }
     }
   }
@@ -1037,8 +1045,9 @@
     HttpNetworkSession::Params session_params;
     HttpNetworkSession::Context session_context;
     MockClientSocketFactory socket_factory;
-    std::unique_ptr<ProxyService> proxy_service =
-        ProxyService::CreateFixedFromPacResult("HTTPS badproxy:99; DIRECT");
+    std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+        ProxyResolutionService::CreateFixedFromPacResult(
+            "HTTPS badproxy:99; DIRECT");
     TestProxyDelegate test_proxy_delegate;
     HttpServerPropertiesImpl http_server_properties;
     MockCertVerifier cert_verifier;
@@ -1051,10 +1060,11 @@
     TransportSecurityState transport_security_state;
 
     SetupForQuicAlternativeProxyTest(
-        &session_params, &session_context, &socket_factory, proxy_service.get(),
-        &test_proxy_delegate, &http_server_properties, &cert_verifier,
-        &ct_policy_enforcer, &ct_verifier, ssl_config_service.get(),
-        &host_resolver, &transport_security_state, true);
+        &session_params, &session_context, &socket_factory,
+        proxy_resolution_service.get(), &test_proxy_delegate,
+        &http_server_properties, &cert_verifier, &ct_policy_enforcer,
+        &ct_verifier, ssl_config_service.get(), &host_resolver,
+        &transport_security_state, true);
 
     HostPortPair host_port_pair("badproxy", 99);
     auto session =
@@ -1062,7 +1072,7 @@
 
     // Before starting the test, verify that there are no proxies marked as
     // bad.
-    ASSERT_TRUE(session->proxy_service()->proxy_retry_info().empty())
+    ASSERT_TRUE(session->proxy_resolution_service()->proxy_retry_info().empty())
         << mock_error;
 
     StaticSocketDataProvider socket_data_proxy_main_job;
@@ -1092,6 +1102,8 @@
     SSLConfig ssl_config;
     StreamRequestWaiter waiter;
 
+    EXPECT_THAT(
+        session->proxy_resolution_service()->proxy_retry_info(), IsEmpty());
     EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
 
     // Start two requests. The first request should consume data from
@@ -1105,21 +1117,15 @@
               /* enable_alternative_services = */ true, NetLogWithSource()));
       waiter.WaitForStream();
 
-      // The proxy that failed should now be known to the proxy_service as
-      // bad.
-      const ProxyRetryInfoMap retry_info =
-          session->proxy_service()->proxy_retry_info();
-      // Proxy should not be marked as bad.
-      EXPECT_EQ(0u, retry_info.size()) << mock_error;
       // Verify that request was fetched using proxy.
       EXPECT_TRUE(waiter.used_proxy_info().is_https());
       EXPECT_TRUE(host_port_pair.Equals(
           waiter.used_proxy_info().proxy_server().host_port_pair()));
-      net::ProxyServer proxy_server;
 
-      // Alternative proxy server should be marked as invalid so that it is
-      // not used for subsequent requests.
-      EXPECT_FALSE(test_proxy_delegate.alternative_proxy_server().is_quic());
+      // Alternative proxy server should be marked as bad so that it is not
+      // used for subsequent requests.
+      EXPECT_THAT(session->proxy_resolution_service()->proxy_retry_info(),
+                  ElementsAre(Key("quic://badproxy:99")));
     }
   }
 }
@@ -1129,7 +1135,7 @@
     GURL url = GURL("https://www.google.com");
 
     SpdySessionDependencies session_deps(
-        ProxyService::CreateFixed("http_proxy"));
+        ProxyResolutionService::CreateFixed("http_proxy"));
 
     // Setup params to disable preconnect, but QUIC doesn't 0RTT.
     HttpNetworkSession::Params session_params =
@@ -1186,8 +1192,9 @@
     for (int num_streams = 1; num_streams < 3; ++num_streams) {
       base::HistogramTester histogram_tester;
       GURL url = GURL("http://www.google.com");
-      std::unique_ptr<ProxyService> proxy_service =
-          ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+          ProxyResolutionService::CreateFixedFromPacResult(
+              "HTTPS myproxy.org:443");
 
       // Set up the proxy server as a server that supports request priorities.
       HttpServerPropertiesImpl http_server_properties;
@@ -1203,7 +1210,7 @@
 
       HttpNetworkSession::Context session_context =
           SpdySessionDependencies::CreateSessionContext(&session_deps);
-      session_context.proxy_service = proxy_service.get();
+      session_context.proxy_resolution_service = proxy_resolution_service.get();
       session_context.http_server_properties = &http_server_properties;
 
       auto session =
@@ -1279,8 +1286,8 @@
   int num_streams = 1;
   base::HistogramTester histogram_tester;
   GURL url = GURL("http://www.google.com");
-  std::unique_ptr<ProxyService> proxy_service =
-      ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
 
   // Set up the proxy server as a server that supports request priorities.
   HttpServerPropertiesImpl http_server_properties;
@@ -1295,7 +1302,7 @@
 
   HttpNetworkSession::Context session_context =
       SpdySessionDependencies::CreateSessionContext(&session_deps);
-  session_context.proxy_service = proxy_service.get();
+  session_context.proxy_resolution_service = proxy_resolution_service.get();
   session_context.http_server_properties = &http_server_properties;
 
   auto session =
@@ -1359,7 +1366,7 @@
 namespace {
 
 TEST_F(HttpStreamFactoryTest, PrivacyModeDisablesChannelId) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   StaticSocketDataProvider socket_data;
   socket_data.set_connect_data(MockConnect(ASYNC, OK));
@@ -1439,7 +1446,7 @@
 }  // namespace
 
 TEST_F(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   StaticSocketDataProvider socket_data_1;
   socket_data_1.set_connect_data(MockConnect(ASYNC, OK));
@@ -1504,7 +1511,7 @@
 }
 
 TEST_F(HttpStreamFactoryTest, GetLoadState) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   // Force asynchronous host resolutions, so that the LoadState will be
   // resolving the host.
@@ -1535,7 +1542,7 @@
 }
 
 TEST_F(HttpStreamFactoryTest, RequestHttpStream) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   StaticSocketDataProvider socket_data;
   socket_data.set_connect_data(MockConnect(ASYNC, OK));
@@ -1580,7 +1587,7 @@
 // may be called on an HttpStreamFactoryImpl::Job after the stream
 // has been created by the job.
 TEST_F(HttpStreamFactoryTest, ReprioritizeAfterStreamReceived) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
   StaticSocketDataProvider socket_data(&mock_read, 1, nullptr, 0);
@@ -1626,7 +1633,7 @@
 }
 
 TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverSSL) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   MockRead mock_read(ASYNC, OK);
   StaticSocketDataProvider socket_data(&mock_read, 1, nullptr, 0);
@@ -1672,7 +1679,7 @@
 
 TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverProxy) {
   SpdySessionDependencies session_deps(
-      ProxyService::CreateFixed("myproxy:8888"));
+      ProxyResolutionService::CreateFixed("myproxy:8888"));
 
   StaticSocketDataProvider socket_data;
   socket_data.set_connect_data(MockConnect(ASYNC, OK));
@@ -1724,7 +1731,7 @@
 // request priorities) the next preconnect job can again open new sockets.
 TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverProxyWithPreconnects) {
   SpdySessionDependencies session_deps(
-      ProxyService::CreateFixed("https://myproxy.org:443"));
+      ProxyResolutionService::CreateFixed("https://myproxy.org:443"));
 
   // Set up the proxy server as a server that supports request priorities.
   auto http_server_properties = std::make_unique<HttpServerPropertiesImpl>();
@@ -1802,7 +1809,7 @@
 }
 
 TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStream) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   StaticSocketDataProvider socket_data;
   socket_data.set_connect_data(MockConnect(ASYNC, OK));
@@ -1842,7 +1849,7 @@
 }
 
 TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverSSL) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   MockRead mock_read(ASYNC, OK);
   StaticSocketDataProvider socket_data(&mock_read, 1, nullptr, 0);
@@ -1887,7 +1894,7 @@
 
 TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverProxy) {
   SpdySessionDependencies session_deps(
-      ProxyService::CreateFixed("myproxy:8888"));
+      ProxyResolutionService::CreateFixed("myproxy:8888"));
 
   MockRead read(SYNCHRONOUS, "HTTP/1.0 200 Connection established\r\n\r\n");
   StaticSocketDataProvider socket_data(&read, 1, 0, 0);
@@ -1939,7 +1946,7 @@
 }
 
 TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStreamHttpsURL) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
   SequencedSocketData socket_data(&mock_read, 1, nullptr, 0);
@@ -1988,9 +1995,10 @@
 TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStreamHttpURL) {
   url::SchemeHostPort scheme_host_port("http", "myproxy.org", 443);
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443"));
-  std::unique_ptr<ProxyService> proxy_service =
-      ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+      ProxyResolutionService::CreateFixedFromPacResult(
+          "HTTPS myproxy.org:443"));
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
 
   MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
   SequencedSocketData socket_data(&mock_read, 1, nullptr, 0);
@@ -2000,7 +2008,7 @@
   SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
   ssl_socket_data.next_proto = kProtoHTTP2;
   session_deps->socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
-  session_deps->proxy_service = std::move(proxy_service);
+  session_deps->proxy_resolution_service = std::move(proxy_resolution_service);
 
   std::unique_ptr<HttpNetworkSession> session(
       SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
@@ -2043,7 +2051,7 @@
 // Tests that when a new SpdySession is established, duplicated idle H2 sockets
 // to the same server are closed.
 TEST_F(HttpStreamFactoryTest, NewSpdySessionCloseIdleH2Sockets) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   const int kNumIdleSockets = 4;
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
@@ -2130,7 +2138,7 @@
 
 // Regression test for https://crbug.com/706974.
 TEST_F(HttpStreamFactoryTest, TwoSpdyConnects) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   SSLSocketDataProvider ssl_socket_data0(ASYNC, OK);
   ssl_socket_data0.next_proto = kProtoHTTP2;
@@ -2190,7 +2198,7 @@
 }
 
 TEST_F(HttpStreamFactoryTest, RequestBidirectionalStreamImpl) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   MockRead mock_read(ASYNC, OK);
   SequencedSocketData socket_data(&mock_read, 1, nullptr, 0);
@@ -2256,7 +2264,7 @@
                              Perspective::IS_SERVER,
                              false),
         random_generator_(0),
-        proxy_service_(ProxyService::CreateDirect()),
+        proxy_resolution_service_(ProxyResolutionService::CreateDirect()),
         ssl_config_service_(new SSLConfigServiceDefaults) {
     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
   }
@@ -2297,7 +2305,7 @@
     session_context.cert_transparency_verifier = &ct_verifier_;
     session_context.ct_policy_enforcer = &ct_policy_enforcer_;
     session_context.host_resolver = &host_resolver_;
-    session_context.proxy_service = proxy_service_.get();
+    session_context.proxy_resolution_service = proxy_resolution_service_.get();
     session_context.ssl_config_service = ssl_config_service_.get();
     session_context.client_socket_factory = &socket_factory_;
     session_.reset(new HttpNetworkSession(params_, session_context));
@@ -2347,7 +2355,7 @@
   MultiLogCTVerifier ct_verifier_;
   CTPolicyEnforcer ct_policy_enforcer_;
   MockHostResolver host_resolver_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
   HttpNetworkSession::Params params_;
 };
@@ -2571,7 +2579,7 @@
 }
 
 TEST_F(HttpStreamFactoryTest, RequestBidirectionalStreamImplFailure) {
-  SpdySessionDependencies session_deps(ProxyService::CreateDirect());
+  SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
 
   MockRead mock_read(ASYNC, OK);
   SequencedSocketData socket_data(&mock_read, 1, nullptr, 0);
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h
index 8e94234..594674b 100644
--- a/net/log/net_log_event_type_list.h
+++ b/net/log/net_log_event_type_list.h
@@ -238,7 +238,7 @@
 EVENT_TYPE(PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE)
 
 // ------------------------------------------------------------------------
-// ProxyService
+// ProxyResolutionService
 // ------------------------------------------------------------------------
 
 // The start/end of a proxy resolve request.
@@ -246,7 +246,7 @@
 
 // The time while a request is waiting on InitProxyResolver to configure
 // against either WPAD or custom PAC URL. The specifics on this time
-// are found from ProxyService::init_proxy_resolver_log().
+// are found from ProxyResolutionService::init_proxy_resolver_log().
 EVENT_TYPE(PROXY_SERVICE_WAITING_FOR_INIT_PAC)
 
 // This event is emitted to show what the PAC script returned. It can contain
@@ -269,8 +269,8 @@
 //   }
 EVENT_TYPE(PROXY_SERVICE_DEPRIORITIZED_BAD_PROXIES)
 
-// This event is emitted whenever the proxy settings used by ProxyService
-// change.
+// This event is emitted whenever the proxy settings used by
+// ProxyResolutionService change.
 //
 // It contains these parameters:
 //  {
diff --git a/net/log/net_log_util.cc b/net/log/net_log_util.cc
index e133b7b..53857e5e 100644
--- a/net/log/net_log_util.cc
+++ b/net/log/net_log_util.cc
@@ -316,13 +316,14 @@
   // TODO(mmenke):  The code for most of these sources should probably be moved
   // into the sources themselves.
   if (info_sources & NET_INFO_PROXY_SETTINGS) {
-    ProxyService* proxy_service = context->proxy_service();
+    ProxyResolutionService* proxy_resolution_service =
+        context->proxy_resolution_service();
 
     std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
-    if (proxy_service->fetched_config().is_valid())
-      dict->Set("original", proxy_service->fetched_config().ToValue());
-    if (proxy_service->config().is_valid())
-      dict->Set("effective", proxy_service->config().ToValue());
+    if (proxy_resolution_service->fetched_config().is_valid())
+      dict->Set("original", proxy_resolution_service->fetched_config().ToValue());
+    if (proxy_resolution_service->config().is_valid())
+      dict->Set("effective", proxy_resolution_service->config().ToValue());
 
     net_info_dict->Set(NetInfoSourceToString(NET_INFO_PROXY_SETTINGS),
                        std::move(dict));
@@ -330,7 +331,7 @@
 
   if (info_sources & NET_INFO_BAD_PROXIES) {
     const ProxyRetryInfoMap& bad_proxies_map =
-        context->proxy_service()->proxy_retry_info();
+        context->proxy_resolution_service()->proxy_retry_info();
 
     auto list = std::make_unique<base::ListValue>();
 
diff --git a/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc b/net/proxy/dhcp_pac_file_adapter_fetcher_win.cc
similarity index 98%
rename from net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc
rename to net/proxy/dhcp_pac_file_adapter_fetcher_win.cc
index 889ad97..31b5dae2 100644
--- a/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc
+++ b/net/proxy/dhcp_pac_file_adapter_fetcher_win.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 "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
+#include "net/proxy/dhcp_pac_file_adapter_fetcher_win.h"
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -15,7 +15,7 @@
 #include "base/time/time.h"
 #include "net/base/net_errors.h"
 #include "net/proxy/dhcpcsvc_init_win.h"
-#include "net/proxy/proxy_script_fetcher_impl.h"
+#include "net/proxy/pac_file_fetcher_impl.h"
 #include "net/url_request/url_request_context.h"
 
 #include <windows.h>
diff --git a/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h b/net/proxy/dhcp_pac_file_adapter_fetcher_win.h
similarity index 97%
rename from net/proxy/dhcp_proxy_script_adapter_fetcher_win.h
rename to net/proxy/dhcp_pac_file_adapter_fetcher_win.h
index 51a4876e..64603e4 100644
--- a/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h
+++ b/net/proxy/dhcp_pac_file_adapter_fetcher_win.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_PROXY_DHCP_PROXY_SCRIPT_ADAPTER_FETCHER_WIN_H_
-#define NET_PROXY_DHCP_PROXY_SCRIPT_ADAPTER_FETCHER_WIN_H_
+#ifndef NET_PROXY_DHCP_PAC_FILE_ADAPTER_FETCHER_WIN_H_
+#define NET_PROXY_DHCP_PAC_FILE_ADAPTER_FETCHER_WIN_H_
 
 #include <stddef.h>
 
@@ -191,4 +191,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_DHCP_PROXY_SCRIPT_ADAPTER_FETCHER_WIN_H_
+#endif  // NET_PROXY_DHCP_PAC_FILE_ADAPTER_FETCHER_WIN_H_
diff --git a/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc b/net/proxy/dhcp_pac_file_adapter_fetcher_win_unittest.cc
similarity index 98%
rename from net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc
rename to net/proxy/dhcp_pac_file_adapter_fetcher_win_unittest.cc
index dee94a4..90e5ae1d 100644
--- a/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc
+++ b/net/proxy/dhcp_pac_file_adapter_fetcher_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 "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
+#include "net/proxy/dhcp_pac_file_adapter_fetcher_win.h"
 
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
@@ -12,8 +12,8 @@
 #include "base/timer/timer.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
-#include "net/proxy/mock_proxy_script_fetcher.h"
-#include "net/proxy/proxy_script_fetcher_impl.h"
+#include "net/proxy/mock_pac_file_fetcher.h"
+#include "net/proxy/pac_file_fetcher_impl.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/gtest_util.h"
 #include "net/url_request/url_request_test_util.h"
diff --git a/net/proxy/dhcp_proxy_script_fetcher.cc b/net/proxy/dhcp_pac_file_fetcher.cc
similarity index 95%
rename from net/proxy/dhcp_proxy_script_fetcher.cc
rename to net/proxy/dhcp_pac_file_fetcher.cc
index 71a32c2..8c1557b 100644
--- a/net/proxy/dhcp_proxy_script_fetcher.cc
+++ b/net/proxy/dhcp_pac_file_fetcher.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 "net/proxy/dhcp_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
 
 #include "net/base/net_errors.h"
 
diff --git a/net/proxy/dhcp_proxy_script_fetcher.h b/net/proxy/dhcp_pac_file_fetcher.h
similarity index 95%
rename from net/proxy/dhcp_proxy_script_fetcher.h
rename to net/proxy/dhcp_pac_file_fetcher.h
index f0059c2..5e8177c 100644
--- a/net/proxy/dhcp_proxy_script_fetcher.h
+++ b/net/proxy/dhcp_pac_file_fetcher.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 NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_H_
-#define NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_H_
+#ifndef NET_PROXY_DHCP_PAC_FILE_FETCHER_H_
+#define NET_PROXY_DHCP_PAC_FILE_FETCHER_H_
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "net/base/completion_callback.h"
 #include "net/base/net_export.h"
-#include "net/proxy/proxy_script_fetcher.h"
+#include "net/proxy/pac_file_fetcher.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -104,4 +104,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_H_
+#endif  // NET_PROXY_DHCP_PAC_FILE_FETCHER_H_
diff --git a/net/proxy/dhcp_proxy_script_fetcher_factory.cc b/net/proxy/dhcp_pac_file_fetcher_factory.cc
similarity index 81%
rename from net/proxy/dhcp_proxy_script_fetcher_factory.cc
rename to net/proxy/dhcp_pac_file_fetcher_factory.cc
index b0188ea..ebcac56 100644
--- a/net/proxy/dhcp_proxy_script_fetcher_factory.cc
+++ b/net/proxy/dhcp_pac_file_fetcher_factory.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
+#include "net/proxy/dhcp_pac_file_fetcher_factory.h"
 
 #include "net/base/net_errors.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
 
 #if defined(OS_WIN)
-#include "net/proxy/dhcp_proxy_script_fetcher_win.h"
+#include "net/proxy/dhcp_pac_file_fetcher_win.h"
 #endif
 
 namespace net {
diff --git a/net/proxy/dhcp_proxy_script_fetcher_factory.h b/net/proxy/dhcp_pac_file_fetcher_factory.h
similarity index 89%
rename from net/proxy/dhcp_proxy_script_fetcher_factory.h
rename to net/proxy/dhcp_pac_file_fetcher_factory.h
index e80c8b6..5c079daa 100644
--- a/net/proxy/dhcp_proxy_script_fetcher_factory.h
+++ b/net/proxy/dhcp_pac_file_fetcher_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_FACTORY_H_
-#define NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_FACTORY_H_
+#ifndef NET_PROXY_DHCP_PAC_FILE_FETCHER_FACTORY_H_
+#define NET_PROXY_DHCP_PAC_FILE_FETCHER_FACTORY_H_
 
 #include <memory>
 
@@ -11,7 +11,7 @@
 #include "base/memory/singleton.h"
 #include "net/base/completion_callback.h"
 #include "net/base/net_export.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
 
 namespace net {
 
@@ -53,4 +53,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_FACTORY_H_
+#endif  // NET_PROXY_DHCP_PAC_FILE_FETCHER_FACTORY_H_
diff --git a/net/proxy/dhcp_proxy_script_fetcher_factory_unittest.cc b/net/proxy/dhcp_pac_file_fetcher_factory_unittest.cc
similarity index 90%
rename from net/proxy/dhcp_proxy_script_fetcher_factory_unittest.cc
rename to net/proxy/dhcp_pac_file_fetcher_factory_unittest.cc
index 700778f..3bbed94 100644
--- a/net/proxy/dhcp_proxy_script_fetcher_factory_unittest.cc
+++ b/net/proxy/dhcp_pac_file_fetcher_factory_unittest.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
-#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher_factory.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/net/proxy/dhcp_proxy_script_fetcher_win.cc b/net/proxy/dhcp_pac_file_fetcher_win.cc
similarity index 98%
rename from net/proxy/dhcp_proxy_script_fetcher_win.cc
rename to net/proxy/dhcp_pac_file_fetcher_win.cc
index 8c89124a..b4ab853 100644
--- a/net/proxy/dhcp_proxy_script_fetcher_win.cc
+++ b/net/proxy/dhcp_pac_file_fetcher_win.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 "net/proxy/dhcp_proxy_script_fetcher_win.h"
+#include "net/proxy/dhcp_pac_file_fetcher_win.h"
 
 #include <memory>
 #include <vector>
@@ -12,7 +12,7 @@
 #include "base/memory/free_deleter.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "net/base/net_errors.h"
-#include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
+#include "net/proxy/dhcp_pac_file_adapter_fetcher_win.h"
 
 #include <winsock2.h>
 #include <iphlpapi.h>
diff --git a/net/proxy/dhcp_proxy_script_fetcher_win.h b/net/proxy/dhcp_pac_file_fetcher_win.h
similarity index 96%
rename from net/proxy/dhcp_proxy_script_fetcher_win.h
rename to net/proxy/dhcp_pac_file_fetcher_win.h
index 4defdd0..a5d9a85 100644
--- a/net/proxy/dhcp_proxy_script_fetcher_win.h
+++ b/net/proxy/dhcp_pac_file_fetcher_win.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_WIN_H_
-#define NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_WIN_H_
+#ifndef NET_PROXY_DHCP_PAC_FILE_FETCHER_WIN_H_
+#define NET_PROXY_DHCP_PAC_FILE_FETCHER_WIN_H_
 
 #include <memory>
 #include <set>
@@ -16,7 +16,7 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "net/base/net_export.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
 
 namespace base {
 class SequencedWorkerPool;
@@ -184,4 +184,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_WIN_H_
+#endif  // NET_PROXY_DHCP_PAC_FILE_FETCHER_WIN_H_
diff --git a/net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc b/net/proxy/dhcp_pac_file_fetcher_win_unittest.cc
similarity index 99%
rename from net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc
rename to net/proxy/dhcp_pac_file_fetcher_win_unittest.cc
index b7e407c9..ebc1993 100644
--- a/net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc
+++ b/net/proxy/dhcp_pac_file_fetcher_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 "net/proxy/dhcp_proxy_script_fetcher_win.h"
+#include "net/proxy/dhcp_pac_file_fetcher_win.h"
 
 #include <vector>
 
@@ -14,7 +14,7 @@
 #include "base/threading/platform_thread.h"
 #include "base/timer/elapsed_timer.h"
 #include "net/base/completion_callback.h"
-#include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
+#include "net/proxy/dhcp_pac_file_adapter_fetcher_win.h"
 #include "net/test/gtest_util.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/net/proxy/mock_proxy_script_fetcher.cc b/net/proxy/mock_pac_file_fetcher.cc
similarity index 97%
rename from net/proxy/mock_proxy_script_fetcher.cc
rename to net/proxy/mock_pac_file_fetcher.cc
index 8e0d3dd..f5215e9 100644
--- a/net/proxy/mock_proxy_script_fetcher.cc
+++ b/net/proxy/mock_pac_file_fetcher.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 "net/proxy/mock_proxy_script_fetcher.h"
+#include "net/proxy/mock_pac_file_fetcher.h"
 
 #include "base/callback_helpers.h"
 #include "base/logging.h"
diff --git a/net/proxy/mock_proxy_script_fetcher.h b/net/proxy/mock_pac_file_fetcher.h
similarity index 86%
rename from net/proxy/mock_proxy_script_fetcher.h
rename to net/proxy/mock_pac_file_fetcher.h
index 8cf6cd5..07a341f 100644
--- a/net/proxy/mock_proxy_script_fetcher.h
+++ b/net/proxy/mock_pac_file_fetcher.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_PROXY_MOCK_PROXY_SCRIPT_FETCHER_H_
-#define NET_PROXY_MOCK_PROXY_SCRIPT_FETCHER_H_
+#ifndef NET_PROXY_MOCK_PAC_FILE_FETCHER_H_
+#define NET_PROXY_MOCK_PAC_FILE_FETCHER_H_
 
 #include "base/compiler_specific.h"
-#include "net/proxy/proxy_script_fetcher.h"
+#include "net/proxy/pac_file_fetcher.h"
 #include "url/gurl.h"
 
 #include <string>
@@ -47,4 +47,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_MOCK_PROXY_SCRIPT_FETCHER_H_
+#endif  // NET_PROXY_MOCK_PAC_FILE_FETCHER_H_
diff --git a/net/proxy/proxy_resolver_script_data.cc b/net/proxy/pac_file_data.cc
similarity index 89%
rename from net/proxy/proxy_resolver_script_data.cc
rename to net/proxy/pac_file_data.cc
index d620955..55d60ed 100644
--- a/net/proxy/proxy_resolver_script_data.cc
+++ b/net/proxy/pac_file_data.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 "net/proxy/proxy_resolver_script_data.h"
+#include "net/proxy/pac_file_data.h"
 
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
@@ -12,8 +12,7 @@
 // static
 scoped_refptr<ProxyResolverScriptData> ProxyResolverScriptData::FromUTF8(
     const std::string& utf8) {
-  return new ProxyResolverScriptData(TYPE_SCRIPT_CONTENTS,
-                                     GURL(),
+  return new ProxyResolverScriptData(TYPE_SCRIPT_CONTENTS, GURL(),
                                      base::UTF8ToUTF16(utf8));
 }
 
@@ -66,10 +65,7 @@
 ProxyResolverScriptData::ProxyResolverScriptData(Type type,
                                                  const GURL& url,
                                                  const base::string16& utf16)
-    : type_(type),
-      url_(url),
-      utf16_(utf16) {
-}
+    : type_(type), url_(url), utf16_(utf16) {}
 
 ProxyResolverScriptData::~ProxyResolverScriptData() = default;
 
diff --git a/net/proxy/proxy_resolver_script_data.h b/net/proxy/pac_file_data.h
similarity index 91%
rename from net/proxy/proxy_resolver_script_data.h
rename to net/proxy/pac_file_data.h
index 16e17fd..88dc1ef 100644
--- a/net/proxy/proxy_resolver_script_data.h
+++ b/net/proxy/pac_file_data.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_PROXY_PROXY_RESOLVER_SCRIPT_DATA_H_
-#define NET_PROXY_PROXY_RESOLVER_SCRIPT_DATA_H_
+#ifndef NET_PROXY_PAC_FILE_DATA_H_
+#define NET_PROXY_PAC_FILE_DATA_H_
 
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
@@ -41,9 +41,7 @@
   // Creates a script data for using an automatically detected PAC URL.
   static scoped_refptr<ProxyResolverScriptData> ForAutoDetect();
 
-  Type type() const {
-    return type_;
-  }
+  Type type() const { return type_; }
 
   // Returns the contents of the script as UTF16.
   // (only valid for type() == TYPE_SCRIPT_CONTENTS).
@@ -63,7 +61,6 @@
                           const base::string16& utf16);
   virtual ~ProxyResolverScriptData();
 
-
   const Type type_;
   const GURL url_;
   const base::string16 utf16_;
@@ -71,4 +68,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_PROXY_RESOLVER_SCRIPT_DATA_H_
+#endif  // NET_PROXY_PAC_FILE_DATA_H_
diff --git a/net/proxy/proxy_script_decider.cc b/net/proxy/pac_file_decider.cc
similarity index 91%
rename from net/proxy/proxy_script_decider.cc
rename to net/proxy/pac_file_decider.cc
index d713b2fa..8e12c596 100644
--- a/net/proxy/proxy_script_decider.cc
+++ b/net/proxy/pac_file_decider.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 "net/proxy/proxy_script_decider.h"
+#include "net/proxy/pac_file_decider.h"
 
 #include <utility>
 
@@ -19,9 +19,9 @@
 #include "net/log/net_log_capture_mode.h"
 #include "net/log/net_log_event_type.h"
 #include "net/log/net_log_source_type.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
-#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
-#include "net/proxy/proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher_factory.h"
+#include "net/proxy/pac_file_fetcher.h"
 #include "net/url_request/url_request_context.h"
 
 namespace net {
@@ -36,7 +36,7 @@
   //
   // An exact test would have to load the script in a javascript evaluator.
   return script.find(base::ASCIIToUTF16("FindProxyForURL")) !=
-             base::string16::npos;
+         base::string16::npos;
 }
 
 }  // anonymous namespace
@@ -56,7 +56,7 @@
 namespace {
 const char kWpadUrl[] = "http://wpad/wpad.dat";
 const int kQuickCheckDelayMs = 1000;
-};
+};  // namespace
 
 std::unique_ptr<base::Value> ProxyScriptDecider::PacSource::NetLogCallback(
     const GURL* effective_pac_url,
@@ -99,9 +99,10 @@
     Cancel();
 }
 
-int ProxyScriptDecider::Start(
-    const ProxyConfig& config, const base::TimeDelta wait_delay,
-    bool fetch_pac_bytes, const CompletionCallback& callback) {
+int ProxyScriptDecider::Start(const ProxyConfig& config,
+                              const base::TimeDelta wait_delay,
+                              bool fetch_pac_bytes,
+                              const CompletionCallback& callback) {
   DCHECK_EQ(STATE_NONE, next_state_);
   DCHECK(!callback.is_null());
   DCHECK(config.HasAutomaticSettings());
@@ -151,8 +152,8 @@
   return effective_config_;
 }
 
-const scoped_refptr<ProxyResolverScriptData>&
-ProxyScriptDecider::script_data() const {
+const scoped_refptr<ProxyResolverScriptData>& ProxyScriptDecider::script_data()
+    const {
   DCHECK_EQ(STATE_NONE, next_state_);
   return script_data_;
 }
@@ -161,8 +162,8 @@
 // (1) WPAD (DHCP).
 // (2) WPAD (DNS).
 // (3) Custom PAC URL.
-ProxyScriptDecider::PacSourceList ProxyScriptDecider::
-    BuildPacSourcesFallbackList(
+ProxyScriptDecider::PacSourceList
+ProxyScriptDecider::BuildPacSourcesFallbackList(
     const ProxyConfig& config) const {
   PacSourceList pac_sources;
   if (config.auto_detect()) {
@@ -273,15 +274,13 @@
   std::string host = current_pac_source().url.host();
   HostResolver::RequestInfo reqinfo(HostPortPair(host, 80));
   reqinfo.set_host_resolver_flags(HOST_RESOLVER_SYSTEM_ONLY);
-  CompletionCallback callback = base::Bind(
-      &ProxyScriptDecider::OnIOCompletion,
-      base::Unretained(this));
+  CompletionCallback callback =
+      base::Bind(&ProxyScriptDecider::OnIOCompletion, base::Unretained(this));
 
   next_state_ = STATE_QUICK_CHECK_COMPLETE;
-  quick_check_timer_.Start(FROM_HERE,
-                           base::TimeDelta::FromMilliseconds(
-                              kQuickCheckDelayMs),
-                           base::Bind(callback, ERR_NAME_NOT_RESOLVED));
+  quick_check_timer_.Start(
+      FROM_HERE, base::TimeDelta::FromMilliseconds(kQuickCheckDelayMs),
+      base::Bind(callback, ERR_NAME_NOT_RESOLVED));
 
   HostResolver* host_resolver =
       proxy_script_fetcher_->GetRequestContext()->host_resolver();
@@ -374,9 +373,9 @@
   if (fetch_pac_bytes_) {
     script_data_ = ProxyResolverScriptData::FromUTF16(pac_script_);
   } else {
-    script_data_ = pac_source.type == PacSource::CUSTOM ?
-        ProxyResolverScriptData::FromURL(pac_source.url) :
-        ProxyResolverScriptData::ForAutoDetect();
+    script_data_ = pac_source.type == PacSource::CUSTOM
+                       ? ProxyResolverScriptData::FromURL(pac_source.url)
+                       : ProxyResolverScriptData::ForAutoDetect();
   }
 
   // Let the caller know which automatic setting we ended up initializing the
@@ -437,7 +436,7 @@
 }
 
 ProxyScriptDecider::State ProxyScriptDecider::GetStartState() const {
-  return fetch_pac_bytes_ ?  STATE_FETCH_PAC_SCRIPT : STATE_VERIFY_PAC_SCRIPT;
+  return fetch_pac_bytes_ ? STATE_FETCH_PAC_SCRIPT : STATE_VERIFY_PAC_SCRIPT;
 }
 
 void ProxyScriptDecider::DetermineURL(const PacSource& pac_source,
@@ -456,8 +455,8 @@
   }
 }
 
-const ProxyScriptDecider::PacSource&
-    ProxyScriptDecider::current_pac_source() const {
+const ProxyScriptDecider::PacSource& ProxyScriptDecider::current_pac_source()
+    const {
   DCHECK_LT(current_pac_source_index_, pac_sources_.size());
   return pac_sources_[current_pac_source_index_];
 }
diff --git a/net/proxy/proxy_script_decider.h b/net/proxy/pac_file_decider.h
similarity index 92%
rename from net/proxy/proxy_script_decider.h
rename to net/proxy/pac_file_decider.h
index b3560ba..d44a906 100644
--- a/net/proxy/proxy_script_decider.h
+++ b/net/proxy/pac_file_decider.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_PROXY_PROXY_SCRIPT_DECIDER_H_
-#define NET_PROXY_PROXY_SCRIPT_DECIDER_H_
+#ifndef NET_PROXY_PAC_FILE_DECIDER_H_
+#define NET_PROXY_PAC_FILE_DECIDER_H_
 
 #include <stddef.h>
 
@@ -36,8 +36,8 @@
 class ProxyResolver;
 class ProxyScriptFetcher;
 
-// ProxyScriptDecider is a helper class used by ProxyService to determine which
-// PAC script to use given our proxy configuration.
+// ProxyScriptDecider is a helper class used by ProxyResolutionService to
+// determine which PAC script to use given our proxy configuration.
 //
 // This involves trying to use PAC scripts in this order:
 //
@@ -89,9 +89,7 @@
 
   const scoped_refptr<ProxyResolverScriptData>& script_data() const;
 
-  void set_quick_check_enabled(bool enabled) {
-    quick_check_enabled_ = enabled;
-  }
+  void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; }
 
   bool quick_check_enabled() const { return quick_check_enabled_; }
 
@@ -99,14 +97,9 @@
   // Represents the sources from which we can get PAC files; two types of
   // auto-detect or a custom URL.
   struct PacSource {
-    enum Type {
-      WPAD_DHCP,
-      WPAD_DNS,
-      CUSTOM
-    };
+    enum Type { WPAD_DHCP, WPAD_DNS, CUSTOM };
 
-    PacSource(Type type, const GURL& url)
-        : type(type), url(url) {}
+    PacSource(Type type, const GURL& url) : type(type), url(url) {}
 
     // Returns a Value representing the PacSource.  |effective_pac_url| must
     // be non-NULL and point to the URL derived from information contained in
@@ -215,4 +208,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_PROXY_SCRIPT_DECIDER_H_
+#endif  // NET_PROXY_PAC_FILE_DECIDER_H_
diff --git a/net/proxy/proxy_script_decider_unittest.cc b/net/proxy/pac_file_decider_unittest.cc
similarity index 92%
rename from net/proxy/proxy_script_decider_unittest.cc
rename to net/proxy/pac_file_decider_unittest.cc
index 15c5d0f..c420f46 100644
--- a/net/proxy/proxy_script_decider_unittest.cc
+++ b/net/proxy/pac_file_decider_unittest.cc
@@ -21,12 +21,12 @@
 #include "net/log/test_net_log.h"
 #include "net/log/test_net_log_entry.h"
 #include "net/log/test_net_log_util.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
-#include "net/proxy/mock_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
+#include "net/proxy/mock_pac_file_fetcher.h"
+#include "net/proxy/pac_file_decider.h"
+#include "net/proxy/pac_file_fetcher.h"
 #include "net/proxy/proxy_config.h"
 #include "net/proxy/proxy_resolver.h"
-#include "net/proxy/proxy_script_decider.h"
-#include "net/proxy/proxy_script_fetcher.h"
 #include "net/test/gtest_util.h"
 #include "net/url_request/url_request_context.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -49,8 +49,7 @@
     Rule(const GURL& url, int fetch_error, bool is_valid_script)
         : url(url),
           fetch_error(fetch_error),
-          is_valid_script(is_valid_script) {
-    }
+          is_valid_script(is_valid_script) {}
 
     base::string16 text() const {
       if (is_valid_script)
@@ -72,8 +71,8 @@
   }
 
   void AddFailDownloadRule(const char* url) {
-    rules_.push_back(Rule(GURL(url), kFailedDownloading /*fetch_error*/,
-        false));
+    rules_.push_back(
+        Rule(GURL(url), kFailedDownloading /*fetch_error*/, false));
   }
 
   void AddFailParsingRule(const char* url) {
@@ -173,7 +172,7 @@
   return ERR_IO_PENDING;
 }
 
-void MockDhcpProxyScriptFetcher::Cancel() { }
+void MockDhcpProxyScriptFetcher::Cancel() {}
 
 void MockDhcpProxyScriptFetcher::OnShutdown() {}
 
@@ -186,7 +185,8 @@
 }
 
 void MockDhcpProxyScriptFetcher::CompleteRequests(
-    int result, const base::string16& script) {
+    int result,
+    const base::string16& script) {
   *utf16_text_ = script;
   callback_.Run(result);
 }
@@ -205,8 +205,8 @@
   TestCompletionCallback callback;
   TestNetLog log;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
-  EXPECT_EQ(OK, decider.Start(
-      config, base::TimeDelta(), true, callback.callback()));
+  EXPECT_EQ(
+      OK, decider.Start(config, base::TimeDelta(), true, callback.callback()));
   EXPECT_EQ(rule.text(), decider.script_data()->utf16());
 
   // Check the NetLog was filled correctly.
@@ -241,9 +241,8 @@
   TestCompletionCallback callback;
   TestNetLog log;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
-  EXPECT_EQ(kFailedDownloading,
-            decider.Start(config, base::TimeDelta(), true,
-                          callback.callback()));
+  EXPECT_EQ(kFailedDownloading, decider.Start(config, base::TimeDelta(), true,
+                                              callback.callback()));
   EXPECT_FALSE(decider.script_data());
 
   // Check the NetLog was filled correctly.
@@ -276,9 +275,8 @@
 
   TestCompletionCallback callback;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
-  EXPECT_EQ(kFailedParsing,
-            decider.Start(config, base::TimeDelta(), true,
-                          callback.callback()));
+  EXPECT_EQ(kFailedParsing, decider.Start(config, base::TimeDelta(), true,
+                                          callback.callback()));
   EXPECT_FALSE(decider.script_data());
 }
 
@@ -292,9 +290,8 @@
 
   TestCompletionCallback callback;
   ProxyScriptDecider decider(NULL, &dhcp_fetcher, NULL);
-  EXPECT_EQ(ERR_UNEXPECTED,
-            decider.Start(config, base::TimeDelta(), true,
-                          callback.callback()));
+  EXPECT_EQ(ERR_UNEXPECTED, decider.Start(config, base::TimeDelta(), true,
+                                          callback.callback()));
   EXPECT_FALSE(decider.script_data());
 }
 
@@ -311,8 +308,8 @@
 
   TestCompletionCallback callback;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
-  EXPECT_EQ(OK, decider.Start(
-      config, base::TimeDelta(), true, callback.callback()));
+  EXPECT_EQ(
+      OK, decider.Start(config, base::TimeDelta(), true, callback.callback()));
   EXPECT_EQ(rule.text(), decider.script_data()->utf16());
 
   EXPECT_TRUE(decider.effective_config().has_pac_url());
@@ -323,7 +320,7 @@
  public:
   ProxyScriptDeciderQuickCheckTest()
       : rule_(rules_.AddSuccessRule("http://wpad/wpad.dat")),
-        fetcher_(&rules_) { }
+        fetcher_(&rules_) {}
 
   void SetUp() override {
     request_context_.set_host_resolver(&resolver_);
@@ -334,7 +331,7 @@
 
   int StartDecider() {
     return decider_->Start(config_, base::TimeDelta(), true,
-                            callback_.callback());
+                           callback_.callback());
   }
 
  protected:
@@ -405,7 +402,7 @@
 // Fails if DHCP check doesn't take place before QuickCheck.
 TEST_F(ProxyScriptDeciderQuickCheckTest, QuickCheckInhibitsDhcp) {
   MockDhcpProxyScriptFetcher dhcp_fetcher;
-  const char *kPac = "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
+  const char* kPac = "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
   base::string16 pac_contents = base::UTF8ToUTF16(kPac);
   GURL url("http://foobar/baz");
   dhcp_fetcher.SetPacURL(url);
@@ -421,7 +418,7 @@
 // mean a QuickCheck failure, then ensure that our ProxyScriptFetcher is still
 // asked to fetch.
 TEST_F(ProxyScriptDeciderQuickCheckTest, QuickCheckDisabled) {
-  const char *kPac = "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
+  const char* kPac = "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
   resolver_.set_synchronous_mode(true);
   resolver_.rules()->AddSimulatedFailure("wpad");
   MockProxyScriptFetcher fetcher;
@@ -432,7 +429,7 @@
 }
 
 TEST_F(ProxyScriptDeciderQuickCheckTest, ExplicitPacUrl) {
-  const char *kCustomUrl = "http://custom/proxy.pac";
+  const char* kCustomUrl = "http://custom/proxy.pac";
   config_.set_pac_url(GURL(kCustomUrl));
   Rules::Rule rule = rules_.AddSuccessRule(kCustomUrl);
   resolver_.rules()->AddSimulatedFailure("wpad");
@@ -479,8 +476,8 @@
 
   TestCompletionCallback callback;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
-  EXPECT_EQ(OK, decider.Start(
-      config, base::TimeDelta(), true, callback.callback()));
+  EXPECT_EQ(
+      OK, decider.Start(config, base::TimeDelta(), true, callback.callback()));
   EXPECT_EQ(rule.text(), decider.script_data()->utf16());
 
   EXPECT_TRUE(decider.effective_config().has_pac_url());
@@ -506,8 +503,8 @@
   TestNetLog log;
 
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
-  EXPECT_EQ(OK, decider.Start(config, base::TimeDelta(),
-                          true, callback.callback()));
+  EXPECT_EQ(
+      OK, decider.Start(config, base::TimeDelta(), true, callback.callback()));
   EXPECT_EQ(rule.text(), decider.script_data()->utf16());
 
   // Verify that the effective configuration no longer contains auto detect or
@@ -567,9 +564,8 @@
 
   TestCompletionCallback callback;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
-  EXPECT_EQ(kFailedDownloading,
-            decider.Start(config, base::TimeDelta(), true,
-                          callback.callback()));
+  EXPECT_EQ(kFailedDownloading, decider.Start(config, base::TimeDelta(), true,
+                                              callback.callback()));
   EXPECT_FALSE(decider.script_data());
 }
 
@@ -588,9 +584,8 @@
 
   TestCompletionCallback callback;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
-  EXPECT_EQ(kFailedParsing,
-            decider.Start(config, base::TimeDelta(), true,
-                          callback.callback()));
+  EXPECT_EQ(kFailedParsing, decider.Start(config, base::TimeDelta(), true,
+                                          callback.callback()));
   EXPECT_FALSE(decider.script_data());
 }
 
@@ -611,8 +606,8 @@
   TestNetLog log;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
   EXPECT_EQ(ERR_IO_PENDING,
-            decider.Start(config, base::TimeDelta::FromMilliseconds(1),
-                      true, callback.callback()));
+            decider.Start(config, base::TimeDelta::FromMilliseconds(1), true,
+                          callback.callback()));
 
   EXPECT_EQ(kFailedDownloading, callback.WaitForResult());
   EXPECT_FALSE(decider.script_data());
@@ -653,8 +648,8 @@
   TestNetLog log;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
   EXPECT_EQ(kFailedDownloading,
-            decider.Start(config, base::TimeDelta::FromSeconds(-5),
-                          true, callback.callback()));
+            decider.Start(config, base::TimeDelta::FromSeconds(-5), true,
+                          callback.callback()));
   EXPECT_FALSE(decider.script_data());
 
   // Check the NetLog was filled correctly.
@@ -675,8 +670,7 @@
 class SynchronousSuccessDhcpFetcher : public DhcpProxyScriptFetcher {
  public:
   explicit SynchronousSuccessDhcpFetcher(const base::string16& expected_text)
-      : gurl_("http://dhcppac/"), expected_text_(expected_text) {
-  }
+      : gurl_("http://dhcppac/"), expected_text_(expected_text) {}
 
   int Fetch(base::string16* utf16_text,
             const CompletionCallback& callback) override {
@@ -690,9 +684,7 @@
 
   const GURL& GetPacURL() const override { return gurl_; }
 
-  const base::string16& expected_text() const {
-    return expected_text_;
-  }
+  const base::string16& expected_text() const { return expected_text_; }
 
  private:
   GURL gurl_;
@@ -720,10 +712,9 @@
 
   TestCompletionCallback callback;
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
-  EXPECT_EQ(OK, decider.Start(
-      config, base::TimeDelta(), true, callback.callback()));
-  EXPECT_EQ(dhcp_fetcher.expected_text(),
-            decider.script_data()->utf16());
+  EXPECT_EQ(
+      OK, decider.Start(config, base::TimeDelta(), true, callback.callback()));
+  EXPECT_EQ(dhcp_fetcher.expected_text(), decider.script_data()->utf16());
 
   EXPECT_TRUE(decider.effective_config().has_pac_url());
   EXPECT_EQ(GURL("http://dhcppac/"), decider.effective_config().pac_url());
@@ -745,8 +736,8 @@
   ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
   // Since there is fallback to DNS-based WPAD, the final error will be that
   // it failed downloading, not that it failed parsing.
-  EXPECT_EQ(kFailedDownloading,
-      decider.Start(config, base::TimeDelta(), true, callback.callback()));
+  EXPECT_EQ(kFailedDownloading, decider.Start(config, base::TimeDelta(), true,
+                                              callback.callback()));
   EXPECT_FALSE(decider.script_data());
 
   EXPECT_FALSE(decider.effective_config().has_pac_url());
diff --git a/net/proxy/proxy_script_fetcher.h b/net/proxy/pac_file_fetcher.h
similarity index 94%
rename from net/proxy/proxy_script_fetcher.h
rename to net/proxy/pac_file_fetcher.h
index 3905b100..d19ed59 100644
--- a/net/proxy/proxy_script_fetcher.h
+++ b/net/proxy/pac_file_fetcher.h
@@ -6,8 +6,8 @@
 // script. It is specific to fetching a PAC script; enforces timeout, max-size,
 // status code.
 
-#ifndef NET_PROXY_PROXY_SCRIPT_FETCHER_H_
-#define NET_PROXY_PROXY_SCRIPT_FETCHER_H_
+#ifndef NET_PROXY_PAC_FILE_FETCHER_H_
+#define NET_PROXY_PAC_FILE_FETCHER_H_
 
 #include "base/strings/string16.h"
 #include "net/base/completion_callback.h"
@@ -64,4 +64,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_PROXY_SCRIPT_FETCHER_H_
+#endif  // NET_PROXY_PAC_FILE_FETCHER_H_
diff --git a/net/proxy/proxy_script_fetcher_impl.cc b/net/proxy/pac_file_fetcher_impl.cc
similarity index 96%
rename from net/proxy/proxy_script_fetcher_impl.cc
rename to net/proxy/pac_file_fetcher_impl.cc
index fe427e2..90c75e2 100644
--- a/net/proxy/proxy_script_fetcher_impl.cc
+++ b/net/proxy/pac_file_fetcher_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/proxy/proxy_script_fetcher_impl.h"
+#include "net/proxy/pac_file_fetcher_impl.h"
 
 #include "base/compiler_specific.h"
 #include "base/location.h"
@@ -49,9 +49,8 @@
 
 // Returns true if |mime_type| is one of the known PAC mime type.
 bool IsPacMimeType(const std::string& mime_type) {
-  static const char * const kSupportedPacMimeTypes[] = {
-    "application/x-ns-proxy-autoconfig",
-    "application/x-javascript-config",
+  static const char* const kSupportedPacMimeTypes[] = {
+      "application/x-ns-proxy-autoconfig", "application/x-javascript-config",
   };
   for (size_t i = 0; i < arraysize(kSupportedPacMimeTypes); ++i) {
     if (base::LowerCaseEqualsASCII(mime_type, kSupportedPacMimeTypes[i]))
@@ -127,8 +126,9 @@
   FetchCompleted();
 }
 
-int ProxyScriptFetcherImpl::Fetch(
-    const GURL& url, base::string16* text, const CompletionCallback& callback) {
+int ProxyScriptFetcherImpl::Fetch(const GURL& url,
+                                  base::string16* text,
+                                  const CompletionCallback& callback) {
   // It is invalid to call Fetch() while a request is already in progress.
   DCHECK(!cur_request_.get());
   DCHECK(!callback.is_null());
@@ -211,8 +211,9 @@
   cur_request_id_ = ++next_id_;
 
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE, base::Bind(&ProxyScriptFetcherImpl::OnTimeout,
-                            weak_factory_.GetWeakPtr(), cur_request_id_),
+      FROM_HERE,
+      base::Bind(&ProxyScriptFetcherImpl::OnTimeout, weak_factory_.GetWeakPtr(),
+                 cur_request_id_),
       max_duration_);
 
   // Start the request.
diff --git a/net/proxy/proxy_script_fetcher_impl.h b/net/proxy/pac_file_fetcher_impl.h
similarity index 95%
rename from net/proxy/proxy_script_fetcher_impl.h
rename to net/proxy/pac_file_fetcher_impl.h
index bc1e192..d68c273 100644
--- a/net/proxy/proxy_script_fetcher_impl.h
+++ b/net/proxy/pac_file_fetcher_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_PROXY_PROXY_SCRIPT_FETCHER_IMPL_H_
-#define NET_PROXY_PROXY_SCRIPT_FETCHER_IMPL_H_
+#ifndef NET_PROXY_PAC_FILE_FETCHER_IMPL_H_
+#define NET_PROXY_PAC_FILE_FETCHER_IMPL_H_
 
 #include <stddef.h>
 
@@ -17,7 +17,7 @@
 #include "base/strings/string16.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
-#include "net/proxy/proxy_script_fetcher.h"
+#include "net/proxy/pac_file_fetcher.h"
 #include "net/url_request/url_request.h"
 
 class GURL;
@@ -136,4 +136,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_PROXY_SCRIPT_FETCHER_IMPL_H_
+#endif  // NET_PROXY_PAC_FILE_FETCHER_IMPL_H_
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/pac_file_fetcher_impl_unittest.cc
similarity index 95%
rename from net/proxy/proxy_script_fetcher_impl_unittest.cc
rename to net/proxy/pac_file_fetcher_impl_unittest.cc
index 5390c5495..284c9a0 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/pac_file_fetcher_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/proxy/proxy_script_fetcher_impl.h"
+#include "net/proxy/pac_file_fetcher_impl.h"
 
 #include <string>
 #include <utility>
@@ -86,7 +86,7 @@
     storage_.set_cert_transparency_verifier(
         std::make_unique<MultiLogCTVerifier>());
     storage_.set_ct_policy_enforcer(std::make_unique<CTPolicyEnforcer>());
-    storage_.set_proxy_service(ProxyService::CreateFixed(no_proxy));
+    storage_.set_proxy_resolution_service(ProxyResolutionService::CreateFixed(no_proxy));
     storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
     storage_.set_http_server_properties(
         std::unique_ptr<HttpServerProperties>(new HttpServerPropertiesImpl()));
@@ -97,7 +97,7 @@
     session_context.transport_security_state = transport_security_state();
     session_context.cert_transparency_verifier = cert_transparency_verifier();
     session_context.ct_policy_enforcer = ct_policy_enforcer();
-    session_context.proxy_service = proxy_service();
+    session_context.proxy_resolution_service = proxy_resolution_service();
     session_context.ssl_config_service = ssl_config_service();
     session_context.http_server_properties = http_server_properties();
     storage_.set_http_network_session(std::make_unique<HttpNetworkSession>(
@@ -226,20 +226,20 @@
 TEST_F(ProxyScriptFetcherImplTest, FileUrl) {
   ProxyScriptFetcherImpl pac_fetcher(&context_);
 
-  { // Fetch a non-existent file.
+  {  // Fetch a non-existent file.
     base::string16 text;
     TestCompletionCallback callback;
-    int result = pac_fetcher.Fetch(GetTestFileUrl("does-not-exist"),
-                                   &text, callback.callback());
+    int result = pac_fetcher.Fetch(GetTestFileUrl("does-not-exist"), &text,
+                                   callback.callback());
     EXPECT_THAT(result, IsError(ERR_IO_PENDING));
     EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FILE_NOT_FOUND));
     EXPECT_TRUE(text.empty());
   }
-  { // Fetch a file that exists.
+  {  // Fetch a file that exists.
     base::string16 text;
     TestCompletionCallback callback;
-    int result = pac_fetcher.Fetch(GetTestFileUrl("pac.txt"),
-                                   &text, callback.callback());
+    int result = pac_fetcher.Fetch(GetTestFileUrl("pac.txt"), &text,
+                                   callback.callback());
     EXPECT_THAT(result, IsError(ERR_IO_PENDING));
     EXPECT_THAT(callback.WaitForResult(), IsOk());
     EXPECT_EQ(ASCIIToUTF16("-pac.txt-\n"), text);
@@ -254,7 +254,7 @@
 
   ProxyScriptFetcherImpl pac_fetcher(&context_);
 
-  { // Fetch a PAC with mime type "text/plain"
+  {  // Fetch a PAC with mime type "text/plain"
     GURL url(test_server_.GetURL("/pac.txt"));
     base::string16 text;
     TestCompletionCallback callback;
@@ -263,7 +263,7 @@
     EXPECT_THAT(callback.WaitForResult(), IsOk());
     EXPECT_EQ(ASCIIToUTF16("-pac.txt-\n"), text);
   }
-  { // Fetch a PAC with mime type "text/html"
+  {  // Fetch a PAC with mime type "text/html"
     GURL url(test_server_.GetURL("/pac.html"));
     base::string16 text;
     TestCompletionCallback callback;
@@ -272,7 +272,7 @@
     EXPECT_THAT(callback.WaitForResult(), IsOk());
     EXPECT_EQ(ASCIIToUTF16("-pac.html-\n"), text);
   }
-  { // Fetch a PAC with mime type "application/x-ns-proxy-autoconfig"
+  {  // Fetch a PAC with mime type "application/x-ns-proxy-autoconfig"
     GURL url(test_server_.GetURL("/pac.nsproxy"));
     base::string16 text;
     TestCompletionCallback callback;
@@ -288,7 +288,7 @@
 
   ProxyScriptFetcherImpl pac_fetcher(&context_);
 
-  { // Fetch a PAC which gives a 500 -- FAIL
+  {  // Fetch a PAC which gives a 500 -- FAIL
     GURL url(test_server_.GetURL("/500.pac"));
     base::string16 text;
     TestCompletionCallback callback;
@@ -297,7 +297,7 @@
     EXPECT_THAT(callback.WaitForResult(), IsError(ERR_PAC_STATUS_NOT_OK));
     EXPECT_TRUE(text.empty());
   }
-  { // Fetch a PAC which gives a 404 -- FAIL
+  {  // Fetch a PAC which gives a 404 -- FAIL
     GURL url(test_server_.GetURL("/404.pac"));
     base::string16 text;
     TestCompletionCallback callback;
@@ -389,7 +389,7 @@
   // Restore the original size bound.
   pac_fetcher.SetSizeConstraint(prev_size);
 
-  { // Make sure we can still fetch regular URLs.
+  {  // Make sure we can still fetch regular URLs.
     GURL url(test_server_.GetURL("/pac.nsproxy"));
     base::string16 text;
     TestCompletionCallback callback;
@@ -406,8 +406,8 @@
   ProxyScriptFetcherImpl pac_fetcher(&context_);
 
   // Set the timeout period to 0.5 seconds.
-  base::TimeDelta prev_timeout = pac_fetcher.SetTimeoutConstraint(
-      base::TimeDelta::FromMilliseconds(500));
+  base::TimeDelta prev_timeout =
+      pac_fetcher.SetTimeoutConstraint(base::TimeDelta::FromMilliseconds(500));
 
   // Try fetching a URL which takes 1.2 seconds. We should abort the request
   // after 500 ms, and fail with a timeout error.
@@ -424,7 +424,7 @@
   // Restore the original timeout period.
   pac_fetcher.SetTimeoutConstraint(prev_timeout);
 
-  { // Make sure we can still fetch regular URLs.
+  {  // Make sure we can still fetch regular URLs.
     GURL url(test_server_.GetURL("/pac.nsproxy"));
     base::string16 text;
     TestCompletionCallback callback;
diff --git a/net/proxy/proxy_config_service.h b/net/proxy/proxy_config_service.h
index 5e14995..56d0c68 100644
--- a/net/proxy/proxy_config_service.h
+++ b/net/proxy/proxy_config_service.h
@@ -53,8 +53,8 @@
   // dispatch any change notifications from within this function.
   virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) = 0;
 
-  // ProxyService will call this periodically during periods of activity.
-  // It can be used as a signal for polling-based implementations.
+  // ProxyResolutionService will call this periodically during periods of
+  // activity. It can be used as a signal for polling-based implementations.
   //
   // Note that this is purely used as an optimization -- polling
   // implementations could simply set a global timer that goes off every
diff --git a/net/proxy/proxy_config_service_linux.cc b/net/proxy/proxy_config_service_linux.cc
index 6e6b5e0..3dd26e7 100644
--- a/net/proxy/proxy_config_service_linux.cc
+++ b/net/proxy/proxy_config_service_linux.cc
@@ -1206,7 +1206,7 @@
   // cached_config_, where GetLatestProxyConfig() running on the main TaskRunner
   // will expect to find it. This is safe to do because we return
   // before this ProxyConfigServiceLinux is passed on to
-  // the ProxyService.
+  // the ProxyResolutionService.
 
   // Note: It would be nice to prioritize environment variables
   // and only fall back to gsettings if env vars were unset. But
diff --git a/net/proxy/proxy_info.cc b/net/proxy/proxy_info.cc
index 01879df..c2da901 100644
--- a/net/proxy/proxy_info.cc
+++ b/net/proxy/proxy_info.cc
@@ -89,6 +89,7 @@
   proxy_resolve_start_time_ = base::TimeTicks();
   proxy_resolve_end_time_ = base::TimeTicks();
   proxy_list_.Clear();
+  alternative_proxy_ = net::ProxyServer();
   proxy_retry_info_.clear();
   config_id_ = ProxyConfig::kInvalidConfigID;
   config_source_ = PROXY_CONFIG_SOURCE_UNKNOWN;
diff --git a/net/proxy/proxy_info.h b/net/proxy/proxy_info.h
index fd3c1178..e6c050c 100644
--- a/net/proxy/proxy_info.h
+++ b/net/proxy/proxy_info.h
@@ -35,8 +35,8 @@
   //
   // Note that this method resets this instance unlike Fallback(), etc. which
   // only modify |proxy_list_|. For example, since |config_id_| is cleared, the
-  // ProxyService may recognize this instance as a new config after UseDirect()
-  // call.
+  // ProxyResolutionService may recognize this instance as a new config after
+  // UseDirect() call.
   void UseDirect();
 
   // Uses a direct connection. did_bypass_proxy() will return true to indicate
@@ -178,7 +178,7 @@
   }
 
  private:
-  friend class ProxyService;
+  friend class ProxyResolutionService;
   FRIEND_TEST_ALL_PREFIXES(ProxyInfoTest, UseVsOverrideProxyList);
 
   const ProxyRetryInfoMap& proxy_retry_info() const {
diff --git a/net/proxy/proxy_list.cc b/net/proxy/proxy_list.cc
index 9eefac04..69b5655 100644
--- a/net/proxy/proxy_list.cc
+++ b/net/proxy/proxy_list.cc
@@ -157,8 +157,8 @@
                          const NetLogWithSource& net_log) {
   // TODO(eroman): It would be good if instead of removing failed proxies
   // from the list, we simply annotated them with the error code they failed
-  // with. Of course, ProxyService::ReconsiderProxyAfterError() would need to
-  // be given this information by the network transaction.
+  // with. Of course, ProxyResolutionService::ReconsiderProxyAfterError() would
+  // need to be given this information by the network transaction.
   //
   // The advantage of this approach is when the network transaction
   // fails, we could output the full list of proxies that were attempted, and
diff --git a/net/proxy/proxy_resolver.h b/net/proxy/proxy_resolver.h
index 9133293..c62e105 100644
--- a/net/proxy/proxy_resolver.h
+++ b/net/proxy/proxy_resolver.h
@@ -13,7 +13,7 @@
 #include "net/base/completion_callback.h"
 #include "net/base/load_states.h"
 #include "net/base/net_export.h"
-#include "net/proxy/proxy_resolver_script_data.h"
+#include "net/proxy/pac_file_data.h"
 #include "url/gurl.h"
 
 namespace net {
diff --git a/net/proxy/proxy_resolver_factory.h b/net/proxy/proxy_resolver_factory.h
index 94ca29a..923257b 100644
--- a/net/proxy/proxy_resolver_factory.h
+++ b/net/proxy/proxy_resolver_factory.h
@@ -12,7 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "net/base/completion_callback.h"
 #include "net/base/net_export.h"
-#include "net/proxy/proxy_resolver_script_data.h"
+#include "net/proxy/pac_file_data.h"
 
 namespace net {
 
diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc
index 40f3e03..a94a6b15 100644
--- a/net/proxy/proxy_resolver_v8.cc
+++ b/net/proxy/proxy_resolver_v8.cc
@@ -24,9 +24,9 @@
 #include "gin/v8_initializer.h"
 #include "net/base/ip_address.h"
 #include "net/base/net_errors.h"
+#include "net/proxy/pac_file_data.h"
 #include "net/proxy/pac_js_library.h"
 #include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_resolver_script_data.h"
 #include "url/gurl.h"
 #include "url/url_canon.h"
 #include "v8/include/v8.h"
diff --git a/net/proxy/proxy_resolver_v8_tracing.cc b/net/proxy/proxy_resolver_v8_tracing.cc
index 4e95dcd..7426055 100644
--- a/net/proxy/proxy_resolver_v8_tracing.cc
+++ b/net/proxy/proxy_resolver_v8_tracing.cc
@@ -364,7 +364,7 @@
 
   // Script initialization uses blocking DNS since there isn't any
   // advantage to using non-blocking mode here. That is because the
-  // parent ProxyService can't submit any ProxyResolve requests until
+  // parent ProxyResolutionService can't submit any ProxyResolve requests until
   // initialization has completed successfully!
   Start(CREATE_V8_RESOLVER, true /*blocking*/, callback);
 }
diff --git a/net/proxy/proxy_resolver_v8_unittest.cc b/net/proxy/proxy_resolver_v8_unittest.cc
index d6f5215..60e7852f 100644
--- a/net/proxy/proxy_resolver_v8_unittest.cc
+++ b/net/proxy/proxy_resolver_v8_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "net/proxy/proxy_resolver_v8.h"
 #include "base/compiler_specific.h"
 #include "base/files/file_util.h"
 #include "base/path_service.h"
@@ -10,9 +11,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "net/base/completion_callback.h"
 #include "net/base/net_errors.h"
+#include "net/proxy/pac_file_data.h"
 #include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_resolver_script_data.h"
-#include "net/proxy/proxy_resolver_v8.h"
 #include "net/test/gtest_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/proxy/proxy_server.h b/net/proxy/proxy_server.h
index 8de93ea..2827846 100644
--- a/net/proxy/proxy_server.h
+++ b/net/proxy/proxy_server.h
@@ -25,7 +25,7 @@
  public:
   // The type of proxy. These are defined as bit flags so they can be ORed
   // together to pass as the |scheme_bit_field| argument to
-  // ProxyService::RemoveProxiesWithoutScheme().
+  // ProxyResolutionService::RemoveProxiesWithoutScheme().
   enum Scheme {
     SCHEME_INVALID = 1 << 0,
     SCHEME_DIRECT  = 1 << 1,
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc
index 369a1ca..b6a860c6 100644
--- a/net/proxy/proxy_service.cc
+++ b/net/proxy/proxy_service.cc
@@ -27,13 +27,13 @@
 #include "net/log/net_log_capture_mode.h"
 #include "net/log/net_log_event_type.h"
 #include "net/log/net_log_with_source.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
 #include "net/proxy/multi_threaded_proxy_resolver.h"
+#include "net/proxy/pac_file_decider.h"
+#include "net/proxy/pac_file_fetcher.h"
 #include "net/proxy/proxy_config_service_fixed.h"
 #include "net/proxy/proxy_resolver.h"
 #include "net/proxy/proxy_resolver_factory.h"
-#include "net/proxy/proxy_script_decider.h"
-#include "net/proxy/proxy_script_fetcher.h"
 #include "net/url_request/url_request_context.h"
 #include "url/gurl.h"
 
@@ -65,9 +65,10 @@
 // Instead, we  wait for |kDelayAfterNetworkChangesMs| before
 // attempting to re-valuate proxy auto-config.
 //
-// During this time window, any resolve requests sent to the ProxyService will
-// be queued. Once we have waited the required amount of them, the proxy
-// auto-config step will be run, and the queued requests resumed.
+// During this time window, any resolve requests sent to the
+// ProxyResolutionService will be queued. Once we have waited the required
+// amount of them, the proxy auto-config step will be run, and the queued
+// requests resumed.
 //
 // The reason we play this game is that our signal for detecting network
 // changes (NetworkChangeNotifier) may fire *before* the system's networking
@@ -123,7 +124,7 @@
 // 5 minutes respectively. It doubles the interval at each attempt.
 //
 // TODO(eroman): Figure out what Internet Explorer does.
-class DefaultPollPolicy : public ProxyService::PacPollPolicy {
+class DefaultPollPolicy : public ProxyResolutionService::PacPollPolicy {
  public:
   DefaultPollPolicy() = default;
 
@@ -336,7 +337,8 @@
 // Returns a sanitized copy of |url| which is safe to pass on to a PAC script.
 // The method for sanitizing is determined by |policy|. See the comments for
 // that enum for details.
-GURL SanitizeUrl(const GURL& url, ProxyService::SanitizeUrlPolicy policy) {
+GURL SanitizeUrl(const GURL& url,
+                 ProxyResolutionService::SanitizeUrlPolicy policy) {
   DCHECK(url.is_valid());
 
   GURL::Replacements replacements;
@@ -344,7 +346,7 @@
   replacements.ClearPassword();
   replacements.ClearRef();
 
-  if (policy == ProxyService::SanitizeUrlPolicy::SAFE &&
+  if (policy == ProxyResolutionService::SanitizeUrlPolicy::SAFE &&
       url.SchemeIsCryptographic()) {
     replacements.ClearPath();
     replacements.ClearQuery();
@@ -355,7 +357,7 @@
 
 }  // namespace
 
-// ProxyService::InitProxyResolver --------------------------------------------
+// ProxyResolutionService::InitProxyResolver ----------------------------------
 
 // This glues together two asynchronous steps:
 //   (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts
@@ -367,7 +369,7 @@
 // once. The instance can be destroyed at any time, and the request will be
 // cancelled.
 
-class ProxyService::InitProxyResolver {
+class ProxyResolutionService::InitProxyResolver {
  public:
   InitProxyResolver()
       : proxy_resolver_factory_(nullptr),
@@ -565,13 +567,13 @@
   DISALLOW_COPY_AND_ASSIGN(InitProxyResolver);
 };
 
-// ProxyService::ProxyScriptDeciderPoller -------------------------------------
+// ProxyResolutionService::ProxyScriptDeciderPoller ---------------------------
 
 // This helper class encapsulates the logic to schedule and run periodic
 // background checks to see if the PAC script (or effective proxy configuration)
 // has changed. If a change is detected, then the caller will be notified via
 // the ChangeCallback.
-class ProxyService::ProxyScriptDeciderPoller {
+class ProxyResolutionService::ProxyScriptDeciderPoller {
  public:
   typedef base::Callback<void(int, ProxyResolverScriptData*,
                               const ProxyConfig&)> ChangeCallback;
@@ -689,9 +691,9 @@
 
   void OnProxyScriptDeciderCompleted(int result) {
     if (HasScriptDataChanged(result, decider_->script_data())) {
-      // Something has changed, we must notify the ProxyService so it can
-      // re-initialize its ProxyResolver. Note that we post a notification task
-      // rather than calling it directly -- this is done to avoid an ugly
+      // Something has changed, we must notify the ProxyResolutionService so it
+      // can re-initialize its ProxyResolver. Note that we post a notification
+      // task rather than calling it directly -- this is done to avoid an ugly
       // destruction sequence, since |this| might be destroyed as a result of
       // the notification.
       base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -737,7 +739,8 @@
       int result,
       const scoped_refptr<ProxyResolverScriptData>& script_data,
       const ProxyConfig& effective_config) {
-    // Note that |this| may be deleted after calling into the ProxyService.
+    // Note that |this| may be deleted after calling into the
+    // ProxyResolutionService.
     change_callback_.Run(result, script_data.get(), effective_config);
   }
 
@@ -770,14 +773,15 @@
 };
 
 // static
-const ProxyService::PacPollPolicy*
-    ProxyService::ProxyScriptDeciderPoller::poll_policy_ = NULL;
+const ProxyResolutionService::PacPollPolicy*
+    ProxyResolutionService::ProxyScriptDeciderPoller::poll_policy_ = NULL;
 
-// ProxyService::Request ---------------------------------------------------
+// ProxyResolutionService::Request --------------------------------------------
 
-class ProxyService::Request : public base::RefCounted<ProxyService::Request> {
+class ProxyResolutionService::Request
+    : public base::RefCounted<ProxyResolutionService::Request> {
  public:
-  Request(ProxyService* service,
+  Request(ProxyResolutionService* service,
           const GURL& url,
           const std::string& method,
           ProxyDelegate* proxy_delegate,
@@ -891,7 +895,7 @@
   }
 
  private:
-  friend class base::RefCounted<ProxyService::Request>;
+  friend class base::RefCounted<ProxyResolutionService::Request>;
 
   ~Request() = default;
 
@@ -910,10 +914,10 @@
 
   ProxyResolver* resolver() const { return service_->resolver_.get(); }
 
-  // Note that we don't hold a reference to the ProxyService. Outstanding
-  // requests are cancelled during ~ProxyService, so this is guaranteed
-  // to be valid throughout our lifetime.
-  ProxyService* service_;
+  // Note that we don't hold a reference to the ProxyResolutionService.
+  // Outstanding requests are cancelled during ~ProxyResolutionService, so this
+  // is guaranteed to be valid throughout our lifetime.
+  ProxyResolutionService* service_;
   CompletionCallback user_callback_;
   ProxyInfo* results_;
   GURL url_;
@@ -928,9 +932,9 @@
   TimeTicks creation_time_;
 };
 
-// ProxyService ---------------------------------------------------------------
+// ProxyResolutionService -----------------------------------------------------
 
-ProxyService::ProxyService(
+ProxyResolutionService::ProxyResolutionService(
     std::unique_ptr<ProxyConfigService> config_service,
     std::unique_ptr<ProxyResolverFactory> resolver_factory,
     NetLog* net_log)
@@ -948,7 +952,8 @@
 }
 
 // static
-std::unique_ptr<ProxyService> ProxyService::CreateUsingSystemProxyResolver(
+std::unique_ptr<ProxyResolutionService>
+ProxyResolutionService::CreateUsingSystemProxyResolver(
     std::unique_ptr<ProxyConfigService> proxy_config_service,
     NetLog* net_log) {
   DCHECK(proxy_config_service);
@@ -958,23 +963,25 @@
     return CreateWithoutProxyResolver(std::move(proxy_config_service), net_log);
   }
 
-  return std::make_unique<ProxyService>(
+  return std::make_unique<ProxyResolutionService>(
       std::move(proxy_config_service),
       std::make_unique<ProxyResolverFactoryForSystem>(kDefaultNumPacThreads),
       net_log);
 }
 
 // static
-std::unique_ptr<ProxyService> ProxyService::CreateWithoutProxyResolver(
+std::unique_ptr<ProxyResolutionService>
+ProxyResolutionService::CreateWithoutProxyResolver(
     std::unique_ptr<ProxyConfigService> proxy_config_service,
     NetLog* net_log) {
-  return std::make_unique<ProxyService>(
+  return std::make_unique<ProxyResolutionService>(
       std::move(proxy_config_service),
       std::make_unique<ProxyResolverFactoryForNullResolver>(), net_log);
 }
 
 // static
-std::unique_ptr<ProxyService> ProxyService::CreateFixed(const ProxyConfig& pc) {
+std::unique_ptr<ProxyResolutionService> ProxyResolutionService::CreateFixed(
+    const ProxyConfig& pc) {
   // TODO(eroman): This isn't quite right, won't work if |pc| specifies
   //               a PAC script.
   return CreateUsingSystemProxyResolver(
@@ -982,58 +989,60 @@
 }
 
 // static
-std::unique_ptr<ProxyService> ProxyService::CreateFixed(
+std::unique_ptr<ProxyResolutionService> ProxyResolutionService::CreateFixed(
     const std::string& proxy) {
   ProxyConfig proxy_config;
   proxy_config.proxy_rules().ParseFromString(proxy);
-  return ProxyService::CreateFixed(proxy_config);
+  return ProxyResolutionService::CreateFixed(proxy_config);
 }
 
 // static
-std::unique_ptr<ProxyService> ProxyService::CreateDirect() {
+std::unique_ptr<ProxyResolutionService> ProxyResolutionService::CreateDirect() {
   return CreateDirectWithNetLog(NULL);
 }
 
-std::unique_ptr<ProxyService> ProxyService::CreateDirectWithNetLog(
-    NetLog* net_log) {
+std::unique_ptr<ProxyResolutionService>
+ProxyResolutionService::CreateDirectWithNetLog(NetLog* net_log) {
   // Use direct connections.
-  return std::make_unique<ProxyService>(
+  return std::make_unique<ProxyResolutionService>(
       std::make_unique<ProxyConfigServiceDirect>(),
       std::make_unique<ProxyResolverFactoryForNullResolver>(), net_log);
 }
 
 // static
-std::unique_ptr<ProxyService> ProxyService::CreateFixedFromPacResult(
+std::unique_ptr<ProxyResolutionService>
+ProxyResolutionService::CreateFixedFromPacResult(
     const std::string& pac_string) {
   // We need the settings to contain an "automatic" setting, otherwise the
   // ProxyResolver dependency we give it will never be used.
   std::unique_ptr<ProxyConfigService> proxy_config_service(
       new ProxyConfigServiceFixed(ProxyConfig::CreateAutoDetect()));
 
-  return std::make_unique<ProxyService>(
+  return std::make_unique<ProxyResolutionService>(
       std::move(proxy_config_service),
       std::make_unique<ProxyResolverFactoryForPacResult>(pac_string), nullptr);
 }
 
-int ProxyService::ResolveProxy(const GURL& raw_url,
-                               const std::string& method,
-                               ProxyInfo* result,
-                               const CompletionCallback& callback,
-                               Request** pac_request,
-                               ProxyDelegate* proxy_delegate,
-                               const NetLogWithSource& net_log) {
+int ProxyResolutionService::ResolveProxy(const GURL& raw_url,
+                                         const std::string& method,
+                                         ProxyInfo* result,
+                                         const CompletionCallback& callback,
+                                         Request** pac_request,
+                                         ProxyDelegate* proxy_delegate,
+                                         const NetLogWithSource& net_log) {
   DCHECK(!callback.is_null());
   return ResolveProxyHelper(raw_url, method, result, callback, pac_request,
                             proxy_delegate, net_log);
 }
 
-int ProxyService::ResolveProxyHelper(const GURL& raw_url,
-                                     const std::string& method,
-                                     ProxyInfo* result,
-                                     const CompletionCallback& callback,
-                                     Request** pac_request,
-                                     ProxyDelegate* proxy_delegate,
-                                     const NetLogWithSource& net_log) {
+int ProxyResolutionService::ResolveProxyHelper(
+    const GURL& raw_url,
+    const std::string& method,
+    ProxyInfo* result,
+    const CompletionCallback& callback,
+    Request** pac_request,
+    ProxyDelegate* proxy_delegate,
+    const NetLogWithSource& net_log) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   net_log.BeginEvent(NetLogEventType::PROXY_SERVICE);
@@ -1089,7 +1098,7 @@
   return rv;  // ERR_IO_PENDING
 }
 
-bool ProxyService::TryResolveProxySynchronously(
+bool ProxyResolutionService::TryResolveProxySynchronously(
     const GURL& raw_url,
     const std::string& method,
     ProxyInfo* result,
@@ -1101,9 +1110,10 @@
                             net_log) == OK;
 }
 
-int ProxyService::TryToCompleteSynchronously(const GURL& url,
-                                             ProxyDelegate* proxy_delegate,
-                                             ProxyInfo* result) {
+int ProxyResolutionService::TryToCompleteSynchronously(
+    const GURL& url,
+    ProxyDelegate* proxy_delegate,
+    ProxyInfo* result) {
   DCHECK_NE(STATE_NONE, current_state_);
 
   if (current_state_ != STATE_READY)
@@ -1127,7 +1137,7 @@
   return OK;
 }
 
-ProxyService::~ProxyService() {
+ProxyResolutionService::~ProxyResolutionService() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   NetworkChangeNotifier::RemoveIPAddressObserver(this);
   NetworkChangeNotifier::RemoveDNSObserver(this);
@@ -1141,7 +1151,7 @@
   }
 }
 
-void ProxyService::SuspendAllPendingRequests() {
+void ProxyResolutionService::SuspendAllPendingRequests() {
   for (PendingRequests::iterator it = pending_requests_.begin();
        it != pending_requests_.end();
        ++it) {
@@ -1155,7 +1165,7 @@
   }
 }
 
-void ProxyService::SetReady() {
+void ProxyResolutionService::SetReady() {
   DCHECK(!init_proxy_resolver_.get());
   current_state_ = STATE_READY;
 
@@ -1179,7 +1189,7 @@
   }
 }
 
-void ProxyService::ApplyProxyConfigIfAvailable() {
+void ProxyResolutionService::ApplyProxyConfigIfAvailable() {
   DCHECK_EQ(STATE_NONE, current_state_);
 
   config_service_->OnLazyPoll();
@@ -1203,7 +1213,7 @@
     OnProxyConfigChanged(config, availability);
 }
 
-void ProxyService::OnInitProxyResolverComplete(int result) {
+void ProxyResolutionService::OnInitProxyResolverComplete(int result) {
   DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
   DCHECK(init_proxy_resolver_.get());
   DCHECK(fetched_config_.HasAutomaticSettings());
@@ -1215,7 +1225,7 @@
   // result of proxy auto-discovery changes, this poller will notice it and
   // will trigger a re-initialization using the newly discovered PAC.
   script_poller_.reset(new ProxyScriptDeciderPoller(
-      base::Bind(&ProxyService::InitializeUsingDecidedConfig,
+      base::Bind(&ProxyResolutionService::InitializeUsingDecidedConfig,
                  base::Unretained(this)),
       fetched_config_, resolver_factory_->expects_pac_bytes(),
       proxy_script_fetcher_.get(), dhcp_proxy_script_fetcher_.get(), result,
@@ -1250,14 +1260,15 @@
   SetReady();
 }
 
-int ProxyService::ReconsiderProxyAfterError(const GURL& url,
-                                            const std::string& method,
-                                            int net_error,
-                                            ProxyInfo* result,
-                                            const CompletionCallback& callback,
-                                            Request** pac_request,
-                                            ProxyDelegate* proxy_delegate,
-                                            const NetLogWithSource& net_log) {
+int ProxyResolutionService::ReconsiderProxyAfterError(
+    const GURL& url,
+    const std::string& method,
+    int net_error,
+    ProxyInfo* result,
+    const CompletionCallback& callback,
+    Request** pac_request,
+    ProxyDelegate* proxy_delegate,
+    const NetLogWithSource& net_log) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   // Check to see if we have a new config since ResolveProxy was called.  We
@@ -1287,7 +1298,7 @@
   return did_fallback ? OK : ERR_FAILED;
 }
 
-bool ProxyService::MarkProxiesAsBadUntil(
+bool ProxyResolutionService::MarkProxiesAsBadUntil(
     const ProxyInfo& result,
     base::TimeDelta retry_delay,
     const std::vector<ProxyServer>& additional_bad_proxies,
@@ -1298,8 +1309,8 @@
   return result.proxy_list_.size() > (additional_bad_proxies.size() + 1);
 }
 
-void ProxyService::ReportSuccess(const ProxyInfo& result,
-                                 ProxyDelegate* proxy_delegate) {
+void ProxyResolutionService::ReportSuccess(const ProxyInfo& result,
+                                           ProxyDelegate* proxy_delegate) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   const ProxyRetryInfoMap& new_retry_info = result.proxy_retry_info();
@@ -1328,35 +1339,36 @@
   }
 }
 
-void ProxyService::CancelRequest(Request* req) {
+void ProxyResolutionService::CancelRequest(Request* req) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(req);
   req->Cancel();
   RemovePendingRequest(req);
 }
 
-LoadState ProxyService::GetLoadState(const Request* req) const {
+LoadState ProxyResolutionService::GetLoadState(const Request* req) const {
   CHECK(req);
   if (current_state_ == STATE_WAITING_FOR_INIT_PROXY_RESOLVER)
     return init_proxy_resolver_->GetLoadState();
   return req->GetLoadState();
 }
 
-bool ProxyService::ContainsPendingRequest(Request* req) {
+bool ProxyResolutionService::ContainsPendingRequest(Request* req) {
   return pending_requests_.count(req) == 1;
 }
 
-void ProxyService::RemovePendingRequest(Request* req) {
+void ProxyResolutionService::RemovePendingRequest(Request* req) {
   DCHECK(ContainsPendingRequest(req));
   pending_requests_.erase(req);
 }
 
-int ProxyService::DidFinishResolvingProxy(const GURL& url,
-                                          const std::string& method,
-                                          ProxyDelegate* proxy_delegate,
-                                          ProxyInfo* result,
-                                          int result_code,
-                                          const NetLogWithSource& net_log) {
+int ProxyResolutionService::DidFinishResolvingProxy(
+    const GURL& url,
+    const std::string& method,
+    ProxyDelegate* proxy_delegate,
+    ProxyInfo* result,
+    int result_code,
+    const NetLogWithSource& net_log) {
   // Log the result of the proxy resolution.
   if (result_code == OK) {
     // Allow the proxy delegate to interpose on the resolution decision,
@@ -1412,7 +1424,7 @@
   return result_code;
 }
 
-void ProxyService::SetProxyScriptFetchers(
+void ProxyResolutionService::SetProxyScriptFetchers(
     std::unique_ptr<ProxyScriptFetcher> proxy_script_fetcher,
     std::unique_ptr<DhcpProxyScriptFetcher> dhcp_proxy_script_fetcher) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -1423,7 +1435,7 @@
     ApplyProxyConfigIfAvailable();
 }
 
-void ProxyService::OnShutdown() {
+void ProxyResolutionService::OnShutdown() {
   // Order here does not matter for correctness. |init_proxy_resolver_| is first
   // because shutting it down also cancels its requests using the fetcher.
   if (init_proxy_resolver_)
@@ -1434,12 +1446,13 @@
     dhcp_proxy_script_fetcher_->OnShutdown();
 }
 
-ProxyScriptFetcher* ProxyService::GetProxyScriptFetcher() const {
+ProxyScriptFetcher* ProxyResolutionService::GetProxyScriptFetcher() const {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   return proxy_script_fetcher_.get();
 }
 
-ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
+ProxyResolutionService::State ProxyResolutionService::ResetProxyConfig(
+    bool reset_fetched_config) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   State previous_state = current_state_;
 
@@ -1457,7 +1470,7 @@
   return previous_state;
 }
 
-void ProxyService::ResetConfigService(
+void ProxyResolutionService::ResetConfigService(
     std::unique_ptr<ProxyConfigService> new_proxy_config_service) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   State previous_state = ResetProxyConfig(true);
@@ -1474,7 +1487,7 @@
     ApplyProxyConfigIfAvailable();
 }
 
-void ProxyService::ForceReloadProxyConfig() {
+void ProxyResolutionService::ForceReloadProxyConfig() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   ResetProxyConfig(false);
   ApplyProxyConfigIfAvailable();
@@ -1482,7 +1495,7 @@
 
 // static
 std::unique_ptr<ProxyConfigService>
-ProxyService::CreateSystemProxyConfigService(
+ProxyResolutionService::CreateSystemProxyConfigService(
     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
 #if defined(OS_WIN)
   return std::make_unique<ProxyConfigServiceWin>();
@@ -1524,18 +1537,19 @@
 }
 
 // static
-const ProxyService::PacPollPolicy* ProxyService::set_pac_script_poll_policy(
+const ProxyResolutionService::PacPollPolicy*
+ProxyResolutionService::set_pac_script_poll_policy(
     const PacPollPolicy* policy) {
   return ProxyScriptDeciderPoller::set_policy(policy);
 }
 
 // static
-std::unique_ptr<ProxyService::PacPollPolicy>
-ProxyService::CreateDefaultPacPollPolicy() {
+std::unique_ptr<ProxyResolutionService::PacPollPolicy>
+ProxyResolutionService::CreateDefaultPacPollPolicy() {
   return std::unique_ptr<PacPollPolicy>(new DefaultPollPolicy());
 }
 
-void ProxyService::OnProxyConfigChanged(
+void ProxyResolutionService::OnProxyConfigChanged(
     const ProxyConfig& config,
     ProxyConfigService::ConfigAvailability availability) {
   // Retrieve the current proxy configuration from the ProxyConfigService.
@@ -1569,7 +1583,7 @@
   InitializeUsingLastFetchedConfig();
 }
 
-void ProxyService::InitializeUsingLastFetchedConfig() {
+void ProxyResolutionService::InitializeUsingLastFetchedConfig() {
   ResetProxyConfig(false);
 
   DCHECK(fetched_config_.is_valid());
@@ -1595,14 +1609,14 @@
   int rv = init_proxy_resolver_->Start(
       &resolver_, resolver_factory_.get(), proxy_script_fetcher_.get(),
       dhcp_proxy_script_fetcher_.get(), net_log_, fetched_config_, wait_delay,
-      base::Bind(&ProxyService::OnInitProxyResolverComplete,
+      base::Bind(&ProxyResolutionService::OnInitProxyResolverComplete,
                  base::Unretained(this)));
 
   if (rv != ERR_IO_PENDING)
     OnInitProxyResolverComplete(rv);
 }
 
-void ProxyService::InitializeUsingDecidedConfig(
+void ProxyResolutionService::InitializeUsingDecidedConfig(
     int decider_result,
     ProxyResolverScriptData* script_data,
     const ProxyConfig& effective_config) {
@@ -1616,14 +1630,15 @@
   init_proxy_resolver_.reset(new InitProxyResolver());
   int rv = init_proxy_resolver_->StartSkipDecider(
       &resolver_, resolver_factory_.get(), effective_config, decider_result,
-      script_data, base::Bind(&ProxyService::OnInitProxyResolverComplete,
-                              base::Unretained(this)));
+      script_data,
+      base::Bind(&ProxyResolutionService::OnInitProxyResolverComplete,
+                 base::Unretained(this)));
 
   if (rv != ERR_IO_PENDING)
     OnInitProxyResolverComplete(rv);
 }
 
-void ProxyService::OnIPAddressChanged() {
+void ProxyResolutionService::OnIPAddressChanged() {
   // See the comment block by |kDelayAfterNetworkChangesMs| for info.
   stall_proxy_autoconfig_until_ =
       TimeTicks::Now() + stall_proxy_auto_config_delay_;
@@ -1633,7 +1648,7 @@
     ApplyProxyConfigIfAvailable();
 }
 
-void ProxyService::OnDNSChanged() {
+void ProxyResolutionService::OnDNSChanged() {
   OnIPAddressChanged();
 }
 
diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h
index b615543..24aa304 100644
--- a/net/proxy/proxy_service.h
+++ b/net/proxy/proxy_service.h
@@ -47,9 +47,10 @@
 // This class can be used to resolve the proxy server to use when loading a
 // HTTP(S) URL.  It uses the given ProxyResolver to handle the actual proxy
 // resolution.  See ProxyResolverV8 for example.
-class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver,
-                                public NetworkChangeNotifier::DNSObserver,
-                                public ProxyConfigService::Observer {
+class NET_EXPORT ProxyResolutionService
+    : public NetworkChangeNotifier::IPAddressObserver,
+      public NetworkChangeNotifier::DNSObserver,
+      public ProxyConfigService::Observer {
  public:
   // Enumerates the policy to use when sanitizing URLs for proxy resolution
   // (before passing them off to PAC scripts).
@@ -112,12 +113,12 @@
   };
 
   // |net_log| is a possibly NULL destination to send log events to. It must
-  // remain alive for the lifetime of this ProxyService.
-  ProxyService(std::unique_ptr<ProxyConfigService> config_service,
-               std::unique_ptr<ProxyResolverFactory> resolver_factory,
-               NetLog* net_log);
+  // remain alive for the lifetime of this ProxyResolutionService.
+  ProxyResolutionService(std::unique_ptr<ProxyConfigService> config_service,
+                         std::unique_ptr<ProxyResolverFactory> resolver_factory,
+                         NetLog* net_log);
 
-  ~ProxyService() override;
+  ~ProxyResolutionService() override;
 
   // Used to track proxy resolution requests that complete asynchronously.
   class Request;
@@ -221,14 +222,15 @@
   ProxyScriptFetcher* GetProxyScriptFetcher() const;
 
   // Cancels all network requests, and prevents the service from creating new
-  // ones.  Must be called before the URLRequestContext the ProxyService was
-  // created with is torn down, if it's torn down before th ProxyService itself.
+  // ones.  Must be called before the URLRequestContext the
+  // ProxyResolutionService was created with is torn down, if it's torn down
+  // before th ProxyResolutionService itself.
   void OnShutdown();
 
-  // Tells this ProxyService to start using a new ProxyConfigService to
-  // retrieve its ProxyConfig from. The new ProxyConfigService will immediately
-  // be queried for new config info which will be used for all subsequent
-  // ResolveProxy calls.
+  // Tells this ProxyResolutionService to start using a new ProxyConfigService
+  // to retrieve its ProxyConfig from. The new ProxyConfigService will
+  // immediately be queried for new config info which will be used for all
+  // subsequent ResolveProxy calls.
   void ResetConfigService(
       std::unique_ptr<ProxyConfigService> new_proxy_config_service);
 
@@ -260,31 +262,34 @@
   // Same as CreateProxyServiceUsingV8ProxyResolver, except it uses system
   // libraries for evaluating the PAC script if available, otherwise skips
   // proxy autoconfig.
-  static std::unique_ptr<ProxyService> CreateUsingSystemProxyResolver(
+  static std::unique_ptr<ProxyResolutionService> CreateUsingSystemProxyResolver(
       std::unique_ptr<ProxyConfigService> proxy_config_service,
       NetLog* net_log);
 
-  // Creates a ProxyService without support for proxy autoconfig.
-  static std::unique_ptr<ProxyService> CreateWithoutProxyResolver(
+  // Creates a ProxyResolutionService without support for proxy autoconfig.
+  static std::unique_ptr<ProxyResolutionService> CreateWithoutProxyResolver(
       std::unique_ptr<ProxyConfigService> proxy_config_service,
       NetLog* net_log);
 
   // Convenience methods that creates a proxy service using the
   // specified fixed settings.
-  static std::unique_ptr<ProxyService> CreateFixed(const ProxyConfig& pc);
-  static std::unique_ptr<ProxyService> CreateFixed(const std::string& proxy);
+  static std::unique_ptr<ProxyResolutionService> CreateFixed(
+      const ProxyConfig& pc);
+  static std::unique_ptr<ProxyResolutionService> CreateFixed(
+      const std::string& proxy);
 
   // Creates a proxy service that uses a DIRECT connection for all requests.
-  static std::unique_ptr<ProxyService> CreateDirect();
-  // |net_log|'s lifetime must exceed ProxyService.
-  static std::unique_ptr<ProxyService> CreateDirectWithNetLog(NetLog* net_log);
+  static std::unique_ptr<ProxyResolutionService> CreateDirect();
+  // |net_log|'s lifetime must exceed ProxyResolutionService.
+  static std::unique_ptr<ProxyResolutionService> CreateDirectWithNetLog(
+      NetLog* net_log);
 
-  // This method is used by tests to create a ProxyService that returns a
-  // hardcoded proxy fallback list (|pac_string|) for every URL.
+  // This method is used by tests to create a ProxyResolutionService that
+  // returns a hardcoded proxy fallback list (|pac_string|) for every URL.
   //
   // |pac_string| is a list of proxy servers, in the format that a PAC script
   // would return it. For example, "PROXY foobar:99; SOCKS fml:2; DIRECT"
-  static std::unique_ptr<ProxyService> CreateFixedFromPacResult(
+  static std::unique_ptr<ProxyResolutionService> CreateFixedFromPacResult(
       const std::string& pac_string);
 
   // Creates a config service appropriate for this platform that fetches the
@@ -303,7 +308,7 @@
       const PacPollPolicy* policy);
 
   // This method should only be used by unit tests. Creates an instance
-  // of the default internal PacPollPolicy used by ProxyService.
+  // of the default internal PacPollPolicy used by ProxyResolutionService.
   static std::unique_ptr<PacPollPolicy> CreateDefaultPacPollPolicy();
 
   void set_quick_check_enabled(bool value) {
@@ -478,7 +483,7 @@
 
   THREAD_CHECKER(thread_checker_);
 
-  DISALLOW_COPY_AND_ASSIGN(ProxyService);
+  DISALLOW_COPY_AND_ASSIGN(ProxyResolutionService);
 };
 
 }  // namespace net
diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc
index c5c60f58..7259d14a 100644
--- a/net/proxy/proxy_service_unittest.cc
+++ b/net/proxy/proxy_service_unittest.cc
@@ -23,12 +23,12 @@
 #include "net/log/test_net_log.h"
 #include "net/log/test_net_log_entry.h"
 #include "net/log/test_net_log_util.h"
-#include "net/proxy/dhcp_proxy_script_fetcher.h"
+#include "net/proxy/dhcp_pac_file_fetcher.h"
+#include "net/proxy/mock_pac_file_fetcher.h"
 #include "net/proxy/mock_proxy_resolver.h"
-#include "net/proxy/mock_proxy_script_fetcher.h"
+#include "net/proxy/pac_file_fetcher.h"
 #include "net/proxy/proxy_config_service.h"
 #include "net/proxy/proxy_resolver.h"
-#include "net/proxy/proxy_script_fetcher.h"
 #include "net/proxy/proxy_server.h"
 #include "net/test/gtest_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -44,12 +44,12 @@
 using base::ASCIIToUTF16;
 
 // TODO(eroman): Write a test which exercises
-//              ProxyService::SuspendAllPendingRequests().
+//              ProxyResolutionService::SuspendAllPendingRequests().
 namespace net {
 namespace {
 
 // This polling policy will decide to poll every 1 ms.
-class ImmediatePollPolicy : public ProxyService::PacPollPolicy {
+class ImmediatePollPolicy : public ProxyResolutionService::PacPollPolicy {
  public:
   ImmediatePollPolicy() = default;
 
@@ -66,7 +66,7 @@
 
 // This polling policy chooses a fantastically large delay. In other words, it
 // will never trigger a poll
-class NeverPollPolicy : public ProxyService::PacPollPolicy {
+class NeverPollPolicy : public ProxyResolutionService::PacPollPolicy {
  public:
   NeverPollPolicy() = default;
 
@@ -82,7 +82,8 @@
 };
 
 // This polling policy starts a poll immediately after network activity.
-class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy {
+class ImmediateAfterActivityPollPolicy
+    : public ProxyResolutionService::PacPollPolicy {
  public:
   ImmediateAfterActivityPollPolicy() = default;
 
@@ -98,8 +99,8 @@
 };
 
 // This test fixture is used to partially disable the background polling done by
-// the ProxyService (which it uses to detect whenever its PAC script contents or
-// WPAD results have changed).
+// the ProxyResolutionService (which it uses to detect whenever its PAC script
+// contents or WPAD results have changed).
 //
 // We disable the feature by setting the poll interval to something really
 // large, so it will never actually be reached even on the slowest bots that run
@@ -117,18 +118,18 @@
   void SetUp() override {
     testing::Test::SetUp();
     previous_policy_ =
-        ProxyService::set_pac_script_poll_policy(&never_poll_policy_);
+        ProxyResolutionService::set_pac_script_poll_policy(&never_poll_policy_);
   }
 
   void TearDown() override {
     // Restore the original policy.
-    ProxyService::set_pac_script_poll_policy(previous_policy_);
+    ProxyResolutionService::set_pac_script_poll_policy(previous_policy_);
     testing::Test::TearDown();
   }
 
  private:
   NeverPollPolicy never_poll_policy_;
-  const ProxyService::PacPollPolicy* previous_policy_;
+  const ProxyResolutionService::PacPollPolicy* previous_policy_;
 };
 
 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL";
@@ -218,8 +219,6 @@
   bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
     return true;
   }
-  void OnAlternativeProxyBroken(
-      const ProxyServer& alternative_proxy_server) override {}
 
  private:
   bool on_resolve_proxy_called_;
@@ -248,8 +247,6 @@
   bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
     return true;
   }
-  void OnAlternativeProxyBroken(
-      const ProxyServer& alternative_proxy_server) override {}
 
   bool on_proxy_fallback_called() const {
     return on_proxy_fallback_called_;
@@ -344,7 +341,7 @@
 TEST_F(ProxyServiceTest, Direct) {
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
-  ProxyService service(
+  ProxyResolutionService service(
       std::make_unique<MockProxyConfigService>(ProxyConfig::CreateDirect()),
       base::WrapUnique(factory), nullptr);
 
@@ -381,8 +378,8 @@
   config.set_auto_detect(false);
   config.proxy_rules().bypass_rules.ParseFromString("*.org");
 
-  ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                       nullptr, nullptr);
+  ProxyResolutionService service(
+      std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
 
   GURL url("http://www.google.com/");
   GURL bypass_url("http://internet.org");
@@ -391,8 +388,8 @@
   TestCompletionCallback callback;
   BoundTestNetLog log;
 
-  // First, warm up the ProxyService and fake an error to mark the first server
-  // as bad.
+  // First, warm up the ProxyResolutionService and fake an error to mark the
+  // first server as bad.
   int rv = service.ResolveProxy(url, std::string(), &info, callback.callback(),
                                 nullptr, nullptr, log.bound());
   EXPECT_THAT(rv, IsOk());
@@ -448,8 +445,8 @@
   config.set_auto_detect(false);
   config.proxy_rules().bypass_rules.ParseFromString("*.org");
 
-  ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                       nullptr, nullptr);
+  ProxyResolutionService service(
+      std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
 
   GURL url("http://www.google.com/");
   GURL bypass_url("http://internet.org");
@@ -458,7 +455,7 @@
   TestCompletionCallback callback;
   BoundTestNetLog log;
 
-  // First, warm up the ProxyService.
+  // First, warm up the ProxyResolutionService.
   int rv = service.ResolveProxy(url, std::string(), &info, callback.callback(),
                                 nullptr, nullptr, log.bound());
   EXPECT_THAT(rv, IsOk());
@@ -492,14 +489,14 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
   ProxyInfo info;
   TestCompletionCallback callback;
-  ProxyService::Request* request;
+  ProxyResolutionService::Request* request;
   BoundTestNetLog log;
 
   int rv = service.ResolveProxy(url, std::string(), &info, callback.callback(),
@@ -553,8 +550,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://username:password@www.google.com/?ref#hash#hash");
 
@@ -574,7 +571,7 @@
             resolver.pending_jobs()[0]->url());
 
   // We end here without ever completing the request -- destruction of
-  // ProxyService will cancel the outstanding request.
+  // ProxyResolutionService will cancel the outstanding request.
 }
 
 TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
@@ -584,8 +581,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -638,8 +635,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://this-causes-js-error/");
 
@@ -696,8 +693,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -772,8 +769,8 @@
   MockAsyncProxyResolver resolver;
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   // Resolve something.
   GURL url("http://www.google.com/");
@@ -810,8 +807,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   // Start first resolve request.
   GURL url("http://www.google.com/");
@@ -831,8 +828,8 @@
   // Fail the first resolve request in MockAsyncProxyResolver.
   resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
 
-  // Although the proxy resolver failed the request, ProxyService implicitly
-  // falls-back to DIRECT.
+  // Although the proxy resolver failed the request, ProxyResolutionService
+  // implicitly falls-back to DIRECT.
   EXPECT_THAT(callback1.WaitForResult(), IsOk());
   EXPECT_TRUE(info.is_direct());
 
@@ -872,8 +869,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   // Start first resolve request.
   GURL url("http://www.google.com/");
@@ -894,8 +891,8 @@
   // Fail the first resolve request in MockAsyncProxyResolver.
   resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
 
-  // Although the proxy resolver failed the request, ProxyService implicitly
-  // falls-back to DIRECT.
+  // Although the proxy resolver failed the request, ProxyResolutionService
+  // implicitly falls-back to DIRECT.
   EXPECT_THAT(callback1.WaitForResult(), IsOk());
   EXPECT_TRUE(info.is_direct());
 
@@ -904,8 +901,8 @@
   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
 
-  // With no other requests, the ProxyService waits for a new request before
-  // initializing a new ProxyResolver.
+  // With no other requests, the ProxyResolutionService waits for a new request
+  // before initializing a new ProxyResolver.
   EXPECT_TRUE(factory->pending_requests().empty());
 
   TestCompletionCallback callback2;
@@ -942,8 +939,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   // Start two resolve requests.
   GURL url1("http://www.google.com/");
@@ -969,8 +966,8 @@
   // Fail the first resolve request in MockAsyncProxyResolver.
   jobs[url1]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
 
-  // Although the proxy resolver failed the request, ProxyService implicitly
-  // falls-back to DIRECT.
+  // Although the proxy resolver failed the request, ProxyResolutionService
+  // implicitly falls-back to DIRECT.
   EXPECT_THAT(callback1.WaitForResult(), IsOk());
   EXPECT_TRUE(info.is_direct());
 
@@ -982,7 +979,7 @@
   // The second request is cancelled when the proxy resolver terminates.
   jobs = GetCancelledJobsForURLs(resolver, url2);
 
-  // Since a second request was in progress, the ProxyService starts
+  // Since a second request was in progress, the ProxyResolutionService starts
   // initializating a new ProxyResolver.
   ASSERT_EQ(1u, factory->pending_requests().size());
   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
@@ -1013,8 +1010,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   // Start first resolve request.
   GURL url("http://www.google.com/");
@@ -1030,13 +1027,15 @@
 
   ASSERT_EQ(0u, factory->pending_requests().size());
   // As the proxy resolver factory failed the request and is configured for a
-  // mandatory PAC script, ProxyService must not implicitly fall-back to DIRECT.
+  // mandatory PAC script, ProxyResolutionService must not implicitly fall-back
+  // to DIRECT.
   EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
             callback1.WaitForResult());
   EXPECT_FALSE(info.is_direct());
 
   // As the proxy resolver factory failed the request and is configured for a
-  // mandatory PAC script, ProxyService must not implicitly fall-back to DIRECT.
+  // mandatory PAC script, ProxyResolutionService must not implicitly fall-back
+  // to DIRECT.
   TestCompletionCallback callback2;
   rv = service.ResolveProxy(url, std::string(), &info, callback2.callback(),
                             nullptr, nullptr, NetLogWithSource());
@@ -1058,8 +1057,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -1086,8 +1085,8 @@
   ASSERT_EQ(0u, factory->pending_requests().size());
 
   // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
-  // mandatory for this configuration, the ProxyService must not implicitly
-  // fall-back to DIRECT.
+  // mandatory for this configuration, the ProxyResolutionService must not
+  // implicitly fall-back to DIRECT.
   EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
             callback.WaitForResult());
   EXPECT_FALSE(info.is_direct());
@@ -1109,8 +1108,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   // Start first resolve request.
   GURL url("http://www.google.com/");
@@ -1131,7 +1130,7 @@
   resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
 
   // As the proxy resolver failed the request and is configured for a mandatory
-  // PAC script, ProxyService must not implicitly fall-back to DIRECT.
+  // PAC script, ProxyResolutionService must not implicitly fall-back to DIRECT.
   EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
             callback1.WaitForResult());
   EXPECT_FALSE(info.is_direct());
@@ -1167,8 +1166,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -1317,8 +1316,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -1390,8 +1389,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -1493,8 +1492,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -1544,8 +1543,8 @@
   // This simulates a javascript runtime error in the PAC script.
   resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
 
-  // Although the resolver failed, the ProxyService will implicitly fall-back
-  // to a DIRECT connection.
+  // Although the resolver failed, the ProxyResolutionService will implicitly
+  // fall-back to a DIRECT connection.
   EXPECT_THAT(callback3.WaitForResult(), IsOk());
   EXPECT_TRUE(info2.is_direct());
   EXPECT_FALSE(info2.is_empty());
@@ -1591,8 +1590,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -1642,7 +1641,7 @@
   // This simulates a javascript runtime error in the PAC script.
   resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
 
-  // Although the resolver failed, the ProxyService will NOT fall-back
+  // Although the resolver failed, the ProxyResolutionService will NOT fall-back
   // to a DIRECT connection as it is configured as mandatory.
   EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
             callback3.WaitForResult());
@@ -1683,8 +1682,8 @@
   config.set_auto_detect(false);
   config.proxy_rules().bypass_rules.ParseFromString("*.org");
 
-  ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                       nullptr, nullptr);
+  ProxyResolutionService service(
+      std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
 
   int rv;
   GURL url1("http://www.webkit.org");
@@ -1724,8 +1723,8 @@
 
   EXPECT_EQ(3u, additional_bad_proxies.size());
 
-  ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                       nullptr, nullptr);
+  ProxyResolutionService service(
+      std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
   ProxyInfo proxy_info;
   proxy_info.UseProxyList(proxy_list);
   const ProxyRetryInfoMap& retry_info = service.proxy_retry_info();
@@ -1745,8 +1744,8 @@
   config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
   config.set_auto_detect(false);
   {
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("http://www.msn.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1758,8 +1757,8 @@
     EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
   }
   {
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("ftp://ftp.google.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1771,8 +1770,8 @@
     EXPECT_EQ("direct://", info.proxy_server().ToURI());
   }
   {
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("https://webbranch.techcu.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1785,8 +1784,8 @@
   }
   {
     config.proxy_rules().ParseFromString("foopy1:8080");
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("http://www.microsoft.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1807,8 +1806,8 @@
     ProxyConfig config;
     config.set_source(PROXY_CONFIG_SOURCE_TEST);
     config.proxy_rules().ParseFromString("https=foopy2:8080");
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("http://www.google.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1823,8 +1822,8 @@
     ProxyConfig config;
     config.set_source(PROXY_CONFIG_SOURCE_TEST);
     config.proxy_rules().ParseFromString("https=foopy2:8080");
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("https://www.google.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1838,8 +1837,8 @@
   {
     ProxyConfig config;
     config.set_source(PROXY_CONFIG_SOURCE_TEST);
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("http://www.google.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1862,8 +1861,8 @@
             config.proxy_rules().type);
 
   {
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("http://www.msn.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1875,8 +1874,8 @@
     EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
   }
   {
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("ftp://ftp.google.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1888,8 +1887,8 @@
     EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
   }
   {
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("https://webbranch.techcu.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1901,8 +1900,8 @@
     EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
   }
   {
-    ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                         nullptr, nullptr);
+    ProxyResolutionService service(
+        std::make_unique<MockProxyConfigService>(config), nullptr, nullptr);
     GURL test_url("unknown://www.microsoft.com");
     ProxyInfo info;
     TestCompletionCallback callback;
@@ -1927,8 +1926,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   // Start 3 requests.
 
@@ -1948,7 +1947,7 @@
 
   ProxyInfo info2;
   TestCompletionCallback callback2;
-  ProxyService::Request* request2;
+  ProxyResolutionService::Request* request2;
   rv = service.ResolveProxy(url2, std::string(), &info2, callback2.callback(),
                             &request2, nullptr, NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -1997,8 +1996,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2009,7 +2008,7 @@
 
   ProxyInfo info1;
   TestCompletionCallback callback1;
-  ProxyService::Request* request1;
+  ProxyResolutionService::Request* request1;
   int rv =
       service.ResolveProxy(url1, std::string(), &info1, callback1.callback(),
                            &request1, nullptr, NetLogWithSource());
@@ -2021,14 +2020,14 @@
 
   ProxyInfo info2;
   TestCompletionCallback callback2;
-  ProxyService::Request* request2;
+  ProxyResolutionService::Request* request2;
   rv = service.ResolveProxy(url2, std::string(), &info2, callback2.callback(),
                             &request2, nullptr, NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   ProxyInfo info3;
   TestCompletionCallback callback3;
-  ProxyService::Request* request3;
+  ProxyResolutionService::Request* request3;
   rv = service.ResolveProxy(url3, std::string(), &info3, callback3.callback(),
                             &request3, nullptr, NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -2043,7 +2042,7 @@
   EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
             service.GetLoadState(request3));
 
-  // At this point the ProxyService should be waiting for the
+  // At this point the ProxyResolutionService should be waiting for the
   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   // PAC script download completion.
   fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
@@ -2105,8 +2104,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2132,12 +2131,12 @@
                             nullptr, nullptr, NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
-  // At this point the ProxyService should be waiting for the
+  // At this point the ProxyResolutionService should be waiting for the
   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   // PAC script download completion.
 
-  // We now change out the ProxyService's script fetcher. We should restart
-  // the initialization with the new fetcher.
+  // We now change out the ProxyResolutionService's script fetcher. We should
+  // restart the initialization with the new fetcher.
 
   fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2167,8 +2166,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2178,7 +2177,7 @@
   // Start 3 requests.
   ProxyInfo info1;
   TestCompletionCallback callback1;
-  ProxyService::Request* request1;
+  ProxyResolutionService::Request* request1;
   BoundTestNetLog log1;
   int rv = service.ResolveProxy(GURL("http://request1"), std::string(), &info1,
                                 callback1.callback(), &request1, nullptr,
@@ -2191,7 +2190,7 @@
 
   ProxyInfo info2;
   TestCompletionCallback callback2;
-  ProxyService::Request* request2;
+  ProxyResolutionService::Request* request2;
   rv = service.ResolveProxy(GURL("http://request2"), std::string(), &info2,
                             callback2.callback(), &request2, nullptr,
                             NetLogWithSource());
@@ -2211,7 +2210,7 @@
   service.CancelRequest(request1);
   service.CancelRequest(request2);
 
-  // At this point the ProxyService should be waiting for the
+  // At this point the ProxyResolutionService should be waiting for the
   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   // PAC script download completion.
   fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
@@ -2266,8 +2265,8 @@
   MockAsyncProxyResolver resolver;
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2285,7 +2284,7 @@
 
   ProxyInfo info2;
   TestCompletionCallback callback2;
-  ProxyService::Request* request2;
+  ProxyResolutionService::Request* request2;
   rv = service.ResolveProxy(url2, std::string(), &info2, callback2.callback(),
                             &request2, nullptr, NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -2350,8 +2349,8 @@
   MockAsyncProxyResolver resolver;
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2369,7 +2368,7 @@
 
   ProxyInfo info2;
   TestCompletionCallback callback2;
-  ProxyService::Request* request2;
+  ProxyResolutionService::Request* request2;
   rv = service.ResolveProxy(url2, std::string(), &info2, callback2.callback(),
                             &request2, nullptr, NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -2427,8 +2426,8 @@
   MockProxyConfigService* config_service = new MockProxyConfigService(config);
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2446,7 +2445,7 @@
 
   ProxyInfo info2;
   TestCompletionCallback callback2;
-  ProxyService::Request* request2;
+  ProxyResolutionService::Request* request2;
   rv = service.ResolveProxy(GURL("http://request2"), std::string(), &info2,
                             callback2.callback(), &request2, nullptr,
                             NetLogWithSource());
@@ -2490,8 +2489,8 @@
   MockAsyncProxyResolver resolver;
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2549,7 +2548,7 @@
   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
 }
 
-// Delete the ProxyService while InitProxyResolver has an outstanding
+// Delete the ProxyResolutionService while InitProxyResolver has an outstanding
 // request to the script fetcher. When run under valgrind, should not
 // have any memory errors (used to be that the ProxyScriptFetcher was
 // being deleted prior to the InitProxyResolver).
@@ -2560,8 +2559,8 @@
   MockProxyConfigService* config_service = new MockProxyConfigService(config);
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2586,7 +2585,7 @@
   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
 }
 
-// Delete the ProxyService while InitProxyResolver has an outstanding
+// Delete the ProxyResolutionService while InitProxyResolver has an outstanding
 // request to the proxy resolver. When run under valgrind, should not
 // have any memory errors (used to be that the ProxyResolver was
 // being deleted prior to the InitProxyResolver).
@@ -2597,8 +2596,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -2616,8 +2615,8 @@
   ProxyConfig config1;
   config1.proxy_rules().ParseFromString("foopy1:8080");
   config1.set_auto_detect(false);
-  ProxyService service(std::make_unique<MockProxyConfigService>(config1),
-                       nullptr, nullptr);
+  ProxyResolutionService service(
+      std::make_unique<MockProxyConfigService>(config1), nullptr, nullptr);
 
   ProxyInfo info;
   TestCompletionCallback callback1;
@@ -2648,8 +2647,8 @@
   MockAsyncProxyResolver resolver;
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   // Start 1 request.
 
@@ -2674,7 +2673,7 @@
   EXPECT_THAT(callback1.WaitForResult(), IsOk());
   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
 
-  // Force the ProxyService to pull down a new proxy configuration.
+  // Force the ProxyResolutionService to pull down a new proxy configuration.
   // (Even though the configuration isn't old/bad).
   //
   // This new configuration no longer has auto_detect set, so
@@ -2702,8 +2701,8 @@
 
   TestNetLog log;
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), &log);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), &log);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2730,7 +2729,7 @@
   // Nothing has been sent to the factory yet.
   EXPECT_TRUE(factory->pending_requests().empty());
 
-  // At this point the ProxyService should be waiting for the
+  // At this point the ProxyResolutionService should be waiting for the
   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   // PAC script download completion.
   fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
@@ -2816,7 +2815,7 @@
   // Change the retry policy to wait a mere 1 ms before retrying, so the test
   // runs quickly.
   ImmediatePollPolicy poll_policy;
-  ProxyService::set_pac_script_poll_policy(&poll_policy);
+  ProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
 
   MockProxyConfigService* config_service =
       new MockProxyConfigService("http://foopy/proxy.pac");
@@ -2825,8 +2824,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2849,7 +2848,7 @@
   // Nothing has been sent to the factory yet.
   EXPECT_TRUE(factory->pending_requests().empty());
 
-  // At this point the ProxyService should be waiting for the
+  // At this point the ProxyResolutionService should be waiting for the
   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   // PAC script download completion.
   //
@@ -2890,9 +2889,9 @@
             factory->pending_requests()[0]->script_data()->utf16());
   factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
 
-  // At this point the ProxyService should have re-configured itself to use the
-  // PAC script (thereby recovering from the initial fetch failure). We will
-  // verify that the next Resolve request uses the resolver rather than
+  // At this point the ProxyResolutionService should have re-configured itself
+  // to use the PAC script (thereby recovering from the initial fetch failure).
+  // We will verify that the next Resolve request uses the resolver rather than
   // DIRECT.
 
   // Start a second request.
@@ -2924,7 +2923,7 @@
   // Change the retry policy to wait a mere 1 ms before retrying, so the test
   // runs quickly.
   ImmediatePollPolicy poll_policy;
-  ProxyService::set_pac_script_poll_policy(&poll_policy);
+  ProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
 
   MockProxyConfigService* config_service =
       new MockProxyConfigService("http://foopy/proxy.pac");
@@ -2933,8 +2932,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -2957,7 +2956,7 @@
   // Nothing has been sent to the factory yet.
   EXPECT_TRUE(factory->pending_requests().empty());
 
-  // At this point the ProxyService should be waiting for the
+  // At this point the ProxyResolutionService should be waiting for the
   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   // PAC script download completion.
   fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
@@ -3006,8 +3005,8 @@
             factory->pending_requests()[0]->script_data()->utf16());
   factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
 
-  // At this point the ProxyService should have re-configured itself to use the
-  // new PAC script.
+  // At this point the ProxyResolutionService should have re-configured itself
+  // to use the new PAC script.
 
   // Start a second request.
   ProxyInfo info2;
@@ -3038,7 +3037,7 @@
   // Change the retry policy to wait a mere 1 ms before retrying, so the test
   // runs quickly.
   ImmediatePollPolicy poll_policy;
-  ProxyService::set_pac_script_poll_policy(&poll_policy);
+  ProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
 
   MockProxyConfigService* config_service =
       new MockProxyConfigService("http://foopy/proxy.pac");
@@ -3047,8 +3046,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -3071,7 +3070,7 @@
   // Nothing has been sent to the factory yet.
   EXPECT_TRUE(factory->pending_requests().empty());
 
-  // At this point the ProxyService should be waiting for the
+  // At this point the ProxyResolutionService should be waiting for the
   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   // PAC script download completion.
   fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
@@ -3117,8 +3116,8 @@
   ASSERT_TRUE(factory->pending_requests().empty());
   ASSERT_TRUE(resolver.pending_jobs().empty());
 
-  // At this point the ProxyService is still running the same PAC script as
-  // before.
+  // At this point the ProxyResolutionService is still running the same PAC
+  // script as before.
 
   // Start a second request.
   ProxyInfo info2;
@@ -3144,12 +3143,12 @@
 // This test verifies that the PAC script specified by the settings is
 // periodically polled for changes. Specifically, if the initial fetch succeeds,
 // however at a later time it starts to fail, we should re-configure the
-// ProxyService to stop using that PAC script.
+// ProxyResolutionService to stop using that PAC script.
 TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
   // Change the retry policy to wait a mere 1 ms before retrying, so the test
   // runs quickly.
   ImmediatePollPolicy poll_policy;
-  ProxyService::set_pac_script_poll_policy(&poll_policy);
+  ProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
 
   MockProxyConfigService* config_service =
       new MockProxyConfigService("http://foopy/proxy.pac");
@@ -3158,8 +3157,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -3182,7 +3181,7 @@
   // Nothing has been sent to the factory yet.
   EXPECT_TRUE(factory->pending_requests().empty());
 
-  // At this point the ProxyService should be waiting for the
+  // At this point the ProxyResolutionService should be waiting for the
   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   // PAC script download completion.
   fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
@@ -3225,8 +3224,8 @@
 
   base::RunLoop().RunUntilIdle();
 
-  // At this point the ProxyService should have re-configured itself to use
-  // DIRECT connections rather than the given proxy resolver.
+  // At this point the ProxyResolutionService should have re-configured itself
+  // to use DIRECT connections rather than the given proxy resolver.
 
   // Start a second request.
   ProxyInfo info2;
@@ -3241,12 +3240,13 @@
 // Tests that the code which decides at what times to poll the PAC
 // script follows the expected policy.
 TEST_F(ProxyServiceTest, PACScriptPollingPolicy) {
-  // Retrieve the internal polling policy implementation used by ProxyService.
-  std::unique_ptr<ProxyService::PacPollPolicy> policy =
-      ProxyService::CreateDefaultPacPollPolicy();
+  // Retrieve the internal polling policy implementation used by
+  // ProxyResolutionService.
+  std::unique_ptr<ProxyResolutionService::PacPollPolicy> policy =
+      ProxyResolutionService::CreateDefaultPacPollPolicy();
 
   int error;
-  ProxyService::PacPollPolicy::Mode mode;
+  ProxyResolutionService::PacPollPolicy::Mode mode;
   const base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(-1);
   base::TimeDelta delay = initial_delay;
 
@@ -3258,27 +3258,31 @@
   // Poll #0
   mode = policy->GetNextDelay(error, initial_delay, &delay);
   EXPECT_EQ(8, delay.InSeconds());
-  EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode);
+  EXPECT_EQ(ProxyResolutionService::PacPollPolicy::MODE_USE_TIMER, mode);
 
   // Poll #1
   mode = policy->GetNextDelay(error, delay, &delay);
   EXPECT_EQ(32, delay.InSeconds());
-  EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
+  EXPECT_EQ(ProxyResolutionService::PacPollPolicy::MODE_START_AFTER_ACTIVITY,
+            mode);
 
   // Poll #2
   mode = policy->GetNextDelay(error, delay, &delay);
   EXPECT_EQ(120, delay.InSeconds());
-  EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
+  EXPECT_EQ(ProxyResolutionService::PacPollPolicy::MODE_START_AFTER_ACTIVITY,
+            mode);
 
   // Poll #3
   mode = policy->GetNextDelay(error, delay, &delay);
   EXPECT_EQ(14400, delay.InSeconds());
-  EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
+  EXPECT_EQ(ProxyResolutionService::PacPollPolicy::MODE_START_AFTER_ACTIVITY,
+            mode);
 
   // Poll #4
   mode = policy->GetNextDelay(error, delay, &delay);
   EXPECT_EQ(14400, delay.InSeconds());
-  EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
+  EXPECT_EQ(ProxyResolutionService::PacPollPolicy::MODE_START_AFTER_ACTIVITY,
+            mode);
 
   // --------------------------------------------------
   // Test the poll sequence in response to a success.
@@ -3288,24 +3292,27 @@
   // Poll #0
   mode = policy->GetNextDelay(error, initial_delay, &delay);
   EXPECT_EQ(43200, delay.InSeconds());
-  EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
+  EXPECT_EQ(ProxyResolutionService::PacPollPolicy::MODE_START_AFTER_ACTIVITY,
+            mode);
 
   // Poll #1
   mode = policy->GetNextDelay(error, delay, &delay);
   EXPECT_EQ(43200, delay.InSeconds());
-  EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
+  EXPECT_EQ(ProxyResolutionService::PacPollPolicy::MODE_START_AFTER_ACTIVITY,
+            mode);
 
   // Poll #2
   mode = policy->GetNextDelay(error, delay, &delay);
   EXPECT_EQ(43200, delay.InSeconds());
-  EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
+  EXPECT_EQ(ProxyResolutionService::PacPollPolicy::MODE_START_AFTER_ACTIVITY,
+            mode);
 }
 
 // This tests the polling of the PAC script. Specifically, it tests that
 // polling occurs in response to user activity.
 TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
   ImmediateAfterActivityPollPolicy poll_policy;
-  ProxyService::set_pac_script_poll_policy(&poll_policy);
+  ProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
 
   MockProxyConfigService* config_service =
       new MockProxyConfigService("http://foopy/proxy.pac");
@@ -3314,8 +3321,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -3338,7 +3345,7 @@
   // Nothing has been sent to the factory yet.
   EXPECT_TRUE(factory->pending_requests().empty());
 
-  // At this point the ProxyService should be waiting for the
+  // At this point the ProxyResolutionService should be waiting for the
   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   // PAC script download completion.
   fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
@@ -3394,7 +3401,7 @@
   // This time we will fail the download, to simulate a PAC script change.
   fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
 
-  // Drain the message loop, so ProxyService is notified of the change
+  // Drain the message loop, so ProxyResolutionService is notified of the change
   // and has a chance to re-configure itself.
   base::RunLoop().RunUntilIdle();
 
@@ -3417,8 +3424,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -3444,8 +3451,9 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(false);
 
-  ProxyService service(std::make_unique<MockProxyConfigService>(config),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(
+      std::make_unique<MockProxyConfigService>(config),
+      base::WrapUnique(factory), nullptr);
 
   GURL url("http://www.google.com/");
 
@@ -3463,9 +3471,9 @@
 }
 
 // Helper class to exercise URL sanitization using the different policies. This
-// works by submitted URLs to the ProxyService. In turn the ProxyService
-// sanitizes the URL and then passes it along to the ProxyResolver. This helper
-// returns the URL seen by the ProxyResolver.
+// works by submitted URLs to the ProxyResolutionService. In turn the
+// ProxyResolutionService sanitizes the URL and then passes it along to the
+// ProxyResolver. This helper returns the URL seen by the ProxyResolver.
 class SanitizeUrlHelper {
  public:
   SanitizeUrlHelper() {
@@ -3474,8 +3482,8 @@
 
     factory = new MockAsyncProxyResolverFactory(false);
 
-    service_.reset(new ProxyService(std::move(config_service),
-                                    base::WrapUnique(factory), nullptr));
+    service_.reset(new ProxyResolutionService(
+        std::move(config_service), base::WrapUnique(factory), nullptr));
 
     // Do an initial request to initialize the service (configure the PAC
     // script).
@@ -3503,14 +3511,14 @@
     EXPECT_TRUE(info.is_direct());
   }
 
-  // Changes the URL sanitization policy for the underlying ProxyService. This
-  // will affect subsequent calls to SanitizeUrl.
-  void SetSanitizeUrlPolicy(ProxyService::SanitizeUrlPolicy policy) {
+  // Changes the URL sanitization policy for the underlying
+  // ProxyResolutionService. This will affect subsequent calls to SanitizeUrl.
+  void SetSanitizeUrlPolicy(ProxyResolutionService::SanitizeUrlPolicy policy) {
     service_->set_sanitize_url_policy(policy);
   }
 
-  // Makes a proxy resolution request through the ProxyService, and returns the
-  // URL that was submitted to the Proxy Resolver.
+  // Makes a proxy resolution request through the ProxyResolutionService, and
+  // returns the URL that was submitted to the Proxy Resolver.
   GURL SanitizeUrl(const GURL& raw_url) {
     // Issue a request and see what URL is sent to the proxy resolver.
     ProxyInfo info;
@@ -3533,10 +3541,10 @@
     return sanitized_url;
   }
 
-  // Changes the ProxyService's URL sanitization policy and then sanitizes
-  // |raw_url|.
+  // Changes the ProxyResolutionService's URL sanitization policy and then
+  // sanitizes |raw_url|.
   GURL SanitizeUrl(const GURL& raw_url,
-                   ProxyService::SanitizeUrlPolicy policy) {
+                   ProxyResolutionService::SanitizeUrlPolicy policy) {
     service_->set_sanitize_url_policy(policy);
     return SanitizeUrl(raw_url);
   }
@@ -3544,7 +3552,7 @@
  private:
   MockAsyncProxyResolver resolver;
   MockAsyncProxyResolverFactory* factory;
-  std::unique_ptr<ProxyService> service_;
+  std::unique_ptr<ProxyResolutionService> service_;
 };
 
 TEST_F(ProxyServiceTest, SanitizeUrlDefaultsToSafe) {
@@ -3606,13 +3614,13 @@
     ASSERT_TRUE(raw_url.is_valid());
     EXPECT_FALSE(raw_url.SchemeIsCryptographic());
 
-    EXPECT_EQ(
-        GURL(test.sanitized_url),
-        helper.SanitizeUrl(raw_url, ProxyService::SanitizeUrlPolicy::UNSAFE));
+    EXPECT_EQ(GURL(test.sanitized_url),
+              helper.SanitizeUrl(
+                  raw_url, ProxyResolutionService::SanitizeUrlPolicy::UNSAFE));
 
-    EXPECT_EQ(
-        GURL(test.sanitized_url),
-        helper.SanitizeUrl(raw_url, ProxyService::SanitizeUrlPolicy::SAFE));
+    EXPECT_EQ(GURL(test.sanitized_url),
+              helper.SanitizeUrl(
+                  raw_url, ProxyResolutionService::SanitizeUrlPolicy::SAFE));
   }
 }
 
@@ -3672,13 +3680,13 @@
     ASSERT_TRUE(raw_url.is_valid());
     EXPECT_TRUE(raw_url.SchemeIsCryptographic());
 
-    EXPECT_EQ(
-        GURL(test.sanitized_url_unstripped),
-        helper.SanitizeUrl(raw_url, ProxyService::SanitizeUrlPolicy::UNSAFE));
+    EXPECT_EQ(GURL(test.sanitized_url_unstripped),
+              helper.SanitizeUrl(
+                  raw_url, ProxyResolutionService::SanitizeUrlPolicy::UNSAFE));
 
-    EXPECT_EQ(
-        GURL(test.sanitized_url),
-        helper.SanitizeUrl(raw_url, ProxyService::SanitizeUrlPolicy::SAFE));
+    EXPECT_EQ(GURL(test.sanitized_url),
+              helper.SanitizeUrl(
+                  raw_url, ProxyResolutionService::SanitizeUrlPolicy::SAFE));
   }
 }
 
@@ -3690,8 +3698,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -3700,7 +3708,7 @@
 
   ProxyInfo info;
   TestCompletionCallback callback;
-  ProxyService::Request* request;
+  ProxyResolutionService::Request* request;
   int rv = service.ResolveProxy(GURL("http://request/"), std::string(), &info,
                                 callback.callback(), &request, nullptr,
                                 NetLogWithSource());
@@ -3724,8 +3732,8 @@
   MockAsyncProxyResolverFactory* factory =
       new MockAsyncProxyResolverFactory(true);
 
-  ProxyService service(base::WrapUnique(config_service),
-                       base::WrapUnique(factory), nullptr);
+  ProxyResolutionService service(base::WrapUnique(config_service),
+                                 base::WrapUnique(factory), nullptr);
 
   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   service.SetProxyScriptFetchers(
@@ -3736,7 +3744,7 @@
 
   ProxyInfo info;
   TestCompletionCallback callback;
-  ProxyService::Request* request;
+  ProxyResolutionService::Request* request;
   int rv = service.ResolveProxy(GURL("http://request/"), std::string(), &info,
                                 callback.callback(), &request, nullptr,
                                 NetLogWithSource());
diff --git a/net/quic/chromium/quic_chromium_client_session_test.cc b/net/quic/chromium/quic_chromium_client_session_test.cc
index aaa3b2eb..61d91cf 100644
--- a/net/quic/chromium/quic_chromium_client_session_test.cc
+++ b/net/quic/chromium/quic_chromium_client_session_test.cc
@@ -598,7 +598,8 @@
 TEST_P(QuicChromiumClientSessionTest, ConnectionCloseBeforeStreamRequest) {
   MockQuicData quic_data;
   quic_data.AddWrite(client_maker_.MakeInitialSettingsPacket(1, nullptr));
-  quic_data.AddRead(server_maker_.MakeConnectionClosePacket(1));
+  quic_data.AddRead(server_maker_.MakeConnectionClosePacket(
+      1, false, QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!"));
   quic_data.AddSocketDataToFactory(&socket_factory_);
 
   Initialize();
@@ -622,7 +623,8 @@
 TEST_P(QuicChromiumClientSessionTest, ConnectionCloseBeforeHandshakeConfirmed) {
   MockQuicData quic_data;
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
-  quic_data.AddRead(server_maker_.MakeConnectionClosePacket(1));
+  quic_data.AddRead(server_maker_.MakeConnectionClosePacket(
+      1, false, QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!"));
   quic_data.AddSocketDataToFactory(&socket_factory_);
 
   Initialize();
@@ -650,7 +652,8 @@
   MockQuicData quic_data;
   quic_data.AddWrite(client_maker_.MakeInitialSettingsPacket(1, nullptr));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
-  quic_data.AddRead(server_maker_.MakeConnectionClosePacket(1));
+  quic_data.AddRead(server_maker_.MakeConnectionClosePacket(
+      1, false, QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!"));
   quic_data.AddSocketDataToFactory(&socket_factory_);
 
   Initialize();
diff --git a/net/quic/chromium/quic_end_to_end_unittest.cc b/net/quic/chromium/quic_end_to_end_unittest.cc
index 0d04152..57f2a92 100644
--- a/net/quic/chromium/quic_end_to_end_unittest.cc
+++ b/net/quic/chromium/quic_end_to_end_unittest.cc
@@ -102,7 +102,7 @@
         host_resolver_(std::move(host_resolver_impl_)),
         cert_transparency_verifier_(new MultiLogCTVerifier()),
         ssl_config_service_(new SSLConfigServiceDefaults),
-        proxy_service_(ProxyService::CreateDirect()),
+        proxy_resolution_service_(ProxyResolutionService::CreateDirect()),
         auth_handler_factory_(
             HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
         strike_register_no_startup_period_(false) {
@@ -122,7 +122,7 @@
     session_context_.cert_transparency_verifier =
         cert_transparency_verifier_.get();
     session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
-    session_context_.proxy_service = proxy_service_.get();
+    session_context_.proxy_resolution_service = proxy_resolution_service_.get();
     session_context_.ssl_config_service = ssl_config_service_.get();
     session_context_.http_auth_handler_factory = auth_handler_factory_.get();
     session_context_.http_server_properties = &http_server_properties_;
@@ -236,7 +236,7 @@
   std::unique_ptr<CTVerifier> cert_transparency_verifier_;
   CTPolicyEnforcer ct_policy_enforcer_;
   scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
   HttpServerPropertiesImpl http_server_properties_;
   HttpNetworkSession::Params session_params_;
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc
index ee1d6067..6eabefa 100644
--- a/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -78,6 +78,9 @@
 #include "testing/platform_test.h"
 #include "url/gurl.h"
 
+using ::testing::ElementsAre;
+using ::testing::Key;
+
 namespace net {
 namespace test {
 
@@ -262,7 +265,7 @@
                       false),
         cert_transparency_verifier_(new MultiLogCTVerifier()),
         ssl_config_service_(new SSLConfigServiceDefaults),
-        proxy_service_(ProxyService::CreateDirect()),
+        proxy_resolution_service_(ProxyResolutionService::CreateDirect()),
         auth_handler_factory_(
             HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
         random_generator_(0),
@@ -298,12 +301,14 @@
 
   std::unique_ptr<QuicEncryptedPacket> ConstructClientConnectionClosePacket(
       QuicPacketNumber num) {
-    return client_maker_.MakeConnectionClosePacket(num);
+    return client_maker_.MakeConnectionClosePacket(
+        num, false, QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!");
   }
 
   std::unique_ptr<QuicEncryptedPacket> ConstructServerConnectionClosePacket(
       QuicPacketNumber num) {
-    return server_maker_.MakeConnectionClosePacket(num);
+    return server_maker_.MakeConnectionClosePacket(
+        num, false, QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!");
   }
 
   std::unique_ptr<QuicEncryptedPacket> ConstructServerGoAwayPacket(
@@ -554,7 +559,7 @@
     session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
     session_context_.socket_performance_watcher_factory =
         &test_socket_performance_watcher_factory_;
-    session_context_.proxy_service = proxy_service_.get();
+    session_context_.proxy_resolution_service = proxy_resolution_service_.get();
     session_context_.ssl_config_service = ssl_config_service_.get();
     session_context_.http_auth_handler_factory = auth_handler_factory_.get();
     session_context_.http_server_properties = &http_server_properties_;
@@ -742,8 +747,9 @@
         ProxyServer::FromPacString("QUIC myproxy.org:443"));
 
     session_context_.proxy_delegate = &test_proxy_delegate;
-    proxy_service_ =
-        ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+    proxy_resolution_service_ =
+        ProxyResolutionService::CreateFixedFromPacResult(
+            "HTTPS myproxy.org:443");
 
     CreateSession();
     EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_valid());
@@ -751,12 +757,10 @@
     // The first request should be fetched via the HTTPS proxy.
     SendRequestAndExpectHttpResponseFromProxy("hello from http", true, 443);
 
-    // Even through the alternative proxy server job failed, the proxy should
-    // not be marked as bad since the main job succeeded.
-    EXPECT_TRUE(session_->proxy_service()->proxy_retry_info().empty());
-
-    // The alternative proxy server should no longer be in use.
-    EXPECT_FALSE(test_proxy_delegate.alternative_proxy_server().is_valid());
+    // Since the main job succeeded only the alternative proxy server should be
+    // marked as bad.
+    EXPECT_THAT(session_->proxy_resolution_service()->proxy_retry_info(),
+                ElementsAre(Key("quic://myproxy.org:443")));
 
     // Verify that the second request completes successfully, and the
     // alternative proxy server job is not started.
@@ -795,7 +799,7 @@
   CTPolicyEnforcer ct_policy_enforcer_;
   TestSocketPerformanceWatcherFactory test_socket_performance_watcher_factory_;
   scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
   MockRandom random_generator_;
   HttpServerPropertiesImpl http_server_properties_;
@@ -1160,8 +1164,8 @@
 
 TEST_P(QuicNetworkTransactionTest, QuicProxy) {
   session_params_.enable_quic = true;
-  proxy_service_ =
-      ProxyService::CreateFixedFromPacResult("QUIC mail.example.org:70");
+  proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
+      "QUIC mail.example.org:70");
 
   MockQuicData mock_quic_data;
   QuicStreamOffset header_stream_offset = 0;
@@ -1202,8 +1206,8 @@
   const std::string proxy_host = "www.example.org";
 
   session_params_.enable_quic = true;
-  proxy_service_ =
-      ProxyService::CreateFixedFromPacResult("QUIC " + proxy_host + ":70");
+  proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
+      "QUIC " + proxy_host + ":70");
 
   client_maker_.set_hostname(origin_host);
   MockQuicData mock_quic_data;
@@ -1998,9 +2002,14 @@
   quic_data.AddWrite(client_maker_.MakeDataPacket(
       10, kHeadersStreamId, true, false, settings_offset, settings_data));
 
-  quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
-      11, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_NETWORK_IDLE_TIMEOUT,
-      "No recent network activity."));
+  if (FLAGS_quic_reloadable_flag_quic_strict_ack_handling) {
+    quic_data.AddWrite(client_maker_.MakeConnectionClosePacket(
+        11, true, QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity."));
+  } else {
+    quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
+        11, true, QuicTime::Delta::Infinite(), 0, 1, 1,
+        QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity."));
+  }
 
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);
@@ -2097,9 +2106,14 @@
   quic_data.AddWrite(client_maker_.MakeDataPacket(
       12, kHeadersStreamId, true, false, settings_offset, settings_data));
   // RTO 5
-  quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
-      13, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_TOO_MANY_RTOS,
-      "5 consecutive retransmission timeouts"));
+  if (FLAGS_quic_reloadable_flag_quic_strict_ack_handling) {
+    quic_data.AddWrite(client_maker_.MakeConnectionClosePacket(
+        13, true, QUIC_TOO_MANY_RTOS, "5 consecutive retransmission timeouts"));
+  } else {
+    quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
+        13, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_TOO_MANY_RTOS,
+        "5 consecutive retransmission timeouts"));
+  }
 
   quic_data.AddRead(ASYNC, OK);
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -2199,9 +2213,14 @@
   quic_data.AddWrite(client_maker_.MakeDataPacket(13, kHeadersStreamId, true,
                                                   false, 0, request_data));
   // RTO 5
-  quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
-      14, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_TOO_MANY_RTOS,
-      "5 consecutive retransmission timeouts"));
+  if (FLAGS_quic_reloadable_flag_quic_strict_ack_handling) {
+    quic_data.AddWrite(client_maker_.MakeConnectionClosePacket(
+        14, true, QUIC_TOO_MANY_RTOS, "5 consecutive retransmission timeouts"));
+  } else {
+    quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
+        14, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_TOO_MANY_RTOS,
+        "5 consecutive retransmission timeouts"));
+  }
 
   quic_data.AddRead(ASYNC, OK);
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -2359,9 +2378,14 @@
   quic_data.AddWrite(client_maker_.MakeDataPacket(
       10, kHeadersStreamId, true, false, settings_offset, settings_data));
 
-  quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
-      11, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_NETWORK_IDLE_TIMEOUT,
-      "No recent network activity."));
+  if (FLAGS_quic_reloadable_flag_quic_strict_ack_handling) {
+    quic_data.AddWrite(client_maker_.MakeConnectionClosePacket(
+        11, true, QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity."));
+  } else {
+    quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
+        11, true, QuicTime::Delta::Infinite(), 0, 1, 1,
+        QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity."));
+  }
 
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);
@@ -2480,9 +2504,14 @@
   quic_data.AddWrite(client_maker_.MakeDataPacket(
       10, kHeadersStreamId, true, false, settings_offset, settings_data));
 
-  quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
-      11, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_NETWORK_IDLE_TIMEOUT,
-      "No recent network activity."));
+  if (FLAGS_quic_reloadable_flag_quic_strict_ack_handling) {
+    quic_data.AddWrite(client_maker_.MakeConnectionClosePacket(
+        11, true, QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity."));
+  } else {
+    quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
+        11, true, QuicTime::Delta::Infinite(), 0, 1, 1,
+        QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity."));
+  }
 
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);
@@ -2725,9 +2754,14 @@
   quic_data.AddWrite(client_maker_.MakeDataPacket(
       12, kHeadersStreamId, true, false, settings_offset, settings_data));
 
-  quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
-      13, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_TOO_MANY_RTOS,
-      "5 consecutive retransmission timeouts"));
+  if (FLAGS_quic_reloadable_flag_quic_strict_ack_handling) {
+    quic_data.AddWrite(client_maker_.MakeConnectionClosePacket(
+        13, true, QUIC_TOO_MANY_RTOS, "5 consecutive retransmission timeouts"));
+  } else {
+    quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
+        13, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_TOO_MANY_RTOS,
+        "5 consecutive retransmission timeouts"));
+  }
 
   quic_data.AddRead(ASYNC, OK);
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -2853,9 +2887,14 @@
   quic_data.AddWrite(client_maker_.MakeDataPacket(13, kHeadersStreamId, true,
                                                   false, 0, request_data));
   // RTO 5
-  quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
-      14, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_TOO_MANY_RTOS,
-      "5 consecutive retransmission timeouts"));
+  if (FLAGS_quic_reloadable_flag_quic_strict_ack_handling) {
+    quic_data.AddWrite(client_maker_.MakeConnectionClosePacket(
+        14, true, QUIC_TOO_MANY_RTOS, "5 consecutive retransmission timeouts"));
+  } else {
+    quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket(
+        14, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_TOO_MANY_RTOS,
+        "5 consecutive retransmission timeouts"));
+  }
 
   quic_data.AddRead(ASYNC, OK);
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -3406,8 +3445,8 @@
 
   TestProxyDelegate test_proxy_delegate;
 
-  proxy_service_ =
-      ProxyService::CreateFixedFromPacResult("HTTPS mail.example.org:443");
+  proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
+      "HTTPS mail.example.org:443");
 
   test_proxy_delegate.set_alternative_proxy_server(
       ProxyServer::FromPacString("QUIC mail.example.org:443"));
@@ -3803,8 +3842,8 @@
 // alternative proxy server.
 TEST_P(QuicNetworkTransactionTest, QuicProxyWithRacing) {
   base::HistogramTester histogram_tester;
-  proxy_service_ =
-      ProxyService::CreateFixedFromPacResult("HTTPS mail.example.org:443");
+  proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
+      "HTTPS mail.example.org:443");
 
   MockQuicData mock_quic_data;
   QuicStreamOffset header_stream_offset = 0;
@@ -3846,7 +3885,7 @@
   EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
 
   // Verify that the proxy server is not marked as broken.
-  EXPECT_TRUE(session_->proxy_service()->proxy_retry_info().empty());
+  EXPECT_TRUE(session_->proxy_resolution_service()->proxy_retry_info().empty());
 
   histogram_tester.ExpectUniqueSample("Net.QuicAlternativeProxy.Usage",
                                       1 /* ALTERNATIVE_PROXY_USAGE_WON_RACE */,
@@ -3969,7 +4008,8 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
-  proxy_service_ = ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
+  proxy_resolution_service_ =
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
 
   // Since we are using a proxy, the QUIC job will not succeed.
   MockWrite http_writes[] = {
@@ -4695,8 +4735,8 @@
   EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
 
   session_context_.proxy_delegate = &test_proxy_delegate;
-  proxy_service_ =
-      ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+  proxy_resolution_service_ =
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
   request_.url = GURL("http://mail.example.org/");
 
   // In order for a new QUIC session to be established via alternate-protocol
@@ -4712,8 +4752,8 @@
 
   CreateSession();
   SendRequestAndExpectHttpResponseFromProxy("hello world", true, 443);
-  EXPECT_FALSE(test_proxy_delegate.alternative_proxy_server().is_valid());
-  EXPECT_TRUE(session_->proxy_service()->proxy_retry_info().empty());
+  EXPECT_THAT(session_->proxy_resolution_service()->proxy_retry_info(),
+              ElementsAre(Key("quic://myproxy.org:443")));
 }
 
 TEST_P(QuicNetworkTransactionTest, SecureResourceOverSecureQuic) {
@@ -4750,8 +4790,8 @@
 TEST_P(QuicNetworkTransactionTest,
        DISABLED_QuicUploadToAlternativeProxyServer) {
   base::HistogramTester histogram_tester;
-  proxy_service_ =
-      ProxyService::CreateFixedFromPacResult("HTTPS mail.example.org:443");
+  proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
+      "HTTPS mail.example.org:443");
 
   TestProxyDelegate test_proxy_delegate;
 
@@ -4788,7 +4828,7 @@
   EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
 
   // Verify that the proxy server is not marked as broken.
-  EXPECT_TRUE(session_->proxy_service()->proxy_retry_info().empty());
+  EXPECT_TRUE(session_->proxy_resolution_service()->proxy_retry_info().empty());
 
   histogram_tester.ExpectUniqueSample("Net.QuicAlternativeProxy.Usage",
                                       1 /* ALTERNATIVE_PROXY_USAGE_WON_RACE */,
@@ -5187,7 +5227,8 @@
     storage_.set_cert_verifier(std::make_unique<MockCertVerifier>());
     storage_.set_transport_security_state(
         std::make_unique<TransportSecurityState>());
-    storage_.set_proxy_service(ProxyService::CreateDirect());
+    storage_.set_proxy_resolution_service(
+        ProxyResolutionService::CreateDirect());
     storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
     storage_.set_http_auth_handler_factory(
         HttpAuthHandlerFactory::CreateDefault(host_resolver()));
@@ -5423,7 +5464,7 @@
         destination_type_(GetParam().destination_type),
         cert_transparency_verifier_(new MultiLogCTVerifier()),
         ssl_config_service_(new SSLConfigServiceDefaults),
-        proxy_service_(ProxyService::CreateDirect()),
+        proxy_resolution_service_(ProxyResolutionService::CreateDirect()),
         auth_handler_factory_(
             HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
         random_generator_(0),
@@ -5461,7 +5502,7 @@
     session_context.socket_performance_watcher_factory =
         &test_socket_performance_watcher_factory_;
     session_context.ssl_config_service = ssl_config_service_.get();
-    session_context.proxy_service = proxy_service_.get();
+    session_context.proxy_resolution_service = proxy_resolution_service_.get();
     session_context.http_auth_handler_factory = auth_handler_factory_.get();
     session_context.http_server_properties = &http_server_properties_;
 
@@ -5651,7 +5692,7 @@
   CTPolicyEnforcer ct_policy_enforcer_;
   TestSocketPerformanceWatcherFactory test_socket_performance_watcher_factory_;
   scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
   MockRandom random_generator_;
   HttpServerPropertiesImpl http_server_properties_;
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index 5cec9cc..b57db4e 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -390,7 +390,8 @@
 
   std::unique_ptr<QuicEncryptedPacket> ConstructClientConnectionClosePacket(
       QuicPacketNumber num) {
-    return client_maker_.MakeConnectionClosePacket(num);
+    return client_maker_.MakeConnectionClosePacket(
+        num, false, QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!");
   }
 
   std::unique_ptr<QuicEncryptedPacket> ConstructClientRstPacket(
diff --git a/net/quic/chromium/quic_test_packet_maker.cc b/net/quic/chromium/quic_test_packet_maker.cc
index 435250f..e93df6f7 100644
--- a/net/quic/chromium/quic_test_packet_maker.cc
+++ b/net/quic/chromium/quic_test_packet_maker.cc
@@ -213,17 +213,21 @@
 }
 
 std::unique_ptr<QuicReceivedPacket>
-QuicTestPacketMaker::MakeConnectionClosePacket(QuicPacketNumber num) {
+QuicTestPacketMaker::MakeConnectionClosePacket(
+    QuicPacketNumber num,
+    bool include_version,
+    QuicErrorCode quic_error,
+    const std::string& quic_error_details) {
   QuicPacketHeader header;
   header.connection_id = connection_id_;
   header.reset_flag = false;
-  header.version_flag = false;
+  header.version_flag = include_version;
   header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
   header.packet_number = num;
 
   QuicConnectionCloseFrame close;
-  close.error_code = QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
-  close.error_details = "Time to panic!";
+  close.error_code = quic_error;
+  close.error_details = quic_error_details;
   return std::unique_ptr<QuicReceivedPacket>(
       MakePacket(header, QuicFrame(&close)));
 }
diff --git a/net/quic/chromium/quic_test_packet_maker.h b/net/quic/chromium/quic_test_packet_maker.h
index 201f5fdb..f011002 100644
--- a/net/quic/chromium/quic_test_packet_maker.h
+++ b/net/quic/chromium/quic_test_packet_maker.h
@@ -86,7 +86,10 @@
       QuicErrorCode quic_error,
       const std::string& quic_error_details);
   std::unique_ptr<QuicReceivedPacket> MakeConnectionClosePacket(
-      QuicPacketNumber num);
+      QuicPacketNumber num,
+      bool include_version,
+      QuicErrorCode quic_error,
+      const std::string& quic_error_details);
   std::unique_ptr<QuicReceivedPacket> MakeGoAwayPacket(
       QuicPacketNumber num,
       QuicErrorCode error_code,
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h
index 3e2a489..bc02bba 100644
--- a/net/quic/core/quic_flags_list.h
+++ b/net/quic/core/quic_flags_list.h
@@ -136,7 +136,7 @@
 // If true, then 1) at sender, avoid sending empty acks, 2) at receiver, close
 // connection when a ack frame\'s first block length is 0, unless the ack is
 // completely empty.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_strict_ack_handling, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_strict_ack_handling, true)
 
 // If true, fixes for the two bugs described in crbug.com/723604 will be
 // enabled.
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index 00a86d27..16fa5d9 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -92,7 +92,7 @@
   SSLClientSocketPoolTest()
       : cert_verifier_(new MockCertVerifier),
         transport_security_state_(new TransportSecurityState),
-        proxy_service_(ProxyService::CreateDirect()),
+        proxy_resolution_service_(ProxyResolutionService::CreateDirect()),
         ssl_config_service_(new SSLConfigServiceDefaults),
         http_auth_handler_factory_(
             HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
@@ -181,7 +181,7 @@
     session_context.transport_security_state = transport_security_state_.get();
     session_context.cert_transparency_verifier = &ct_verifier_;
     session_context.ct_policy_enforcer = &ct_policy_enforcer_;
-    session_context.proxy_service = proxy_service_.get();
+    session_context.proxy_resolution_service = proxy_resolution_service_.get();
     session_context.client_socket_factory = &socket_factory_;
     session_context.ssl_config_service = ssl_config_service_.get();
     session_context.http_auth_handler_factory =
@@ -199,7 +199,7 @@
   std::unique_ptr<TransportSecurityState> transport_security_state_;
   MultiLogCTVerifier ct_verifier_;
   CTPolicyEnforcer ct_policy_enforcer_;
-  const std::unique_ptr<ProxyService> proxy_service_;
+  const std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   const scoped_refptr<SSLConfigService> ssl_config_service_;
   const std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
   const std::unique_ptr<HttpServerPropertiesImpl> http_server_properties_;
diff --git a/net/spdy/chromium/spdy_network_transaction_unittest.cc b/net/spdy/chromium/spdy_network_transaction_unittest.cc
index 160830d4..8fbd5ef 100644
--- a/net/spdy/chromium/spdy_network_transaction_unittest.cc
+++ b/net/spdy/chromium/spdy_network_transaction_unittest.cc
@@ -4525,7 +4525,7 @@
 TEST_F(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
   request_.method = "GET";
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS myproxy:70"));
   // Do not force SPDY so that second socket can negotiate HTTP/1.1.
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
                                      std::move(session_deps));
@@ -4612,7 +4612,7 @@
 // Test to make sure we can correctly connect through a proxy.
 TEST_F(SpdyNetworkTransactionTest, ProxyConnect) {
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70"));
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
                                      std::move(session_deps));
   helper.RunPreTestSetup();
@@ -4669,7 +4669,8 @@
   // to simply DIRECT. The reason for appending the second proxy is to verify
   // that the session pool key used does is just "DIRECT".
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70"));
+      ProxyResolutionService::CreateFixedFromPacResult(
+          "DIRECT; PROXY myproxy:70"));
   // When setting up the first transaction, we store the SpdySessionPool so that
   // we can use the same pool in the second transaction.
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
@@ -4754,7 +4755,7 @@
   request_.method = "GET";
   request_.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
   auto session_deps_proxy = std::make_unique<SpdySessionDependencies>(
-      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
+      ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70"));
   NormalSpdyTransactionHelper helper_proxy(request_, DEFAULT_PRIORITY, log_,
                                            std::move(session_deps_proxy));
 
@@ -6880,7 +6881,7 @@
 
   // Need secure proxy so that insecure URL can use HTTP/2.
   auto session_deps = std::make_unique<SpdySessionDependencies>(
-      ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
+      ProxyResolutionService::CreateFixedFromPacResult("HTTPS myproxy:70"));
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_,
                                      std::move(session_deps));
 
diff --git a/net/spdy/chromium/spdy_test_util_common.cc b/net/spdy/chromium/spdy_test_util_common.cc
index daa832c..534686d 100644
--- a/net/spdy/chromium/spdy_test_util_common.cc
+++ b/net/spdy/chromium/spdy_test_util_common.cc
@@ -301,17 +301,17 @@
 }
 
 SpdySessionDependencies::SpdySessionDependencies()
-    : SpdySessionDependencies(ProxyService::CreateDirect()) {}
+    : SpdySessionDependencies(ProxyResolutionService::CreateDirect()) {}
 
 SpdySessionDependencies::SpdySessionDependencies(
-    std::unique_ptr<ProxyService> proxy_service)
+    std::unique_ptr<ProxyResolutionService> proxy_resolution_service)
     : host_resolver(std::make_unique<MockCachingHostResolver>()),
       cert_verifier(std::make_unique<MockCertVerifier>()),
       channel_id_service(nullptr),
       transport_security_state(std::make_unique<TransportSecurityState>()),
       cert_transparency_verifier(std::make_unique<DoNothingCTVerifier>()),
       ct_policy_enforcer(std::make_unique<CTPolicyEnforcer>()),
-      proxy_service(std::move(proxy_service)),
+      proxy_resolution_service(std::move(proxy_resolution_service)),
       ssl_config_service(base::MakeRefCounted<SSLConfigServiceDefaults>()),
       socket_factory(std::make_unique<MockClientSocketFactory>()),
       http_auth_handler_factory(
@@ -398,7 +398,7 @@
   context.cert_transparency_verifier =
       session_deps->cert_transparency_verifier.get();
   context.ct_policy_enforcer = session_deps->ct_policy_enforcer.get();
-  context.proxy_service = session_deps->proxy_service.get();
+  context.proxy_resolution_service = session_deps->proxy_resolution_service.get();
   context.ssl_config_service = session_deps->ssl_config_service.get();
   context.http_auth_handler_factory =
       session_deps->http_auth_handler_factory.get();
@@ -426,7 +426,7 @@
   storage_.set_cert_verifier(std::make_unique<MockCertVerifier>());
   storage_.set_transport_security_state(
       std::make_unique<TransportSecurityState>());
-  storage_.set_proxy_service(ProxyService::CreateDirect());
+  storage_.set_proxy_resolution_service(ProxyResolutionService::CreateDirect());
   storage_.set_ct_policy_enforcer(
       std::make_unique<AllowAnyCertCTPolicyEnforcer>());
   storage_.set_cert_transparency_verifier(
@@ -445,7 +445,7 @@
   session_context.host_resolver = host_resolver();
   session_context.cert_verifier = cert_verifier();
   session_context.transport_security_state = transport_security_state();
-  session_context.proxy_service = proxy_service();
+  session_context.proxy_resolution_service = proxy_resolution_service();
   session_context.ct_policy_enforcer = ct_policy_enforcer();
   session_context.cert_transparency_verifier = cert_transparency_verifier();
   session_context.ssl_config_service = ssl_config_service();
diff --git a/net/spdy/chromium/spdy_test_util_common.h b/net/spdy/chromium/spdy_test_util_common.h
index 5aa3cd6..44401d8 100644
--- a/net/spdy/chromium/spdy_test_util_common.h
+++ b/net/spdy/chromium/spdy_test_util_common.h
@@ -179,7 +179,8 @@
   SpdySessionDependencies();
 
   // Custom proxy service dependency.
-  explicit SpdySessionDependencies(std::unique_ptr<ProxyService> proxy_service);
+  explicit SpdySessionDependencies(
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service);
 
   ~SpdySessionDependencies();
 
@@ -203,7 +204,7 @@
   std::unique_ptr<TransportSecurityState> transport_security_state;
   std::unique_ptr<CTVerifier> cert_transparency_verifier;
   std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer;
-  std::unique_ptr<ProxyService> proxy_service;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service;
   scoped_refptr<SSLConfigService> ssl_config_service;
   std::unique_ptr<MockClientSocketFactory> socket_factory;
   std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
diff --git a/net/test/spawned_test_server/remote_test_server.cc b/net/test/spawned_test_server/remote_test_server.cc
index 23025c4..ce5b2db 100644
--- a/net/test/spawned_test_server/remote_test_server.cc
+++ b/net/test/spawned_test_server/remote_test_server.cc
@@ -97,7 +97,7 @@
                                !ssl_options().GetOCSPArgument().empty());
   if (config_.address() != IPAddress::IPv4Localhost() && ocsp_server_enabled) {
     ocsp_proxy_ = std::make_unique<TcpSocketProxy>(io_thread_.task_runner());
-    bool initialized = !ocsp_proxy_->Initialize();
+    bool initialized = ocsp_proxy_->Initialize();
     CHECK(initialized);
     arguments_dict.SetKey("ocsp-proxy-port-number",
                           base::Value(ocsp_proxy_->local_port()));
@@ -137,7 +137,7 @@
   if (config_.address() != IPAddress::IPv4Localhost()) {
     test_server_proxy_ =
         std::make_unique<TcpSocketProxy>(io_thread_.task_runner());
-    bool initialized = !test_server_proxy_->Initialize();
+    bool initialized = test_server_proxy_->Initialize();
     CHECK(initialized);
     test_server_proxy_->Start(IPEndPoint(config_.address(), remote_port_));
 
diff --git a/net/tools/net_watcher/net_watcher.cc b/net/tools/net_watcher/net_watcher.cc
index 8f6f61f..817ed64e 100644
--- a/net/tools/net_watcher/net_watcher.cc
+++ b/net/tools/net_watcher/net_watcher.cc
@@ -180,7 +180,7 @@
 
   // Use the network loop as the file loop also.
   std::unique_ptr<net::ProxyConfigService> proxy_config_service(
-      net::ProxyService::CreateSystemProxyConfigService(
+      net::ProxyResolutionService::CreateSystemProxyConfigService(
           network_loop.task_runner()));
 
   // Uses |network_change_notifier|.
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc
index 080d1101..57d1a57 100644
--- a/net/url_request/url_fetcher_impl_unittest.cc
+++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -182,8 +182,9 @@
  public:
   // All requests for |hanging_domain| will hang on host resolution until the
   // mock_resolver()->ResolveAllPending() is called.
-  FetcherTestURLRequestContext(const std::string& hanging_domain,
-                               std::unique_ptr<ProxyService> proxy_service)
+  FetcherTestURLRequestContext(
+      const std::string& hanging_domain,
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service)
       : TestURLRequestContext(true), mock_resolver_(new MockHostResolver()) {
     mock_resolver_->set_ondemand_mode(true);
     mock_resolver_->rules()->AddRule(hanging_domain, "127.0.0.1");
@@ -192,7 +193,8 @@
         std::unique_ptr<HostResolver>(mock_resolver_));
     context_storage_.set_throttler_manager(
         std::make_unique<URLRequestThrottlerManager>());
-    context_storage_.set_proxy_service(std::move(proxy_service));
+    context_storage_.set_proxy_resolution_service(
+        std::move(proxy_resolution_service));
     Init();
   }
 
@@ -230,7 +232,7 @@
 
     if (!context_) {
       context_.reset(new FetcherTestURLRequestContext(
-          hanging_domain_, std::move(proxy_service_)));
+          hanging_domain_, std::move(proxy_resolution_service_)));
     }
 
     return context_.get();
@@ -302,9 +304,10 @@
     return context_.get();
   }
 
-  void set_proxy_service(std::unique_ptr<ProxyService> proxy_service) {
-    DCHECK(proxy_service);
-    proxy_service_ = std::move(proxy_service);
+  void set_proxy_resolution_service(
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service) {
+    DCHECK(proxy_resolution_service);
+    proxy_resolution_service_ = std::move(proxy_resolution_service);
   }
 
  protected:
@@ -321,7 +324,7 @@
   const std::string hanging_domain_;
 
   // May be null.
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
 
   std::unique_ptr<FetcherTestURLRequestContext> context_;
   bool shutting_down_;
@@ -510,9 +513,11 @@
   const net::ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
                                       test_server_->host_port_pair());
 
-  std::unique_ptr<ProxyService> proxy_service =
-      ProxyService::CreateFixedFromPacResult(proxy_server.ToPacString());
-  context_getter->set_proxy_service(std::move(proxy_service));
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult(
+          proxy_server.ToPacString());
+  context_getter->set_proxy_resolution_service(
+      std::move(proxy_resolution_service));
 
   delegate.CreateFetcher(test_server_->GetURL(kDefaultResponsePath),
                          URLFetcher::GET, context_getter);
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index 17736d522..914b645 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -34,7 +34,7 @@
       cert_verifier_(nullptr),
       channel_id_service_(nullptr),
       http_auth_handler_factory_(nullptr),
-      proxy_service_(nullptr),
+      proxy_resolution_service_(nullptr),
       network_delegate_(nullptr),
       http_server_properties_(nullptr),
       http_user_agent_settings_(nullptr),
@@ -72,7 +72,7 @@
   set_cert_verifier(other->cert_verifier_);
   set_channel_id_service(other->channel_id_service_);
   set_http_auth_handler_factory(other->http_auth_handler_factory_);
-  set_proxy_service(other->proxy_service_);
+  set_proxy_resolution_service(other->proxy_resolution_service_);
   set_ssl_config_service(other->ssl_config_service_.get());
   set_network_delegate(other->network_delegate_);
   set_http_server_properties(other->http_server_properties_);
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index 30fc9851a..2aa154a6 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -46,7 +46,7 @@
 class NetLog;
 class NetworkDelegate;
 class NetworkQualityEstimator;
-class ProxyService;
+class ProxyResolutionService;
 class URLRequest;
 class URLRequestJobFactory;
 class URLRequestThrottlerManager;
@@ -132,9 +132,12 @@
   }
 
   // Get the proxy service for this context.
-  ProxyService* proxy_service() const { return proxy_service_; }
-  void set_proxy_service(ProxyService* proxy_service) {
-    proxy_service_ = proxy_service;
+  ProxyResolutionService* proxy_resolution_service() const {
+    return proxy_resolution_service_;
+  }
+  void set_proxy_resolution_service(
+      ProxyResolutionService* proxy_resolution_service) {
+    proxy_resolution_service_ = proxy_resolution_service;
   }
 
   // Get the ssl config service for this context.
@@ -301,7 +304,7 @@
   CertVerifier* cert_verifier_;
   ChannelIDService* channel_id_service_;
   HttpAuthHandlerFactory* http_auth_handler_factory_;
-  ProxyService* proxy_service_;
+  ProxyResolutionService* proxy_resolution_service_;
   scoped_refptr<SSLConfigService> ssl_config_service_;
   NetworkDelegate* network_delegate_;
   HttpServerProperties* http_server_properties_;
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 6bdf43ed..8bbdb638 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -161,11 +161,11 @@
     storage_.set_reporting_service(nullptr);
 #endif  // BUILDFLAG(ENABLE_REPORTING)
 
-    // Shut down the ProxyService, as it may have pending URLRequests using this
-    // context. Since this cancels requests, it's not safe to subclass this, as
-    // some parts of the URLRequestContext may then be torn down before this
-    // cancels the ProxyService's URLRequests.
-    proxy_service()->OnShutdown();
+    // Shut down the ProxyResolutionService, as it may have pending URLRequests
+    // using this context. Since this cancels requests, it's not safe to
+    // subclass this, as some parts of the URLRequestContext may then be torn
+    // down before this cancels the ProxyResolutionService's URLRequests.
+    proxy_resolution_service()->OnShutdown();
 
     AssertNoURLRequests();
   }
@@ -211,7 +211,7 @@
       net_log_(nullptr),
       shared_host_resolver_(nullptr),
       pac_quick_check_enabled_(true),
-      pac_sanitize_url_policy_(ProxyService::SanitizeUrlPolicy::SAFE),
+      pac_sanitize_url_policy_(ProxyResolutionService::SanitizeUrlPolicy::SAFE),
       shared_proxy_delegate_(nullptr),
 #if BUILDFLAG(ENABLE_REPORTING)
       shared_http_auth_handler_factory_(nullptr),
@@ -233,7 +233,8 @@
   session_context->cert_transparency_verifier =
       request_context->cert_transparency_verifier();
   session_context->ct_policy_enforcer = request_context->ct_policy_enforcer();
-  session_context->proxy_service = request_context->proxy_service();
+  session_context->proxy_resolution_service =
+      request_context->proxy_resolution_service();
   session_context->ssl_config_service = request_context->ssl_config_service();
   session_context->http_auth_handler_factory =
       request_context->http_auth_handler_factory();
@@ -505,23 +506,25 @@
         std::make_unique<URLRequestThrottlerManager>());
   }
 
-  if (!proxy_service_) {
+  if (!proxy_resolution_service_) {
 #if !defined(OS_LINUX) && !defined(OS_ANDROID)
     // TODO(willchan): Switch to using this code when
-    // ProxyService::CreateSystemProxyConfigService()'s signature doesn't suck.
+    // ProxyResolutionService::CreateSystemProxyConfigService()'s signature
+    // doesn't suck.
     if (!proxy_config_service_) {
-      proxy_config_service_ = ProxyService::CreateSystemProxyConfigService(
-          base::ThreadTaskRunnerHandle::Get().get());
+      proxy_config_service_ =
+          ProxyResolutionService::CreateSystemProxyConfigService(
+              base::ThreadTaskRunnerHandle::Get().get());
     }
 #endif  // !defined(OS_LINUX) && !defined(OS_ANDROID)
-    proxy_service_ =
+    proxy_resolution_service_ =
         CreateProxyService(std::move(proxy_config_service_), context.get(),
                            context->host_resolver(),
                            context->network_delegate(), context->net_log());
-    proxy_service_->set_quick_check_enabled(pac_quick_check_enabled_);
-    proxy_service_->set_sanitize_url_policy(pac_sanitize_url_policy_);
+    proxy_resolution_service_->set_quick_check_enabled(pac_quick_check_enabled_);
+    proxy_resolution_service_->set_sanitize_url_policy(pac_sanitize_url_policy_);
   }
-  storage->set_proxy_service(std::move(proxy_service_));
+  storage->set_proxy_resolution_service(std::move(proxy_resolution_service_));
 
   HttpNetworkSession::Context network_session_context;
   SetHttpNetworkSessionComponents(context.get(), &network_session_context);
@@ -655,13 +658,14 @@
   return std::move(context);
 }
 
-std::unique_ptr<ProxyService> URLRequestContextBuilder::CreateProxyService(
+std::unique_ptr<ProxyResolutionService>
+URLRequestContextBuilder::CreateProxyService(
     std::unique_ptr<ProxyConfigService> proxy_config_service,
     URLRequestContext* url_request_context,
     HostResolver* host_resolver,
     NetworkDelegate* network_delegate,
     NetLog* net_log) {
-  return ProxyService::CreateUsingSystemProxyResolver(
+  return ProxyResolutionService::CreateUsingSystemProxyResolver(
       std::move(proxy_config_service), net_log);
 }
 
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index f8109d39..22923fab 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -144,23 +144,23 @@
       HttpNetworkSession::Context* session_context);
 
   // These functions are mutually exclusive.  The ProxyConfigService, if
-  // set, will be used to construct a ProxyService.
+  // set, will be used to construct a ProxyResolutionService.
   void set_proxy_config_service(
       std::unique_ptr<ProxyConfigService> proxy_config_service) {
     proxy_config_service_ = std::move(proxy_config_service);
   }
 
   // Sets whether quick PAC checks are enabled. Defaults to true. Ignored if
-  // a ProxyService is set directly.
+  // a ProxyResolutionService is set directly.
   void set_pac_quick_check_enabled(bool pac_quick_check_enabled) {
     pac_quick_check_enabled_ = pac_quick_check_enabled;
   }
 
   // Sets policy for sanitizing URLs before passing them to a PAC. Defaults to
-  // ProxyService::SanitizeUrlPolicy::SAFE. Ignored if
-  // a ProxyService is set directly.
+  // ProxyResolutionService::SanitizeUrlPolicy::SAFE. Ignored if
+  // a ProxyResolutionService is set directly.
   void set_pac_sanitize_url_policy(
-      net::ProxyService::SanitizeUrlPolicy pac_sanitize_url_policy) {
+      net::ProxyResolutionService::SanitizeUrlPolicy pac_sanitize_url_policy) {
     pac_sanitize_url_policy_ = pac_sanitize_url_policy;
   }
 
@@ -168,8 +168,9 @@
   // libraries to evaluate PAC scripts, if available (And if not, skips PAC
   // resolution). Subclasses may override CreateProxyService for different
   // default behavior.
-  void set_proxy_service(std::unique_ptr<ProxyService> proxy_service) {
-    proxy_service_ = std::move(proxy_service);
+  void set_proxy_resolution_service(
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service) {
+    proxy_resolution_service_ = std::move(proxy_resolution_service);
   }
 
   void set_ssl_config_service(
@@ -345,10 +346,11 @@
   std::unique_ptr<URLRequestContext> Build();
 
  protected:
-  // Lets subclasses override ProxyService creation, using a ProxyService that
-  // uses the URLRequestContext itself to get PAC scripts. When this method is
-  // invoked, the URLRequestContext is not yet ready to service requests.
-  virtual std::unique_ptr<ProxyService> CreateProxyService(
+  // Lets subclasses override ProxyResolutionService creation, using a
+  // ProxyResolutionService that uses the URLRequestContext itself to get PAC
+  // scripts. When this method is invoked, the URLRequestContext is not yet
+  // ready to service requests.
+  virtual std::unique_ptr<ProxyResolutionService> CreateProxyService(
       std::unique_ptr<ProxyConfigService> proxy_config_service,
       URLRequestContext* url_request_context,
       HostResolver* host_resolver,
@@ -388,8 +390,8 @@
   std::unique_ptr<ChannelIDService> channel_id_service_;
   std::unique_ptr<ProxyConfigService> proxy_config_service_;
   bool pac_quick_check_enabled_;
-  ProxyService::SanitizeUrlPolicy pac_sanitize_url_policy_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  ProxyResolutionService::SanitizeUrlPolicy pac_sanitize_url_policy_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   scoped_refptr<net::SSLConfigService> ssl_config_service_;
   std::unique_ptr<NetworkDelegate> network_delegate_;
   std::unique_ptr<ProxyDelegate> proxy_delegate_;
diff --git a/net/url_request/url_request_context_storage.cc b/net/url_request/url_request_context_storage.cc
index b804e251..448cdc8 100644
--- a/net/url_request/url_request_context_storage.cc
+++ b/net/url_request/url_request_context_storage.cc
@@ -79,10 +79,10 @@
   network_delegate_ = std::move(network_delegate);
 }
 
-void URLRequestContextStorage::set_proxy_service(
-    std::unique_ptr<ProxyService> proxy_service) {
-  context_->set_proxy_service(proxy_service.get());
-  proxy_service_ = std::move(proxy_service);
+void URLRequestContextStorage::set_proxy_resolution_service(
+    std::unique_ptr<ProxyResolutionService> proxy_resolution_service) {
+  context_->set_proxy_resolution_service(proxy_resolution_service.get());
+  proxy_resolution_service_ = std::move(proxy_resolution_service);
 }
 
 void URLRequestContextStorage::set_ssl_config_service(
diff --git a/net/url_request/url_request_context_storage.h b/net/url_request/url_request_context_storage.h
index e019405..1f48d7c 100644
--- a/net/url_request/url_request_context_storage.h
+++ b/net/url_request/url_request_context_storage.h
@@ -29,7 +29,7 @@
 class NetLog;
 class NetworkDelegate;
 class ProxyDelegate;
-class ProxyService;
+class ProxyResolutionService;
 class SSLConfigService;
 class TransportSecurityState;
 class URLRequestContext;
@@ -63,7 +63,8 @@
       std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory);
   void set_proxy_delegate(std::unique_ptr<ProxyDelegate> proxy_delegate);
   void set_network_delegate(std::unique_ptr<NetworkDelegate> network_delegate);
-  void set_proxy_service(std::unique_ptr<ProxyService> proxy_service);
+  void set_proxy_resolution_service(
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service);
   void set_ssl_config_service(SSLConfigService* ssl_config_service);
   void set_http_server_properties(
       std::unique_ptr<HttpServerProperties> http_server_properties);
@@ -112,7 +113,7 @@
   std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
   std::unique_ptr<ProxyDelegate> proxy_delegate_;
   std::unique_ptr<NetworkDelegate> network_delegate_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   // TODO(willchan): Remove refcounting on this member.
   scoped_refptr<SSLConfigService> ssl_config_service_;
   std::unique_ptr<HttpServerProperties> http_server_properties_;
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc
index 1d7ff64..2575d0b 100644
--- a/net/url_request/url_request_ftp_job.cc
+++ b/net/url_request/url_request_ftp_job.cc
@@ -44,14 +44,15 @@
     FtpAuthCache* ftp_auth_cache)
     : URLRequestJob(request, network_delegate),
       priority_(DEFAULT_PRIORITY),
-      proxy_service_(request_->context()->proxy_service()),
+      proxy_resolution_service_(
+          request_->context()->proxy_resolution_service()),
       proxy_resolve_request_(NULL),
       http_response_info_(NULL),
       read_in_progress_(false),
       ftp_transaction_factory_(ftp_transaction_factory),
       ftp_auth_cache_(ftp_auth_cache),
       weak_factory_(this) {
-  DCHECK(proxy_service_);
+  DCHECK(proxy_resolution_service_);
   DCHECK(ftp_transaction_factory);
   DCHECK(ftp_auth_cache);
 }
@@ -112,8 +113,9 @@
   if (request_->load_flags() & LOAD_BYPASS_PROXY) {
     proxy_info_.UseDirect();
   } else {
-    DCHECK_EQ(request_->context()->proxy_service(), proxy_service_);
-    rv = proxy_service_->ResolveProxy(
+    DCHECK_EQ(request_->context()->proxy_resolution_service(),
+              proxy_resolution_service_);
+    rv = proxy_resolution_service_->ResolveProxy(
         request_->url(), "GET", &proxy_info_,
         base::Bind(&URLRequestFtpJob::OnResolveProxyComplete,
                    base::Unretained(this)),
@@ -127,7 +129,7 @@
 
 void URLRequestFtpJob::Kill() {
   if (proxy_resolve_request_) {
-    proxy_service_->CancelRequest(proxy_resolve_request_);
+    proxy_resolution_service_->CancelRequest(proxy_resolve_request_);
     proxy_resolve_request_ = nullptr;
   }
   if (ftp_transaction_)
@@ -278,7 +280,7 @@
 
 LoadState URLRequestFtpJob::GetLoadState() const {
   if (proxy_resolve_request_)
-    return proxy_service_->GetLoadState(proxy_resolve_request_);
+    return proxy_resolution_service_->GetLoadState(proxy_resolve_request_);
   if (proxy_info_.is_direct()) {
     return ftp_transaction_ ?
         ftp_transaction_->GetLoadState() : LOAD_STATE_IDLE;
diff --git a/net/url_request/url_request_ftp_job.h b/net/url_request/url_request_ftp_job.h
index 0edb4d661..4d1b12c 100644
--- a/net/url_request/url_request_ftp_job.h
+++ b/net/url_request/url_request_ftp_job.h
@@ -79,9 +79,9 @@
 
   RequestPriority priority_;
 
-  ProxyService* proxy_service_;
+  ProxyResolutionService* proxy_resolution_service_;
   ProxyInfo proxy_info_;
-  ProxyService::Request* proxy_resolve_request_;
+  ProxyResolutionService::Request* proxy_resolve_request_;
 
   FtpRequestInfo ftp_request_info_;
   std::unique_ptr<FtpTransaction> ftp_transaction_;
diff --git a/net/url_request/url_request_ftp_job_unittest.cc b/net/url_request/url_request_ftp_job_unittest.cc
index 770c5ab..7708001 100644
--- a/net/url_request/url_request_ftp_job_unittest.cc
+++ b/net/url_request/url_request_ftp_job_unittest.cc
@@ -76,12 +76,14 @@
 
 class FtpTestURLRequestContext : public TestURLRequestContext {
  public:
-  FtpTestURLRequestContext(ClientSocketFactory* socket_factory,
-                           std::unique_ptr<ProxyService> proxy_service,
-                           NetworkDelegate* network_delegate)
+  FtpTestURLRequestContext(
+      ClientSocketFactory* socket_factory,
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service,
+      NetworkDelegate* network_delegate)
       : TestURLRequestContext(true) {
     set_client_socket_factory(socket_factory);
-    context_storage_.set_proxy_service(std::move(proxy_service));
+    context_storage_.set_proxy_resolution_service(
+        std::move(proxy_resolution_service));
     set_network_delegate(network_delegate);
     std::unique_ptr<FtpProtocolHandler> ftp_protocol_handler(
         FtpProtocolHandler::CreateForTesting(
@@ -95,8 +97,10 @@
 
   FtpAuthCache* GetFtpAuthCache() { return auth_cache_; }
 
-  void set_proxy_service(std::unique_ptr<ProxyService> proxy_service) {
-    context_storage_.set_proxy_service(std::move(proxy_service));
+  void set_proxy_resolution_service(
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service) {
+    context_storage_.set_proxy_resolution_service(
+        std::move(proxy_resolution_service));
   }
 
  private:
@@ -159,18 +163,18 @@
 class URLRequestFtpJobPriorityTest : public testing::Test {
  protected:
   URLRequestFtpJobPriorityTest()
-      : proxy_service_(std::make_unique<SimpleProxyConfigService>(),
-                       NULL,
-                       NULL),
+      : proxy_resolution_service_(std::make_unique<SimpleProxyConfigService>(),
+                                  NULL,
+                                  NULL),
         req_(context_.CreateRequest(GURL("ftp://ftp.example.com"),
                                     DEFAULT_PRIORITY,
                                     &delegate_,
                                     TRAFFIC_ANNOTATION_FOR_TESTS)) {
-    context_.set_proxy_service(&proxy_service_);
+    context_.set_proxy_resolution_service(&proxy_resolution_service_);
     context_.set_http_transaction_factory(&network_layer_);
   }
 
-  ProxyService proxy_service_;
+  ProxyResolutionService proxy_resolution_service_;
   MockNetworkLayer network_layer_;
   MockFtpTransactionFactory ftp_factory_;
   FtpAuthCache ftp_auth_cache_;
@@ -252,7 +256,7 @@
  public:
   URLRequestFtpJobTest()
       : request_context_(&socket_factory_,
-                         std::make_unique<ProxyService>(
+                         std::make_unique<ProxyResolutionService>(
                              std::make_unique<SimpleProxyConfigService>(),
                              nullptr,
                              nullptr),
@@ -326,10 +330,11 @@
   MockProxyResolverFactory* resolver_factory = owned_resolver_factory.get();
 
   // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL.
-  request_context()->set_proxy_service(std::make_unique<ProxyService>(
-      std::make_unique<ProxyConfigServiceFixed>(
-          ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
-      std::move(owned_resolver_factory), nullptr));
+  request_context()->set_proxy_resolution_service(
+      std::make_unique<ProxyResolutionService>(
+          std::make_unique<ProxyConfigServiceFixed>(
+              ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
+          std::move(owned_resolver_factory), nullptr));
 
   TestDelegate request_delegate;
   std::unique_ptr<URLRequest> url_request(request_context()->CreateRequest(
@@ -358,10 +363,11 @@
   MockProxyResolverFactory* resolver_factory = owned_resolver_factory.get();
 
   // Use a PAC URL so that URLRequestFtpJob's |pac_request_| field is non-NULL.
-  request_context()->set_proxy_service(std::make_unique<ProxyService>(
-      std::make_unique<ProxyConfigServiceFixed>(
-          ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
-      std::move(owned_resolver_factory), nullptr));
+  request_context()->set_proxy_resolution_service(
+      std::make_unique<ProxyResolutionService>(
+          std::make_unique<ProxyConfigServiceFixed>(
+              ProxyConfig::CreateFromCustomPacURL(GURL("http://foo"))),
+          std::move(owned_resolver_factory), nullptr));
 
   TestDelegate request_delegate;
   std::unique_ptr<URLRequest> url_request(request_context()->CreateRequest(
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index fd3601a..ab0a6bc 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -409,7 +409,7 @@
   if (network_delegate()) {
     network_delegate()->NotifyBeforeSendHeaders(
         request_, proxy_info,
-        request_->context()->proxy_service()->proxy_retry_info(),
+        request_->context()->proxy_resolution_service()->proxy_retry_info(),
         request_headers);
   }
 }
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc
index 10b36de2..bef92b1 100644
--- a/net/url_request/url_request_http_job_unittest.cc
+++ b/net/url_request/url_request_http_job_unittest.cc
@@ -189,18 +189,18 @@
 class URLRequestHttpJobWithProxy {
  public:
   explicit URLRequestHttpJobWithProxy(
-      std::unique_ptr<ProxyService> proxy_service)
-      : proxy_service_(std::move(proxy_service)),
+      std::unique_ptr<ProxyResolutionService> proxy_resolution_service)
+      : proxy_resolution_service_(std::move(proxy_resolution_service)),
         context_(new TestURLRequestContext(true)) {
     context_->set_client_socket_factory(&socket_factory_);
     context_->set_network_delegate(&network_delegate_);
-    context_->set_proxy_service(proxy_service_.get());
+    context_->set_proxy_resolution_service(proxy_resolution_service_.get());
     context_->Init();
   }
 
   MockClientSocketFactory socket_factory_;
   TestNetworkDelegate network_delegate_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   std::unique_ptr<TestURLRequestContext> context_;
 
  private:
@@ -258,8 +258,9 @@
   const ProxyServer proxy_server =
       ProxyServer::FromURI("http://origin.net:80", ProxyServer::SCHEME_HTTP);
 
-  std::unique_ptr<ProxyService> proxy_service =
-      ProxyService::CreateFixedFromPacResult(proxy_server.ToPacString());
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult(
+          proxy_server.ToPacString());
 
   MockWrite writes[] = {MockWrite(kSimpleProxyGetMockWrite)};
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET)};
@@ -267,7 +268,8 @@
   StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
                                        arraysize(writes));
 
-  URLRequestHttpJobWithProxy http_job_with_proxy(std::move(proxy_service));
+  URLRequestHttpJobWithProxy http_job_with_proxy(
+      std::move(proxy_resolution_service));
   http_job_with_proxy.socket_factory_.AddSocketDataProvider(&socket_data);
 
   TestDelegate delegate;
@@ -304,8 +306,8 @@
 
   // Connection to |proxy_server| would fail. Request should be fetched over
   // DIRECT.
-  std::unique_ptr<ProxyService> proxy_service =
-      ProxyService::CreateFixedFromPacResult(
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
+      ProxyResolutionService::CreateFixedFromPacResult(
           proxy_server.ToPacString() + "; " +
           ProxyServer::Direct().ToPacString());
 
@@ -321,7 +323,8 @@
   StaticSocketDataProvider socket_data(reads, arraysize(reads), writes,
                                        arraysize(writes));
 
-  URLRequestHttpJobWithProxy http_job_with_proxy(std::move(proxy_service));
+  URLRequestHttpJobWithProxy http_job_with_proxy(
+      std::move(proxy_resolution_service));
   http_job_with_proxy.socket_factory_.AddSocketDataProvider(&connect_data_1);
   http_job_with_proxy.socket_factory_.AddSocketDataProvider(&socket_data);
 
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index 59bcad5..73c2b07 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -72,8 +72,8 @@
   if (!host_resolver())
     context_storage_.set_host_resolver(
         std::unique_ptr<HostResolver>(new MockCachingHostResolver()));
-  if (!proxy_service())
-    context_storage_.set_proxy_service(ProxyService::CreateDirect());
+  if (!proxy_resolution_service())
+    context_storage_.set_proxy_resolution_service(ProxyResolutionService::CreateDirect());
   if (!cert_verifier())
     context_storage_.set_cert_verifier(CertVerifier::CreateDefault());
   if (!transport_security_state()) {
@@ -126,7 +126,7 @@
     session_context.cert_transparency_verifier = cert_transparency_verifier();
     session_context.ct_policy_enforcer = ct_policy_enforcer();
     session_context.transport_security_state = transport_security_state();
-    session_context.proxy_service = proxy_service();
+    session_context.proxy_resolution_service = proxy_resolution_service();
     session_context.ssl_config_service = ssl_config_service();
     session_context.http_auth_handler_factory = http_auth_handler_factory();
     session_context.http_server_properties = http_server_properties();
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index a0a04b6..6cfc3a38 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -733,7 +733,8 @@
   TestURLRequestContextWithProxy(const std::string& proxy,
                                  NetworkDelegate* delegate)
       : TestURLRequestContext(true) {
-    context_storage_.set_proxy_service(ProxyService::CreateFixed(proxy));
+    context_storage_.set_proxy_resolution_service(
+        ProxyResolutionService::CreateFixed(proxy));
     set_network_delegate(delegate);
     Init();
   }
@@ -10145,7 +10146,7 @@
   session_context.cert_transparency_verifier =
       default_context_.cert_transparency_verifier();
   session_context.ct_policy_enforcer = default_context_.ct_policy_enforcer();
-  session_context.proxy_service = default_context_.proxy_service();
+  session_context.proxy_resolution_service = default_context_.proxy_resolution_service();
   session_context.ssl_config_service = default_context_.ssl_config_service();
   session_context.http_auth_handler_factory =
       default_context_.http_auth_handler_factory();
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc
index d869f83..b1164c4 100644
--- a/net/websockets/websocket_end_to_end_test.cc
+++ b/net/websockets/websocket_end_to_end_test.cc
@@ -231,8 +231,6 @@
   bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
     return true;
   }
-  void OnAlternativeProxyBroken(
-      const ProxyServer& alternative_proxy_server) override {}
 
  private:
   ResolvedProxyInfo resolved_proxy_info_;
@@ -306,10 +304,10 @@
   ASSERT_TRUE(ws_server.BlockUntilStarted());
   std::string proxy_config =
       "https=" + proxy_server.host_port_pair().ToString();
-  std::unique_ptr<ProxyService> proxy_service(
-      ProxyService::CreateFixed(proxy_config));
-  ASSERT_TRUE(proxy_service);
-  context_.set_proxy_service(proxy_service.get());
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service(
+      ProxyResolutionService::CreateFixed(proxy_config));
+  ASSERT_TRUE(proxy_resolution_service);
+  context_.set_proxy_resolution_service(proxy_resolution_service.get());
   EXPECT_FALSE(ConnectAndWait(ws_server.GetURL(kEchoServer)));
   EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message());
 }
@@ -336,10 +334,10 @@
   ASSERT_TRUE(wss_server.BlockUntilStarted());
   std::string proxy_config =
       "https=" + proxy_server.host_port_pair().ToString();
-  std::unique_ptr<ProxyService> proxy_service(
-      ProxyService::CreateFixed(proxy_config));
-  ASSERT_TRUE(proxy_service);
-  context_.set_proxy_service(proxy_service.get());
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service(
+      ProxyResolutionService::CreateFixed(proxy_config));
+  ASSERT_TRUE(proxy_resolution_service);
+  context_.set_proxy_resolution_service(proxy_resolution_service.get());
   EXPECT_FALSE(ConnectAndWait(wss_server.GetURL(kEchoServer)));
   EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message());
 }
@@ -358,9 +356,9 @@
   std::string proxy_config = "https=" +
                              proxy_server.host_port_pair().ToString() + ";" +
                              "http=" + proxy_server.host_port_pair().ToString();
-  std::unique_ptr<ProxyService> proxy_service(
-      ProxyService::CreateFixed(proxy_config));
-  context_.set_proxy_service(proxy_service.get());
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service(
+      ProxyResolutionService::CreateFixed(proxy_config));
+  context_.set_proxy_resolution_service(proxy_resolution_service.get());
   InitialiseContext();
 
   // The test server doesn't have an unauthenticated proxy mode. WebSockets
diff --git a/net/websockets/websocket_test_util.cc b/net/websockets/websocket_test_util.cc
index e2c2244..bddb3a5 100644
--- a/net/websockets/websocket_test_util.cc
+++ b/net/websockets/websocket_test_util.cc
@@ -172,8 +172,9 @@
 void WebSocketTestURLRequestContextHost::SetProxyConfig(
     const std::string& proxy_rules) {
   DCHECK(!url_request_context_initialized_);
-  proxy_service_ = ProxyService::CreateFixed(proxy_rules);
-  url_request_context_.set_proxy_service(proxy_service_.get());
+  proxy_resolution_service_ = ProxyResolutionService::CreateFixed(proxy_rules);
+  url_request_context_.set_proxy_resolution_service(
+      proxy_resolution_service_.get());
 }
 
 TestURLRequestContext*
diff --git a/net/websockets/websocket_test_util.h b/net/websockets/websocket_test_util.h
index 23769404..945220632 100644
--- a/net/websockets/websocket_test_util.h
+++ b/net/websockets/websocket_test_util.h
@@ -21,7 +21,7 @@
 namespace net {
 
 class MockClientSocketFactory;
-class ProxyService;
+class ProxyResolutionService;
 class SequencedSocketData;
 struct SSLSocketDataProvider;
 
@@ -134,7 +134,7 @@
   WebSocketMockClientSocketFactoryMaker maker_;
   TestURLRequestContext url_request_context_;
   TestNetworkDelegate network_delegate_;
-  std::unique_ptr<ProxyService> proxy_service_;
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
   bool url_request_context_initialized_;
 
   DISALLOW_COPY_AND_ASSIGN(WebSocketTestURLRequestContextHost);
diff --git a/remoting/base/url_request_context_getter.cc b/remoting/base/url_request_context_getter.cc
index 2008e2d..fbf00762 100644
--- a/remoting/base/url_request_context_getter.cc
+++ b/remoting/base/url_request_context_getter.cc
@@ -19,8 +19,9 @@
     scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)
     : network_task_runner_(network_task_runner),
       file_task_runner_(file_task_runner),
-      proxy_config_service_(net::ProxyService::CreateSystemProxyConfigService(
-          network_task_runner)) {}
+      proxy_config_service_(
+          net::ProxyResolutionService::CreateSystemProxyConfigService(
+              network_task_runner)) {}
 
 net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
   if (!url_request_context_.get()) {
diff --git a/remoting/protocol/webrtc_frame_scheduler_simple.cc b/remoting/protocol/webrtc_frame_scheduler_simple.cc
index 7a34f976..96cf6e2 100644
--- a/remoting/protocol/webrtc_frame_scheduler_simple.cc
+++ b/remoting/protocol/webrtc_frame_scheduler_simple.cc
@@ -146,7 +146,13 @@
     }
   }
 
-  params_out->duration = (now - latest_frame_encode_start_time_);
+  // Encoder uses frame duration to calculate portion of the target bitrate it
+  // can use for this frame. Higher values normally will cause bigger encoded
+  // frames that will take longer to be delivered to the client. To keep
+  // end-to-end latency low always pass the target frame duration. The actual
+  // interval between frames can be longer than the target value, depending on
+  // the size of the encoded frames.
+  params_out->duration = kTargetFrameInterval;
   params_out->fps = processing_time_estimator_.EstimatedFrameRate();
 
   latest_frame_encode_start_time_ = now;
diff --git a/remoting/protocol/webrtc_frame_scheduler_unittest.cc b/remoting/protocol/webrtc_frame_scheduler_unittest.cc
index 79553bb6..bbf021a9 100644
--- a/remoting/protocol/webrtc_frame_scheduler_unittest.cc
+++ b/remoting/protocol/webrtc_frame_scheduler_unittest.cc
@@ -110,8 +110,6 @@
   frame.mutable_updated_region()->Clear();
   bool result = scheduler_->OnFrameCaptured(&frame, &out_params);
 
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(300), out_params.duration);
-
   // Empty frames should be sent at the throttled rate.
   EXPECT_TRUE(result);
 };
diff --git a/services/network/public/cpp/proxy_resolving_client_socket.cc b/services/network/public/cpp/proxy_resolving_client_socket.cc
index 444c5f3..d199c7f 100644
--- a/services/network/public/cpp/proxy_resolving_client_socket.cc
+++ b/services/network/public/cpp/proxy_resolving_client_socket.cc
@@ -64,7 +64,8 @@
   // these classes is thread safe. Figure out if the comment's wrong, or if this
   // entire class is badly broken.
   session_context.channel_id_service = NULL;
-  session_context.proxy_service = request_context->proxy_service();
+  session_context.proxy_resolution_service =
+      request_context->proxy_resolution_service();
   session_context.ssl_config_service = request_context->ssl_config_service();
   session_context.http_auth_handler_factory =
       request_context->http_auth_handler_factory();
@@ -144,7 +145,7 @@
   // TODO(xunjieli): Having a null ProxyDelegate is bad. Figure out how to
   // interact with the new interface for proxy delegate.
   // https://crbug.com/793071.
-  int net_error = network_session_->proxy_service()->ResolveProxy(
+  int net_error = network_session_->proxy_resolution_service()->ResolveProxy(
       url_, "POST", &proxy_info_,
       base::BindRepeating(&ProxyResolvingClientSocket::ConnectToProxy,
                           base::Unretained(this)),
@@ -164,7 +165,8 @@
 void ProxyResolvingClientSocket::Disconnect() {
   CloseTransportSocket();
   if (proxy_resolve_request_) {
-    network_session_->proxy_service()->CancelRequest(proxy_resolve_request_);
+    network_session_->proxy_resolution_service()
+                    ->CancelRequest(proxy_resolve_request_);
     proxy_resolve_request_ = NULL;
   }
   user_connect_callback_.Reset();
@@ -312,7 +314,8 @@
     }
     CloseTransportSocket();
   } else {
-    network_session_->proxy_service()->ReportSuccess(proxy_info_, NULL);
+    network_session_->proxy_resolution_service()->ReportSuccess(
+        proxy_info_, NULL);
   }
   base::ResetAndReturn(&user_connect_callback_).Run(net_error);
 }
@@ -384,11 +387,12 @@
         proxy_info_.proxy_server().host_port_pair());
   }
 
-  int rv = network_session_->proxy_service()->ReconsiderProxyAfterError(
-      url_, std::string(), error, &proxy_info_,
-      base::BindRepeating(&ProxyResolvingClientSocket::ConnectToProxy,
-                          base::Unretained(this)),
-      &proxy_resolve_request_, NULL, net_log_);
+  int rv =
+      network_session_->proxy_resolution_service()->ReconsiderProxyAfterError(
+          url_, std::string(), error, &proxy_info_,
+          base::BindRepeating(&ProxyResolvingClientSocket::ConnectToProxy,
+                              base::Unretained(this)),
+          &proxy_resolve_request_, NULL, net_log_);
   if (rv == net::OK || rv == net::ERR_IO_PENDING) {
     CloseTransportSocket();
   } else {
diff --git a/services/network/public/cpp/proxy_resolving_client_socket.h b/services/network/public/cpp/proxy_resolving_client_socket.h
index 8d6b0c98..276f792 100644
--- a/services/network/public/cpp/proxy_resolving_client_socket.h
+++ b/services/network/public/cpp/proxy_resolving_client_socket.h
@@ -51,8 +51,8 @@
   // will be only used for proxy resolution. Caller doesn't need to explicitly
   // sanitize the url, any sensitive data (like embedded usernames and
   // passwords), and local data (i.e. reference fragment) will be sanitized by
-  // net::ProxyService::ResolveProxyHelper() before the url is disclosed to the
-  // proxy.
+  // net::ProxyResolutionService::ResolveProxyHelper() before the url is
+  // disclosed to the proxy.
   ProxyResolvingClientSocket(
       net::ClientSocketFactory* socket_factory,
       const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
@@ -107,7 +107,7 @@
   std::unique_ptr<net::ClientSocketHandle> transport_;
 
   const net::SSLConfig ssl_config_;
-  net::ProxyService::Request* proxy_resolve_request_;
+  net::ProxyResolutionService::Request* proxy_resolve_request_;
   net::ProxyInfo proxy_info_;
   const GURL url_;
   net::NetLogWithSource net_log_;
diff --git a/services/network/public/cpp/proxy_resolving_client_socket_unittest.cc b/services/network/public/cpp/proxy_resolving_client_socket_unittest.cc
index 5e372a8..b319667 100644
--- a/services/network/public/cpp/proxy_resolving_client_socket_unittest.cc
+++ b/services/network/public/cpp/proxy_resolving_client_socket_unittest.cc
@@ -32,8 +32,8 @@
  public:
   TestURLRequestContextWithProxy(const std::string& pac_result)
       : TestURLRequestContext(true) {
-    context_storage_.set_proxy_service(
-        net::ProxyService::CreateFixedFromPacResult(pac_result));
+    context_storage_.set_proxy_resolution_service(
+        net::ProxyResolutionService::CreateFixedFromPacResult(pac_result));
     // net::MockHostResolver maps all hosts to localhost.
     auto host_resolver = std::make_unique<net::MockHostResolver>();
     context_storage_.set_host_resolver(std::move(host_resolver));
@@ -300,7 +300,7 @@
   net::URLRequestContext* context =
       context_getter_with_proxy_->GetURLRequestContext();
   const net::ProxyRetryInfoMap& retry_info =
-      context->proxy_service()->proxy_retry_info();
+      context->proxy_resolution_service()->proxy_retry_info();
 
   EXPECT_EQ(1u, retry_info.size());
   net::ProxyRetryInfoMap::const_iterator iter = retry_info.find("bad:99");
@@ -450,10 +450,10 @@
       std::make_unique<net::MockAsyncProxyResolverFactory>(false);
   net::MockAsyncProxyResolverFactory* proxy_resolver_factory_raw =
       proxy_resolver_factory.get();
-  net::ProxyService service(
+  net::ProxyResolutionService service(
       std::make_unique<net::ProxyConfigServiceFixed>(proxy_config),
       std::move(proxy_resolver_factory), nullptr);
-  context->set_proxy_service(&service);
+  context->set_proxy_resolution_service(&service);
   context->Init();
 
   scoped_refptr<net::TestURLRequestContextGetter> context_getter_with_proxy(
@@ -483,9 +483,9 @@
 TEST_F(ProxyResolvingClientSocketTest, ProxyConfigChanged) {
   auto context = std::make_unique<net::TestURLRequestContext>(true);
   // Use direct connection.
-  std::unique_ptr<net::ProxyService> proxy_service =
-      net::ProxyService::CreateDirect();
-  context->set_proxy_service(proxy_service.get());
+  std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service =
+      net::ProxyResolutionService::CreateDirect();
+  context->set_proxy_resolution_service(proxy_resolution_service.get());
   context->Init();
 
   scoped_refptr<net::TestURLRequestContextGetter> context_getter_with_proxy(
@@ -517,7 +517,7 @@
   // change. It will still be the direct connection but the configuration
   // version will be bumped. That is enough for the job controller to restart
   // the jobs.
-  proxy_service->ForceReloadProxyConfig();
+  proxy_resolution_service->ForceReloadProxyConfig();
   EXPECT_EQ(net::OK, callback.WaitForResult());
   EXPECT_TRUE(data_1.AllReadDataConsumed());
   EXPECT_TRUE(data_1.AllWriteDataConsumed());
@@ -572,7 +572,7 @@
       context_getter_with_proxy_->GetURLRequestContext();
 
   // Before starting the test, verify that there are no proxies marked as bad.
-  ASSERT_TRUE(context->proxy_service()->proxy_retry_info().empty())
+  ASSERT_TRUE(context->proxy_resolution_service()->proxy_retry_info().empty())
       << mock_error;
 
   net::MockClientSocketFactory socket_factory;
@@ -603,7 +603,7 @@
   EXPECT_EQ(net::OK, status);
 
   const net::ProxyRetryInfoMap& retry_info =
-      context->proxy_service()->proxy_retry_info();
+      context->proxy_resolution_service()->proxy_retry_info();
   EXPECT_EQ(2u, retry_info.size()) << mock_error;
   EXPECT_NE(retry_info.end(), retry_info.find("https://badproxy:99"));
   EXPECT_NE(retry_info.end(), retry_info.find("https://badfallbackproxy:98"));
diff --git a/services/proxy_resolver/proxy_resolver_impl.cc b/services/proxy_resolver/proxy_resolver_impl.cc
index bfca068..c1cb4d6 100644
--- a/services/proxy_resolver/proxy_resolver_impl.cc
+++ b/services/proxy_resolver/proxy_resolver_impl.cc
@@ -10,8 +10,8 @@
 #include "base/memory/ptr_util.h"
 #include "net/base/net_errors.h"
 #include "net/proxy/mojo_proxy_resolver_v8_tracing_bindings.h"
+#include "net/proxy/pac_file_data.h"
 #include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_resolver_script_data.h"
 #include "net/proxy/proxy_resolver_v8_tracing.h"
 #include "services/service_manager/public/cpp/service_context_ref.h"
 
diff --git a/services/test/run_all_service_tests.cc b/services/test/run_all_service_tests.cc
index d9bfbce..deb9fc3 100644
--- a/services/test/run_all_service_tests.cc
+++ b/services/test/run_all_service_tests.cc
@@ -36,7 +36,6 @@
     ui::OzonePlatform::InitParams params;
     params.single_process = true;
     ui::OzonePlatform::InitializeForGPU(params);
-    ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
 #endif
 
     // base::TestSuite and ViewsInit both try to load icu. That's ok for tests.
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index 9489a2b3..2b1fe33 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -95,7 +95,6 @@
 -NewlibPackagedAppTest.NoSocketPermissions
 -NewlibPackagedAppTest.SocketPermissions
 -NewlibPackagedAppTest.SuccessfulLoad
--PageLoadMetricsBrowserTest.ChromeErrorPage
 -PageLoadMetricsBrowserTest.LoadingMetrics
 -PageLoadMetricsBrowserTest.LoadingMetricsFailed
 -PageLoadMetricsBrowserTest.PayloadSize
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175
index c66f51b8..f917f38 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175
@@ -83,31 +83,21 @@
 crbug.com/769942 virtual/gpu-rasterization/images/color-profile-svg-foreign-object.html [ Failure ]
 crbug.com/769942 virtual/exotic-color-space/images/color-profile-svg-foreign-object.html [ Failure ]
 
-crbug.com/771643 css3/filters/effect-reference-image-lazy-attach.html [ Failure ]
-crbug.com/771643 css3/filters/effect-reference-image.html [ Failure ]
-crbug.com/771643 css3/filters/effect-reference-on-transparent-element.html [ Failure ]
 crbug.com/771643 css3/filters/effect-reference-tile.html [ Pass Failure Crash ]
-crbug.com/771643 css3/filters/empty-element-with-filter.html [ Failure ]
-crbug.com/771643 css3/filters/filterRegions.html [ Failure ]
 crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ]
 crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ]
 crbug.com/771643 fast/reflections/reflection-masks-outset.html [ Pass Failure ]
-crbug.com/771643 fast/replaced/width100percent-textarea.html [ Failure ]
-crbug.com/771643 http/tests/misc/slow-loading-mask.html [ Failure ]
 crbug.com/771643 images/cross-fade-invalidation.html [ Failure ]
 crbug.com/771643 images/drag-image-transformed-parent.html [ Failure ]
 crbug.com/771643 plugins/webview-plugin-lifecycle.html [ Failure ]
 crbug.com/771643 plugins/webview-plugin-nested-iframe-scroll.html [ Failure ]
-crbug.com/771643 scrollbars/border-box-rect-clips-scrollbars.html [ Failure ]
+# This will pass with --root-layer-scrolls.
 crbug.com/771643 scrollbars/custom-scrollbars-paint-outside-iframe.html [ Failure ]
 crbug.com/771643 svg/as-background-image/animated-svg-as-background.html [ Failure ]
 crbug.com/771643 svg/as-background-image/svg-as-background-6.html [ Failure ]
 crbug.com/771643 svg/as-image/svg-image-with-css-animation.html [ Failure ]
 crbug.com/771643 svg/batik/masking/maskRegions.svg [ Failure ]
 crbug.com/771643 svg/custom/local-url-references.html [ Failure ]
-crbug.com/771643 svg/hixie/mixed/006.xml [ Failure ]
-crbug.com/771643 svg/hixie/mixed/011.xml [ Failure ]
-crbug.com/771643 svg/overflow/overflow-on-foreignObject.svg [ Failure ]
 crbug.com/771643 svg/zoom/page/zoom-mask-with-percentages.svg [ Failure ]
 crbug.com/771643 tables/table-transform-absolute-position-child.html [ Failure ]
 crbug.com/771643 virtual/exotic-color-space/images/cross-fade-invalidation.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 86cb17a..1ba11692 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -710,6 +710,8 @@
 
 crbug.com/788110 [ Linux Win10 ] inspector-protocol/layout-fonts/unicode-range-combining-chars-fallback.js [ Pass Failure ]
 
+crbug.com/803276 [ Mac Win ] inspector-protocol/memory/sampling-native-profile.js [ Skip ]
+
 # Run these tests with under virtual/scalefactor... only.
 crbug.com/567837 fast/hidpi/static [ Skip ]
 
@@ -2599,6 +2601,8 @@
 # Crashes
 crbug.com/709227 external/wpt/offscreen-canvas/fill-and-stroke-styles/2d.pattern.basic.nocontext.worker.html [ Crash ]
 
+crbug.com/803943 [ Win ] external/wpt/html/syntax/parsing/html5lib_tests16.html?run_type=uri [ Pass Timeout ]
+
 # ====== Tests from enabling .any.js/.worker.js tests end here ========
 
 crbug.com/789139 http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Failure Pass Timeout Crash ]
diff --git a/third_party/WebKit/LayoutTests/animations/OWNERS b/third_party/WebKit/LayoutTests/animations/OWNERS
index 767fca00..6264d8a 100644
--- a/third_party/WebKit/LayoutTests/animations/OWNERS
+++ b/third_party/WebKit/LayoutTests/animations/OWNERS
@@ -1,2 +1,2 @@
-# TEAM: style-dev@chromium.org
+# TEAM: animations-dev@chromium.org
 # COMPONENT: Blink>Animation
diff --git a/third_party/WebKit/LayoutTests/compositing/animation/OWNERS b/third_party/WebKit/LayoutTests/compositing/animation/OWNERS
index 767fca00..6264d8a 100644
--- a/third_party/WebKit/LayoutTests/compositing/animation/OWNERS
+++ b/third_party/WebKit/LayoutTests/compositing/animation/OWNERS
@@ -1,2 +1,2 @@
-# TEAM: style-dev@chromium.org
+# TEAM: animations-dev@chromium.org
 # COMPONENT: Blink>Animation
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 23182f39..646fe916 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -116414,6 +116414,11 @@
      {}
     ]
    ],
+   "css/css-typed-om/stylevalue-serialization/cssMathValue.tentative-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-typed-om/stylevalue-subclasses/cssVariableReferenceValue.tentative-expected.txt": [
     [
      {}
@@ -128504,6 +128509,11 @@
      {}
     ]
    ],
+   "html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/browsers/browsing-the-web/history-traversal/contains.json": [
     [
      {}
@@ -136709,6 +136719,11 @@
      {}
     ]
    ],
+   "html/semantics/document-metadata/the-link-element/link-style-error-01-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/semantics/document-metadata/the-link-element/resources/bad.css": [
     [
      {}
@@ -141749,6 +141764,11 @@
      {}
     ]
    ],
+   "interfaces/screen-orientation.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/touchevents.idl": [
     [
      {}
@@ -212653,6 +212673,12 @@
      {}
     ]
    ],
+   "screen-orientation/interfaces.html": [
+    [
+     "/screen-orientation/interfaces.html",
+     {}
+    ]
+   ],
    "screen-orientation/lock-bad-argument.html": [
     [
      "/screen-orientation/lock-bad-argument.html",
@@ -212683,12 +212709,6 @@
      {}
     ]
    ],
-   "screen-orientation/orientation-api.html": [
-    [
-     "/screen-orientation/orientation-api.html",
-     {}
-    ]
-   ],
    "screen-orientation/orientation-reading.html": [
     [
      "/screen-orientation/orientation-reading.html",
@@ -213005,6 +213025,12 @@
      {}
     ]
    ],
+   "server-timing/cross_origin.html": [
+    [
+     "/server-timing/cross_origin.html",
+     {}
+    ]
+   ],
    "server-timing/server_timing_header-parsing.html": [
     [
      "/server-timing/server_timing_header-parsing.html",
@@ -272983,7 +273009,7 @@
    "support"
   ],
   "css/css-paint-api/style-background-image.https.html": [
-   "54f213635749ffeae4d21a5e3d4391901fbfe984",
+   "4288eba641144a33ba79390102d141693a2c14d6",
    "reftest"
   ],
   "css/css-paint-api/style-before-pseudo-ref.html": [
@@ -272991,7 +273017,7 @@
    "support"
   ],
   "css/css-paint-api/style-before-pseudo.https.html": [
-   "7e8263880905e254e7c27274d6314ba23bd1cb04",
+   "e491dcde66880750f3b277d520f5288e0508d13a",
    "reftest"
   ],
   "css/css-paint-api/style-first-letter-pseudo-ref.html": [
@@ -285518,8 +285544,12 @@
    "004752ad2e9682845697d668af158679031f65dc",
    "testharness"
   ],
+  "css/css-typed-om/stylevalue-serialization/cssMathValue.tentative-expected.txt": [
+   "11864594c531e22f5e798701524ee1c8fda0b77d",
+   "support"
+  ],
   "css/css-typed-om/stylevalue-serialization/cssMathValue.tentative.html": [
-   "9bcb4ff6461793d61925d173da7650230e3b4555",
+   "4c5bf7630548c90a1397b6f1f215bd3be76b6cf6",
    "testharness"
   ],
   "css/css-typed-om/stylevalue-serialization/cssPositionValue.html": [
@@ -307514,6 +307544,10 @@
    "3924bc14b2b90880c939e384bf4b075531793a57",
    "testharness"
   ],
+  "html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3-expected.txt": [
+   "1edf0b02a5a459d3377b3c3fae3019d021f3d3c7",
+   "support"
+  ],
   "html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3.html": [
    "4ceab904264ef4e4151a3fac41f662d83a80072e",
    "testharness"
@@ -309259,7 +309293,7 @@
    "support"
   ],
   "html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt": [
-   "956fca935e7c7836852d8b250480eb7021b4bf3d",
+   "d3e56cfc9ca0941723708d12f3db82f4ac543379",
    "support"
   ],
   "html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html": [
@@ -309683,7 +309717,7 @@
    "support"
   ],
   "html/browsers/the-window-object/security-window/window-security-expected.txt": [
-   "7ba322fa261796fab5fab2f9002caf35acd33c29",
+   "55446512a7bb2d7e0b2492aee6d93ed2d8f08324",
    "support"
   ],
   "html/browsers/the-window-object/security-window/window-security.html": [
@@ -317430,6 +317464,10 @@
    "e18655ffb90bb039c50b262d145d63ca5efc22ca",
    "testharness"
   ],
+  "html/semantics/document-metadata/the-link-element/link-style-error-01-expected.txt": [
+   "de2c53df8463973130cbe7b20f35919dedf50e23",
+   "support"
+  ],
   "html/semantics/document-metadata/the-link-element/link-style-error-01.html": [
    "285208d6cf3113ec16bedd107c0740b8c7c8a9d8",
    "testharness"
@@ -326978,6 +327016,10 @@
    "fc724b70bc1e1d30e538ee5154a99d4871414302",
    "support"
   ],
+  "interfaces/screen-orientation.idl": [
+   "b280c2a72795d4abd55a361a0afd8adce70562dc",
+   "support"
+  ],
   "interfaces/touchevents.idl": [
    "6ce4f601cda6cd3b99a300e0b28d2886647f06d3",
    "support"
@@ -336423,7 +336465,7 @@
    "testharness"
   ],
   "payment-request/payment-request-id-attribute.https.html": [
-   "9a8a1ffc3cd7ba3c29380c4a9962bd17f35087c3",
+   "34dd889e8bc906eb9a99c192e547fab831099f7c",
    "testharness"
   ],
   "payment-request/payment-request-not-exposed.https.worker.js": [
@@ -345298,6 +345340,10 @@
    "970c0e5b33815109f17231ffeaf4cea22cf9096c",
    "support"
   ],
+  "screen-orientation/interfaces.html": [
+   "d54475008731fafd00c3cae73f11eac94dba0883",
+   "testharness"
+  ],
   "screen-orientation/lock-bad-argument-expected.txt": [
    "a27f6264d5dce06d487ff4f8bf06766b96082dfa",
    "support"
@@ -345322,10 +345368,6 @@
    "b2c9679f11ebae5968c063bfb2449edfae46fc08",
    "testharness"
   ],
-  "screen-orientation/orientation-api.html": [
-   "44225c2493c6ac472a9f2d4b871ee17368cf02be",
-   "testharness"
-  ],
   "screen-orientation/orientation-reading-expected.txt": [
    "f58f1832c431c86aff963229ac92569b5396bc31",
    "support"
@@ -345638,6 +345680,10 @@
    "2d4c432bb4394da88cb55e11d1e7a0c5dd5203d8",
    "support"
   ],
+  "server-timing/cross_origin.html": [
+   "74333db517babacbb84bb20c91ccfc8b2627b934",
+   "testharness"
+  ],
   "server-timing/resources/blue.png": [
    "7de5cdb5ad04ac365430b3b5f5ba01d2ba57ea23",
    "support"
@@ -352195,7 +352241,7 @@
    "testharness"
   ],
   "web-animations/OWNERS": [
-   "4725570730034e4d9b66695acfcfa7b246c79311",
+   "ea63f4f72946580ffc58d64c7401a03140896fd6",
    "support"
   ],
   "web-animations/README.md": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-background-image.https.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-background-image.https.html
index cb894e57..7853607 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-background-image.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-background-image.https.html
@@ -25,7 +25,7 @@
             '--bar',
             '--foo',
             'align-items',
-            'border-radius',
+            'border-top-left-radius',
         ];
     }
     paint(ctx, geom, styleMap) {
@@ -41,13 +41,13 @@
             serializedStrings.push(serialized);
         }
         ctx.strokeStyle = 'green';
-        if (serializedStrings[0] != "--bar: [null]")
+        if (serializedStrings[0] != "--bar: [CSSUnparsedValue=]")
             ctx.strokeStyle = 'red';
         if (serializedStrings[1] != "--foo: [CSSUnparsedValue= bar]")
             ctx.strokeStyle = 'blue';
         if (serializedStrings[2] != "align-items: [CSSKeywordValue=normal]")
             ctx.strokeStyle = 'yellow';
-        if (serializedStrings[3] != "border-radius: [CSSStyleValue=2px]")
+        if (serializedStrings[3] != "border-top-left-radius: [CSSUnitValue=2px]")
             ctx.strokeStyle = 'cyan';
         ctx.lineWidth = 4;
         ctx.strokeRect(0, 0, geom.width, geom.height);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-before-pseudo.https.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-before-pseudo.https.html
index 707d02b..5249f58 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-before-pseudo.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/style-before-pseudo.https.html
@@ -28,7 +28,7 @@
         return [
             '--bar',
             '--foo',
-            'border-radius',
+            'border-top-left-radius',
         ];
     }
     paint(ctx, geom, styleMap) {
@@ -44,11 +44,11 @@
             serializedStrings.push(serialized);
         }
         ctx.strokeStyle = 'green';
-        if (serializedStrings[0] != "--bar: [null]")
+        if (serializedStrings[0] != "--bar: [CSSUnparsedValue=]")
             ctx.strokeStyle = 'red';
         if (serializedStrings[1] != "--foo: [CSSUnparsedValue= bar]")
             ctx.strokeStyle = 'blue';
-        if (serializedStrings[2] != "border-radius: [CSSStyleValue=2px]")
+        if (serializedStrings[2] != "border-top-left-radius: [CSSUnitValue=2px]")
             ctx.strokeStyle = 'yellow';
         ctx.lineWidth = 4;
         ctx.strokeRect(0, 0, geom.width, geom.height);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/stylevalue-serialization/cssMathValue.tentative-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/stylevalue-serialization/cssMathValue.tentative-expected.txt
new file mode 100644
index 0000000..08efcc70
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/stylevalue-serialization/cssMathValue.tentative-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS CSSMathSum with 1 argument serializes correctly
+PASS CSSMathSum with 2 arguments serializes correctly
+PASS CSSMathSum with more than 2 arguments serializes correctly
+PASS CSSMathProduct with 1 argument serializes correctly
+PASS CSSMathProduct with 2 arguments serializes correctly
+PASS CSSMathProduct with more than 2 arguments serializes correctly
+FAIL CSSMathProduct of two different base types serializes correctly Failed to execute 'toString' on 'CSSStyleValue': Some CSSMathValues can't be serialized yet. See crbug.com/803739
+FAIL CSSMathMax with one argument serializes correctly Failed to execute 'toString' on 'CSSStyleValue': Some CSSMathValues can't be serialized yet. See crbug.com/803739
+FAIL CSSMathMax with more than one argument serializes correctly Failed to execute 'toString' on 'CSSStyleValue': Some CSSMathValues can't be serialized yet. See crbug.com/803739
+FAIL CSSMathMin with one argument serializes correctly Failed to execute 'toString' on 'CSSStyleValue': Some CSSMathValues can't be serialized yet. See crbug.com/803739
+FAIL CSSMathMin with more than one argument serializes correctly Failed to execute 'toString' on 'CSSStyleValue': Some CSSMathValues can't be serialized yet. See crbug.com/803739
+FAIL CSSMathNegate serializes correctly Failed to execute 'toString' on 'CSSStyleValue': Some CSSMathValues can't be serialized yet. See crbug.com/803739
+FAIL CSSMathInvert serializes correctly Failed to execute 'toString' on 'CSSStyleValue': Some CSSMathValues can't be serialized yet. See crbug.com/803739
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/stylevalue-serialization/cssMathValue.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/stylevalue-serialization/cssMathValue.tentative.html
index 6ce739b6..814812e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/stylevalue-serialization/cssMathValue.tentative.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/stylevalue-serialization/cssMathValue.tentative.html
@@ -1,6 +1,8 @@
 <!doctype html>
 <meta charset="utf-8">
 <title>IDL-constructed CSSMathValue serialization tests</title>
+<!-- Tentative because this depends on css-values-4 spec, which is still WIP:
+     https://drafts.csswg.org/css-values-4/#calc-notation -->
 <link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#calc-serialization">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
@@ -10,72 +12,76 @@
 
 const gTestCases = [
   {
+    description: 'CSSMathSum with 1 argument',
     value: new CSSMathSum(CSS.px(1)),
     cssText: 'calc(1px)',
-    desc: 'CSSMathSum with 1 argument'
   },
   {
+    description: 'CSSMathSum with 2 arguments',
     value: new CSSMathSum(CSS.px(1), CSS.px(2)),
     cssText: 'calc(1px + 2px)',
-    desc: 'CSSMathSum with 2 arguments'
   },
   {
+    description: 'CSSMathSum with more than 2 arguments',
     value: new CSSMathSum(CSS.px(1), CSS.px(2), CSS.px(3)),
     cssText: 'calc((1px + 2px) + 3px)',
-    desc: 'CSSMathSum with more than 2 arguments'
   },
   {
+    description: 'CSSMathProduct with 1 argument',
     value: new CSSMathProduct(CSS.px(1)),
     cssText: 'calc(1px)',
-    desc: 'CSSMathProduct with 1 argument'
   },
   {
+    description: 'CSSMathProduct with 2 arguments',
     value: new CSSMathProduct(CSS.px(1), 2),
     cssText: 'calc(1px * 2)',
-    desc: 'CSSMathProduct with 2 arguments'
   },
   {
+    description: 'CSSMathProduct with more than 2 arguments',
     value: new CSSMathProduct(CSS.px(1), 2, 3),
     cssText: 'calc((1px * 2) * 3)',
-    desc: 'CSSMathProduct with more than 2 arguments'
+  },
+  {
+    description: 'CSSMathProduct of two different base types',
+    value: new CSSMathProduct(CSS.px(1), CSS.s(1)),
+    cssText: 'calc(1px * 1s)',
+  },
+  {
+    description: 'CSSMathMax with one argument',
+    value: new CSSMathMax(CSS.px(2)),
+    cssText: 'max(1px)',
+  },
+  {
+    description: 'CSSMathMax with more than one argument',
+    value: new CSSMathMax(CSS.px(2), CSS.px(1)),
+    cssText: 'max(1px, 1s)',
+  },
+  {
+    description: 'CSSMathMin with one argument',
+    value: new CSSMathMin(CSS.px(1)),
+    cssText: 'min(1px)',
+  },
+  {
+    description: 'CSSMathMin with more than one argument',
+    value: new CSSMathMin(CSS.px(1), CSS.px(2)),
+    cssText: 'min(1px, 2px)',
+  },
+  {
+    description: 'CSSMathNegate',
+    value: new CSSMathNegate(CSS.px(1)),
+    cssText: 'calc(- 1px)',
+  },
+  {
+    description: 'CSSMathInvert',
+    value: new CSSMathInvert(CSS.px(1)),
+    cssText: 'calc(1 / 1px)',
   },
 ];
 
-for (const {value, cssText, desc} of gTestCases) {
+for (const {value, cssText, description} of gTestCases) {
   test(() => {
     assert_equals(value.toString(), cssText);
-  }, desc + ' serializes correctly');
-}
-
-// TODO(crbug.com/782103): Convert these to actual tests once we have spec
-// for these. For now, let's just test that they don't crash.
-const gInvalidTestCases = [
-  {
-    value: new CSSMathProduct(CSS.px(1), CSS.s(1)),
-    desc: 'CSSMathProduct of two different base types'
-  },
-  {
-    value: new CSSMathMax(CSS.px(2), CSS.px(1)),
-    desc: 'CSSMathMax'
-  },
-  {
-    value: new CSSMathMin(CSS.px(1), CSS.px(2)),
-    desc: 'CSSMathMin'
-  },
-  {
-    value: new CSSMathNegate(CSS.px(1)),
-    desc: 'CSSMathNegate'
-  },
-  {
-    value: new CSSMathInvert(CSS.px(1)),
-    desc: 'CSSMathInvert'
-  },
-];
-
-for (const {value, desc} of gInvalidTestCases) {
-  test(() => {
-    value.toString();
-  }, 'Serializing ' + desc + ' does not crash');
+  }, description + ' serializes correctly');
 }
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-orientation.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-orientation.idl
new file mode 100644
index 0000000..7db942e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-orientation.idl
@@ -0,0 +1,28 @@
+partial interface Screen {
+    [SameObject]
+    readonly attribute ScreenOrientation orientation;
+};
+[Exposed=Window]
+interface ScreenOrientation : EventTarget {
+    Promise<void> lock(OrientationLockType orientation);
+    void          unlock();
+    readonly attribute OrientationType type;
+    readonly attribute unsigned short  angle;
+             attribute EventHandler    onchange;
+};
+enum OrientationType {
+    "portrait-primary",
+    "portrait-secondary",
+    "landscape-primary",
+    "landscape-secondary"
+};
+enum OrientationLockType {
+    "any",
+    "natural",
+    "landscape",
+    "portrait",
+    "portrait-primary",
+    "portrait-secondary",
+    "landscape-primary",
+    "landscape-secondary"
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-id-attribute.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-id-attribute.https.html
index 9d77a88..455b65a7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-id-attribute.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-id-attribute.https.html
@@ -2,24 +2,38 @@
 <!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
 <meta charset="utf-8">
 <title>Test for PaymentRequest id attribute</title>
+<link rel="help" href="https://w3c.github.io/payment-request/#constructor">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
+const methods = [{ supportedMethods: "foo" }];
+const total = { label: "label", amount: { currency: "USD", value: "5.00" } };
+
 test(() => {
-  const methods = [{ supportedMethods: "foo" }];
-  const total = { label: "label", amount: { currency: "USD", value: "5.00" } };
   const request1 = new PaymentRequest(methods, {
     id: "pass",
     total,
   });
   assert_idl_attribute(request1, "id");
   assert_equals(request1.id, "pass", "Expected PaymentRequest.id to be 'pass'");
+}, "PaymentRequest's id attribute's value can be set via PaymentDetailsInit dictionary");
+
+// Test for https://github.com/w3c/payment-request/pull/665
+test(() => {
+  const uuidRegExp = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-4][0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
+  const request1 = new PaymentRequest(methods, {
+    total,
+  });
   const request2 = new PaymentRequest(methods, {
     total,
   });
   assert_true(
-    request2.id && typeof request2.id === "string",
-    "Expected PaymentRequest.id to be some auto-generated truthy string"
+    uuidRegExp.test(request1.id) && uuidRegExp.test(request2.id) ,
+    "Expected PaymentRequest.id be a UUID"
   );
-}, "PaymentRequest id attribute");
+  assert_not_equals(
+    request1.id, request2.id,
+    "Expected PaymentRequest.id be unique per instance"
+  );
+}, "PaymentRequest's id attribute must be a UUID when PaymentDetailsInit.id is missing");
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/interfaces.html b/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/interfaces.html
new file mode 100644
index 0000000..26d46ae
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/interfaces.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Screen Orientation API IDL tests</title>
+<link rel="help" href="https://w3c.github.io/screen-orientation/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script>
+"use strict";
+
+promise_test(async () => {
+  const idl_array = new IdlArray();
+  const dom_idl = await fetch("/interfaces/dom.idl").then(r => r.text());
+  const screenorientation_idl = await fetch("/interfaces/screen-orientation.idl").then(r => r.text());
+
+  idl_array.add_untested_idls(dom_idl);
+  idl_array.add_untested_idls('interface EventHandler {};');
+  idl_array.add_untested_idls('interface Screen {};');
+  idl_array.add_idls(screenorientation_idl);
+
+  idl_array.add_objects({
+    Screen: ['screen'],
+    ScreenOrientation: ['screen.orientation']
+  });
+  idl_array.test();
+}, "Test IDL implementation of Screen Orientation API");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/orientation-api.html b/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/orientation-api.html
deleted file mode 100644
index 80910a3a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/orientation-api.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-
-test(function() {
-    assert_true('orientation' in window.screen);
-    assert_true('angle' in window.screen.orientation);
-    assert_true('type' in window.screen.orientation);
-    assert_true('lock' in window.screen.orientation);
-    assert_true('unlock' in window.screen.orientation);
-    assert_true('onchange' in window.screen.orientation);
-}, "Test that the Screen Orientation API is present.")
-
-test(function() {
-  assert_equals(typeof(screen.orientation), "object");
-  assert_equals(typeof(screen.orientation.angle), "number");
-  assert_equals(typeof(screen.orientation.type), "string");
-  assert_equals(typeof(screen.orientation.lock), "function");
-  assert_equals(typeof(screen.orientation.unlock), "function");
-  assert_equals(typeof(screen.orientation.onchange), "object");
-}, "Test Screen Orientation API property types.");
-
-test(function() {
-  assert_true('addEventListener' in screen.orientation);
-  assert_true('removeEventListener' in screen.orientation);
-  assert_true('dispatchEvent' in screen.orientation);
-  assert_true(screen.orientation instanceof EventTarget)
-}, "Test that screen.orientation is an EventTarget.");
-
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/web-animations/OWNERS
index 2a09e1f3..9bafb3b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/OWNERS
@@ -1,3 +1,3 @@
-# TEAM: style-dev@chromium.org
+# TEAM: animations-dev@chromium.org
 # COMPONENT: Blink>Animation
 meade@chromium.org
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/svg/hixie/mixed/006-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/svg/hixie/mixed/006-expected.txt
new file mode 100644
index 0000000..e5cc188f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/svg/hixie/mixed/006-expected.txt
@@ -0,0 +1,18 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x421
+  LayoutBlockFlow {html} at (0,0) size 800x421
+    LayoutBlockFlow {body} at (8,8) size 784x405
+      LayoutSVGRoot {svg} at (0,200) size 200x200
+        LayoutSVGEllipse {circle} at (50,50) size 100x100 [fill={[type=SOLID] [color=#008000]}] [cx=100.00] [cy=100.00] [r=50.00]
+        LayoutSVGForeignObject {foreignObject} at (0,0) size 200x200
+      LayoutText {#text} at (0,0) size 0x0
+layer at (8,8) size 200x200
+  LayoutBlockFlow (positioned) {div} at (8,8) size 200x200 [bgcolor=#FFFFFF]
+    LayoutText {#text} at (0,0) size 199x39
+      text run at (0,0) width 190: "There should be a green circle"
+      text run at (0,20) width 199: "below with no red on this page."
+layer at (8,8) size 200x200 backgroundClip at (8,208) size 200x200 clip at (8,208) size 200x200
+  LayoutBlockFlow (positioned) {div} at (0,-200) size 200x200 [color=#FFFF00] [bgcolor=#FF0000]
+    LayoutText {#text} at (0,0) size 35x19
+      text run at (0,0) width 35: "FAIL"
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/svg/hixie/mixed/011-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/svg/hixie/mixed/011-expected.png
new file mode 100644
index 0000000..493376f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/svg/hixie/mixed/011-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/svg/hixie/mixed/011-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/svg/hixie/mixed/011-expected.txt
new file mode 100644
index 0000000..d2b5ef2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/svg/hixie/mixed/011-expected.txt
@@ -0,0 +1,16 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x221
+  LayoutBlockFlow {html} at (0,0) size 800x221
+    LayoutBlockFlow {body} at (8,8) size 784x205
+      LayoutSVGRoot {svg} at (0,0) size 200x200
+        LayoutSVGEllipse {circle} at (50,50) size 100x100 [fill={[type=SOLID] [color=#008000]}] [cx=100.00] [cy=100.00] [r=50.00]
+        LayoutSVGForeignObject {foreignObject} at (0,0) size 200x200
+      LayoutText {#text} at (0,0) size 0x0
+layer at (50,0) size 150x200 backgroundClip at (0,8) size 149x283 clip at (0,8) size 149x283
+  LayoutBlockFlow (positioned) {div} at (50,0) size 150x200
+    LayoutText {#text} at (0,0) size 135x79
+      text run at (0,0) width 113: "There should be a"
+      text run at (0,20) width 126: "green circle and this"
+      text run at (0,40) width 135: "text should be rotated"
+      text run at (0,60) width 92: "by 45 degrees."
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom/dom-getFrameOwner-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom/dom-getFrameOwner-expected.txt
new file mode 100644
index 0000000..2e0403bd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom/dom-getFrameOwner-expected.txt
@@ -0,0 +1,3 @@
+Tests DOM.getFrameOwner method.
+IFRAME id,inner_frame,src,http://devtools.oopif.test:8000/resources/dummy.html
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom/dom-getFrameOwner.js b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom/dom-getFrameOwner.js
new file mode 100644
index 0000000..a5557a6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/dom/dom-getFrameOwner.js
@@ -0,0 +1,18 @@
+(async function(testRunner) {
+  var {page, session, dp} = await testRunner.startBlank('Tests DOM.getFrameOwner method.');
+  await dp.Target.setDiscoverTargets({discover: true});
+  await session.evaluate(`
+    var iframe = document.createElement('iframe');
+    iframe.id = 'outer_frame';
+    iframe.src = 'data:text/html,<iframe id=inner_frame src="http://devtools.oopif.test:8000/resources/dummy.html">';
+    document.body.appendChild(iframe);
+  `);
+
+  var frameId = (await dp.Target.onceTargetCreated()).params.targetInfo.targetId;
+  await dp.DOM.enable();
+  await dp.DOM.getDocument();
+  var r = await dp.DOM.getFrameOwner({frameId});
+  r = await dp.DOM.describeNode({nodeId: r.result.nodeId});
+  testRunner.log(r.result.node.nodeName + ' ' + r.result.node.attributes);
+  testRunner.completeTest();
+})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/memory/sampling-native-profile-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/memory/sampling-native-profile-expected.txt
new file mode 100644
index 0000000..1664a79a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/memory/sampling-native-profile-expected.txt
@@ -0,0 +1,5 @@
+Test sampling native memory profiler.
+Sampling started
+Sampling stopped
+Found sample: true
+
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/memory/sampling-native-profile.js b/third_party/WebKit/LayoutTests/inspector-protocol/memory/sampling-native-profile.js
new file mode 100644
index 0000000..e054cca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/memory/sampling-native-profile.js
@@ -0,0 +1,28 @@
+(async function(testRunner) {
+  var {page, session, dp} = await testRunner.startBlank(`Test sampling native memory profiler.`);
+
+  await dp.Memory.startSampling({
+      samplingInterval: 100000, suppressRandomness: true});
+  testRunner.log('Sampling started');
+  await session.evaluate(`
+    const canvas = document.createElement('canvas');
+    canvas.width = 500;
+    canvas.height = 200;
+    const ctx = canvas.getContext('2d');
+    ctx.fillStyle = 'green';
+    ctx.fillRect(0, 0, 10, 10);
+    document.body.appendChild(canvas);
+    `);
+  const message = await dp.Memory.getSamplingProfile();
+  await dp.Memory.stopSampling();
+  testRunner.log('Sampling stopped');
+
+  const profile = message.result.profile;
+  const foundTheSample = profile.samples.some(sample =>
+    sample.size >= 500 * 200 && sample.stack.some(frame => frame.includes('HTMLCanvasElement')));
+  testRunner.log('Found sample: ' + foundTheSample);
+  if (!foundTheSample)
+    testRunner.log(profile);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/css-cascade-upgrade-from-v0-to-v1.html b/third_party/WebKit/LayoutTests/shadow-dom/css-cascade-upgrade-from-v0-to-v1.html
index 12ef1c96..ff0ee104 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/css-cascade-upgrade-from-v0-to-v1.html
+++ b/third_party/WebKit/LayoutTests/shadow-dom/css-cascade-upgrade-from-v0-to-v1.html
@@ -13,9 +13,25 @@
 root.innerHTML = '<style>:host(#host) { color: green; }</style>';
 
 test(() => {
-  assert_equals(window.getComputedStyle(host).color, 'rgb(0, 128, 0)');
+  assert_equals(window.getComputedStyle(host).color, 'rgb(0, 128, 0)',
+                'V0 cascade order should be used by default.');
+
+  // Adding V1 user-agent shadow should not switch cascading order.
+  var option = document.createElement('option');
+  dummy.appendChild(option);
+  assert_equals(window.getComputedStyle(host).color, 'rgb(0, 128, 0)',
+                'Adding UA shadow should not change the cascade order.');
+
+  // Adopting V1 user-agent shadow should not switch cascading order.
+  var doc2 = document.implementation.createHTMLDocument();
+  var option2 = doc2.createElement('option');
+  dummy.appendChild(option2);
+  assert_equals(window.getComputedStyle(host).color, 'rgb(0, 128, 0)',
+                'Adopting UA shadow should not change the cascade order.');
+
   // Trigger "V1" shadow cascading order.
   dummy.attachShadow({mode: 'open'});
-  assert_equals(window.getComputedStyle(host).color, 'rgb(255, 0, 0)');
+  assert_equals(window.getComputedStyle(host).color, 'rgb(255, 0, 0)',
+                'Adding author V1 shadow should change the cascade order.');
 }, 'Upgrading V0 to V1 should cause style recalculation.');
 </script>
diff --git a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/filters/effect-reference-repaint-lighting-expected.txt b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/filters/effect-reference-repaint-lighting-expected.txt
index 0ec1492..acc2cec 100644
--- a/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/filters/effect-reference-repaint-lighting-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/spv175/paint/invalidation/filters/effect-reference-repaint-lighting-expected.txt
@@ -17,6 +17,11 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
+          "object": "LayoutBlockFlow DIV class='before box'",
+          "rect": [78, 70, 100, 100],
+          "reason": "disappeared"
+        },
+        {
           "object": "LayoutBlockFlow DIV class='box'",
           "rect": [78, 70, 100, 100],
           "reason": "appeared"
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
index 6627d3e1..5867bc5 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -33,6 +33,7 @@
     property assignedSlot
     property attachShadow
     property attributes
+    property autocapitalize
     property baseURI
     property before
     property blur
@@ -606,7 +607,6 @@
     property accept
     property align
     property alt
-    property autocapitalize
     property autocomplete
     property autofocus
     property checkValidity
@@ -932,7 +932,6 @@
 html element template
     property content
 html element textarea
-    property autocapitalize
     property autofocus
     property checkValidity
     property cols
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index 8341dd68..b33b951 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -1804,6 +1804,7 @@
 interface HTMLElement : Element
     attribute @@toStringTag
     getter accessKey
+    getter autocapitalize
     getter contentEditable
     getter dataset
     getter dir
@@ -1903,6 +1904,7 @@
     method constructor
     method focus
     setter accessKey
+    setter autocapitalize
     setter contentEditable
     setter dir
     setter draggable
@@ -2252,7 +2254,6 @@
     getter accept
     getter align
     getter alt
-    getter autocapitalize
     getter autocomplete
     getter autofocus
     getter checked
@@ -2311,7 +2312,6 @@
     setter accept
     setter align
     setter alt
-    setter autocapitalize
     setter autocomplete
     setter autofocus
     setter checked
@@ -2924,7 +2924,6 @@
     method constructor
 interface HTMLTextAreaElement : HTMLElement
     attribute @@toStringTag
-    getter autocapitalize
     getter autofocus
     getter cols
     getter defaultValue
@@ -2956,7 +2955,6 @@
     method setCustomValidity
     method setRangeText
     method setSelectionRange
-    setter autocapitalize
     setter autofocus
     setter cols
     setter defaultValue
diff --git a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
index 2b75bd1..b5f5ae3 100644
--- a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
@@ -35,6 +35,7 @@
     property attachShadow
     property attributeStyleMap
     property attributes
+    property autocapitalize
     property baseURI
     property before
     property blur
@@ -625,7 +626,6 @@
     property accept
     property align
     property alt
-    property autocapitalize
     property autocomplete
     property autofocus
     property checkValidity
@@ -951,7 +951,6 @@
 html element template
     property content
 html element textarea
-    property autocapitalize
     property autofocus
     property checkValidity
     property cols
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 58dd784..c27f0165 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -2405,6 +2405,7 @@
 interface HTMLElement : Element
     attribute @@toStringTag
     getter accessKey
+    getter autocapitalize
     getter contentEditable
     getter dataset
     getter dir
@@ -2506,6 +2507,7 @@
     method constructor
     method focus
     setter accessKey
+    setter autocapitalize
     setter contentEditable
     setter dir
     setter draggable
@@ -2862,7 +2864,6 @@
     getter accept
     getter align
     getter alt
-    getter autocapitalize
     getter autocomplete
     getter autofocus
     getter checked
@@ -2921,7 +2922,6 @@
     setter accept
     setter align
     setter alt
-    setter autocapitalize
     setter autocomplete
     setter autofocus
     setter checked
@@ -3536,7 +3536,6 @@
     method constructor
 interface HTMLTextAreaElement : HTMLElement
     attribute @@toStringTag
-    getter autocapitalize
     getter autofocus
     getter cols
     getter defaultValue
@@ -3568,7 +3567,6 @@
     method setCustomValidity
     method setRangeText
     method setSelectionRange
-    setter autocapitalize
     setter autofocus
     setter cols
     setter defaultValue
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
index 7dc18482..0b6b84d 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
@@ -193,15 +193,7 @@
 
   // ScriptWrappableVisitor overrides.
 
-  void MarkWrappersInAllWorlds(
-      const ScriptWrappable* traceable) const override {
-    // Only mark the main thread wrapper as we cannot properly intercept
-    // DOMWrapperMap::markWrapper. This means that edges from the isolated
-    // worlds are missing in the snapshot.
-    traceable->MarkWrapper(this);
-  }
-
-  void DispatchTraceWrappers(const TraceWrapperBase* traceable) const override {
+  void DispatchTraceWrappers(const TraceWrapperBase* traceable) const final {
     if (!only_trace_single_level_ || !traceable->IsScriptWrappable() ||
         !reinterpret_cast<const ScriptWrappable*>(traceable)
              ->ContainsWrapper() ||
@@ -214,13 +206,21 @@
  protected:
   // ScriptWrappableVisitor override.
   void Visit(
-      const TraceWrapperV8Reference<v8::Value>& traced_wrapper) const override {
+      const TraceWrapperV8Reference<v8::Value>& traced_wrapper) const final {
     const v8::PersistentBase<v8::Value>* value = &traced_wrapper.Get();
     if (current_parent_ && current_parent_ != value)
       edges_.push_back(std::make_pair(current_parent_, value));
     found_v8_wrappers_.insert(value);
   }
 
+  void Visit(DOMWrapperMap<ScriptWrappable>*,
+             const ScriptWrappable* key) const final {
+    // The found_v8_wrappers are PersistentBase pointers. We only mark the
+    // main world wrapper as we cannot properly record DOMWrapperMap values.
+    // This means that edges from the isolated worlds are missing in the
+    // snapshot. This will be fixed with crbug.com/749490.
+  }
+
  private:
   inline v8::PersistentBase<v8::Value>* PersistentForWrappable(
       ScriptWrappable* wrappable) {
diff --git a/third_party/WebKit/Source/core/animation/OWNERS b/third_party/WebKit/Source/core/animation/OWNERS
index 9c5abe21..4364bfb73 100644
--- a/third_party/WebKit/Source/core/animation/OWNERS
+++ b/third_party/WebKit/Source/core/animation/OWNERS
@@ -1,11 +1,13 @@
+flackr@chromium.org
+
+# Legacy owners:
 alancutter@chromium.org
 dstockwell@chromium.org
 ericwilligers@chromium.org
-flackr@chromium.org
 shans@chromium.org
 timloh@chromium.org
 
 per-file Compositor*=loyso@chromium.org
 
-# TEAM: style-dev@chromium.org
+# TEAM: animations-dev@chromium.org
 # COMPONENT: Blink>Animation
diff --git a/third_party/WebKit/Source/core/animation/README.md b/third_party/WebKit/Source/core/animation/README.md
index a46695a7..bee9d10 100644
--- a/third_party/WebKit/Source/core/animation/README.md
+++ b/third_party/WebKit/Source/core/animation/README.md
@@ -19,7 +19,7 @@
 
 ## Integration with Chromium
 
-The Blink animation engine has three main integration points:
+The Blink animation engine interacts with Blink/Chrome in the following ways:
 
 *   ### [Blink's Style engine](../css)
 
@@ -52,12 +52,10 @@
 
 *   ### [Chromium's Compositor](../../../../../cc/README.md)
 
-    Blink uses a multi-threaded LayerTreeHost to render websites as a tree of
-    layers. The compositor creates frames on a separate thread which maintains a
-    copy of Blinks layers and can implement some effects without involving Blink
-    (i.e. while Blink is busy). In particular, the
-    [compositor animations infrastructure](../../../../../cc/animations/README.md)
-    is capable of implementing a subset of web animations.
+    Chromium's compositor has a separate, more lightweight [animation
+    engine](../../../../../cc/animation/README.md) that runs separate to the
+    main thread. Blink's animation engine delegates animations to the compositor
+    where possible for better performance and power utilisation.
 
     #### Compositable animations
 
@@ -70,7 +68,8 @@
     Whether or not an animation can be accelerated is determined by
     [CheckCanStartAnimationOnCompositor()][] which looks at several aspects
     such as the composite mode, other animations affecting same property, and
-    whether the target element can be promoted and mutated in compositor.
+    whether the target element can be promoted and mutated in compositor.  
+    Reasons for not compositing animations are captured in [FailureCodes][].
 
     #### Lifetime of a compositor animation
 
@@ -100,6 +99,7 @@
     output.
 
 [CheckCanStartAnimationOnCompositor()]: https://cs.chromium.org/search/?q=file:Animation.h+function:CheckCanStartAnimationOnCompositor
+[FailureCodes]: https://cs.chromium.org/search/?q=return%5Cs%2B(CompositorAnimations::)?FailureCode
 [cc::AnimationPlayer]: https://cs.chromium.org/search/?q=file:src/cc/animation/animation_player.h+class:AnimationPlayer
 [PendingAnimations]: https://cs.chromium.org/search/?q=file:PendingAnimations.h+class:PendingAnimations
 [Animation::PreCommit()]: https://cs.chromium.org/search/?q=file:Animation.h+function:PreCommit
diff --git a/third_party/WebKit/Source/core/css/CSSVariableData.h b/third_party/WebKit/Source/core/css/CSSVariableData.h
index 81de3b8..1c778a5e 100644
--- a/third_party/WebKit/Source/core/css/CSSVariableData.h
+++ b/third_party/WebKit/Source/core/css/CSSVariableData.h
@@ -21,6 +21,9 @@
   USING_FAST_MALLOC(CSSVariableData);
 
  public:
+  static scoped_refptr<CSSVariableData> Create() {
+    return base::AdoptRef(new CSSVariableData());
+  }
   static scoped_refptr<CSSVariableData> Create(const CSSParserTokenRange& range,
                                                bool is_animation_tainted,
                                                bool needs_variable_resolution) {
@@ -51,6 +54,9 @@
                                  SecureContextMode) const;
 
  private:
+  CSSVariableData()
+      : is_animation_tainted_(false), needs_variable_resolution_(false){};
+
   CSSVariableData(const CSSParserTokenRange&,
                   bool is_animation_tainted,
                   bool needs_variable_resolution);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
index 47599bbf..73043e79 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
@@ -73,11 +73,16 @@
   return style_value_vector;
 }
 
-String CSSStyleValue::toString() const {
+String CSSStyleValue::toString(ExceptionState& exception_state) const {
   const CSSValue* result = ToCSSValue();
-  // TODO(crbug.com/782103): Remove this once all CSSStyleValues
+  // TODO(crbug.com/803739): Remove this once all CSSStyleValues
   // support toCSSValue().
-  return result ? result->CssText() : "";
+  if (!result) {
+    exception_state.ThrowTypeError(
+        "Some CSSMathValues can't be serialized yet. See crbug.com/803739");
+    return "";
+  }
+  return result->CssText();
 }
 
 String CSSStyleValue::StyleValueTypeToString(StyleValueType type) {
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h
index 5e01552f..48cee80 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h
+++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h
@@ -70,7 +70,7 @@
   virtual const CSSValue* ToCSSValueWithProperty(CSSPropertyID) const {
     return ToCSSValue();
   }
-  virtual String toString() const;
+  virtual String toString(ExceptionState&) const;
 
  protected:
   static String StyleValueTypeToString(StyleValueType);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl
index 8fe50596..b74f460 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl
+++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.idl
@@ -9,7 +9,7 @@
 [
   Exposed(Window CSSTypedOM, PaintWorklet CSSPaintAPI)
 ] interface CSSStyleValue {
-  stringifier;
+  [RaisesException] stringifier;
   // Putting Exposed=Window in the next line makes |parse| not exposed to PaintWorklet.
   [RaisesException, Exposed=Window, CallWith=ExecutionContext] static CSSStyleValue? parse(DOMString property, DOMString cssText);
   [RaisesException, Exposed=Window, CallWith=ExecutionContext] static sequence<CSSStyleValue>? parseAll(DOMString property, DOMString cssText);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
index 71a3f18..7a654bf 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
@@ -77,6 +77,10 @@
 }
 
 const CSSValue* CSSUnparsedValue::ToCSSValue() const {
+  if (tokens_.IsEmpty()) {
+    return CSSVariableReferenceValue::Create(CSSVariableData::Create());
+  }
+
   CSSTokenizer tokenizer(ToString());
   const auto tokens = tokenizer.TokenizeToEOF();
   return CSSVariableReferenceValue::Create(CSSVariableData::Create(
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
index 42cb87b..4a56da28 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
@@ -24,6 +24,10 @@
     return new CSSUnparsedValue(tokens);
   }
 
+  // Blink-internal constructor
+  static CSSUnparsedValue* Create() {
+    return Create(HeapVector<StringOrCSSVariableReferenceValue>());
+  }
   static CSSUnparsedValue* FromCSSValue(const CSSVariableReferenceValue&);
   static CSSUnparsedValue* FromCSSValue(const CSSVariableData&);
 
diff --git a/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMap.cpp b/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMap.cpp
index e553928..8911637 100644
--- a/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMap.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMap.cpp
@@ -5,6 +5,7 @@
 #include "core/css/cssom/FilteredComputedStylePropertyMap.h"
 
 #include "core/css/CSSCustomPropertyDeclaration.h"
+#include "core/css/cssom/CSSUnparsedValue.h"
 
 namespace blink {
 
@@ -14,6 +15,11 @@
     const Vector<AtomicString>& custom_properties)
     : ComputedStylePropertyMap(node) {
   for (const auto& native_property : native_properties) {
+    // Silently drop shorthand properties.
+    DCHECK_NE(native_property, CSSPropertyInvalid);
+    if (CSSProperty::Get(native_property).IsShorthand())
+      continue;
+
     native_properties_.insert(native_property);
   }
 
@@ -35,18 +41,17 @@
   if (!custom_properties_.Contains(AtomicString(property_name)))
     return nullptr;
 
-  return ComputedStylePropertyMap::GetCustomProperty(property_name);
+  const CSSValue* value =
+      ComputedStylePropertyMap::GetCustomProperty(property_name);
+  if (!value)
+    return CSSUnparsedValue::Create()->ToCSSValue();
+  return value;
 }
 
 void FilteredComputedStylePropertyMap::ForEachProperty(
     const IterationCallback& callback) {
-  // FIXME: We should be filtering out properties from ComputedStylePropertyMap,
-  // but native_properties_ may contain invalid properties (e.g. shorthands).
-  // The correct behaviour would be to ignore invalid properties, but there
-  // are a few tests that rely on this.
   for (const auto property_id : native_properties_) {
-    const CSSValue* value = GetProperty(property_id);
-    if (value) {
+    if (const CSSValue* value = GetProperty(property_id)) {
       callback(CSSProperty::Get(property_id).GetPropertyNameAtomicString(),
                *value);
     }
@@ -54,15 +59,8 @@
 
   for (const auto& name : custom_properties_) {
     const CSSValue* value = GetCustomProperty(name);
-    // FIXME: If custom_properties_ contains an invalid custom property, the
-    // current behaviour is to treat it as valid. The best we can do here is
-    // returning a dummy 'initial' value until we fix this.
-    if (value) {
-      callback(name, *value);
-    } else {
-      callback(name,
-               *CSSCustomPropertyDeclaration::Create(name, CSSValueInitial));
-    }
+    DCHECK(value);
+    callback(name, *value);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMapTest.cpp b/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMapTest.cpp
index fff39e3..1da6213 100644
--- a/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMapTest.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMapTest.cpp
@@ -108,13 +108,18 @@
 
   DummyExceptionStateForTesting exception_state;
 
-  EXPECT_EQ(nullptr, map->get("--foo", exception_state));
+  const CSSStyleValue* foo = map->get("--foo", exception_state);
+  ASSERT_NE(nullptr, foo);
+  ASSERT_EQ(CSSStyleValue::kUnparsedType, foo->GetType());
   EXPECT_FALSE(exception_state.HadException());
 
-  EXPECT_EQ(false, map->has("--foo", exception_state));
+  EXPECT_EQ(true, map->has("--foo", exception_state));
   EXPECT_FALSE(exception_state.HadException());
 
-  EXPECT_EQ(CSSStyleValueVector(), map->getAll("--foo", exception_state));
+  CSSStyleValueVector fooAll = map->getAll("--foo", exception_state);
+  EXPECT_EQ(1U, fooAll.size());
+  ASSERT_NE(nullptr, fooAll[0]);
+  ASSERT_EQ(CSSStyleValue::kUnparsedType, fooAll[0]->GetType());
   EXPECT_FALSE(exception_state.HadException());
 
   EXPECT_EQ(nullptr, map->get("--quix", exception_state));
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index d86cd4f7..516e6bdb 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -2500,9 +2500,9 @@
   return EnsureShadow().AddShadowRoot(*this, ShadowRootType::V0);
 }
 
-ShadowRoot& Element::CreateUserAgentShadowRootV1() {
+ShadowRoot& Element::CreateUserAgentShadowRoot() {
   DCHECK(!GetShadowRoot());
-  return EnsureShadow().AddShadowRoot(*this, ShadowRootType::kUserAgentV1);
+  return EnsureShadow().AddShadowRoot(*this, ShadowRootType::kUserAgent);
 }
 
 ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type,
@@ -2560,13 +2560,13 @@
   return nullptr;
 }
 
-ShadowRoot& Element::EnsureUserAgentShadowRootV1() {
+ShadowRoot& Element::EnsureUserAgentShadowRoot() {
   if (ShadowRoot* shadow_root = UserAgentShadowRoot()) {
-    DCHECK(shadow_root->GetType() == ShadowRootType::kUserAgentV1);
+    DCHECK(shadow_root->GetType() == ShadowRootType::kUserAgent);
     return *shadow_root;
   }
   ShadowRoot& shadow_root =
-      EnsureShadow().AddShadowRoot(*this, ShadowRootType::kUserAgentV1);
+      EnsureShadow().AddShadowRoot(*this, ShadowRootType::kUserAgent);
   DidAddUserAgentShadowRoot(shadow_root);
   return shadow_root;
 }
@@ -4607,9 +4607,9 @@
 void Element::AddPropertyToPresentationAttributeStyle(
     MutableCSSPropertyValueSet* style,
     CSSPropertyID property_id,
-    const CSSValue* value) {
+    const CSSValue& value) {
   DCHECK(IsStyledElement());
-  style->SetProperty(property_id, *value);
+  style->SetProperty(property_id, value);
 }
 
 void Element::LogAddElementIfIsolatedWorldAndInDocument(
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h
index 5c86464..3ca2c75 100644
--- a/third_party/WebKit/Source/core/dom/Element.h
+++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -497,7 +497,7 @@
                            const ShadowRootInit&,
                            ExceptionState&);
   ShadowRoot& CreateShadowRootInternal();
-  ShadowRoot& CreateUserAgentShadowRootV1();
+  ShadowRoot& CreateUserAgentShadowRoot();
   ShadowRoot& AttachShadowRootInternal(ShadowRootType,
                                        bool delegates_focus = false);
 
@@ -510,7 +510,7 @@
 
   ShadowRoot* ShadowRootIfV1() const;
 
-  ShadowRoot& EnsureUserAgentShadowRootV1();
+  ShadowRoot& EnsureUserAgentShadowRoot();
 
   bool IsInDescendantTreeOf(const Element* shadow_host) const;
 
@@ -855,10 +855,9 @@
   void AddPropertyToPresentationAttributeStyle(MutableCSSPropertyValueSet*,
                                                CSSPropertyID,
                                                const String& value);
-  // TODO(sashab): Make this take a const CSSValue&.
   void AddPropertyToPresentationAttributeStyle(MutableCSSPropertyValueSet*,
                                                CSSPropertyID,
-                                               const CSSValue*);
+                                               const CSSValue&);
 
   InsertionNotificationRequest InsertedInto(ContainerNode*) override;
   void RemovedFrom(ContainerNode*) override;
diff --git a/third_party/WebKit/Source/core/dom/NodeTest.cpp b/third_party/WebKit/Source/core/dom/NodeTest.cpp
index 32060cf..71c5d91c 100644
--- a/third_party/WebKit/Source/core/dom/NodeTest.cpp
+++ b/third_party/WebKit/Source/core/dom/NodeTest.cpp
@@ -56,10 +56,10 @@
   Node* InitializeUserAgentShadowTree(Element* test_node) {
     SetBodyContent("<div id=\"root\"></div>");
     Element* root = GetDocument().getElementById("root");
-    ShadowRoot& first_shadow = root->CreateUserAgentShadowRootV1();
+    ShadowRoot& first_shadow = root->CreateUserAgentShadowRoot();
 
     first_shadow.AppendChild(test_node);
-    ShadowRoot& second_shadow = test_node->CreateUserAgentShadowRootV1();
+    ShadowRoot& second_shadow = test_node->CreateUserAgentShadowRoot();
 
     HTMLDivElement* class_div = HTMLDivElement::Create(GetDocument());
     class_div->setAttribute("class", "test");
diff --git a/third_party/WebKit/Source/core/dom/ShadowRoot.cpp b/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
index bcbd02b9..ff4c56d 100644
--- a/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
+++ b/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
@@ -368,7 +368,7 @@
 
 std::ostream& operator<<(std::ostream& ostream, const ShadowRootType& type) {
   switch (type) {
-    case ShadowRootType::kUserAgentV1:
+    case ShadowRootType::kUserAgent:
       ostream << "UserAgent";
       break;
     case ShadowRootType::V0:
diff --git a/third_party/WebKit/Source/core/dom/ShadowRoot.h b/third_party/WebKit/Source/core/dom/ShadowRoot.h
index d5c08d5..69d0f29 100644
--- a/third_party/WebKit/Source/core/dom/ShadowRoot.h
+++ b/third_party/WebKit/Source/core/dom/ShadowRoot.h
@@ -49,12 +49,7 @@
 class V0InsertionPoint;
 class WhitespaceAttacher;
 
-enum class ShadowRootType {
-  V0,
-  kOpen,
-  kClosed,
-  kUserAgentV1
-};
+enum class ShadowRootType { V0, kOpen, kClosed, kUserAgent };
 
 class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
   DEFINE_WRAPPERTYPEINFO();
@@ -99,9 +94,9 @@
   bool IsV1() const {
     return GetType() == ShadowRootType::kOpen ||
            GetType() == ShadowRootType::kClosed ||
-           GetType() == ShadowRootType::kUserAgentV1;
+           GetType() == ShadowRootType::kUserAgent;
   }
-  bool IsUserAgent() const { return GetType() == ShadowRootType::kUserAgentV1; }
+  bool IsUserAgent() const { return GetType() == ShadowRootType::kUserAgent; }
 
   void AttachLayoutTree(AttachContext&) override;
   void DetachLayoutTree(const AttachContext& = AttachContext()) override;
diff --git a/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp b/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
index f4b7217..1365eda 100644
--- a/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
+++ b/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
@@ -86,7 +86,7 @@
         if (shadow->GetType() == ShadowRootType::V0) {
           new_document.SetShadowCascadeOrder(
               ShadowCascadeOrder::kShadowCascadeV0);
-        } else if (shadow->IsV1()) {
+        } else if (shadow->IsV1() && !shadow->IsUserAgent()) {
           new_document.SetShadowCascadeOrder(
               ShadowCascadeOrder::kShadowCascadeV1);
         }
diff --git a/third_party/WebKit/Source/core/editing/BUILD.gn b/third_party/WebKit/Source/core/editing/BUILD.gn
index 701acec4..dc814d7 100644
--- a/third_party/WebKit/Source/core/editing/BUILD.gn
+++ b/third_party/WebKit/Source/core/editing/BUILD.gn
@@ -112,6 +112,8 @@
     "commands/DragAndDropCommand.h",
     "commands/EditCommand.cpp",
     "commands/EditCommand.h",
+    "commands/EditingCommandsUtilities.cpp",
+    "commands/EditingCommandsUtilities.h",
     "commands/EditingState.cpp",
     "commands/EditingState.h",
     "commands/EditorCommand.cpp",
@@ -340,6 +342,7 @@
     "commands/CompositeEditCommandTest.cpp",
     "commands/DeleteSelectionCommandTest.cpp",
     "commands/EditingCommandTest.cpp",
+    "commands/EditingCommandsUtilitiesTest.cpp",
     "commands/InsertIncrementalTextCommandTest.cpp",
     "commands/InsertListCommandTest.cpp",
     "commands/InsertParagraphSeparatorCommandTest.cpp",
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
index 3af4f80..c86b5d7 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -1078,20 +1078,6 @@
   return rebalanced_string.ToString();
 }
 
-bool IsTableStructureNode(const Node* node) {
-  LayoutObject* layout_object = node->GetLayoutObject();
-  return (layout_object &&
-          (layout_object->IsTableCell() || layout_object->IsTableRow() ||
-           layout_object->IsTableSection() ||
-           layout_object->IsLayoutTableCol()));
-}
-
-const String& NonBreakingSpaceString() {
-  DEFINE_STATIC_LOCAL(String, non_breaking_space_string,
-                      (&kNoBreakSpaceCharacter, 1));
-  return non_breaking_space_string;
-}
-
 String RepeatString(const String& string, unsigned count) {
   StringBuilder builder;
   builder.ReserveCapacity(string.length() * count);
@@ -1100,104 +1086,6 @@
   return builder.ToString();
 }
 
-// FIXME: need to dump this
-static bool IsSpecialHTMLElement(const Node& n) {
-  if (!n.IsHTMLElement())
-    return false;
-
-  if (n.IsLink())
-    return true;
-
-  LayoutObject* layout_object = n.GetLayoutObject();
-  if (!layout_object)
-    return false;
-
-  if (layout_object->Style()->Display() == EDisplay::kTable ||
-      layout_object->Style()->Display() == EDisplay::kInlineTable)
-    return true;
-
-  if (layout_object->Style()->IsFloating())
-    return true;
-
-  return false;
-}
-
-static HTMLElement* FirstInSpecialElement(const Position& pos) {
-  DCHECK(!NeedsLayoutTreeUpdate(pos));
-  Element* element = RootEditableElement(*pos.ComputeContainerNode());
-  for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*pos.AnchorNode())) {
-    if (RootEditableElement(runner) != element)
-      break;
-    if (IsSpecialHTMLElement(runner)) {
-      HTMLElement* special_element = ToHTMLElement(&runner);
-      VisiblePosition v_pos = CreateVisiblePosition(pos);
-      VisiblePosition first_in_element =
-          CreateVisiblePosition(FirstPositionInOrBeforeNode(*special_element));
-      if (IsDisplayInsideTable(special_element) &&
-          v_pos.DeepEquivalent() ==
-              NextPositionOf(first_in_element).DeepEquivalent())
-        return special_element;
-      if (v_pos.DeepEquivalent() == first_in_element.DeepEquivalent())
-        return special_element;
-    }
-  }
-  return nullptr;
-}
-
-static HTMLElement* LastInSpecialElement(const Position& pos) {
-  DCHECK(!NeedsLayoutTreeUpdate(pos));
-  Element* element = RootEditableElement(*pos.ComputeContainerNode());
-  for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*pos.AnchorNode())) {
-    if (RootEditableElement(runner) != element)
-      break;
-    if (IsSpecialHTMLElement(runner)) {
-      HTMLElement* special_element = ToHTMLElement(&runner);
-      VisiblePosition v_pos = CreateVisiblePosition(pos);
-      VisiblePosition last_in_element =
-          CreateVisiblePosition(LastPositionInOrAfterNode(*special_element));
-      if (IsDisplayInsideTable(special_element) &&
-          v_pos.DeepEquivalent() ==
-              PreviousPositionOf(last_in_element).DeepEquivalent())
-        return special_element;
-      if (v_pos.DeepEquivalent() == last_in_element.DeepEquivalent())
-        return special_element;
-    }
-  }
-  return nullptr;
-}
-
-Position PositionBeforeContainingSpecialElement(
-    const Position& pos,
-    HTMLElement** containing_special_element) {
-  DCHECK(!NeedsLayoutTreeUpdate(pos));
-  HTMLElement* n = FirstInSpecialElement(pos);
-  if (!n)
-    return pos;
-  Position result = Position::InParentBeforeNode(*n);
-  if (result.IsNull() || RootEditableElement(*result.AnchorNode()) !=
-                             RootEditableElement(*pos.AnchorNode()))
-    return pos;
-  if (containing_special_element)
-    *containing_special_element = n;
-  return result;
-}
-
-Position PositionAfterContainingSpecialElement(
-    const Position& pos,
-    HTMLElement** containing_special_element) {
-  DCHECK(!NeedsLayoutTreeUpdate(pos));
-  HTMLElement* n = LastInSpecialElement(pos);
-  if (!n)
-    return pos;
-  Position result = Position::InParentAfterNode(*n);
-  if (result.IsNull() || RootEditableElement(*result.AnchorNode()) !=
-                             RootEditableElement(*pos.AnchorNode()))
-    return pos;
-  if (containing_special_element)
-    *containing_special_element = n;
-  return result;
-}
-
 template <typename Strategy>
 static Element* TableElementJustBeforeAlgorithm(
     const VisiblePositionTemplate<Strategy>& visible_position) {
@@ -1361,39 +1249,6 @@
   return highest;
 }
 
-static bool HasARenderedDescendant(const Node* node,
-                                   const Node* excluded_node) {
-  for (const Node* n = node->firstChild(); n;) {
-    if (n == excluded_node) {
-      n = NodeTraversal::NextSkippingChildren(*n, node);
-      continue;
-    }
-    if (n->GetLayoutObject())
-      return true;
-    n = NodeTraversal::Next(*n, node);
-  }
-  return false;
-}
-
-Node* HighestNodeToRemoveInPruning(Node* node, const Node* exclude_node) {
-  Node* previous_node = nullptr;
-  Element* element = node ? RootEditableElement(*node) : nullptr;
-  for (; node; node = node->parentNode()) {
-    if (LayoutObject* layout_object = node->GetLayoutObject()) {
-      if (!layout_object->CanHaveChildren() ||
-          HasARenderedDescendant(node, previous_node) || element == node ||
-          exclude_node == node)
-        return previous_node;
-    }
-    previous_node = node;
-  }
-  return nullptr;
-}
-
-Element* EnclosingTableCell(const Position& p) {
-  return ToElement(EnclosingNodeOfType(p, IsTableCell));
-}
-
 Element* EnclosingAnchorElement(const Position& p) {
   if (p.IsNull())
     return nullptr;
@@ -1407,112 +1262,6 @@
   return nullptr;
 }
 
-HTMLElement* EnclosingList(const Node* node) {
-  if (!node)
-    return nullptr;
-
-  ContainerNode* root = HighestEditableRoot(FirstPositionInOrBeforeNode(*node));
-
-  for (Node& runner : NodeTraversal::AncestorsOf(*node)) {
-    if (IsHTMLUListElement(runner) || IsHTMLOListElement(runner))
-      return ToHTMLElement(&runner);
-    if (runner == root)
-      return nullptr;
-  }
-
-  return nullptr;
-}
-
-Node* EnclosingListChild(const Node* node) {
-  if (!node)
-    return nullptr;
-  // Check for a list item element, or for a node whose parent is a list
-  // element. Such a node will appear visually as a list item (but without a
-  // list marker)
-  ContainerNode* root = HighestEditableRoot(FirstPositionInOrBeforeNode(*node));
-
-  // FIXME: This function is inappropriately named if it starts with node
-  // instead of node->parentNode()
-  // TODO(editing-dev): We should make this function return |const Node*| and
-  // make const_cast<> restricted inside editing/commands.
-  for (Node* n = const_cast<Node*>(node); n && n->parentNode();
-       n = n->parentNode()) {
-    if (IsHTMLLIElement(*n) ||
-        (IsHTMLListElement(n->parentNode()) && n != root))
-      return n;
-    if (n == root || IsTableCell(n))
-      return nullptr;
-  }
-
-  return nullptr;
-}
-
-// FIXME: This method should not need to call
-// isStartOfParagraph/isEndOfParagraph
-Node* EnclosingEmptyListItem(const VisiblePosition& visible_pos) {
-  DCHECK(visible_pos.IsValid());
-
-  // Check that position is on a line by itself inside a list item
-  Node* list_child_node =
-      EnclosingListChild(visible_pos.DeepEquivalent().AnchorNode());
-  if (!list_child_node || !IsStartOfParagraph(visible_pos) ||
-      !IsEndOfParagraph(visible_pos))
-    return nullptr;
-
-  VisiblePosition first_in_list_child =
-      CreateVisiblePosition(FirstPositionInOrBeforeNode(*list_child_node));
-  VisiblePosition last_in_list_child =
-      CreateVisiblePosition(LastPositionInOrAfterNode(*list_child_node));
-
-  if (first_in_list_child.DeepEquivalent() != visible_pos.DeepEquivalent() ||
-      last_in_list_child.DeepEquivalent() != visible_pos.DeepEquivalent())
-    return nullptr;
-
-  return list_child_node;
-}
-
-HTMLElement* OutermostEnclosingList(const Node* node,
-                                    const HTMLElement* root_list) {
-  HTMLElement* list = EnclosingList(node);
-  if (!list)
-    return nullptr;
-
-  while (HTMLElement* next_list = EnclosingList(list)) {
-    if (next_list == root_list)
-      break;
-    list = next_list;
-  }
-
-  return list;
-}
-
-// Determines whether two positions are visibly next to each other (first then
-// second) while ignoring whitespaces and unrendered nodes
-static bool IsVisiblyAdjacent(const Position& first, const Position& second) {
-  return CreateVisiblePosition(first).DeepEquivalent() ==
-         CreateVisiblePosition(MostBackwardCaretPosition(second))
-             .DeepEquivalent();
-}
-
-bool CanMergeLists(const Element& first_list, const Element& second_list) {
-  if (!first_list.IsHTMLElement() || !second_list.IsHTMLElement())
-    return false;
-
-  DCHECK(!NeedsLayoutTreeUpdate(first_list));
-  DCHECK(!NeedsLayoutTreeUpdate(second_list));
-  return first_list.HasTagName(
-             second_list
-                 .TagQName())  // make sure the list types match (ol vs. ul)
-         && HasEditableStyle(first_list) &&
-         HasEditableStyle(second_list)  // both lists are editable
-         &&
-         RootEditableElement(first_list) ==
-             RootEditableElement(second_list)  // don't cross editing boundaries
-         && IsVisiblyAdjacent(Position::InParentAfterNode(first_list),
-                              Position::InParentBeforeNode(second_list));
-  // Make sure there is no visible content between this li and the previous list
-}
-
 bool IsDisplayInsideTable(const Node* node) {
   return node && node->GetLayoutObject() && IsHTMLTableElement(node);
 }
@@ -1569,11 +1318,6 @@
   return nullptr;
 }
 
-HTMLElement* CreateHTMLElement(Document& document, const QualifiedName& name) {
-  return HTMLElementFactory::createHTMLElement(name.LocalName(), document,
-                                               kCreatedByCloneNode);
-}
-
 bool IsTabHTMLSpanElement(const Node* node) {
   if (!IsHTMLSpanElement(node))
     return false;
@@ -1623,118 +1367,6 @@
   return CreateTabSpanElement(document, nullptr);
 }
 
-bool IsNodeRendered(const Node& node) {
-  LayoutObject* layout_object = node.GetLayoutObject();
-  if (!layout_object)
-    return false;
-
-  return layout_object->Style()->Visibility() == EVisibility::kVisible;
-}
-
-// return first preceding DOM position rendered at a different location, or
-// "this"
-static Position PreviousCharacterPosition(const Position& position,
-                                          TextAffinity affinity) {
-  DCHECK(!NeedsLayoutTreeUpdate(position));
-  if (position.IsNull())
-    return Position();
-
-  Element* from_root_editable_element =
-      RootEditableElement(*position.AnchorNode());
-
-  bool at_start_of_line =
-      IsStartOfLine(CreateVisiblePosition(position, affinity));
-  bool rendered = IsVisuallyEquivalentCandidate(position);
-
-  Position current_pos = position;
-  while (!current_pos.AtStartOfTree()) {
-    // TODO(yosin) When we use |previousCharacterPosition()| other than
-    // finding leading whitespace, we should use |Character| instead of
-    // |CodePoint|.
-    current_pos = PreviousPositionOf(current_pos, PositionMoveType::kCodeUnit);
-
-    if (RootEditableElement(*current_pos.AnchorNode()) !=
-        from_root_editable_element)
-      return position;
-
-    if (at_start_of_line || !rendered) {
-      if (IsVisuallyEquivalentCandidate(current_pos))
-        return current_pos;
-    } else if (RendersInDifferentPosition(position, current_pos)) {
-      return current_pos;
-    }
-  }
-
-  return position;
-}
-
-// This assumes that it starts in editable content.
-Position LeadingCollapsibleWhitespacePosition(const Position& position,
-                                              TextAffinity affinity,
-                                              WhitespacePositionOption option) {
-  DCHECK(!NeedsLayoutTreeUpdate(position));
-  DCHECK(IsEditablePosition(position)) << position;
-  if (position.IsNull())
-    return Position();
-
-  if (IsHTMLBRElement(*MostBackwardCaretPosition(position).AnchorNode()))
-    return Position();
-
-  const Position& prev = PreviousCharacterPosition(position, affinity);
-  if (prev == position)
-    return Position();
-  const Node* const anchor_node = prev.AnchorNode();
-  if (!anchor_node || !anchor_node->IsTextNode())
-    return Position();
-  if (EnclosingBlockFlowElement(*anchor_node) !=
-      EnclosingBlockFlowElement(*position.AnchorNode()))
-    return Position();
-  if (option == kNotConsiderNonCollapsibleWhitespace &&
-      anchor_node->GetLayoutObject() &&
-      !anchor_node->GetLayoutObject()->Style()->CollapseWhiteSpace())
-    return Position();
-  const String& string = ToText(anchor_node)->data();
-  const UChar previous_character = string[prev.ComputeOffsetInContainerNode()];
-  const bool is_space = option == kConsiderNonCollapsibleWhitespace
-                            ? (IsSpaceOrNewline(previous_character) ||
-                               previous_character == kNoBreakSpaceCharacter)
-                            : IsCollapsibleWhitespace(previous_character);
-  if (!is_space || !IsEditablePosition(prev))
-    return Position();
-  return prev;
-}
-
-// This assumes that it starts in editable content.
-Position TrailingWhitespacePosition(const Position& position,
-                                    WhitespacePositionOption option) {
-  DCHECK(!NeedsLayoutTreeUpdate(position));
-  DCHECK(IsEditablePosition(position)) << position;
-  if (position.IsNull())
-    return Position();
-
-  VisiblePosition visible_position = CreateVisiblePosition(position);
-  UChar character_after_visible_position = CharacterAfter(visible_position);
-  bool is_space =
-      option == kConsiderNonCollapsibleWhitespace
-          ? (IsSpaceOrNewline(character_after_visible_position) ||
-             character_after_visible_position == kNoBreakSpaceCharacter)
-          : IsCollapsibleWhitespace(character_after_visible_position);
-  // The space must not be in another paragraph and it must be editable.
-  if (is_space && !IsEndOfParagraph(visible_position) &&
-      NextPositionOf(visible_position, kCannotCrossEditingBoundary).IsNotNull())
-    return position;
-  return Position();
-}
-
-unsigned NumEnclosingMailBlockquotes(const Position& p) {
-  unsigned num = 0;
-  for (const Node* n = p.AnchorNode(); n; n = n->parentNode()) {
-    if (IsMailHTMLBlockquoteElement(n))
-      num++;
-  }
-  return num;
-}
-
 PositionWithAffinity PositionRespectingEditingBoundary(
     const Position& position,
     const LayoutPoint& local_point,
@@ -1810,31 +1442,6 @@
          element.getAttribute("type") == "cite";
 }
 
-bool LineBreakExistsAtVisiblePosition(const VisiblePosition& visible_position) {
-  return LineBreakExistsAtPosition(
-      MostForwardCaretPosition(visible_position.DeepEquivalent()));
-}
-
-bool LineBreakExistsAtPosition(const Position& position) {
-  if (position.IsNull())
-    return false;
-
-  if (IsHTMLBRElement(*position.AnchorNode()) &&
-      position.AtFirstEditingPositionForNode())
-    return true;
-
-  if (!position.AnchorNode()->GetLayoutObject())
-    return false;
-
-  if (!position.AnchorNode()->IsTextNode() ||
-      !position.AnchorNode()->GetLayoutObject()->Style()->PreserveNewline())
-    return false;
-
-  const Text* text_node = ToText(position.AnchorNode());
-  unsigned offset = position.OffsetInContainerNode();
-  return offset < text_node->length() && text_node->data()[offset] == '\n';
-}
-
 bool ElementCannotHaveEndTag(const Node& node) {
   if (!node.IsHTMLElement())
     return false;
@@ -1842,65 +1449,6 @@
   return !ToHTMLElement(node).ShouldSerializeEndTag();
 }
 
-// Modifies selections that have an end point at the edge of a table
-// that contains the other endpoint so that they don't confuse
-// code that iterates over selected paragraphs.
-VisibleSelection SelectionForParagraphIteration(
-    const VisibleSelection& original) {
-  VisibleSelection new_selection(original);
-  VisiblePosition start_of_selection(new_selection.VisibleStart());
-  VisiblePosition end_of_selection(new_selection.VisibleEnd());
-
-  // If the end of the selection to modify is just after a table, and if the
-  // start of the selection is inside that table, then the last paragraph that
-  // we'll want modify is the last one inside the table, not the table itself (a
-  // table is itself a paragraph).
-  if (Element* table = TableElementJustBefore(end_of_selection)) {
-    if (start_of_selection.DeepEquivalent().AnchorNode()->IsDescendantOf(
-            table)) {
-      const VisiblePosition& new_end =
-          PreviousPositionOf(end_of_selection, kCannotCrossEditingBoundary);
-      if (new_end.IsNotNull()) {
-        new_selection = CreateVisibleSelection(
-            SelectionInDOMTree::Builder()
-                .Collapse(start_of_selection.ToPositionWithAffinity())
-                .Extend(new_end.DeepEquivalent())
-                .Build());
-      } else {
-        new_selection = CreateVisibleSelection(
-            SelectionInDOMTree::Builder()
-                .Collapse(start_of_selection.ToPositionWithAffinity())
-                .Build());
-      }
-    }
-  }
-
-  // If the start of the selection to modify is just before a table, and if the
-  // end of the selection is inside that table, then the first paragraph we'll
-  // want to modify is the first one inside the table, not the paragraph
-  // containing the table itself.
-  if (Element* table = TableElementJustAfter(start_of_selection)) {
-    if (end_of_selection.DeepEquivalent().AnchorNode()->IsDescendantOf(table)) {
-      const VisiblePosition new_start =
-          NextPositionOf(start_of_selection, kCannotCrossEditingBoundary);
-      if (new_start.IsNotNull()) {
-        new_selection = CreateVisibleSelection(
-            SelectionInDOMTree::Builder()
-                .Collapse(new_start.ToPositionWithAffinity())
-                .Extend(end_of_selection.DeepEquivalent())
-                .Build());
-      } else {
-        new_selection = CreateVisibleSelection(
-            SelectionInDOMTree::Builder()
-                .Collapse(end_of_selection.ToPositionWithAffinity())
-                .Build());
-      }
-    }
-  }
-
-  return new_selection;
-}
-
 // FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators
 // to convert between VisiblePositions and indices. But TextIterator iteration
 // using TextIteratorEmitsCharactersBetweenAllVisiblePositions does not exactly
@@ -2004,21 +1552,6 @@
           layout_object->IsHR());
 }
 
-bool AreIdenticalElements(const Node& first, const Node& second) {
-  if (!first.IsElementNode() || !second.IsElementNode())
-    return false;
-
-  const Element& first_element = ToElement(first);
-  const Element& second_element = ToElement(second);
-  if (!first_element.HasTagName(second_element.TagQName()))
-    return false;
-
-  if (!first_element.HasEquivalentAttributes(&second_element))
-    return false;
-
-  return HasEditableStyle(first_element) && HasEditableStyle(second_element);
-}
-
 bool IsNonTableCellHTMLBlockElement(const Node* node) {
   if (!node->IsHTMLElement())
     return false;
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.h b/third_party/WebKit/Source/core/editing/EditingUtilities.h
index d1b5b14..c0bd3f3 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.h
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.h
@@ -98,7 +98,6 @@
     bool (*node_is_of_type)(const Node*),
     EditingBoundaryCrossingRule = kCannotCrossEditingBoundary,
     Node* stay_within = nullptr);
-Node* HighestNodeToRemoveInPruning(Node*, const Node* exclude_node = nullptr);
 
 Element* EnclosingBlock(
     const Node*,
@@ -109,9 +108,7 @@
                                     EditingBoundaryCrossingRule);
 Element* EnclosingBlockFlowElement(
     const Node&);  // Deprecated, use enclosingBlock instead.
-Element* EnclosingTableCell(const Position&);
 Element* AssociatedElementOf(const Position&);
-Node* EnclosingEmptyListItem(const VisiblePosition&);
 Element* EnclosingAnchorElement(const Position&);
 // Returns the lowest ancestor with the specified QualifiedName. If the
 // specified Position is editable, this function returns an editable
@@ -169,15 +166,10 @@
 bool IsInline(const Node*);
 bool IsTableCell(const Node*);
 bool IsEmptyTableCell(const Node*);
-bool IsTableStructureNode(const Node*);
 bool IsHTMLListElement(const Node*);
 bool IsListItem(const Node*);
 bool IsPresentationalHTMLElement(const Node*);
-bool IsNodeRendered(const Node&);
 bool IsRenderedAsNonInlineTableImageOrHR(const Node*);
-// Returns true if specified nodes are elements, have identical tag names,
-// have identical attributes, and are editable.
-CORE_EXPORT bool AreIdenticalElements(const Node&, const Node&);
 bool IsNonTableCellHTMLBlockElement(const Node*);
 bool IsBlockFlowElement(const Node&);
 EUserSelect UsedValueOfUserSelect(const Node&);
@@ -205,13 +197,6 @@
 Position PreviousVisuallyDistinctCandidate(const Position&);
 PositionInFlatTree PreviousVisuallyDistinctCandidate(const PositionInFlatTree&);
 
-Position PositionBeforeContainingSpecialElement(
-    const Position&,
-    HTMLElement** containing_special_element = nullptr);
-Position PositionAfterContainingSpecialElement(
-    const Position&,
-    HTMLElement** containing_special_element = nullptr);
-
 // This is a |const Node&| versions of two deprecated functions above.
 inline Position FirstPositionInOrBeforeNode(const Node& node) {
   return Position::FirstPositionInOrBeforeNode(node);
@@ -274,32 +259,7 @@
 CORE_EXPORT bool IsEditablePosition(const Position&);
 bool IsEditablePosition(const PositionInFlatTree&);
 bool IsRichlyEditablePosition(const Position&);
-bool LineBreakExistsAtPosition(const Position&);
 
-// miscellaneous functions on Position
-
-enum WhitespacePositionOption {
-  kNotConsiderNonCollapsibleWhitespace,
-  kConsiderNonCollapsibleWhitespace
-};
-
-// |leadingCollapsibleWhitespacePosition(position)| returns a previous position
-// of |position| if it is at collapsible whitespace, otherwise it returns null
-// position. When it is called with |NotConsiderNonCollapsibleWhitespace| and
-// a previous position in a element which has CSS property "white-space:pre",
-// or its variant, |leadingCollapsibleWhitespacePosition()| returns null
-// position.
-Position LeadingCollapsibleWhitespacePosition(
-    const Position&,
-    TextAffinity,
-    WhitespacePositionOption = kNotConsiderNonCollapsibleWhitespace);
-
-// TDOO(editing-dev): We should move |TrailingWhitespacePosition()| to
-// "DeleteSelection.cpp" since it is used only in "DeleteSelection.cpp".
-Position TrailingWhitespacePosition(
-    const Position&,
-    WhitespacePositionOption = kNotConsiderNonCollapsibleWhitespace);
-unsigned NumEnclosingMailBlockquotes(const Position&);
 PositionWithAffinity PositionRespectingEditingBoundary(
     const Position&,
     const LayoutPoint& local_point,
@@ -335,8 +295,6 @@
 CORE_EXPORT VisiblePosition VisiblePositionBeforeNode(const Node&);
 VisiblePosition VisiblePositionAfterNode(const Node&);
 
-bool LineBreakExistsAtVisiblePosition(const VisiblePosition&);
-
 int ComparePositions(const VisiblePosition&, const VisiblePosition&);
 
 CORE_EXPORT int IndexForVisiblePosition(const VisiblePosition&,
@@ -354,12 +312,6 @@
 // Functions returning HTMLElement
 
 HTMLElement* CreateDefaultParagraphElement(Document&);
-HTMLElement* CreateHTMLElement(Document&, const QualifiedName&);
-
-HTMLElement* EnclosingList(const Node*);
-HTMLElement* OutermostEnclosingList(const Node*,
-                                    const HTMLElement* root_list = nullptr);
-Node* EnclosingListChild(const Node*);
 
 // -------------------------------------------------------------------------
 // Element
@@ -372,17 +324,12 @@
 
 // Boolean functions on Element
 
-bool CanMergeLists(const Element& first_list, const Element& second_list);
-
 CORE_EXPORT bool ElementCannotHaveEndTag(const Node&);
 
 // -------------------------------------------------------------------------
 // VisibleSelection
 // -------------------------------------------------------------------------
 
-// Functions returning VisibleSelection
-VisibleSelection SelectionForParagraphIteration(const VisibleSelection&);
-
 // Miscellaneous functions on Text
 inline bool IsWhitespace(UChar c) {
   return c == kNoBreakSpaceCharacter || c == ' ' || c == '\n' || c == '\t';
@@ -408,7 +355,6 @@
 String StringWithRebalancedWhitespace(const String&,
                                       bool start_is_start_of_paragraph,
                                       bool should_emit_nbs_pbefore_end);
-const String& NonBreakingSpaceString();
 
 CORE_EXPORT String RepeatString(const String&, unsigned);
 
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp b/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
index 588cb8a..1513de4 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
@@ -244,36 +244,6 @@
             NextVisuallyDistinctCandidate(PositionInFlatTree(one, 1)));
 }
 
-TEST_F(EditingUtilitiesTest, AreaIdenticalElements) {
-  SetBodyContent(
-      "<style>li:nth-child(even) { -webkit-user-modify: read-write; "
-      "}</style><ul><li>first item</li><li>second item</li><li "
-      "class=foo>third</li><li>fourth</li></ul>");
-  StaticElementList* items =
-      GetDocument().QuerySelectorAll("li", ASSERT_NO_EXCEPTION);
-  DCHECK_EQ(items->length(), 4u);
-
-  EXPECT_FALSE(AreIdenticalElements(*items->item(0)->firstChild(),
-                                    *items->item(1)->firstChild()))
-      << "Can't merge non-elements.  e.g. Text nodes";
-
-  // Compare a LI and a UL.
-  EXPECT_FALSE(
-      AreIdenticalElements(*items->item(0), *items->item(0)->parentNode()))
-      << "Can't merge different tag names.";
-
-  EXPECT_FALSE(AreIdenticalElements(*items->item(0), *items->item(2)))
-      << "Can't merge a element with no attributes and another element with an "
-         "attribute.";
-
-  // We can't use contenteditable attribute to make editability difference
-  // because the hasEquivalentAttributes check is done earier.
-  EXPECT_FALSE(AreIdenticalElements(*items->item(0), *items->item(1)))
-      << "Can't merge non-editable nodes.";
-
-  EXPECT_TRUE(AreIdenticalElements(*items->item(1), *items->item(3)));
-}
-
 TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset_FirstLetter) {
   SetBodyContent(
       "<style>p::first-letter {color:red;}</style><p id='target'>abc</p>");
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
index a66d2e1..5dc17974 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -1137,19 +1137,25 @@
           .Build());
 }
 
-// TODO(yosin): We should make |FrameSelection::moveRangeSelection()| to take
-// two |IntPoint| instead of two |VisiblePosition| like
-// |moveRangeSelectionExtent()|.
-void FrameSelection::MoveRangeSelection(const VisiblePosition& base_position,
-                                        const VisiblePosition& extent_position,
+void FrameSelection::MoveRangeSelection(const IntPoint& base_point,
+                                        const IntPoint& extent_point,
                                         TextGranularity granularity) {
-  SelectionInDOMTree new_selection =
+  const VisiblePosition& base_position =
+      VisiblePositionForContentsPoint(base_point, GetFrame());
+  const VisiblePosition& extent_position =
+      VisiblePositionForContentsPoint(extent_point, GetFrame());
+  MoveRangeSelectionInternal(
       SelectionInDOMTree::Builder()
           .SetBaseAndExtentDeprecated(base_position.DeepEquivalent(),
                                       extent_position.DeepEquivalent())
           .SetAffinity(base_position.Affinity())
-          .Build();
+          .Build(),
+      granularity);
+}
 
+void FrameSelection::MoveRangeSelectionInternal(
+    const SelectionInDOMTree& new_selection,
+    TextGranularity granularity) {
   if (new_selection.IsNone())
     return;
 
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.h b/third_party/WebKit/Source/core/editing/FrameSelection.h
index c8ade75..9306dd4 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.h
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.h
@@ -125,8 +125,8 @@
   // extent is resolved to the same position as the current base, this
   // function will do nothing.
   void MoveRangeSelectionExtent(const IntPoint&);
-  void MoveRangeSelection(const VisiblePosition& base,
-                          const VisiblePosition& extent,
+  void MoveRangeSelection(const IntPoint& base_point,
+                          const IntPoint& extent_point,
                           TextGranularity);
 
   TextGranularity Granularity() const { return granularity_; }
@@ -253,6 +253,8 @@
 
   IntRect ComputeRectToScroll(RevealExtentOption);
 
+  void MoveRangeSelectionInternal(const SelectionInDOMTree&, TextGranularity);
+
   // Implementation of |SynchronousMutationObserver| member functions.
   void ContextDestroyed(Document*) final;
   void NodeChildrenWillBeRemoved(ContainerNode&) final;
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
index 75cc7f1..31101a0 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -54,6 +54,14 @@
   // Returns if a word is is selected.
   bool SelectWordAroundPosition(const Position&);
 
+  void MoveRangeSelectionInternal(const Position& base,
+                                  const Position& extent,
+                                  TextGranularity granularity) {
+    Selection().MoveRangeSelectionInternal(
+        SelectionInDOMTree::Builder().SetBaseAndExtent(base, extent).Build(),
+        granularity);
+  }
+
  private:
   Persistent<Text> text_node_;
 };
@@ -224,24 +232,20 @@
   EXPECT_EQ_SELECTED_TEXT("a");
 
   // "Foo B|ar B>az," with the Character granularity.
-  Selection().MoveRangeSelection(CreateVisiblePosition(Position(text, 5)),
-                                 CreateVisiblePosition(Position(text, 9)),
-                                 TextGranularity::kCharacter);
+  MoveRangeSelectionInternal(Position(text, 5), Position(text, 9),
+                             TextGranularity::kCharacter);
   EXPECT_EQ_SELECTED_TEXT("ar B");
   // "Foo B|ar B>az," with the Word granularity.
-  Selection().MoveRangeSelection(CreateVisiblePosition(Position(text, 5)),
-                                 CreateVisiblePosition(Position(text, 9)),
-                                 TextGranularity::kWord);
+  MoveRangeSelectionInternal(Position(text, 5), Position(text, 9),
+                             TextGranularity::kWord);
   EXPECT_EQ_SELECTED_TEXT("Bar Baz");
   // "Fo<o B|ar Baz," with the Character granularity.
-  Selection().MoveRangeSelection(CreateVisiblePosition(Position(text, 5)),
-                                 CreateVisiblePosition(Position(text, 2)),
-                                 TextGranularity::kCharacter);
+  MoveRangeSelectionInternal(Position(text, 5), Position(text, 2),
+                             TextGranularity::kCharacter);
   EXPECT_EQ_SELECTED_TEXT("o B");
   // "Fo<o B|ar Baz," with the Word granularity.
-  Selection().MoveRangeSelection(CreateVisiblePosition(Position(text, 5)),
-                                 CreateVisiblePosition(Position(text, 2)),
-                                 TextGranularity::kWord);
+  MoveRangeSelectionInternal(Position(text, 5), Position(text, 2),
+                             TextGranularity::kWord);
   EXPECT_EQ_SELECTED_TEXT("Foo Bar");
 }
 
@@ -249,10 +253,9 @@
   SetBodyContent("<span id=sample>xyz</span>");
   Element* const sample = GetDocument().getElementById("sample");
   // Select as: <span id=sample>^xyz|</span>
-  Selection().MoveRangeSelection(
-      CreateVisiblePosition(Position(sample->firstChild(), 1)),
-      CreateVisiblePosition(Position(sample->firstChild(), 1)),
-      TextGranularity::kWord);
+  MoveRangeSelectionInternal(Position(sample->firstChild(), 1),
+                             Position(sample->firstChild(), 1),
+                             TextGranularity::kWord);
   EXPECT_EQ("xyz", Selection().SelectedText());
   sample->insertBefore(Text::Create(GetDocument(), "abc"),
                        sample->firstChild());
diff --git a/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp b/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp
index 72a6ac03..ce163303 100644
--- a/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp
+++ b/third_party/WebKit/Source/core/editing/InlineBoxPosition.cpp
@@ -153,12 +153,10 @@
   return InlineBoxPosition(result_box, result_box->CaretLeftmostOffset());
 }
 
-// TODO(editing-dev): We should get rid of |TextDirection| parameter.
 InlineBoxPosition AdjustInlineBoxPositionForTextDirection(
     InlineBox* inline_box,
     int caret_offset,
-    UnicodeBidi unicode_bidi,
-    TextDirection) {
+    UnicodeBidi unicode_bidi) {
   const TextDirection primary_direction =
       inline_box->Root().Block().Style()->Direction();
   if (inline_box->Direction() == primary_direction)
@@ -243,8 +241,7 @@
 InlineBoxPosition ComputeInlineBoxPositionForTextNode(
     const LayoutText* text_layout_object,
     int caret_offset,
-    TextAffinity affinity,
-    TextDirection primary_direction) {
+    TextAffinity affinity) {
   // TODO(editing-dev): Add the following DCHECK when ready.
   // DCHECK(CanUseInlineBox(*text_layout_object));
 
@@ -281,14 +278,12 @@
   if (!inline_box)
     return InlineBoxPosition();
   return AdjustInlineBoxPositionForTextDirection(
-      inline_box, caret_offset, text_layout_object->Style()->GetUnicodeBidi(),
-      primary_direction);
+      inline_box, caret_offset, text_layout_object->Style()->GetUnicodeBidi());
 }
 
 InlineBoxPosition ComputeInlineBoxPositionForAtomicInline(
     const LayoutObject* layout_object,
-    int caret_offset,
-    TextDirection primary_direction) {
+    int caret_offset) {
   // TODO(editing-dev): Add the following DCHECK when ready.
   // DCHECK(CanUseInlineBox(*layout_object);
   DCHECK(layout_object->IsBox());
@@ -299,8 +294,7 @@
        caret_offset < inline_box->CaretMaxOffset()))
     return InlineBoxPosition(inline_box, caret_offset);
   return AdjustInlineBoxPositionForTextDirection(
-      inline_box, caret_offset, layout_object->Style()->GetUnicodeBidi(),
-      primary_direction);
+      inline_box, caret_offset, layout_object->Style()->GetUnicodeBidi());
 }
 
 template <typename Strategy>
@@ -357,8 +351,7 @@
 
 template <typename Strategy>
 InlineBoxPosition ComputeInlineBoxPositionForInlineAdjustedPositionAlgorithm(
-    const PositionWithAffinityTemplate<Strategy>& adjusted,
-    TextDirection primary_direction) {
+    const PositionWithAffinityTemplate<Strategy>& adjusted) {
   const PositionTemplate<Strategy>& position = adjusted.GetPosition();
   const LayoutObject& layout_object =
       GetLayoutObjectSkippingShadowRoot(position);
@@ -366,40 +359,22 @@
 
   if (layout_object.IsText()) {
     return ComputeInlineBoxPositionForTextNode(
-        &ToLayoutText(layout_object), caret_offset, adjusted.Affinity(),
-        primary_direction);
+        &ToLayoutText(layout_object), caret_offset, adjusted.Affinity());
   }
 
   DCHECK(layout_object.IsAtomicInlineLevel());
   DCHECK(layout_object.IsInline());
-  return ComputeInlineBoxPositionForAtomicInline(&layout_object, caret_offset,
-                                                 primary_direction);
-}
-
-template <typename Strategy>
-InlineBoxPosition ComputeInlineBoxPositionForInlineAdjustedPositionAlgorithm(
-    const PositionWithAffinityTemplate<Strategy>& position) {
-  return ComputeInlineBoxPositionForInlineAdjustedPositionAlgorithm(
-      position, PrimaryDirectionOf(*position.AnchorNode()));
+  return ComputeInlineBoxPositionForAtomicInline(&layout_object, caret_offset);
 }
 
 template <typename Strategy>
 InlineBoxPosition ComputeInlineBoxPositionTemplate(
-    const PositionWithAffinityTemplate<Strategy>& position,
-    TextDirection primary_direction) {
+    const PositionWithAffinityTemplate<Strategy>& position) {
   const PositionWithAffinityTemplate<Strategy> adjusted =
       ComputeInlineAdjustedPosition(position);
   if (adjusted.IsNull())
     return InlineBoxPosition();
-  return ComputeInlineBoxPositionForInlineAdjustedPosition(adjusted,
-                                                           primary_direction);
-}
-
-template <typename Strategy>
-InlineBoxPosition ComputeInlineBoxPositionTemplate(
-    const PositionWithAffinityTemplate<Strategy>& position) {
-  return ComputeInlineBoxPositionTemplate<Strategy>(
-      position, PrimaryDirectionOf(*position.AnchorNode()));
+  return ComputeInlineBoxPositionForInlineAdjustedPosition(adjusted);
 }
 
 }  // namespace
@@ -422,19 +397,6 @@
   return ComputeInlineBoxPosition(position.ToPositionWithAffinity());
 }
 
-InlineBoxPosition ComputeInlineBoxPosition(const PositionWithAffinity& position,
-                                           TextDirection primary_direction) {
-  return ComputeInlineBoxPositionTemplate<EditingStrategy>(position,
-                                                           primary_direction);
-}
-
-InlineBoxPosition ComputeInlineBoxPosition(
-    const PositionInFlatTreeWithAffinity& position,
-    TextDirection primary_direction) {
-  return ComputeInlineBoxPositionTemplate<EditingInFlatTreeStrategy>(
-      position, primary_direction);
-}
-
 PositionWithAffinity ComputeInlineAdjustedPosition(
     const PositionWithAffinity& position) {
   return ComputeInlineAdjustedPositionAlgorithm(position);
@@ -462,18 +424,4 @@
   return ComputeInlineBoxPositionForInlineAdjustedPositionAlgorithm(position);
 }
 
-InlineBoxPosition ComputeInlineBoxPositionForInlineAdjustedPosition(
-    const PositionWithAffinity& position,
-    TextDirection primary_direction) {
-  return ComputeInlineBoxPositionForInlineAdjustedPositionAlgorithm(
-      position, primary_direction);
-}
-
-InlineBoxPosition ComputeInlineBoxPositionForInlineAdjustedPosition(
-    const PositionInFlatTreeWithAffinity& position,
-    TextDirection primary_direction) {
-  return ComputeInlineBoxPositionForInlineAdjustedPositionAlgorithm(
-      position, primary_direction);
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/InlineBoxPosition.h b/third_party/WebKit/Source/core/editing/InlineBoxPosition.h
index 0bb2594a..528dd25 100644
--- a/third_party/WebKit/Source/core/editing/InlineBoxPosition.h
+++ b/third_party/WebKit/Source/core/editing/InlineBoxPosition.h
@@ -32,7 +32,6 @@
 
 #include "core/CoreExport.h"
 #include "core/editing/Forward.h"
-#include "platform/text/TextDirection.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/Assertions.h"
 
@@ -78,13 +77,7 @@
 InlineBoxPosition ComputeInlineBoxPositionForInlineAdjustedPosition(
     const PositionWithAffinity&);
 InlineBoxPosition ComputeInlineBoxPositionForInlineAdjustedPosition(
-    const PositionWithAffinity&,
-    TextDirection primary_direction);
-InlineBoxPosition ComputeInlineBoxPositionForInlineAdjustedPosition(
     const PositionInFlatTreeWithAffinity&);
-InlineBoxPosition ComputeInlineBoxPositionForInlineAdjustedPosition(
-    const PositionInFlatTreeWithAffinity&,
-    TextDirection primary_direction);
 
 // The print for |InlineBoxPosition| is available only for testing
 // in "webkit_unit_tests", and implemented in
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommand.cpp
index 22748f0..6ffd41f 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommand.cpp
@@ -34,6 +34,7 @@
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleSelection.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/html/HTMLBRElement.h"
 #include "core/html/HTMLElement.h"
 #include "core/html_names.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
index 13ace3f..e7fa252 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -44,6 +44,7 @@
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleSelection.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/editing/iterators/TextIterator.h"
 #include "core/editing/serializers/HTMLInterchange.h"
 #include "core/frame/UseCounter.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp b/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
index 3a9f6f06..ebd43dd 100644
--- a/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
@@ -32,6 +32,7 @@
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleSelection.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/html/HTMLBRElement.h"
 #include "core/html/HTMLElement.h"
 #include "core/html/HTMLQuoteElement.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
index 0809029..6b6ea8c7 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -48,6 +48,7 @@
 #include "core/editing/commands/ApplyStyleCommand.h"
 #include "core/editing/commands/DeleteFromTextNodeCommand.h"
 #include "core/editing/commands/DeleteSelectionCommand.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/editing/commands/InsertIntoTextNodeCommand.h"
 #include "core/editing/commands/InsertLineBreakCommand.h"
 #include "core/editing/commands/InsertNodeBeforeCommand.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
index 8c8c206..9fb5b1e 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -37,6 +37,7 @@
 #include "core/editing/SelectionTemplate.h"
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/frame/LocalFrame.h"
 #include "core/html/HTMLBRElement.h"
 #include "core/html/HTMLStyleElement.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp
new file mode 100644
index 0000000..54b2c2e
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.cpp
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// 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 "core/editing/commands/EditingCommandsUtilities.h"
+
+#include "core/editing/EditingUtilities.h"
+#include "core/editing/SelectionTemplate.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/editing/VisibleSelection.h"
+#include "core/html_element_factory.h"
+#include "core/layout/LayoutObject.h"
+
+namespace blink {
+
+static bool HasARenderedDescendant(const Node* node,
+                                   const Node* excluded_node) {
+  for (const Node* n = node->firstChild(); n;) {
+    if (n == excluded_node) {
+      n = NodeTraversal::NextSkippingChildren(*n, node);
+      continue;
+    }
+    if (n->GetLayoutObject())
+      return true;
+    n = NodeTraversal::Next(*n, node);
+  }
+  return false;
+}
+
+Node* HighestNodeToRemoveInPruning(Node* node, const Node* exclude_node) {
+  Node* previous_node = nullptr;
+  Element* element = node ? RootEditableElement(*node) : nullptr;
+  for (; node; node = node->parentNode()) {
+    if (LayoutObject* layout_object = node->GetLayoutObject()) {
+      if (!layout_object->CanHaveChildren() ||
+          HasARenderedDescendant(node, previous_node) || element == node ||
+          exclude_node == node)
+        return previous_node;
+    }
+    previous_node = node;
+  }
+  return nullptr;
+}
+
+Element* EnclosingTableCell(const Position& p) {
+  return ToElement(EnclosingNodeOfType(p, IsTableCell));
+}
+
+bool IsTableStructureNode(const Node* node) {
+  LayoutObject* layout_object = node->GetLayoutObject();
+  return (layout_object &&
+          (layout_object->IsTableCell() || layout_object->IsTableRow() ||
+           layout_object->IsTableSection() ||
+           layout_object->IsLayoutTableCol()));
+}
+
+bool IsNodeRendered(const Node& node) {
+  LayoutObject* layout_object = node.GetLayoutObject();
+  if (!layout_object)
+    return false;
+
+  return layout_object->Style()->Visibility() == EVisibility::kVisible;
+}
+
+// FIXME: This method should not need to call
+// isStartOfParagraph/isEndOfParagraph
+Node* EnclosingEmptyListItem(const VisiblePosition& visible_pos) {
+  DCHECK(visible_pos.IsValid());
+
+  // Check that position is on a line by itself inside a list item
+  Node* list_child_node =
+      EnclosingListChild(visible_pos.DeepEquivalent().AnchorNode());
+  if (!list_child_node || !IsStartOfParagraph(visible_pos) ||
+      !IsEndOfParagraph(visible_pos))
+    return nullptr;
+
+  VisiblePosition first_in_list_child =
+      CreateVisiblePosition(FirstPositionInOrBeforeNode(*list_child_node));
+  VisiblePosition last_in_list_child =
+      CreateVisiblePosition(LastPositionInOrAfterNode(*list_child_node));
+
+  if (first_in_list_child.DeepEquivalent() != visible_pos.DeepEquivalent() ||
+      last_in_list_child.DeepEquivalent() != visible_pos.DeepEquivalent())
+    return nullptr;
+
+  return list_child_node;
+}
+
+bool AreIdenticalElements(const Node& first, const Node& second) {
+  if (!first.IsElementNode() || !second.IsElementNode())
+    return false;
+
+  const Element& first_element = ToElement(first);
+  const Element& second_element = ToElement(second);
+  if (!first_element.HasTagName(second_element.TagQName()))
+    return false;
+
+  if (!first_element.HasEquivalentAttributes(&second_element))
+    return false;
+
+  return HasEditableStyle(first_element) && HasEditableStyle(second_element);
+}
+
+// FIXME: need to dump this
+static bool IsSpecialHTMLElement(const Node& n) {
+  if (!n.IsHTMLElement())
+    return false;
+
+  if (n.IsLink())
+    return true;
+
+  LayoutObject* layout_object = n.GetLayoutObject();
+  if (!layout_object)
+    return false;
+
+  if (layout_object->Style()->Display() == EDisplay::kTable ||
+      layout_object->Style()->Display() == EDisplay::kInlineTable)
+    return true;
+
+  if (layout_object->Style()->IsFloating())
+    return true;
+
+  return false;
+}
+
+static HTMLElement* FirstInSpecialElement(const Position& pos) {
+  DCHECK(!NeedsLayoutTreeUpdate(pos));
+  Element* element = RootEditableElement(*pos.ComputeContainerNode());
+  for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*pos.AnchorNode())) {
+    if (RootEditableElement(runner) != element)
+      break;
+    if (IsSpecialHTMLElement(runner)) {
+      HTMLElement* special_element = ToHTMLElement(&runner);
+      VisiblePosition v_pos = CreateVisiblePosition(pos);
+      VisiblePosition first_in_element =
+          CreateVisiblePosition(FirstPositionInOrBeforeNode(*special_element));
+      if (IsDisplayInsideTable(special_element) &&
+          v_pos.DeepEquivalent() ==
+              NextPositionOf(first_in_element).DeepEquivalent())
+        return special_element;
+      if (v_pos.DeepEquivalent() == first_in_element.DeepEquivalent())
+        return special_element;
+    }
+  }
+  return nullptr;
+}
+
+static HTMLElement* LastInSpecialElement(const Position& pos) {
+  DCHECK(!NeedsLayoutTreeUpdate(pos));
+  Element* element = RootEditableElement(*pos.ComputeContainerNode());
+  for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*pos.AnchorNode())) {
+    if (RootEditableElement(runner) != element)
+      break;
+    if (IsSpecialHTMLElement(runner)) {
+      HTMLElement* special_element = ToHTMLElement(&runner);
+      VisiblePosition v_pos = CreateVisiblePosition(pos);
+      VisiblePosition last_in_element =
+          CreateVisiblePosition(LastPositionInOrAfterNode(*special_element));
+      if (IsDisplayInsideTable(special_element) &&
+          v_pos.DeepEquivalent() ==
+              PreviousPositionOf(last_in_element).DeepEquivalent())
+        return special_element;
+      if (v_pos.DeepEquivalent() == last_in_element.DeepEquivalent())
+        return special_element;
+    }
+  }
+  return nullptr;
+}
+
+Position PositionBeforeContainingSpecialElement(
+    const Position& pos,
+    HTMLElement** containing_special_element) {
+  DCHECK(!NeedsLayoutTreeUpdate(pos));
+  HTMLElement* n = FirstInSpecialElement(pos);
+  if (!n)
+    return pos;
+  Position result = Position::InParentBeforeNode(*n);
+  if (result.IsNull() || RootEditableElement(*result.AnchorNode()) !=
+                             RootEditableElement(*pos.AnchorNode()))
+    return pos;
+  if (containing_special_element)
+    *containing_special_element = n;
+  return result;
+}
+
+Position PositionAfterContainingSpecialElement(
+    const Position& pos,
+    HTMLElement** containing_special_element) {
+  DCHECK(!NeedsLayoutTreeUpdate(pos));
+  HTMLElement* n = LastInSpecialElement(pos);
+  if (!n)
+    return pos;
+  Position result = Position::InParentAfterNode(*n);
+  if (result.IsNull() || RootEditableElement(*result.AnchorNode()) !=
+                             RootEditableElement(*pos.AnchorNode()))
+    return pos;
+  if (containing_special_element)
+    *containing_special_element = n;
+  return result;
+}
+
+bool LineBreakExistsAtPosition(const Position& position) {
+  if (position.IsNull())
+    return false;
+
+  if (IsHTMLBRElement(*position.AnchorNode()) &&
+      position.AtFirstEditingPositionForNode())
+    return true;
+
+  if (!position.AnchorNode()->GetLayoutObject())
+    return false;
+
+  if (!position.AnchorNode()->IsTextNode() ||
+      !position.AnchorNode()->GetLayoutObject()->Style()->PreserveNewline())
+    return false;
+
+  const Text* text_node = ToText(position.AnchorNode());
+  unsigned offset = position.OffsetInContainerNode();
+  return offset < text_node->length() && text_node->data()[offset] == '\n';
+}
+
+// return first preceding DOM position rendered at a different location, or
+// "this"
+static Position PreviousCharacterPosition(const Position& position,
+                                          TextAffinity affinity) {
+  DCHECK(!NeedsLayoutTreeUpdate(position));
+  if (position.IsNull())
+    return Position();
+
+  Element* from_root_editable_element =
+      RootEditableElement(*position.AnchorNode());
+
+  bool at_start_of_line =
+      IsStartOfLine(CreateVisiblePosition(position, affinity));
+  bool rendered = IsVisuallyEquivalentCandidate(position);
+
+  Position current_pos = position;
+  while (!current_pos.AtStartOfTree()) {
+    // TODO(yosin) When we use |previousCharacterPosition()| other than
+    // finding leading whitespace, we should use |Character| instead of
+    // |CodePoint|.
+    current_pos = PreviousPositionOf(current_pos, PositionMoveType::kCodeUnit);
+
+    if (RootEditableElement(*current_pos.AnchorNode()) !=
+        from_root_editable_element)
+      return position;
+
+    if (at_start_of_line || !rendered) {
+      if (IsVisuallyEquivalentCandidate(current_pos))
+        return current_pos;
+    } else if (RendersInDifferentPosition(position, current_pos)) {
+      return current_pos;
+    }
+  }
+
+  return position;
+}
+
+// This assumes that it starts in editable content.
+Position LeadingCollapsibleWhitespacePosition(const Position& position,
+                                              TextAffinity affinity,
+                                              WhitespacePositionOption option) {
+  DCHECK(!NeedsLayoutTreeUpdate(position));
+  DCHECK(IsEditablePosition(position)) << position;
+  if (position.IsNull())
+    return Position();
+
+  if (IsHTMLBRElement(*MostBackwardCaretPosition(position).AnchorNode()))
+    return Position();
+
+  const Position& prev = PreviousCharacterPosition(position, affinity);
+  if (prev == position)
+    return Position();
+  const Node* const anchor_node = prev.AnchorNode();
+  if (!anchor_node || !anchor_node->IsTextNode())
+    return Position();
+  if (EnclosingBlockFlowElement(*anchor_node) !=
+      EnclosingBlockFlowElement(*position.AnchorNode()))
+    return Position();
+  if (option == kNotConsiderNonCollapsibleWhitespace &&
+      anchor_node->GetLayoutObject() &&
+      !anchor_node->GetLayoutObject()->Style()->CollapseWhiteSpace())
+    return Position();
+  const String& string = ToText(anchor_node)->data();
+  const UChar previous_character = string[prev.ComputeOffsetInContainerNode()];
+  const bool is_space = option == kConsiderNonCollapsibleWhitespace
+                            ? (IsSpaceOrNewline(previous_character) ||
+                               previous_character == kNoBreakSpaceCharacter)
+                            : IsCollapsibleWhitespace(previous_character);
+  if (!is_space || !IsEditablePosition(prev))
+    return Position();
+  return prev;
+}
+
+// This assumes that it starts in editable content.
+Position TrailingWhitespacePosition(const Position& position,
+                                    WhitespacePositionOption option) {
+  DCHECK(!NeedsLayoutTreeUpdate(position));
+  DCHECK(IsEditablePosition(position)) << position;
+  if (position.IsNull())
+    return Position();
+
+  VisiblePosition visible_position = CreateVisiblePosition(position);
+  UChar character_after_visible_position = CharacterAfter(visible_position);
+  bool is_space =
+      option == kConsiderNonCollapsibleWhitespace
+          ? (IsSpaceOrNewline(character_after_visible_position) ||
+             character_after_visible_position == kNoBreakSpaceCharacter)
+          : IsCollapsibleWhitespace(character_after_visible_position);
+  // The space must not be in another paragraph and it must be editable.
+  if (is_space && !IsEndOfParagraph(visible_position) &&
+      NextPositionOf(visible_position, kCannotCrossEditingBoundary).IsNotNull())
+    return position;
+  return Position();
+}
+
+unsigned NumEnclosingMailBlockquotes(const Position& p) {
+  unsigned num = 0;
+  for (const Node* n = p.AnchorNode(); n; n = n->parentNode()) {
+    if (IsMailHTMLBlockquoteElement(n))
+      num++;
+  }
+  return num;
+}
+
+bool LineBreakExistsAtVisiblePosition(const VisiblePosition& visible_position) {
+  return LineBreakExistsAtPosition(
+      MostForwardCaretPosition(visible_position.DeepEquivalent()));
+}
+
+HTMLElement* CreateHTMLElement(Document& document, const QualifiedName& name) {
+  return HTMLElementFactory::createHTMLElement(name.LocalName(), document,
+                                               kCreatedByCloneNode);
+}
+
+HTMLElement* EnclosingList(const Node* node) {
+  if (!node)
+    return nullptr;
+
+  ContainerNode* root = HighestEditableRoot(FirstPositionInOrBeforeNode(*node));
+
+  for (Node& runner : NodeTraversal::AncestorsOf(*node)) {
+    if (IsHTMLUListElement(runner) || IsHTMLOListElement(runner))
+      return ToHTMLElement(&runner);
+    if (runner == root)
+      return nullptr;
+  }
+
+  return nullptr;
+}
+
+Node* EnclosingListChild(const Node* node) {
+  if (!node)
+    return nullptr;
+  // Check for a list item element, or for a node whose parent is a list
+  // element. Such a node will appear visually as a list item (but without a
+  // list marker)
+  ContainerNode* root = HighestEditableRoot(FirstPositionInOrBeforeNode(*node));
+
+  // FIXME: This function is inappropriately named if it starts with node
+  // instead of node->parentNode()
+  for (Node* n = const_cast<Node*>(node); n && n->parentNode();
+       n = n->parentNode()) {
+    if (IsHTMLLIElement(*n) ||
+        (IsHTMLListElement(n->parentNode()) && n != root))
+      return n;
+    if (n == root || IsTableCell(n))
+      return nullptr;
+  }
+
+  return nullptr;
+}
+
+HTMLElement* OutermostEnclosingList(const Node* node,
+                                    const HTMLElement* root_list) {
+  HTMLElement* list = EnclosingList(node);
+  if (!list)
+    return nullptr;
+
+  while (HTMLElement* next_list = EnclosingList(list)) {
+    if (next_list == root_list)
+      break;
+    list = next_list;
+  }
+
+  return list;
+}
+
+// Determines whether two positions are visibly next to each other (first then
+// second) while ignoring whitespaces and unrendered nodes
+static bool IsVisiblyAdjacent(const Position& first, const Position& second) {
+  return CreateVisiblePosition(first).DeepEquivalent() ==
+         CreateVisiblePosition(MostBackwardCaretPosition(second))
+             .DeepEquivalent();
+}
+
+bool CanMergeLists(const Element& first_list, const Element& second_list) {
+  if (!first_list.IsHTMLElement() || !second_list.IsHTMLElement())
+    return false;
+
+  DCHECK(!NeedsLayoutTreeUpdate(first_list));
+  DCHECK(!NeedsLayoutTreeUpdate(second_list));
+  return first_list.HasTagName(
+             second_list
+                 .TagQName())  // make sure the list types match (ol vs. ul)
+         && HasEditableStyle(first_list) &&
+         HasEditableStyle(second_list)  // both lists are editable
+         &&
+         RootEditableElement(first_list) ==
+             RootEditableElement(second_list)  // don't cross editing boundaries
+         && IsVisiblyAdjacent(Position::InParentAfterNode(first_list),
+                              Position::InParentBeforeNode(second_list));
+  // Make sure there is no visible content between this li and the previous list
+}
+
+// Modifies selections that have an end point at the edge of a table
+// that contains the other endpoint so that they don't confuse
+// code that iterates over selected paragraphs.
+VisibleSelection SelectionForParagraphIteration(
+    const VisibleSelection& original) {
+  VisibleSelection new_selection(original);
+  VisiblePosition start_of_selection(new_selection.VisibleStart());
+  VisiblePosition end_of_selection(new_selection.VisibleEnd());
+
+  // If the end of the selection to modify is just after a table, and if the
+  // start of the selection is inside that table, then the last paragraph that
+  // we'll want modify is the last one inside the table, not the table itself (a
+  // table is itself a paragraph).
+  if (Element* table = TableElementJustBefore(end_of_selection)) {
+    if (start_of_selection.DeepEquivalent().AnchorNode()->IsDescendantOf(
+            table)) {
+      const VisiblePosition& new_end =
+          PreviousPositionOf(end_of_selection, kCannotCrossEditingBoundary);
+      if (new_end.IsNotNull()) {
+        new_selection = CreateVisibleSelection(
+            SelectionInDOMTree::Builder()
+                .Collapse(start_of_selection.ToPositionWithAffinity())
+                .Extend(new_end.DeepEquivalent())
+                .Build());
+      } else {
+        new_selection = CreateVisibleSelection(
+            SelectionInDOMTree::Builder()
+                .Collapse(start_of_selection.ToPositionWithAffinity())
+                .Build());
+      }
+    }
+  }
+
+  // If the start of the selection to modify is just before a table, and if the
+  // end of the selection is inside that table, then the first paragraph we'll
+  // want to modify is the first one inside the table, not the paragraph
+  // containing the table itself.
+  if (Element* table = TableElementJustAfter(start_of_selection)) {
+    if (end_of_selection.DeepEquivalent().AnchorNode()->IsDescendantOf(table)) {
+      const VisiblePosition new_start =
+          NextPositionOf(start_of_selection, kCannotCrossEditingBoundary);
+      if (new_start.IsNotNull()) {
+        new_selection = CreateVisibleSelection(
+            SelectionInDOMTree::Builder()
+                .Collapse(new_start.ToPositionWithAffinity())
+                .Extend(end_of_selection.DeepEquivalent())
+                .Build());
+      } else {
+        new_selection = CreateVisibleSelection(
+            SelectionInDOMTree::Builder()
+                .Collapse(end_of_selection.ToPositionWithAffinity())
+                .Build());
+      }
+    }
+  }
+
+  return new_selection;
+}
+
+const String& NonBreakingSpaceString() {
+  DEFINE_STATIC_LOCAL(String, non_breaking_space_string,
+                      (&kNoBreakSpaceCharacter, 1));
+  return non_breaking_space_string;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.h b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.h
new file mode 100644
index 0000000..dbfd222
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilities.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// 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 EditingCommandsUtilities_h
+#define EditingCommandsUtilities_h
+
+#include "core/CoreExport.h"
+#include "core/editing/Forward.h"
+#include "platform/wtf/text/CharacterNames.h"
+#include "platform/wtf/text/WTFString.h"
+
+namespace blink {
+
+class Document;
+class Element;
+class HTMLElement;
+class Node;
+class QualifiedName;
+
+// -------------------------------------------------------------------------
+// Node
+// -------------------------------------------------------------------------
+
+Node* HighestNodeToRemoveInPruning(Node*, const Node* exclude_node = nullptr);
+
+Element* EnclosingTableCell(const Position&);
+Node* EnclosingEmptyListItem(const VisiblePosition&);
+
+bool IsTableStructureNode(const Node*);
+bool IsNodeRendered(const Node&);
+// Returns true if specified nodes are elements, have identical tag names,
+// have identical attributes, and are editable.
+CORE_EXPORT bool AreIdenticalElements(const Node&, const Node&);
+
+// -------------------------------------------------------------------------
+// Position
+// -------------------------------------------------------------------------
+
+Position PositionBeforeContainingSpecialElement(
+    const Position&,
+    HTMLElement** containing_special_element = nullptr);
+Position PositionAfterContainingSpecialElement(
+    const Position&,
+    HTMLElement** containing_special_element = nullptr);
+
+bool LineBreakExistsAtPosition(const Position&);
+
+// miscellaneous functions on Position
+
+enum WhitespacePositionOption {
+  kNotConsiderNonCollapsibleWhitespace,
+  kConsiderNonCollapsibleWhitespace
+};
+
+// |leadingCollapsibleWhitespacePosition(position)| returns a previous position
+// of |position| if it is at collapsible whitespace, otherwise it returns null
+// position. When it is called with |NotConsiderNonCollapsibleWhitespace| and
+// a previous position in a element which has CSS property "white-space:pre",
+// or its variant, |leadingCollapsibleWhitespacePosition()| returns null
+// position.
+Position LeadingCollapsibleWhitespacePosition(
+    const Position&,
+    TextAffinity,
+    WhitespacePositionOption = kNotConsiderNonCollapsibleWhitespace);
+
+// TDOO(editing-dev): We should move |TrailingWhitespacePosition()| to
+// "DeleteSelection.cpp" since it is used only in "DeleteSelection.cpp".
+Position TrailingWhitespacePosition(
+    const Position&,
+    WhitespacePositionOption = kNotConsiderNonCollapsibleWhitespace);
+
+unsigned NumEnclosingMailBlockquotes(const Position&);
+
+// -------------------------------------------------------------------------
+// VisiblePosition
+// -------------------------------------------------------------------------
+
+bool LineBreakExistsAtVisiblePosition(const VisiblePosition&);
+
+// -------------------------------------------------------------------------
+// HTMLElement
+// -------------------------------------------------------------------------
+
+HTMLElement* CreateHTMLElement(Document&, const QualifiedName&);
+HTMLElement* EnclosingList(const Node*);
+HTMLElement* OutermostEnclosingList(const Node*,
+                                    const HTMLElement* root_list = nullptr);
+Node* EnclosingListChild(const Node*);
+
+// -------------------------------------------------------------------------
+// Element
+// -------------------------------------------------------------------------
+
+bool CanMergeLists(const Element& first_list, const Element& second_list);
+
+// -------------------------------------------------------------------------
+// VisibleSelection
+// -------------------------------------------------------------------------
+
+// Functions returning VisibleSelection
+VisibleSelection SelectionForParagraphIteration(const VisibleSelection&);
+
+const String& NonBreakingSpaceString();
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilitiesTest.cpp b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilitiesTest.cpp
new file mode 100644
index 0000000..6db5fc6
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/commands/EditingCommandsUtilitiesTest.cpp
@@ -0,0 +1,45 @@
+// 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 "core/editing/commands/EditingCommandsUtilities.h"
+
+#include "core/dom/StaticNodeList.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/editing/testing/EditingTestBase.h"
+
+namespace blink {
+
+class EditingCommandsUtilitiesTest : public EditingTestBase {};
+
+TEST_F(EditingCommandsUtilitiesTest, AreaIdenticalElements) {
+  SetBodyContent(
+      "<style>li:nth-child(even) { -webkit-user-modify: read-write; "
+      "}</style><ul><li>first item</li><li>second item</li><li "
+      "class=foo>third</li><li>fourth</li></ul>");
+  StaticElementList* items =
+      GetDocument().QuerySelectorAll("li", ASSERT_NO_EXCEPTION);
+  DCHECK_EQ(items->length(), 4u);
+
+  EXPECT_FALSE(AreIdenticalElements(*items->item(0)->firstChild(),
+                                    *items->item(1)->firstChild()))
+      << "Can't merge non-elements.  e.g. Text nodes";
+
+  // Compare a LI and a UL.
+  EXPECT_FALSE(
+      AreIdenticalElements(*items->item(0), *items->item(0)->parentNode()))
+      << "Can't merge different tag names.";
+
+  EXPECT_FALSE(AreIdenticalElements(*items->item(0), *items->item(2)))
+      << "Can't merge a element with no attributes and another element with an "
+         "attribute.";
+
+  // We can't use contenteditable attribute to make editability difference
+  // because the hasEquivalentAttributes check is done earier.
+  EXPECT_FALSE(AreIdenticalElements(*items->item(0), *items->item(1)))
+      << "Can't merge non-editable nodes.";
+
+  EXPECT_TRUE(AreIdenticalElements(*items->item(1), *items->item(3)));
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
index dfd0e6c6..42cfce1 100644
--- a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
@@ -32,6 +32,7 @@
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleSelection.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/editing/commands/InsertListCommand.h"
 #include "core/html/HTMLBRElement.h"
 #include "core/html/HTMLElement.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp
index f210d850..97bf354 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp
@@ -33,6 +33,7 @@
 #include "core/editing/SelectionTemplate.h"
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/frame/LocalFrame.h"
 #include "core/html/HTMLBRElement.h"
 #include "core/html/HTMLElement.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
index 1dbbdd4..2592a93 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -35,6 +35,7 @@
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleSelection.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/editing/iterators/TextIterator.h"
 #include "core/html/HTMLBRElement.h"
 #include "core/html/HTMLElement.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
index 77fb013..e2c14650 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -34,6 +34,7 @@
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleSelection.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/editing/commands/InsertLineBreakCommand.h"
 #include "core/html/HTMLBRElement.h"
 #include "core/html/HTMLElement.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp
index b0f35663..3128b45 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp
@@ -33,6 +33,7 @@
 #include "core/editing/SelectionTemplate.h"
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleUnits.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/frame/LocalFrame.h"
 #include "core/html/HTMLSpanElement.h"
 
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
index 61c5e679..e7965865 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -44,6 +44,7 @@
 #include "core/editing/VisibleUnits.h"
 #include "core/editing/commands/ApplyStyleCommand.h"
 #include "core/editing/commands/BreakBlockquoteCommand.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/editing/commands/SimplifyMarkupCommand.h"
 #include "core/editing/commands/SmartReplace.h"
 #include "core/editing/iterators/TextIterator.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
index d7d372a..eee3e2c 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -41,6 +41,7 @@
 #include "core/editing/VisibleUnits.h"
 #include "core/editing/commands/BreakBlockquoteCommand.h"
 #include "core/editing/commands/DeleteSelectionCommand.h"
+#include "core/editing/commands/EditingCommandsUtilities.h"
 #include "core/editing/commands/InsertIncrementalTextCommand.h"
 #include "core/editing/commands/InsertLineBreakCommand.h"
 #include "core/editing/commands/InsertParagraphSeparatorCommand.h"
diff --git a/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
index 093932d..1f17705 100644
--- a/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
@@ -318,18 +318,14 @@
 }
 
 int ComputeAutocapitalizeFlags(const Element* element) {
-  const TextControlElement* const text_control =
-      ToTextControlElementOrNull(element);
-  if (!text_control)
-    return 0;
-
-  if (!text_control->SupportsAutocapitalize())
+  const HTMLElement* const html_element = ToHTMLElementOrNull(element);
+  if (!html_element)
     return 0;
 
   // We set the autocapitalization flag corresponding to the "used
   // autocapitalization hint" for the focused element:
   // https://html.spec.whatwg.org/multipage/interaction.html#used-autocapitalization-hint
-  if (auto* input = ToHTMLInputElementOrNull(*element)) {
+  if (auto* input = ToHTMLInputElementOrNull(*html_element)) {
     const AtomicString& input_type = input->type();
     if (input_type == InputTypeNames::email ||
         input_type == InputTypeNames::url ||
@@ -347,7 +343,7 @@
   DEFINE_STATIC_LOCAL(const AtomicString, words, ("words"));
   DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences"));
 
-  const AtomicString& autocapitalize = text_control->autocapitalize();
+  const AtomicString& autocapitalize = html_element->autocapitalize();
   if (autocapitalize == none)
     flags |= kWebTextInputFlagAutocapitalizeNone;
   else if (autocapitalize == characters)
diff --git a/third_party/WebKit/Source/core/editing/ime/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/ime/InputMethodControllerTest.cpp
index 3538805..2b11e5b 100644
--- a/third_party/WebKit/Source/core/editing/ime/InputMethodControllerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/ime/InputMethodControllerTest.cpp
@@ -3115,11 +3115,15 @@
       {"<textarea autocapitalize='words'></textarea>",
        kWebTextInputFlagAutocapitalizeWords},
 
-      {"<div contenteditable></div>", 0},
-      {"<div contenteditable autocapitalize='none'></div>", 0},
-      {"<div contenteditable autocapitalize='characters'></div>", 0},
-      {"<div contenteditable autocapitalize='sentences'></div>", 0},
-      {"<div contenteditable autocapitalize='words'></div>", 0},
+      {"<div contenteditable></div>", kWebTextInputFlagAutocapitalizeSentences},
+      {"<div contenteditable autocapitalize='none'></div>",
+       kWebTextInputFlagAutocapitalizeNone},
+      {"<div contenteditable autocapitalize='characters'></div>",
+       kWebTextInputFlagAutocapitalizeCharacters},
+      {"<div contenteditable autocapitalize='sentences'></div>",
+       kWebTextInputFlagAutocapitalizeSentences},
+      {"<div contenteditable autocapitalize='words'></div>",
+       kWebTextInputFlagAutocapitalizeWords},
   };
 
   const int autocapitalize_mask = kWebTextInputFlagAutocapitalizeNone |
diff --git a/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp b/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
index 8c38ed6b..148e84f 100644
--- a/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
@@ -357,7 +357,7 @@
 
   String shadow_mode;
   switch (shadow_root.GetType()) {
-    case ShadowRootType::kUserAgentV1:
+    case ShadowRootType::kUserAgent:
       // No need to serialize.
       return std::pair<Node*, Element*>();
     case ShadowRootType::V0:
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
index 9ba0b146..f07a696 100644
--- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -1104,7 +1104,7 @@
     return false;
   }
 
-  return selection.ComputeVisibleSelectionInDOMTreeDeprecated().IsBaseFirst();
+  return selection.GetSelectionInDOMTree().IsBaseFirst();
 }
 
 void WebLocalFrameImpl::SetTextDirection(WebTextDirection direction) {
@@ -1312,8 +1312,9 @@
   if (granularity == WebFrame::kWordGranularity)
     blink_granularity = blink::TextGranularity::kWord;
   GetFrame()->Selection().MoveRangeSelection(
-      VisiblePositionForViewportPoint(base_in_viewport),
-      VisiblePositionForViewportPoint(extent_in_viewport), blink_granularity);
+      GetFrame()->View()->ViewportToContents(base_in_viewport),
+      GetFrame()->View()->ViewportToContents(extent_in_viewport),
+      blink_granularity);
 }
 
 void WebLocalFrameImpl::MoveCaretSelection(const WebPoint& point_in_viewport) {
diff --git a/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp b/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp
index 1827f31..6ab4d7c 100644
--- a/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLDetailsElement.cpp
@@ -44,7 +44,7 @@
 
 HTMLDetailsElement* HTMLDetailsElement::Create(Document& document) {
   HTMLDetailsElement* details = new HTMLDetailsElement(document);
-  details->EnsureUserAgentShadowRootV1();
+  details->EnsureUserAgentShadowRoot();
   return details;
 }
 
@@ -120,7 +120,7 @@
         WTF::Bind(&HTMLDetailsElement::DispatchPendingEvent,
                   WrapPersistent(this)));
 
-    Element* content = EnsureUserAgentShadowRootV1().getElementById(
+    Element* content = EnsureUserAgentShadowRoot().getElementById(
         ShadowElementNames::DetailsContent());
     DCHECK(content);
     if (is_open_)
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.cpp b/third_party/WebKit/Source/core/html/HTMLElement.cpp
index 3f4a9c7..2d6e295 100644
--- a/third_party/WebKit/Source/core/html/HTMLElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLElement.cpp
@@ -58,6 +58,7 @@
 #include "core/html/forms/HTMLInputElement.h"
 #include "core/html/parser/HTMLParserIdioms.h"
 #include "core/html_names.h"
+#include "core/input_type_names.h"
 #include "core/layout/AdjustForAbsoluteZoom.h"
 #include "core/layout/LayoutBoxModelObject.h"
 #include "core/layout/LayoutObject.h"
@@ -530,6 +531,8 @@
        nullptr},
       {aria_valuetextAttr, WebFeature::kARIAValueTextAttribute, kNoEvent,
        nullptr},
+      {autocapitalizeAttr, WebFeature::kAutocapitalizeAttribute, kNoEvent,
+       nullptr},
   };
 
   using AttributeToTriggerIndexMap = HashMap<QualifiedName, int>;
@@ -794,6 +797,38 @@
                                           "'plaintext-only', or 'inherit'.");
 }
 
+const AtomicString& HTMLElement::autocapitalize() const {
+  DEFINE_STATIC_LOCAL(const AtomicString, kOff, ("off"));
+  DEFINE_STATIC_LOCAL(const AtomicString, kNone, ("none"));
+  DEFINE_STATIC_LOCAL(const AtomicString, kCharacters, ("characters"));
+  DEFINE_STATIC_LOCAL(const AtomicString, kWords, ("words"));
+  DEFINE_STATIC_LOCAL(const AtomicString, kSentences, ("sentences"));
+
+  if (auto* input = ToHTMLInputElementOrNull(*this)) {
+    const AtomicString& input_type = input->type();
+    if (input_type != InputTypeNames::text &&
+        input_type != InputTypeNames::search) {
+      // Autocapitalize is only supported for these two input types.
+      return kNone;
+    }
+  }
+
+  const AtomicString& value = FastGetAttribute(autocapitalizeAttr);
+  if (EqualIgnoringASCIICase(value, kNone) ||
+      EqualIgnoringASCIICase(value, kOff))
+    return kNone;
+  if (EqualIgnoringASCIICase(value, kCharacters))
+    return kCharacters;
+  if (EqualIgnoringASCIICase(value, kWords))
+    return kWords;
+  // "sentences", "on", empty string, or an invalid value
+  return kSentences;
+}
+
+void HTMLElement::setAutocapitalize(const AtomicString& value) {
+  setAttribute(autocapitalizeAttr, value);
+}
+
 bool HTMLElement::isContentEditableForBinding() const {
   return IsEditingHost(*this) || IsEditable(*this);
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.h b/third_party/WebKit/Source/core/html/HTMLElement.h
index 53cd4df..0fe4157 100644
--- a/third_party/WebKit/Source/core/html/HTMLElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLElement.h
@@ -68,6 +68,9 @@
   // use this function in Blink.
   bool isContentEditableForBinding() const;
 
+  virtual const AtomicString& autocapitalize() const;
+  void setAutocapitalize(const AtomicString&);
+
   virtual bool draggable() const;
   void setDraggable(bool);
 
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.idl b/third_party/WebKit/Source/core/html/HTMLElement.idl
index 6cc1edb..42fb788 100644
--- a/third_party/WebKit/Source/core/html/HTMLElement.idl
+++ b/third_party/WebKit/Source/core/html/HTMLElement.idl
@@ -38,6 +38,7 @@
     [CEReactions, Reflect] attribute DOMString accessKey;
     [CEReactions, CustomElementCallbacks] attribute boolean draggable;
     [CEReactions] attribute boolean spellcheck;
+    [Measure] attribute DOMString autocapitalize;
 
     // HTMLElement implements ElementContentEditable
     // https://html.spec.whatwg.org/#contenteditable
diff --git a/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp b/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp
index fbc589dd..d0c130e0 100644
--- a/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp
@@ -51,7 +51,7 @@
 HTMLEmbedElement* HTMLEmbedElement::Create(Document& document,
                                            bool created_by_parser) {
   HTMLEmbedElement* element = new HTMLEmbedElement(document, created_by_parser);
-  element->EnsureUserAgentShadowRootV1();
+  element->EnsureUserAgentShadowRoot();
   return element;
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
index e9c7942..c52669e9 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -789,7 +789,7 @@
   } else {
     if (layout_disposition_ == LayoutDisposition::kFallbackContent) {
       EventDispatchForbiddenScope::AllowUserAgentEvents allow_events;
-      EnsureUserAgentShadowRootV1();
+      EnsureUserAgentShadowRoot();
     }
     LazyReattachIfAttached();
   }
diff --git a/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp b/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp
index 309dd40..4dc07fc 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp
@@ -53,7 +53,7 @@
 }
 
 void HTMLImageFallbackHelper::CreateAltTextShadowTree(Element& element) {
-  ShadowRoot& root = element.EnsureUserAgentShadowRootV1();
+  ShadowRoot& root = element.EnsureUserAgentShadowRoot();
 
   HTMLSpanElement* container = HTMLSpanElement::Create(element.GetDocument());
   root.AppendChild(container);
diff --git a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
index 1eac5c8..16cac563 100644
--- a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
@@ -56,7 +56,7 @@
 
 HTMLMarqueeElement* HTMLMarqueeElement::Create(Document& document) {
   HTMLMarqueeElement* marquee_element = new HTMLMarqueeElement(document);
-  marquee_element->EnsureUserAgentShadowRootV1();
+  marquee_element->EnsureUserAgentShadowRoot();
   return marquee_element;
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLMeterElement.cpp b/third_party/WebKit/Source/core/html/HTMLMeterElement.cpp
index 6e80b5e61..9e2dc290 100644
--- a/third_party/WebKit/Source/core/html/HTMLMeterElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMeterElement.cpp
@@ -44,7 +44,7 @@
 
 HTMLMeterElement* HTMLMeterElement::Create(Document& document) {
   HTMLMeterElement* meter = new HTMLMeterElement(document);
-  meter->EnsureUserAgentShadowRootV1();
+  meter->EnsureUserAgentShadowRoot();
   return meter;
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
index 0112cc7..bf042d8 100644
--- a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
@@ -62,7 +62,7 @@
                                              bool created_by_parser) {
   HTMLObjectElement* element =
       new HTMLObjectElement(document, created_by_parser);
-  element->EnsureUserAgentShadowRootV1();
+  element->EnsureUserAgentShadowRoot();
   return element;
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLProgressElement.cpp b/third_party/WebKit/Source/core/html/HTMLProgressElement.cpp
index 9fa2407..fd5937a 100644
--- a/third_party/WebKit/Source/core/html/HTMLProgressElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLProgressElement.cpp
@@ -45,7 +45,7 @@
 
 HTMLProgressElement* HTMLProgressElement::Create(Document& document) {
   HTMLProgressElement* progress = new HTMLProgressElement(document);
-  progress->EnsureUserAgentShadowRootV1();
+  progress->EnsureUserAgentShadowRoot();
   return progress;
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp b/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp
index ca26303..c5dcb8c 100644
--- a/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSummaryElement.cpp
@@ -37,7 +37,7 @@
 
 HTMLSummaryElement* HTMLSummaryElement::Create(Document& document) {
   HTMLSummaryElement* summary = new HTMLSummaryElement(document);
-  summary->EnsureUserAgentShadowRootV1();
+  summary->EnsureUserAgentShadowRoot();
   return summary;
 }
 
@@ -70,7 +70,7 @@
 }
 
 Element* HTMLSummaryElement::MarkerControl() {
-  return EnsureUserAgentShadowRootV1().getElementById(
+  return EnsureUserAgentShadowRoot().getElementById(
       ShadowElementNames::DetailsMarker());
 }
 
diff --git a/third_party/WebKit/Source/core/html/ImageDocument.cpp b/third_party/WebKit/Source/core/html/ImageDocument.cpp
index f20e627d..57115b8 100644
--- a/third_party/WebKit/Source/core/html/ImageDocument.cpp
+++ b/third_party/WebKit/Source/core/html/ImageDocument.cpp
@@ -242,7 +242,7 @@
     HTMLSlotElement* slot = HTMLSlotElement::CreateUserAgentDefaultSlot(*this);
     div_element_->AppendChild(slot);
 
-    ShadowRoot& shadow_root = body->EnsureUserAgentShadowRootV1();
+    ShadowRoot& shadow_root = body->EnsureUserAgentShadowRoot();
     shadow_root.AppendChild(div_element_);
   } else {
     body->setAttribute(styleAttr, "margin: 0px;");
diff --git a/third_party/WebKit/Source/core/html/forms/BaseTextInputType.cpp b/third_party/WebKit/Source/core/html/forms/BaseTextInputType.cpp
index 4d3424f6..0e50dee8 100644
--- a/third_party/WebKit/Source/core/html/forms/BaseTextInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/BaseTextInputType.cpp
@@ -120,8 +120,4 @@
   return true;
 }
 
-bool BaseTextInputType::SupportsAutocapitalize() const {
-  return true;
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/BaseTextInputType.h b/third_party/WebKit/Source/core/html/forms/BaseTextInputType.h
index 72afc8b..4cbfe57 100644
--- a/third_party/WebKit/Source/core/html/forms/BaseTextInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/BaseTextInputType.h
@@ -54,7 +54,6 @@
   bool PatternMismatch(const String&) const final;
   bool SupportsPlaceholder() const final;
   bool SupportsSelectionAPI() const override;
-  bool SupportsAutocapitalize() const override;
 
   // m_regexp and m_patternForRegexp are mutable because they are kinds of
   // cache.
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLInputElement.cpp b/third_party/WebKit/Source/core/html/forms/HTMLInputElement.cpp
index 93abefc..8aa21dc 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLInputElement.cpp
+++ b/third_party/WebKit/Source/core/html/forms/HTMLInputElement.cpp
@@ -128,7 +128,7 @@
       new HTMLInputElement(document, created_by_parser);
   if (!created_by_parser) {
     DCHECK(input_element->input_type_view_->NeedsShadowSubtree());
-    input_element->CreateUserAgentShadowRootV1();
+    input_element->CreateUserAgentShadowRoot();
     input_element->CreateShadowSubtree();
   }
   return input_element;
@@ -381,7 +381,7 @@
   has_been_password_field_ |= new_type_name == InputTypeNames::password;
 
   if (input_type_view_->NeedsShadowSubtree()) {
-    CreateUserAgentShadowRootV1();
+    CreateUserAgentShadowRoot();
     CreateShadowSubtree();
   }
 
@@ -440,7 +440,7 @@
   input_type_ = new_type;
   input_type_view_ = input_type_->CreateView();
   if (input_type_view_->NeedsShadowSubtree()) {
-    EnsureUserAgentShadowRootV1();
+    EnsureUserAgentShadowRoot();
     CreateShadowSubtree();
   }
 
@@ -1725,14 +1725,6 @@
   return !SuggestedValue().IsEmpty() ? SuggestedValue() : StrippedPlaceholder();
 }
 
-bool HTMLInputElement::SupportsAutocapitalize() const {
-  return input_type_->SupportsAutocapitalize();
-}
-
-const AtomicString& HTMLInputElement::DefaultAutocapitalize() const {
-  return input_type_->DefaultAutocapitalize();
-}
-
 String HTMLInputElement::DefaultToolTip() const {
   return input_type_->DefaultToolTip(*input_type_view_);
 }
@@ -1957,7 +1949,7 @@
   // Some input types only need shadow roots to hide any children that may
   // have been appended by script. For such types, shadow roots are lazily
   // created when children are added for the first time.
-  EnsureUserAgentShadowRootV1();
+  EnsureUserAgentShadowRoot();
   ContainerNode::ChildrenChanged(change);
 }
 
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLInputElement.h b/third_party/WebKit/Source/core/html/forms/HTMLInputElement.h
index a88fdad..c945fa84 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLInputElement.h
+++ b/third_party/WebKit/Source/core/html/forms/HTMLInputElement.h
@@ -380,8 +380,6 @@
                             Element* old_focused_element,
                             WebFocusType,
                             InputDeviceCapabilities* source_capabilities) final;
-  bool SupportsAutocapitalize() const final;
-  const AtomicString& DefaultAutocapitalize() const final;
 
   bool IsOptionalFormControl() const final { return !IsRequiredFormControl(); }
   bool IsRequiredFormControl() const final;
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLInputElement.idl b/third_party/WebKit/Source/core/html/forms/HTMLInputElement.idl
index ed63dcb..7175841 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLInputElement.idl
+++ b/third_party/WebKit/Source/core/html/forms/HTMLInputElement.idl
@@ -99,10 +99,6 @@
     [CEReactions, Reflect] attribute DOMString align;
     [CEReactions, Reflect] attribute DOMString useMap;
 
-    // HTML autocapitalize proposal
-    // https://github.com/mounirlamouri/html-autocapitalize/blob/master/proposal.md
-    [Measure] attribute DOMString autocapitalize;
-
     // HTML Media Capture
     // https://w3c.github.io/html-media-capture/#the-capture-attribute
     [Measure, RuntimeEnabled=MediaCapture, Reflect] attribute DOMString capture;
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLOptGroupElement.cpp b/third_party/WebKit/Source/core/html/forms/HTMLOptGroupElement.cpp
index 83bf472..f7e4d22 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLOptGroupElement.cpp
+++ b/third_party/WebKit/Source/core/html/forms/HTMLOptGroupElement.cpp
@@ -51,7 +51,7 @@
 
 HTMLOptGroupElement* HTMLOptGroupElement::Create(Document& document) {
   HTMLOptGroupElement* opt_group_element = new HTMLOptGroupElement(document);
-  opt_group_element->EnsureUserAgentShadowRootV1();
+  opt_group_element->EnsureUserAgentShadowRoot();
   return opt_group_element;
 }
 
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLOptionElement.cpp b/third_party/WebKit/Source/core/html/forms/HTMLOptionElement.cpp
index 7e72639a..50e152e 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLOptionElement.cpp
+++ b/third_party/WebKit/Source/core/html/forms/HTMLOptionElement.cpp
@@ -58,7 +58,7 @@
 
 HTMLOptionElement* HTMLOptionElement::Create(Document& document) {
   HTMLOptionElement* option = new HTMLOptionElement(document);
-  option->EnsureUserAgentShadowRootV1();
+  option->EnsureUserAgentShadowRoot();
   return option;
 }
 
@@ -70,7 +70,7 @@
     bool selected,
     ExceptionState& exception_state) {
   HTMLOptionElement* element = new HTMLOptionElement(document);
-  element->EnsureUserAgentShadowRootV1();
+  element->EnsureUserAgentShadowRoot();
   if (!data.IsEmpty()) {
     element->AppendChild(Text::Create(document, data), exception_state);
     if (exception_state.HadException())
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.cpp
index 818b211..2ed2c37b 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.cpp
+++ b/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.cpp
@@ -100,7 +100,7 @@
 
 HTMLSelectElement* HTMLSelectElement::Create(Document& document) {
   HTMLSelectElement* select = new HTMLSelectElement(document);
-  select->EnsureUserAgentShadowRootV1();
+  select->EnsureUserAgentShadowRoot();
   return select;
 }
 
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.cpp b/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.cpp
index ac33d28..03115d3 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.cpp
+++ b/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.cpp
@@ -79,7 +79,7 @@
 
 HTMLTextAreaElement* HTMLTextAreaElement::Create(Document& document) {
   HTMLTextAreaElement* text_area = new HTMLTextAreaElement(document);
-  text_area->EnsureUserAgentShadowRootV1();
+  text_area->EnsureUserAgentShadowRoot();
   return text_area;
 }
 
@@ -623,11 +623,6 @@
   return true;
 }
 
-const AtomicString& HTMLTextAreaElement::DefaultAutocapitalize() const {
-  DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences"));
-  return sentences;
-}
-
 void HTMLTextAreaElement::CopyNonAttributePropertiesFromElement(
     const Element& source) {
   const HTMLTextAreaElement& source_element =
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.h b/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.h
index 356eb4d5d..9eb6be4 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.h
+++ b/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.h
@@ -89,8 +89,6 @@
   String GetPlaceholderValue() const final;
   void UpdatePlaceholderText() override;
   bool IsEmptyValue() const override { return value().IsEmpty(); }
-  bool SupportsAutocapitalize() const override { return true; }
-  const AtomicString& DefaultAutocapitalize() const override;
 
   bool IsOptionalFormControl() const override {
     return !IsRequiredFormControl();
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.idl b/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.idl
index 39421b2..9598eba 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.idl
+++ b/third_party/WebKit/Source/core/html/forms/HTMLTextAreaElement.idl
@@ -64,8 +64,4 @@
     void setSelectionRange(unsigned long start,
                            unsigned long end,
                            optional DOMString direction);
-
-    // HTML autocapitalize proposal
-    // https://github.com/mounirlamouri/html-autocapitalize/blob/master/proposal.md
-    [Measure] attribute DOMString autocapitalize;
 };
diff --git a/third_party/WebKit/Source/core/html/forms/InputType.cpp b/third_party/WebKit/Source/core/html/forms/InputType.cpp
index e4e4205..424a9f3 100644
--- a/third_party/WebKit/Source/core/html/forms/InputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/InputType.cpp
@@ -642,15 +642,6 @@
   return QualifiedName::Null();
 }
 
-bool InputType::SupportsAutocapitalize() const {
-  return false;
-}
-
-const AtomicString& InputType::DefaultAutocapitalize() const {
-  DEFINE_STATIC_LOCAL(const AtomicString, none, ("none"));
-  return none;
-}
-
 void InputType::CopyNonAttributeProperties(const HTMLInputElement&) {}
 
 void InputType::OnAttachWithLayoutObject() {}
diff --git a/third_party/WebKit/Source/core/html/forms/InputType.h b/third_party/WebKit/Source/core/html/forms/InputType.h
index 67679776..cc4c3b8 100644
--- a/third_party/WebKit/Source/core/html/forms/InputType.h
+++ b/third_party/WebKit/Source/core/html/forms/InputType.h
@@ -194,8 +194,6 @@
   virtual Decimal FindClosestTickMarkValue(const Decimal&);
   virtual bool HasLegalLinkAttribute(const QualifiedName&) const;
   virtual const QualifiedName& SubResourceAttributeName() const;
-  virtual bool SupportsAutocapitalize() const;
-  virtual const AtomicString& DefaultAutocapitalize() const;
   virtual void CopyNonAttributeProperties(const HTMLInputElement&);
   virtual void OnAttachWithLayoutObject();
   virtual void OnDetachWithLayoutObject();
diff --git a/third_party/WebKit/Source/core/html/forms/SearchInputType.cpp b/third_party/WebKit/Source/core/html/forms/SearchInputType.cpp
index b85e202..7780335 100644
--- a/third_party/WebKit/Source/core/html/forms/SearchInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/SearchInputType.cpp
@@ -148,11 +148,6 @@
   UpdateCancelButtonVisibility();
 }
 
-const AtomicString& SearchInputType::DefaultAutocapitalize() const {
-  DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences"));
-  return sentences;
-}
-
 void SearchInputType::UpdateCancelButtonVisibility() {
   Element* button = GetElement().UserAgentShadowRoot()->getElementById(
       ShadowElementNames::SearchClearButton());
diff --git a/third_party/WebKit/Source/core/html/forms/SearchInputType.h b/third_party/WebKit/Source/core/html/forms/SearchInputType.h
index e4f2cb8..2256f7e 100644
--- a/third_party/WebKit/Source/core/html/forms/SearchInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/SearchInputType.h
@@ -51,7 +51,6 @@
   void DidSetValueByUserEdit() override;
   bool SupportsInputModeAttribute() const override;
   void UpdateView() override;
-  const AtomicString& DefaultAutocapitalize() const override;
   void DispatchSearchEvent() override;
 
   void SearchEventTimerFired(TimerBase*);
diff --git a/third_party/WebKit/Source/core/html/forms/TextControlElement.cpp b/third_party/WebKit/Source/core/html/forms/TextControlElement.cpp
index 829b1076..14875e7 100644
--- a/third_party/WebKit/Source/core/html/forms/TextControlElement.cpp
+++ b/third_party/WebKit/Source/core/html/forms/TextControlElement.cpp
@@ -659,32 +659,6 @@
       .Build();
 }
 
-const AtomicString& TextControlElement::autocapitalize() const {
-  DEFINE_STATIC_LOCAL(const AtomicString, off, ("off"));
-  DEFINE_STATIC_LOCAL(const AtomicString, none, ("none"));
-  DEFINE_STATIC_LOCAL(const AtomicString, characters, ("characters"));
-  DEFINE_STATIC_LOCAL(const AtomicString, words, ("words"));
-  DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences"));
-
-  const AtomicString& value = FastGetAttribute(autocapitalizeAttr);
-  if (DeprecatedEqualIgnoringCase(value, none) ||
-      DeprecatedEqualIgnoringCase(value, off))
-    return none;
-  if (DeprecatedEqualIgnoringCase(value, characters))
-    return characters;
-  if (DeprecatedEqualIgnoringCase(value, words))
-    return words;
-  if (DeprecatedEqualIgnoringCase(value, sentences))
-    return sentences;
-
-  // Invalid or missing value.
-  return DefaultAutocapitalize();
-}
-
-void TextControlElement::setAutocapitalize(const AtomicString& autocapitalize) {
-  setAttribute(autocapitalizeAttr, autocapitalize);
-}
-
 int TextControlElement::maxLength() const {
   int value;
   if (!ParseHTMLInteger(FastGetAttribute(maxlengthAttr), value))
@@ -764,9 +738,6 @@
 
 void TextControlElement::ParseAttribute(
     const AttributeModificationParams& params) {
-  if (params.name == autocapitalizeAttr)
-    UseCounter::Count(GetDocument(), WebFeature::kAutocapitalizeAttribute);
-
   if (params.name == placeholderAttr) {
     UpdatePlaceholderText();
     UpdatePlaceholderVisibility();
diff --git a/third_party/WebKit/Source/core/html/forms/TextControlElement.h b/third_party/WebKit/Source/core/html/forms/TextControlElement.h
index 8b3a265..36f75be 100644
--- a/third_party/WebKit/Source/core/html/forms/TextControlElement.h
+++ b/third_party/WebKit/Source/core/html/forms/TextControlElement.h
@@ -102,11 +102,6 @@
       TextFieldSelectionDirection = kSelectionHasNoDirection);
   SelectionInDOMTree Selection() const;
 
-  virtual bool SupportsAutocapitalize() const = 0;
-  virtual const AtomicString& DefaultAutocapitalize() const = 0;
-  const AtomicString& autocapitalize() const;
-  void setAutocapitalize(const AtomicString&);
-
   int maxLength() const;
   int minLength() const;
   void setMaxLength(int, ExceptionState&);
diff --git a/third_party/WebKit/Source/core/html/forms/TextInputType.cpp b/third_party/WebKit/Source/core/html/forms/TextInputType.cpp
index 03702c1..58c0737 100644
--- a/third_party/WebKit/Source/core/html/forms/TextInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/TextInputType.cpp
@@ -61,9 +61,4 @@
   return true;
 }
 
-const AtomicString& TextInputType::DefaultAutocapitalize() const {
-  DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences"));
-  return sentences;
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/TextInputType.h b/third_party/WebKit/Source/core/html/forms/TextInputType.h
index d08f312..2537f82 100644
--- a/third_party/WebKit/Source/core/html/forms/TextInputType.h
+++ b/third_party/WebKit/Source/core/html/forms/TextInputType.h
@@ -44,7 +44,6 @@
   void CountUsage() override;
   const AtomicString& FormControlType() const override;
   bool SupportsInputModeAttribute() const override;
-  const AtomicString& DefaultAutocapitalize() const override;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/media/HTMLAudioElement.cpp b/third_party/WebKit/Source/core/html/media/HTMLAudioElement.cpp
index 84548c4..3b92d1e1 100644
--- a/third_party/WebKit/Source/core/html/media/HTMLAudioElement.cpp
+++ b/third_party/WebKit/Source/core/html/media/HTMLAudioElement.cpp
@@ -37,7 +37,7 @@
 
 HTMLAudioElement* HTMLAudioElement::Create(Document& document) {
   HTMLAudioElement* audio = new HTMLAudioElement(document);
-  audio->EnsureUserAgentShadowRootV1();
+  audio->EnsureUserAgentShadowRoot();
   audio->PauseIfNeeded();
   return audio;
 }
@@ -46,7 +46,7 @@
     Document& document,
     const AtomicString& src) {
   HTMLAudioElement* audio = new HTMLAudioElement(document);
-  audio->EnsureUserAgentShadowRootV1();
+  audio->EnsureUserAgentShadowRoot();
   audio->setPreload(AtomicString("auto"));
   if (!src.IsNull())
     audio->SetSrc(src);
diff --git a/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp
index f07f1e1..241d5d8 100644
--- a/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp
@@ -3639,7 +3639,7 @@
 }
 
 TextTrackContainer& HTMLMediaElement::EnsureTextTrackContainer() {
-  ShadowRoot& shadow_root = EnsureUserAgentShadowRootV1();
+  ShadowRoot& shadow_root = EnsureUserAgentShadowRoot();
   AssertShadowRootChildren(shadow_root);
 
   Node* first_child = shadow_root.firstChild();
@@ -3768,7 +3768,7 @@
   if (GetMediaControls())
     return;
 
-  ShadowRoot& shadow_root = EnsureUserAgentShadowRootV1();
+  ShadowRoot& shadow_root = EnsureUserAgentShadowRoot();
   media_controls_ =
       CoreInitializer::GetInstance().CreateMediaControls(*this, shadow_root);
 
diff --git a/third_party/WebKit/Source/core/html/media/HTMLVideoElement.cpp b/third_party/WebKit/Source/core/html/media/HTMLVideoElement.cpp
index ff797c2..97cebe9 100644
--- a/third_party/WebKit/Source/core/html/media/HTMLVideoElement.cpp
+++ b/third_party/WebKit/Source/core/html/media/HTMLVideoElement.cpp
@@ -83,7 +83,7 @@
 
 HTMLVideoElement* HTMLVideoElement::Create(Document& document) {
   HTMLVideoElement* video = new HTMLVideoElement(document);
-  video->EnsureUserAgentShadowRootV1();
+  video->EnsureUserAgentShadowRoot();
   video->PauseIfNeeded();
   return video;
 }
@@ -521,7 +521,7 @@
     const WebString& remote_device_friendly_name) {
   if (!remoting_interstitial_) {
     remoting_interstitial_ = new MediaRemotingInterstitial(*this);
-    ShadowRoot& shadow_root = EnsureUserAgentShadowRootV1();
+    ShadowRoot& shadow_root = EnsureUserAgentShadowRoot();
     shadow_root.InsertBefore(remoting_interstitial_, shadow_root.firstChild());
     HTMLMediaElement::AssertShadowRootChildren(shadow_root);
   }
@@ -537,7 +537,7 @@
 void HTMLVideoElement::PictureInPictureStarted() {
   if (!picture_in_picture_interstitial_) {
     picture_in_picture_interstitial_ = new PictureInPictureInterstitial(*this);
-    ShadowRoot& shadow_root = EnsureUserAgentShadowRootV1();
+    ShadowRoot& shadow_root = EnsureUserAgentShadowRoot();
     shadow_root.InsertBefore(picture_in_picture_interstitial_,
                              shadow_root.firstChild());
     HTMLMediaElement::AssertShadowRootChildren(shadow_root);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
index 8caa621..0822f86 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -1386,7 +1386,7 @@
 static protocol::DOM::ShadowRootType GetShadowRootType(
     ShadowRoot* shadow_root) {
   switch (shadow_root->GetType()) {
-    case ShadowRootType::kUserAgentV1:
+    case ShadowRootType::kUserAgent:
       return protocol::DOM::ShadowRootTypeEnum::UserAgent;
     case ShadowRootType::V0:
     case ShadowRootType::kOpen:
@@ -2199,6 +2199,23 @@
   return Response::OK();
 }
 
+protocol::Response InspectorDOMAgent::getFrameOwner(const String& frame_id,
+                                                    int* node_id) {
+  Frame* frame = inspected_frames_->Root();
+  for (; frame; frame = frame->Tree().TraverseNext(inspected_frames_->Root())) {
+    if (frame->GetDevToolsFrameToken() == frame_id)
+      break;
+  }
+  if (!frame || !frame->Owner()->IsLocal())
+    return Response::Error("Frame with given id does not belong to target.");
+  HTMLFrameOwnerElement* frame_owner = ToHTMLFrameOwnerElement(frame->Owner());
+  if (!frame_owner)
+    return Response::Error("No iframe owner for given node");
+  *node_id =
+      PushNodePathToFrontend(frame_owner, document_node_to_id_map_.Get());
+  return Response::OK();
+}
+
 Response InspectorDOMAgent::PushDocumentUponHandlelessOperation() {
   if (!document_node_to_id_map_->Contains(document_)) {
     std::unique_ptr<protocol::DOM::Node> root;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
index 307733e4..cc22048 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
@@ -204,6 +204,9 @@
       protocol::Maybe<bool> pierce,
       std::unique_ptr<protocol::DOM::Node>*) override;
 
+  protocol::Response getFrameOwner(const String& frame_id,
+                                   int* node_id) override;
+
   bool Enabled() const;
   void ReleaseDanglingNodes();
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.cpp
index 2fd5a1f..b425d02 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.cpp
@@ -30,12 +30,21 @@
 
 #include "core/inspector/InspectorMemoryAgent.h"
 
+#include "base/debug/stack_trace.h"
 #include "core/frame/LocalFrameClient.h"
 #include "core/inspector/InspectedFrames.h"
 #include "platform/InstanceCounters.h"
+#include "platform/memory_profiler/SamplingNativeHeapProfiler.h"
 
 namespace blink {
 
+const unsigned kDefaultNativeMemorySamplingInterval = 128 * 1024;
+
+namespace MemoryAgentState {
+static const char samplingProfileInterval[] =
+    "memoryAgentSamplingProfileInterval";
+}  // namespace MemoryAgentState
+
 using PrepareForLeakDetectionCallback =
     protocol::Memory::Backend::PrepareForLeakDetectionCallback;
 using protocol::Response;
@@ -76,4 +85,87 @@
   InspectorBaseAgent::Trace(visitor);
 }
 
+void InspectorMemoryAgent::Restore() {
+  int sampling_interval = 0;
+  state_->getInteger(MemoryAgentState::samplingProfileInterval,
+                     &sampling_interval);
+  // The action below won't start sampling if the sampling_interval is zero.
+  startSampling(protocol::Maybe<int>(sampling_interval),
+                protocol::Maybe<bool>());
+}
+
+Response InspectorMemoryAgent::startSampling(
+    protocol::Maybe<int> in_sampling_interval,
+    protocol::Maybe<bool> in_suppressRandomness) {
+  int interval =
+      in_sampling_interval.fromMaybe(kDefaultNativeMemorySamplingInterval);
+  if (interval <= 0)
+    return Response::Error("Invalid sampling rate.");
+  SamplingNativeHeapProfiler::GetInstance()->SetSamplingInterval(interval);
+  state_->setInteger(MemoryAgentState::samplingProfileInterval, interval);
+  if (in_suppressRandomness.fromMaybe(false))
+    SamplingNativeHeapProfiler::GetInstance()->SuppressRandomnessForTest();
+  SamplingNativeHeapProfiler::GetInstance()->Start();
+  return Response::OK();
+}
+
+Response InspectorMemoryAgent::stopSampling() {
+  int sampling_interval = 0;
+  state_->getInteger(MemoryAgentState::samplingProfileInterval,
+                     &sampling_interval);
+  if (!sampling_interval)
+    return Response::Error("Sampling profiler is not started.");
+  SamplingNativeHeapProfiler::GetInstance()->Stop();
+  state_->setInteger(MemoryAgentState::samplingProfileInterval, 0);
+  return Response::OK();
+}
+
+Response InspectorMemoryAgent::getSamplingProfile(
+    std::unique_ptr<protocol::Memory::SamplingProfile>* out_profile) {
+  std::unique_ptr<protocol::Array<protocol::Memory::SamplingProfileNode>>
+      samples =
+          protocol::Array<protocol::Memory::SamplingProfileNode>::create();
+  std::vector<SamplingNativeHeapProfiler::Sample> raw_samples =
+      SamplingNativeHeapProfiler::GetInstance()->GetSamples();
+  // TODO(alph): Only report samples recorded within the current session.
+  for (auto it = raw_samples.begin(); it != raw_samples.end(); ++it) {
+    std::unique_ptr<protocol::Array<protocol::String>> stack =
+        protocol::Array<protocol::String>::create();
+    std::vector<std::string> source_stack = Symbolize(it->stack);
+    for (auto it2 = source_stack.begin(); it2 != source_stack.end(); ++it2)
+      stack->addItem(it2->c_str());
+    samples->addItem(protocol::Memory::SamplingProfileNode::create()
+                         .setSize(it->size)
+                         .setCount(it->count)
+                         .setStack(std::move(stack))
+                         .build());
+  }
+  std::unique_ptr<protocol::Memory::SamplingProfile> result =
+      protocol::Memory::SamplingProfile::create()
+          .setSamples(std::move(samples))
+          .build();
+  *out_profile = std::move(result);
+  return Response::OK();
+}
+
+std::vector<std::string> InspectorMemoryAgent::Symbolize(
+    const std::vector<void*>& addresses) {
+  // TODO(alph): Move symbolization to the client.
+  std::vector<std::string> result;
+  base::debug::StackTrace trace(addresses.data(), addresses.size());
+  std::string text = trace.ToString();
+
+  size_t next_pos;
+  for (size_t pos = 0;; pos = next_pos + 1) {
+    next_pos = text.find('\n', pos);
+    if (next_pos == std::string::npos)
+      break;
+    std::string line = text.substr(pos, next_pos - pos);
+    size_t space_pos = line.rfind(' ');
+    result.push_back(
+        line.substr(space_pos == std::string::npos ? 0 : space_pos + 1));
+  }
+  return result;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.h b/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.h
index 2c953846..8f88c04a 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorMemoryAgent.h
@@ -52,6 +52,7 @@
   ~InspectorMemoryAgent() override;
 
   void Trace(blink::Visitor*) override;
+  void Restore() override;
 
   protocol::Response getDOMCounters(int* documents,
                                     int* nodes,
@@ -62,11 +63,24 @@
   // BlinkLeakDetectorClient:
   void OnLeakDetectionComplete() override;
 
+  // Memory protocol domain:
+  protocol::Response startSampling(
+      protocol::Maybe<int> in_samplingInterval,
+      protocol::Maybe<bool> in_suppressRandomness) override;
+  protocol::Response stopSampling() override;
+  protocol::Response getSamplingProfile(
+      std::unique_ptr<protocol::Memory::SamplingProfile>*) override;
+
  private:
   explicit InspectorMemoryAgent(InspectedFrames*);
+
+  std::vector<std::string> Symbolize(const std::vector<void*>& addresses);
+
   std::unique_ptr<BlinkLeakDetector> detector_;
   std::unique_ptr<PrepareForLeakDetectionCallback> callback_;
   Member<InspectedFrames> frames_;
+  std::map<void*, std::string> symbols_cache_;
+
   DISALLOW_COPY_AND_ASSIGN(InspectorMemoryAgent);
 };
 
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json
index b4f0f4e..a19cf00 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.json
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -3686,6 +3686,23 @@
                     "name": "undo",
                     "description": "Undoes the last performed action.",
                     "experimental": true
+                },
+                {
+                    "name": "getFrameOwner",
+                    "description": "Returns iframe node that owns iframe with the given domain.",
+                    "experimental": true,
+                    "parameters": [
+                        {
+                            "name": "frameId",
+                            "$ref": "Page.FrameId"
+                        }
+                    ],
+                    "returns": [
+                        {
+                            "name": "nodeId",
+                            "$ref": "NodeId"
+                        }
+                    ]
                 }
             ],
             "events": [
@@ -6869,6 +6886,45 @@
                         "moderate",
                         "critical"
                     ]
+                },
+                {
+                    "id": "SamplingProfileNode",
+                    "description": "Heap profile sample.",
+                    "type": "object",
+                    "properties": [
+                        {
+                            "name": "size",
+                            "description": "Size of the sampled allocation.",
+                            "type": "number"
+                        },
+                        {
+                            "name": "count",
+                            "description": "Number of sampled allocations of that size.",
+                            "type": "number"
+                        },
+                        {
+                            "name": "stack",
+                            "description": "Execution stack at the point of allocation.",
+                            "type": "array",
+                            "items": {
+                                "type": "string"
+                            }
+                        }
+                    ]
+                },
+                {
+                    "id": "SamplingProfile",
+                    "description": "Array of heap profile samples.",
+                    "type": "object",
+                    "properties": [
+                        {
+                            "name": "samples",
+                            "type": "array",
+                            "items": {
+                                "$ref": "SamplingProfileNode"
+                            }
+                        }
+                    ]
                 }
             ],
             "commands": [
@@ -6913,6 +6969,38 @@
                             "$ref": "PressureLevel"
                         }
                     ]
+                },
+                {
+                    "name": "startSampling",
+                    "description": "Start collecting native memory profile.",
+                    "parameters": [
+                        {
+                            "name": "samplingInterval",
+                            "description": "Average number of bytes between samples.",
+                            "optional": true,
+                            "type": "integer"
+                        },
+                        {
+                            "name": "suppressRandomness",
+                            "description": "Do not randomize intervals between samples.",
+                            "optional": true,
+                            "type": "boolean"
+                        }
+                    ]
+                },
+                {
+                    "name": "stopSampling",
+                    "description": "Stop collecting native memory profile."
+                },
+                {
+                    "name": "getSamplingProfile",
+                    "description": "Retrieve collected native memory profile.",
+                    "returns": [
+                        {
+                            "name": "profile",
+                            "$ref": "SamplingProfile"
+                        }
+                    ]
                 }
             ]
         },
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.pdl b/third_party/WebKit/Source/core/inspector/browser_protocol.pdl
index f5714ff..2ce44ef 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.pdl
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.pdl
@@ -1694,6 +1694,13 @@
   # Undoes the last performed action.
   experimental command undo
 
+  # Returns iframe node that owns iframe with the given domain.
+  experimental command getFrameOwner
+    parameters
+      Page.FrameId frameId
+    returns
+      NodeId nodeId
+
   # Fired when `Element`'s attribute is modified.
   event attributeModified
     parameters
@@ -3144,6 +3151,37 @@
       # Memory pressure level of the notification.
       PressureLevel level
 
+  # Start collecting native memory profile.
+  command startSampling
+    parameters
+      # Average number of bytes between samples.
+      optional integer samplingInterval
+      # Do not randomize intervals between samples.
+      optional boolean suppressRandomness
+
+  # Stop collecting native memory profile.
+  command stopSampling
+
+  # Retrieve collected native memory profile.
+  command getSamplingProfile
+    returns
+      SamplingProfile profile
+
+  # Heap profile sample.
+  type SamplingProfileNode extends object
+    properties
+      # Size of the sampled allocation.
+      number size
+      # Number of sampled allocations of that size.
+      number count
+      # Execution stack at the point of allocation.
+      array of string stack
+
+  # Array of heap profile samples.
+  type SamplingProfile extends object
+    properties
+      array of SamplingProfileNode samples
+
 # Network domain allows tracking network activities of the page. It exposes information about http,
 # file, data and other requests and responses, their headers, bodies, timing, etc.
 domain Network
diff --git a/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json b/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json
index 7cc7e78..0a1aa05 100644
--- a/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json
+++ b/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json
@@ -69,7 +69,7 @@
             },
             {
                 "domain": "Memory",
-                "include": ["getDOMCounters", "prepareForLeakDetection"],
+                "include": ["getDOMCounters", "prepareForLeakDetection", "startSampling", "stopSampling", "getSamplingProfile"],
                 "async": ["prepareForLeakDetection"]
             },
             {
diff --git a/third_party/WebKit/Source/core/paint/BlockPainter.cpp b/third_party/WebKit/Source/core/paint/BlockPainter.cpp
index 2af0541..1278970f7 100644
--- a/third_party/WebKit/Source/core/paint/BlockPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/BlockPainter.cpp
@@ -96,9 +96,8 @@
                             PixelSnappedIntRect(clip_rect));
     }
     ScrollableAreaPainter(*layout_block_.Layer()->GetScrollableArea())
-        .PaintOverflowControls(
-            paint_info.context, RoundedIntPoint(paint_offset),
-            paint_info.GetCullRect(), false /* paintingOverlayControls */);
+        .PaintOverflowControls(paint_info, RoundedIntPoint(paint_offset),
+                               false /* painting_overlay_controls */);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h b/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h
index c11df04e..51a8f96 100644
--- a/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h
+++ b/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h
@@ -178,6 +178,9 @@
                                 original_properties_->CssClipFixedPosition(),
                                 object_properties->CssClipFixedPosition());
       DCHECK_OBJECT_PROPERTY_EQ(object_,
+                                original_properties_->OverflowControlsClip(),
+                                object_properties->OverflowControlsClip());
+      DCHECK_OBJECT_PROPERTY_EQ(object_,
                                 original_properties_->InnerBorderRadiusClip(),
                                 object_properties->InnerBorderRadiusClip());
       DCHECK_OBJECT_PROPERTY_EQ(object_, original_properties_->OverflowClip(),
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
index 8f2b0e5..05974a97 100644
--- a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
+++ b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
@@ -103,6 +103,9 @@
   //     |   Clip created by CSS clip. CSS clip applies to all descendants, this
   //     |   node only applies to containing block descendants. For descendants
   //     |   not contained by this object, use [ css clip fixed position ].
+  //     +-[ overflow controls clip ]
+  //     |   Clip created by overflow clip to clip overflow controls
+  //     |   (scrollbars, resizer, scroll corner) that would overflow the box.
   //     +-[ inner border radius clip]
   //       |   Clip created by a rounded border with overflow clip. This clip is
   //       |   not inset by scrollbars.
@@ -119,6 +122,9 @@
   const ClipPaintPropertyNode* CssClipFixedPosition() const {
     return css_clip_fixed_position_.get();
   }
+  const ClipPaintPropertyNode* OverflowControlsClip() const {
+    return overflow_controls_clip_.get();
+  }
   const ClipPaintPropertyNode* InnerBorderRadiusClip() const {
     return inner_border_radius_clip_.get();
   }
@@ -141,6 +147,7 @@
   bool ClearMaskClip() { return Clear(mask_clip_); }
   bool ClearCssClip() { return Clear(css_clip_); }
   bool ClearCssClipFixedPosition() { return Clear(css_clip_fixed_position_); }
+  bool ClearOverflowControlsClip() { return Clear(overflow_controls_clip_); }
   bool ClearInnerBorderRadiusClip() { return Clear(inner_border_radius_clip_); }
   bool ClearOverflowClip() { return Clear(overflow_clip_); }
   bool ClearPerspective() { return Clear(perspective_); }
@@ -222,6 +229,10 @@
     return Update(css_clip_fixed_position_, std::forward<Args>(args)...);
   }
   template <typename... Args>
+  UpdateResult UpdateOverflowControlsClip(Args&&... args) {
+    return Update(overflow_controls_clip_, std::forward<Args>(args)...);
+  }
+  template <typename... Args>
   UpdateResult UpdateInnerBorderRadiusClip(Args&&... args) {
     return Update(inner_border_radius_clip_, std::forward<Args>(args)...);
   }
@@ -252,6 +263,8 @@
       cloned->css_clip_ = css_clip_->Clone();
     if (css_clip_fixed_position_)
       cloned->css_clip_fixed_position_ = css_clip_fixed_position_->Clone();
+    if (overflow_controls_clip_)
+      cloned->overflow_controls_clip_ = overflow_controls_clip_->Clone();
     if (inner_border_radius_clip_)
       cloned->inner_border_radius_clip_ = inner_border_radius_clip_->Clone();
     if (overflow_clip_)
@@ -310,6 +323,7 @@
   scoped_refptr<ClipPaintPropertyNode> mask_clip_;
   scoped_refptr<ClipPaintPropertyNode> css_clip_;
   scoped_refptr<ClipPaintPropertyNode> css_clip_fixed_position_;
+  scoped_refptr<ClipPaintPropertyNode> overflow_controls_clip_;
   scoped_refptr<ClipPaintPropertyNode> inner_border_radius_clip_;
   scoped_refptr<ClipPaintPropertyNode> overflow_clip_;
   scoped_refptr<TransformPaintPropertyNode> perspective_;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
index a4ccb3e..e6b1031 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -563,9 +563,14 @@
 
   bool selection_only =
       local_painting_info.GetGlobalPaintFlags() & kGlobalPaintSelectionOnly;
+
   {  // Begin block for the lifetime of any filter.
+    size_t display_item_list_size_before_painting =
+        context.GetPaintController().NewDisplayItemList().size();
+
     Optional<FilterPainter> filter_painter;
     if (image_filter) {
+      DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
       // Compute clips outside the filter (#3, see above for discussion).
       PaintLayerFragments filter_fragments;
       paint_layer_.AppendSingleFragmentIgnoringPagination(
@@ -579,6 +584,8 @@
                                  ? ClipRect()
                                  : filter_fragments[0].background_rect,
                              local_painting_info, paint_flags);
+    } else if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
+               paint_layer_.PaintsWithFilters()) {
     }
 
     bool is_painting_root_layer = (&paint_layer_) == painting_info.root_layer;
@@ -628,6 +635,15 @@
       PaintOverflowControlsForFragments(layer_fragments, context,
                                         local_painting_info, paint_flags);
     }
+
+    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
+        !is_painting_overlay_scrollbars && paint_layer_.PaintsWithFilters() &&
+        display_item_list_size_before_painting ==
+            context.GetPaintController().NewDisplayItemList().size()) {
+      // If a layer with filters painted nothing, we need to issue a no-op
+      // display item to ensure the filters won't be ignored.
+      PaintEmptyContentForFilters(context);
+    }
   }  // FilterPainter block
 
   bool should_paint_mask =
@@ -955,7 +971,7 @@
 void PaintLayerPainter::PaintOverflowControlsForFragments(
     const PaintLayerFragments& layer_fragments,
     GraphicsContext& context,
-    const PaintLayerPaintingInfo& local_painting_info,
+    const PaintLayerPaintingInfo& painting_info,
     PaintLayerFlags paint_flags) {
   PaintLayerScrollableArea* scrollable_area = paint_layer_.GetScrollableArea();
   if (!scrollable_area)
@@ -979,32 +995,38 @@
         LayoutRect cull_rect = fragment.background_rect.Rect();
 
         Optional<LayerClipRecorder> clip_recorder;
-        if (NeedsToClip(local_painting_info, fragment.background_rect,
-                        paint_flags, paint_layer_.GetLayoutObject())) {
+        if (NeedsToClip(painting_info, fragment.background_rect, paint_flags,
+                        paint_layer_.GetLayoutObject())) {
           clip_recorder.emplace(
               context, paint_layer_, DisplayItem::kClipLayerOverflowControls,
-              fragment.background_rect, local_painting_info.root_layer,
+              fragment.background_rect, painting_info.root_layer,
               fragment.pagination_offset, paint_flags,
               paint_layer_.GetLayoutObject());
         }
 
         Optional<ScrollRecorder> scroll_recorder;
         if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
-            !local_painting_info.scroll_offset_accumulation.IsZero()) {
-          cull_rect.Move(local_painting_info.scroll_offset_accumulation);
-          scroll_recorder.emplace(
-              context, paint_layer_.GetLayoutObject(),
-              DisplayItem::kScrollOverflowControls,
-              local_painting_info.scroll_offset_accumulation);
+            !painting_info.scroll_offset_accumulation.IsZero()) {
+          cull_rect.Move(painting_info.scroll_offset_accumulation);
+          scroll_recorder.emplace(context, paint_layer_.GetLayoutObject(),
+                                  DisplayItem::kScrollOverflowControls,
+                                  painting_info.scroll_offset_accumulation);
         }
 
+        PaintInfo paint_info(
+            context, PixelSnappedIntRect(cull_rect),
+            PaintPhase::kSelfBlockBackgroundOnly,
+            painting_info.GetGlobalPaintFlags(), paint_flags,
+            &painting_info.root_layer->GetLayoutObject(),
+            fragment.fragment_data
+                ? fragment.fragment_data->LogicalTopInFlowThread()
+                : LayoutUnit());
         // We pass IntPoint() as the paint offset here, because
         // ScrollableArea::paintOverflowControls just ignores it and uses the
         // offset found in a previous pass.
-        CullRect snapped_cull_rect(PixelSnappedIntRect(cull_rect));
         ScrollableAreaPainter(*scrollable_area)
-            .PaintOverflowControls(context, IntPoint(), snapped_cull_rect,
-                                   true);
+            .PaintOverflowControls(paint_info, IntPoint(),
+                                   true /* painting_overlay_controls */);
       });
 }
 
@@ -1358,4 +1380,23 @@
   context.FillRect(snapped_clip_rect, Color::kBlack);
 }
 
+// Generate a no-op DrawingDisplayItem to ensure a non-empty chunk for the
+// filter without content.
+void PaintLayerPainter::PaintEmptyContentForFilters(GraphicsContext& context) {
+  DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
+  DCHECK(paint_layer_.PaintsWithFilters());
+
+  ScopedPaintChunkProperties paint_chunk_properties(
+      context.GetPaintController(),
+      *paint_layer_.GetLayoutObject()
+           .FirstFragment()
+           .LocalBorderBoxProperties(),
+      paint_layer_, DisplayItem::kEmptyContentForFilters);
+  if (DrawingRecorder::UseCachedDrawingIfPossible(
+          context, paint_layer_, DisplayItem::kEmptyContentForFilters))
+    return;
+  DrawingRecorder recorder(context, paint_layer_,
+                           DisplayItem::kEmptyContentForFilters);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
index 07b3afb..f1842af 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
@@ -140,6 +140,8 @@
                            const ClipRect&,
                            const DisplayItemClient&);
 
+  void PaintEmptyContentForFilters(GraphicsContext&);
+
   static bool NeedsToClip(const PaintLayerPaintingInfo& local_painting_info,
                           const ClipRect&,
                           const PaintLayerFlags&,
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index 307dcd5..bb13fbe 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -303,6 +303,7 @@
   ALWAYS_INLINE void UpdateFragmentClip(const PaintLayer&);
   ALWAYS_INLINE void UpdateCssClip();
   ALWAYS_INLINE void UpdateLocalBorderBoxContext();
+  ALWAYS_INLINE void UpdateOverflowControlsClip();
   ALWAYS_INLINE void UpdateInnerBorderRadiusClip();
   ALWAYS_INLINE void UpdateOverflowClip();
   ALWAYS_INLINE void UpdatePerspective();
@@ -974,6 +975,22 @@
           NeedsFrameContentClip(*ToLayoutView(object).GetFrame()));
 }
 
+static bool NeedsOverflowControlsClip(const LayoutObject& object) {
+  if (!object.HasOverflowClip())
+    return false;
+
+  const auto& box = ToLayoutBox(object);
+  const auto* scrollable_area = box.GetScrollableArea();
+  IntRect scroll_controls_bounds =
+      scrollable_area->ScrollCornerAndResizerRect();
+  if (const auto* scrollbar = scrollable_area->HorizontalScrollbar())
+    scroll_controls_bounds.Unite(scrollbar->FrameRect());
+  if (const auto* scrollbar = scrollable_area->VerticalScrollbar())
+    scroll_controls_bounds.Unite(scrollbar->FrameRect());
+  IntRect conservative_border_box_rect(IntPoint(), FlooredIntSize(box.Size()));
+  return !conservative_border_box_rect.Contains(scroll_controls_bounds);
+}
+
 static bool NeedsInnerBorderRadiusClip(const LayoutObject& object) {
   if (!object.StyleRef().HasBorderRadius())
     return false;
@@ -1010,6 +1027,29 @@
   return result;
 }
 
+void FragmentPaintPropertyTreeBuilder::UpdateOverflowControlsClip() {
+  DCHECK(properties_);
+
+  if (!object_.NeedsPaintPropertyUpdate() &&
+      !full_context_.force_subtree_update)
+    return;
+
+  if (NeedsOverflowControlsClip(object_)) {
+    // Clip overflow controls to the border box rect.
+    properties_->UpdateOverflowControlsClip(
+        context_.current.clip, context_.current.transform,
+        FloatRoundedRect(FloatRect(LayoutRect(context_.current.paint_offset,
+                                              ToLayoutBox(object_).Size()))));
+  } else {
+    properties_->ClearOverflowControlsClip();
+  }
+
+  // No need to set force_subtree_update and clip_changed because
+  // OverflowControlsClip applies to overflow controls only, not descendants.
+  // We also don't walk into custom scrollbars in PrePaintTreeWalk and
+  // LayoutObjects under custom scrollbars don't support paint properties.
+}
+
 void FragmentPaintPropertyTreeBuilder::UpdateInnerBorderRadiusClip() {
   DCHECK(properties_);
 
@@ -1682,6 +1722,7 @@
     if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
       UpdateEffect();
     UpdateFilter();
+    UpdateOverflowControlsClip();
   }
   UpdateLocalBorderBoxContext();
 }
@@ -1942,7 +1983,8 @@
       NeedsInnerBorderRadiusClip(object_) || NeedsOverflowClip(object_) ||
       NeedsPerspective(object_) || NeedsSVGLocalToBorderBoxTransform(object_) ||
       NeedsScrollOrScrollTranslation(object_) ||
-      NeedsFragmentationClip(object_, *context_.painting_layer);
+      NeedsFragmentationClip(object_, *context_.painting_layer) ||
+      NeedsOverflowControlsClip(object_);
 
   if (!NeedsFragmentation(object_, *context_.painting_layer)) {
     InitSingleFragmentFromParent(needs_paint_properties);
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index 56f9703..639cb3e 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -4877,4 +4877,21 @@
   }
 }
 
+TEST_P(PaintPropertyTreeBuilderTest, OverflowControlsClip) {
+  SetBodyInnerHTML(R"HTML(
+    <style>::-webkit-scrollbar { width: 20px }</style>
+    <div id='div1' style='overflow: scroll; width: 5px; height: 50px'></div>
+    <div id='div2' style='overflow: scroll; width: 50px; height: 50px'></div>
+  )HTML");
+
+  const auto* properties1 = PaintPropertiesForElement("div1");
+  ASSERT_NE(nullptr, properties1);
+  const auto* overflow_controls_clip = properties1->OverflowControlsClip();
+  EXPECT_EQ(FloatRect(0, 0, 5, 50), overflow_controls_clip->ClipRect().Rect());
+
+  const auto* properties2 = PaintPropertiesForElement("div2");
+  ASSERT_NE(nullptr, properties2);
+  EXPECT_EQ(nullptr, properties2->OverflowControlsClip());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinter.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinter.cpp
index 44d187e..c0842526 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinter.cpp
@@ -177,6 +177,8 @@
       printer.AddPropertyNode(c, "CssClip", object);
     if (const auto* c = properties.CssClipFixedPosition())
       printer.AddPropertyNode(c, "CssClipFixedPosition", object);
+    if (const auto* c = properties.OverflowControlsClip())
+      printer.AddPropertyNode(c, "OverflowControlsClip", object);
     if (const auto* c = properties.InnerBorderRadiusClip())
       printer.AddPropertyNode(c, "InnerBorderRadiusClip", object);
     if (const auto* c = properties.OverflowClip())
diff --git a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp
index c03b265..59976722 100644
--- a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp
@@ -18,6 +18,7 @@
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/graphics/paint/ClipRecorder.h"
 #include "platform/graphics/paint/DrawingRecorder.h"
+#include "platform/graphics/paint/ScopedPaintChunkProperties.h"
 
 namespace blink {
 
@@ -122,9 +123,8 @@
 }
 
 void ScrollableAreaPainter::PaintOverflowControls(
-    GraphicsContext& context,
+    const PaintInfo& paint_info,
     const IntPoint& paint_offset,
-    const CullRect& cull_rect,
     bool painting_overlay_controls) {
   // Don't do anything if we have no overflow.
   if (!GetScrollableArea().GetLayoutBox()->HasOverflowClip())
@@ -134,7 +134,7 @@
   if (painting_overlay_controls)
     adjusted_paint_offset = GetScrollableArea().CachedOverlayScrollbarOffset();
 
-  CullRect adjusted_cull_rect(cull_rect, -adjusted_paint_offset);
+  CullRect adjusted_cull_rect(paint_info.GetCullRect(), -adjusted_paint_offset);
   // Overlay scrollbars paint in a second pass through the layer tree so that
   // they will paint on top of everything else. If this is the normal painting
   // pass, paintingOverlayControls will be false, and we should just tell the
@@ -171,11 +171,27 @@
   if (painting_overlay_controls && !GetScrollableArea().HasOverlayScrollbars())
     return;
 
-  IntRect clip_rect(adjusted_paint_offset,
-                    GetScrollableArea().Layer()->PixelSnappedSize());
-  ClipRecorder clip_recorder(context, *GetScrollableArea().GetLayoutBox(),
-                             DisplayItem::kClipLayerOverflowControls,
-                             clip_rect);
+  GraphicsContext& context = paint_info.context;
+
+  Optional<ClipRecorder> clip_recorder;
+  Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
+  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+    const auto& box = *GetScrollableArea().GetLayoutBox();
+    if (const auto* fragment = paint_info.FragmentToPaint(box)) {
+      const auto* properties = fragment->PaintProperties();
+      DCHECK(properties);
+      if (const auto* clip = properties->OverflowControlsClip()) {
+        scoped_paint_chunk_properties.emplace(
+            context.GetPaintController(), clip, box,
+            DisplayItem::kClipLayerOverflowControls);
+      }
+    }
+  } else {
+    IntRect clip_rect(adjusted_paint_offset,
+                      GetScrollableArea().Layer()->PixelSnappedSize());
+    clip_recorder.emplace(context, *GetScrollableArea().GetLayoutBox(),
+                          DisplayItem::kClipLayerOverflowControls, clip_rect);
+  }
 
   if (GetScrollableArea().HorizontalScrollbar() &&
       !GetScrollableArea().LayerForHorizontalScrollbar()) {
@@ -197,10 +213,10 @@
   if (!GetScrollableArea().LayerForScrollCorner()) {
     // We fill our scroll corner with white if we have a scrollbar that doesn't
     // run all the way up to the edge of the box.
-    PaintScrollCorner(context, adjusted_paint_offset, cull_rect);
+    PaintScrollCorner(context, adjusted_paint_offset, paint_info.GetCullRect());
 
     // Paint our resizer last, since it sits on top of the scroll corner.
-    PaintResizer(context, adjusted_paint_offset, cull_rect);
+    PaintResizer(context, adjusted_paint_offset, paint_info.GetCullRect());
   }
 }
 
diff --git a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.h b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.h
index f0a71230..6f0b93c2 100644
--- a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.h
+++ b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.h
@@ -15,6 +15,7 @@
 class GraphicsContext;
 class IntPoint;
 class IntRect;
+struct PaintInfo;
 class PaintLayerScrollableArea;
 
 class ScrollableAreaPainter {
@@ -25,13 +26,13 @@
       PaintLayerScrollableArea& paint_layer_scrollable_area)
       : scrollable_area_(&paint_layer_scrollable_area) {}
 
+  void PaintOverflowControls(const PaintInfo&,
+                             const IntPoint& paint_offset,
+                             bool painting_overlay_controls);
+
   void PaintResizer(GraphicsContext&,
                     const IntPoint& paint_offset,
                     const CullRect&);
-  void PaintOverflowControls(GraphicsContext&,
-                             const IntPoint& paint_offset,
-                             const CullRect&,
-                             bool painting_overlay_controls);
   void PaintScrollCorner(GraphicsContext&,
                          const IntPoint& paint_offset,
                          const CullRect&);
diff --git a/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc b/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc
index 0f0edad..c92e6520 100644
--- a/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc
@@ -547,9 +547,8 @@
                               PixelSnappedIntRect(clip_rect));
       }
       ScrollableAreaPainter(*layout_block->Layer()->GetScrollableArea())
-          .PaintOverflowControls(
-              paint_info.context, RoundedIntPoint(paint_offset),
-              paint_info.GetCullRect(), false /* paintingOverlayControls */);
+          .PaintOverflowControls(paint_info, RoundedIntPoint(paint_offset),
+                                 false /* painting_overlay_controls */);
     }
   }
 }
diff --git a/third_party/WebKit/Source/core/svg/SVGCircleElement.cpp b/third_party/WebKit/Source/core/svg/SVGCircleElement.cpp
index 376621ab..f30b777 100644
--- a/third_party/WebKit/Source/core/svg/SVGCircleElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGCircleElement.cpp
@@ -80,13 +80,13 @@
   SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
   if (property == cx_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &cx_->CssValue());
+                                            cx_->CssValue());
   } else if (property == cy_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &cy_->CssValue());
+                                            cy_->CssValue());
   } else if (property == r_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &r_->CssValue());
+                                            r_->CssValue());
   } else {
     SVGGeometryElement::CollectStyleForPresentationAttribute(name, value,
                                                              style);
diff --git a/third_party/WebKit/Source/core/svg/SVGEllipseElement.cpp b/third_party/WebKit/Source/core/svg/SVGEllipseElement.cpp
index 937c02ef..2339906 100644
--- a/third_party/WebKit/Source/core/svg/SVGEllipseElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGEllipseElement.cpp
@@ -87,16 +87,16 @@
   SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
   if (property == cx_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &cx_->CssValue());
+                                            cx_->CssValue());
   } else if (property == cy_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &cy_->CssValue());
+                                            cy_->CssValue());
   } else if (property == rx_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &rx_->CssValue());
+                                            rx_->CssValue());
   } else if (property == ry_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &ry_->CssValue());
+                                            ry_->CssValue());
   } else {
     SVGGeometryElement::CollectStyleForPresentationAttribute(name, value,
                                                              style);
diff --git a/third_party/WebKit/Source/core/svg/SVGForeignObjectElement.cpp b/third_party/WebKit/Source/core/svg/SVGForeignObjectElement.cpp
index bcedf00..4ba04b50 100644
--- a/third_party/WebKit/Source/core/svg/SVGForeignObjectElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGForeignObjectElement.cpp
@@ -72,16 +72,16 @@
   SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
   if (property == width_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &width_->CssValue());
+                                            width_->CssValue());
   } else if (property == height_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &height_->CssValue());
+                                            height_->CssValue());
   } else if (property == x_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &x_->CssValue());
+                                            x_->CssValue());
   } else if (property == y_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &y_->CssValue());
+                                            y_->CssValue());
   } else {
     SVGGraphicsElement::CollectStyleForPresentationAttribute(name, value,
                                                              style);
diff --git a/third_party/WebKit/Source/core/svg/SVGGradientElement.cpp b/third_party/WebKit/Source/core/svg/SVGGradientElement.cpp
index 215628c..a027840 100644
--- a/third_party/WebKit/Source/core/svg/SVGGradientElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGGradientElement.cpp
@@ -79,7 +79,7 @@
   if (name == SVGNames::gradientTransformAttr) {
     AddPropertyToPresentationAttributeStyle(
         style, CSSPropertyTransform,
-        gradient_transform_->CurrentValue()->CssValue());
+        *gradient_transform_->CurrentValue()->CssValue());
     return;
   }
   SVGElement::CollectStyleForPresentationAttribute(name, value, style);
diff --git a/third_party/WebKit/Source/core/svg/SVGGraphicsElement.cpp b/third_party/WebKit/Source/core/svg/SVGGraphicsElement.cpp
index 25ae51c..6ae78f3 100644
--- a/third_party/WebKit/Source/core/svg/SVGGraphicsElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGGraphicsElement.cpp
@@ -105,7 +105,7 @@
     MutableCSSPropertyValueSet* style) {
   if (name == SVGNames::transformAttr) {
     AddPropertyToPresentationAttributeStyle(
-        style, CSSPropertyTransform, transform_->CurrentValue()->CssValue());
+        style, CSSPropertyTransform, *transform_->CurrentValue()->CssValue());
     return;
   }
   SVGElement::CollectStyleForPresentationAttribute(name, value, style);
diff --git a/third_party/WebKit/Source/core/svg/SVGImageElement.cpp b/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
index c6cda0d0..b33a9b74 100644
--- a/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
@@ -99,16 +99,16 @@
   SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
   if (property == width_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &width_->CssValue());
+                                            width_->CssValue());
   } else if (property == height_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &height_->CssValue());
+                                            height_->CssValue());
   } else if (property == x_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &x_->CssValue());
+                                            x_->CssValue());
   } else if (property == y_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &y_->CssValue());
+                                            y_->CssValue());
   } else {
     SVGGraphicsElement::CollectStyleForPresentationAttribute(name, value,
                                                              style);
diff --git a/third_party/WebKit/Source/core/svg/SVGMaskElement.cpp b/third_party/WebKit/Source/core/svg/SVGMaskElement.cpp
index d469069d..5c2c5ece 100644
--- a/third_party/WebKit/Source/core/svg/SVGMaskElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGMaskElement.cpp
@@ -95,16 +95,16 @@
   SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
   if (property == x_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &x_->CssValue());
+                                            x_->CssValue());
   } else if (property == y_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &y_->CssValue());
+                                            y_->CssValue());
   } else if (property == width_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &width_->CssValue());
+                                            width_->CssValue());
   } else if (property == height_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &height_->CssValue());
+                                            height_->CssValue());
   } else {
     SVGElement::CollectStyleForPresentationAttribute(name, value, style);
   }
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
index 0cd5644d..2d1212a 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
@@ -114,7 +114,7 @@
     if (const SVGElement* element = CorrespondingElement())
       path = ToSVGPathElement(element)->GetPath();
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &path->CssValue());
+                                            path->CssValue());
     return;
   }
   SVGGeometryElement::CollectStyleForPresentationAttribute(name, value, style);
diff --git a/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp b/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp
index 118e3c5..6d2fee4 100644
--- a/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp
@@ -94,7 +94,7 @@
   if (name == SVGNames::patternTransformAttr) {
     AddPropertyToPresentationAttributeStyle(
         style, CSSPropertyTransform,
-        pattern_transform_->CurrentValue()->CssValue());
+        *pattern_transform_->CurrentValue()->CssValue());
     return;
   }
   SVGElement::CollectStyleForPresentationAttribute(name, value, style);
diff --git a/third_party/WebKit/Source/core/svg/SVGRectElement.cpp b/third_party/WebKit/Source/core/svg/SVGRectElement.cpp
index da166db..48df6f9 100644
--- a/third_party/WebKit/Source/core/svg/SVGRectElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGRectElement.cpp
@@ -112,22 +112,22 @@
   SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
   if (property == x_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &x_->CssValue());
+                                            x_->CssValue());
   } else if (property == y_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &y_->CssValue());
+                                            y_->CssValue());
   } else if (property == width_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &width_->CssValue());
+                                            width_->CssValue());
   } else if (property == height_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &height_->CssValue());
+                                            height_->CssValue());
   } else if (property == rx_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &rx_->CssValue());
+                                            rx_->CssValue());
   } else if (property == ry_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &ry_->CssValue());
+                                            ry_->CssValue());
   } else {
     SVGGeometryElement::CollectStyleForPresentationAttribute(name, value,
                                                              style);
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
index e159cf6..f75381c 100644
--- a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
@@ -232,18 +232,18 @@
   SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
   if (property == x_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &x_->CssValue());
+                                            x_->CssValue());
   } else if (property == y_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &y_->CssValue());
+                                            y_->CssValue());
   } else if (IsOutermostSVGSVGElement() &&
              (property == width_ || property == height_)) {
     if (property == width_) {
       AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                              &width_->CssValue());
+                                              width_->CssValue());
     } else if (property == height_) {
       AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                              &height_->CssValue());
+                                              height_->CssValue());
     }
   } else {
     SVGGraphicsElement::CollectStyleForPresentationAttribute(name, value,
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
index 64a7c953..436fb3f 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
@@ -183,10 +183,10 @@
   SVGAnimatedPropertyBase* property = PropertyFromAttribute(name);
   if (property == x_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &x_->CssValue());
+                                            x_->CssValue());
   } else if (property == y_) {
     AddPropertyToPresentationAttributeStyle(style, property->CssPropertyId(),
-                                            &y_->CssValue());
+                                            y_->CssValue());
   } else {
     SVGGraphicsElement::CollectStyleForPresentationAttribute(name, value,
                                                              style);
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 59d1b7d..968faed5 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -735,7 +735,7 @@
 
 ShadowRoot* Internals::createUserAgentShadowRoot(Element* host) {
   DCHECK(host);
-  return &host->EnsureUserAgentShadowRootV1();
+  return &host->EnsureUserAgentShadowRoot();
 }
 
 void Internals::setBrowserControlsState(float top_height,
@@ -792,7 +792,7 @@
   }
 
   switch (ToShadowRoot(root)->GetType()) {
-    case ShadowRootType::kUserAgentV1:
+    case ShadowRootType::kUserAgent:
       return String("UserAgentShadowRoot");
     case ShadowRootType::V0:
       return String("V0ShadowRoot");
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
index a15e129..c1a9a82 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
@@ -199,12 +199,12 @@
     this._dialog = new UI.Dialog();
     this._dialog.setOutsideClickCallback(event => event.consume(true));
     var root = UI.createShadowRootWithCoreStyles(this._dialog.contentElement, 'audits2/audits2Dialog.css');
-    var auditsViewElement = root.createChild('div', 'audits2-view');
+    var auditsViewElement = root.createChild('div', 'audits2-view vbox');
 
     var closeButton = auditsViewElement.createChild('div', 'dialog-close-button', 'dt-close-button');
     closeButton.addEventListener('click', () => this._cancelAndClose());
 
-    var uiElement = auditsViewElement.createChild('div');
+    var uiElement = auditsViewElement.createChild('div', 'vbox launcher-container');
     var headerElement = uiElement.createChild('header');
     this._headerTitleElement = headerElement.createChild('p');
     this._headerTitleElement.textContent = Common.UIString('Audits to perform');
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/audits2Dialog.css b/third_party/WebKit/Source/devtools/front_end/audits2/audits2Dialog.css
index 14f8b2c..0b2c950 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/audits2Dialog.css
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/audits2Dialog.css
@@ -9,18 +9,30 @@
     margin: 7px var(--view-horizontal-margin);
     flex: auto;
     align-items: center;
+    width: 100%;
+    max-width: 500px;
+}
+
+.launcher-container {
+  width: 100%;
 }
 
 .audits2-view .dialog-close-button {
     position: absolute;
-    top: 10px;
-    right: 10px;
+    top: 0px;
+    right: -14px;
 }
 
 header {
     color: #666;
     font-weight: bold;
     font-size: 14px;
+    flex: none;
+}
+
+.audits2-form {
+  flex: auto;
+  overflow-y: scroll;
 }
 
 .audits2-form label {
@@ -127,4 +139,5 @@
 
 .audits2-dialog-buttons {
     justify-content: center;
-}
\ No newline at end of file
+    min-height: 40px;
+}
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp
index fe84edac..42cffce 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp
@@ -113,7 +113,7 @@
     MediaControlElementType display_type)
     : HTMLInputElement(media_controls.GetDocument(), false),
       MediaControlElementBase(media_controls, display_type, this) {
-  CreateUserAgentShadowRootV1();
+  CreateUserAgentShadowRoot();
   CreateShadowSubtree();
 }
 
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
index 57a6b929..4374402 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
@@ -111,7 +111,7 @@
       internal_button_(nullptr),
       left_jump_arrow_(nullptr),
       right_jump_arrow_(nullptr) {
-  EnsureUserAgentShadowRootV1();
+  EnsureUserAgentShadowRoot();
   setType(InputTypeNames::button);
   SetShadowPseudoId(AtomicString("-webkit-media-controls-overlay-play-button"));
 
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp b/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
index d5830a9..b49adc58 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
@@ -198,7 +198,6 @@
 
 void MediaDevices::OnDevicesChanged(
     MediaDeviceType type,
-    uint32_t subscription_id,
     Vector<mojom::blink::MediaDeviceInfoPtr> device_infos) {
   Document* document = ToDocument(GetExecutionContext());
   DCHECK(document);
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaDevices.h b/third_party/WebKit/Source/modules/mediastream/MediaDevices.h
index b8e9baf..ee569e8 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaDevices.h
+++ b/third_party/WebKit/Source/modules/mediastream/MediaDevices.h
@@ -60,7 +60,6 @@
 
   // mojom::blink::MediaDevicesListener implementation.
   void OnDevicesChanged(MediaDeviceType,
-                        uint32_t subscription_id,
                         Vector<mojom::blink::MediaDeviceInfoPtr>) override;
 
   // Callback for testing only.
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaDevicesTest.cpp b/third_party/WebKit/Source/modules/mediastream/MediaDevicesTest.cpp
index c712c9f4..7bb08b6 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaDevicesTest.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/MediaDevicesTest.cpp
@@ -104,11 +104,6 @@
     listener_ = std::move(listener);
   };
 
-  MOCK_METHOD2(SubscribeDeviceChangeNotifications,
-               void(MediaDeviceType type, uint32_t subscription_id));
-  MOCK_METHOD2(UnsubscribeDeviceChangeNotifications,
-               void(MediaDeviceType type, uint32_t subscription_id));
-
   mojom::blink::MediaDevicesDispatcherHostPtr CreateInterfacePtrAndBind() {
     mojom::blink::MediaDevicesDispatcherHostPtr ptr;
     binding_.Bind(mojo::MakeRequest(&ptr));
@@ -194,7 +189,7 @@
 
   void SimulateDeviceChange() {
     DCHECK(listener());
-    listener()->OnDevicesChanged(MediaDeviceType::MEDIA_AUDIO_INPUT, 1u,
+    listener()->OnDevicesChanged(MediaDeviceType::MEDIA_AUDIO_INPUT,
                                  Vector<MediaDeviceInfoPtr>());
   }
 
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 0f4d3b5..6ec3dd05 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1289,6 +1289,8 @@
     "mediastream/MediaStreamSource.h",
     "mediastream/MediaStreamWebAudioSource.cpp",
     "mediastream/MediaStreamWebAudioSource.h",
+    "memory_profiler/SamplingNativeHeapProfiler.cpp",
+    "memory_profiler/SamplingNativeHeapProfiler.h",
     "mhtml/ArchiveResource.cpp",
     "mhtml/ArchiveResource.h",
     "mhtml/MHTMLArchive.cpp",
@@ -1529,6 +1531,7 @@
     "//third_party/WebKit/Source/platform/scheduler",
   ]
   deps = [
+    "//base/allocator:features",
     "//components/viz/service",
     "//device/base/synchronization",
     "//device/vr:mojo_bindings_blink",
diff --git a/third_party/WebKit/Source/platform/animation/OWNERS b/third_party/WebKit/Source/platform/animation/OWNERS
index 72985ce..82773a0 100644
--- a/third_party/WebKit/Source/platform/animation/OWNERS
+++ b/third_party/WebKit/Source/platform/animation/OWNERS
@@ -2,5 +2,5 @@
 
 loyso@chromium.org
 
-# TEAM: style-dev@chromium.org
+# TEAM: animations-dev@chromium.org
 # COMPONENT: Blink>Animation
diff --git a/third_party/WebKit/Source/platform/bindings/DOMDataStore.h b/third_party/WebKit/Source/platform/bindings/DOMDataStore.h
index ef280fa..e519368 100644
--- a/third_party/WebKit/Source/platform/bindings/DOMDataStore.h
+++ b/third_party/WebKit/Source/platform/bindings/DOMDataStore.h
@@ -116,7 +116,8 @@
     return Current(isolate).Set(isolate, object, wrapper_type_info, wrapper);
   }
 
-  static bool ContainsWrapper(ScriptWrappable* object, v8::Isolate* isolate) {
+  static bool ContainsWrapper(const ScriptWrappable* object,
+                              v8::Isolate* isolate) {
     return Current(isolate).ContainsWrapper(object);
   }
 
@@ -142,6 +143,11 @@
     return updated;
   }
 
+  void TraceWrappers(const ScriptWrappable* script_wrappable,
+                     const ScriptWrappableVisitor* visitor) {
+    visitor->TraceWrappers(&wrapper_map_.value(), script_wrappable);
+  }
+
   void MarkWrapper(ScriptWrappable* script_wrappable) {
     wrapper_map_->MarkWrapper(script_wrappable);
   }
@@ -159,7 +165,7 @@
     return wrapper_map_->SetReturnValueFrom(return_value, object);
   }
 
-  bool ContainsWrapper(ScriptWrappable* object) {
+  bool ContainsWrapper(const ScriptWrappable* object) {
     if (is_main_world_)
       return object->ContainsWrapper();
     return wrapper_map_->ContainsKey(object);
diff --git a/third_party/WebKit/Source/platform/bindings/DOMWrapperMap.h b/third_party/WebKit/Source/platform/bindings/DOMWrapperMap.h
index 7f725393..4f0988cf 100644
--- a/third_party/WebKit/Source/platform/bindings/DOMWrapperMap.h
+++ b/third_party/WebKit/Source/platform/bindings/DOMWrapperMap.h
@@ -67,7 +67,9 @@
     map_.SetReference(key, parent);
   }
 
-  bool ContainsKey(KeyType* key) { return map_.Contains(key); }
+  bool ContainsKey(const KeyType* key) {
+    return map_.Contains(const_cast<KeyType*>(key));
+  }
 
   WARN_UNUSED_RESULT bool Set(KeyType* key,
                               const WrapperTypeInfo* wrapper_type_info,
diff --git a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp
index 46d5e5ae..e7c4c3cd 100644
--- a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp
+++ b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp
@@ -116,20 +116,15 @@
     worlds.push_back(world);
 }
 
-void DOMWrapperWorld::MarkWrappersInAllWorlds(
-    ScriptWrappable* script_wrappable,
-    const ScriptWrappableVisitor* visitor) {
+void DOMWrapperWorld::TraceWrappers(const ScriptWrappable* script_wrappable,
+                                    const ScriptWrappableVisitor* visitor) {
   // Marking for worlds other than the main world.
   DCHECK(ThreadState::Current()->GetIsolate());
   for (DOMWrapperWorld* world : GetWorldMap().Values()) {
     DOMDataStore& data_store = world->DomDataStore();
     if (data_store.ContainsWrapper(script_wrappable))
-      data_store.MarkWrapper(script_wrappable);
+      data_store.TraceWrappers(script_wrappable, visitor);
   }
-
-  // Marking for the main world.
-  if (IsMainThread())
-    script_wrappable->MarkWrapper(visitor);
 }
 
 DOMWrapperWorld::~DOMWrapperWorld() {
diff --git a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.h b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.h
index 88c42d3..d61d6a7 100644
--- a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.h
+++ b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.h
@@ -93,8 +93,10 @@
 
   static void AllWorldsInCurrentThread(
       Vector<scoped_refptr<DOMWrapperWorld>>& worlds);
-  static void MarkWrappersInAllWorlds(ScriptWrappable*,
-                                      const ScriptWrappableVisitor*);
+
+  // Traces wrappers corresponding to the ScriptWrappable in DOM data stores.
+  static void TraceWrappers(const ScriptWrappable*,
+                            const ScriptWrappableVisitor*);
 
   static DOMWrapperWorld& World(v8::Local<v8::Context> context) {
     return ScriptState::From(context)->World();
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptWrappable.cpp b/third_party/WebKit/Source/platform/bindings/ScriptWrappable.cpp
index 5175ef04..84120ce 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptWrappable.cpp
+++ b/third_party/WebKit/Source/platform/bindings/ScriptWrappable.cpp
@@ -39,9 +39,10 @@
                                                   wrapper_type_info, wrapper);
 }
 
-void ScriptWrappable::MarkWrapper(const ScriptWrappableVisitor* visitor) const {
-  if (ContainsWrapper())
-    visitor->TraceWrappers(main_world_wrapper_);
+void ScriptWrappable::TraceWrappers(
+    const ScriptWrappableVisitor* visitor) const {
+  visitor->TraceWrappers(main_world_wrapper_);
+  DOMWrapperWorld::TraceWrappers(this, visitor);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptWrappable.h b/third_party/WebKit/Source/platform/bindings/ScriptWrappable.h
index 8eb2c24..6f45735 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptWrappable.h
+++ b/third_party/WebKit/Source/platform/bindings/ScriptWrappable.h
@@ -59,10 +59,8 @@
 
   virtual void Trace(blink::Visitor*) {}
 
-  void TraceWrappers(const ScriptWrappableVisitor*) const override {
-    // TODO(mlippautz/ulan): Trace |main_world_wrapper_| here once the GC plugin
-    // can make sure that all children properly dispatch to ScriptWrappable.
-  }
+  // Traces wrapper objects corresponding to this ScriptWrappable in all worlds.
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
 
   bool IsScriptWrappable() const override { return true; }
 
@@ -148,14 +146,6 @@
 
   bool ContainsWrapper() const { return !main_world_wrapper_.IsEmpty(); }
 
-  // Mark wrapper of this ScriptWrappable as alive in V8. Only marks
-  // wrapper in the main world. To mark wrappers in all worlds call
-  // ScriptWrappableVisitor::MarkWrappersInAllWorlds.
-  // TODO(ulan): Move body of this function to TraceWrappers and
-  // remove this function once all ScriptWrappable objects dispatch to
-  // ScriptWrappable::TraceWrappers from their overriden TraceWrappers.
-  void MarkWrapper(const ScriptWrappableVisitor*) const;
-
  protected:
   ScriptWrappable() = default;
 
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.cpp b/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.cpp
index a5193b9..2292cbc6 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.cpp
+++ b/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.cpp
@@ -215,12 +215,6 @@
   headers_to_unmark_.push_back(header);
 }
 
-void ScriptWrappableVisitor::MarkWrappersInAllWorlds(
-    const ScriptWrappable* script_wrappable) const {
-  DOMWrapperWorld::MarkWrappersInAllWorlds(
-      const_cast<ScriptWrappable*>(script_wrappable), this);
-}
-
 void ScriptWrappableVisitor::WriteBarrier(
     v8::Isolate* isolate,
     const TraceWrapperV8Reference<v8::Value>& dst_object) {
@@ -246,7 +240,7 @@
 
 void ScriptWrappableVisitor::TraceWrappers(
     DOMWrapperMap<ScriptWrappable>* wrapper_map,
-    ScriptWrappable* key) {
+    const ScriptWrappable* key) const {
   Visit(wrapper_map, key);
 }
 
@@ -278,8 +272,8 @@
 }
 
 void ScriptWrappableVisitor::Visit(DOMWrapperMap<ScriptWrappable>* wrapper_map,
-                                   ScriptWrappable* key) {
-  wrapper_map->MarkWrapper(key);
+                                   const ScriptWrappable* key) const {
+  wrapper_map->MarkWrapper(const_cast<ScriptWrappable*>(key));
 }
 
 void ScriptWrappableVisitor::DispatchTraceWrappers(
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.h b/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.h
index 072b3a9..a388901 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.h
+++ b/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitor.h
@@ -193,9 +193,8 @@
   }
 
   // Trace a wrapper in a non-main world.
-  // TODO(ulan): call this from ScriptWrappable::TraceWrappers and
-  // remove all MarkWrappersInAllWorlds methods.
-  void TraceWrappers(DOMWrapperMap<ScriptWrappable>*, ScriptWrappable* key);
+  void TraceWrappers(DOMWrapperMap<ScriptWrappable>*,
+                     const ScriptWrappable* key) const;
 
   virtual void DispatchTraceWrappers(const TraceWrapperBase*) const;
   template <typename T>
@@ -206,20 +205,6 @@
   // Catch all handlers needed because of mixins except for Supplement<T>.
   void DispatchTraceWrappers(const void*) const { CHECK(false); }
 
-  // Mark wrappers in all worlds for the given ScriptWrappable as alive in V8.
-  virtual void MarkWrappersInAllWorlds(const ScriptWrappable*) const;
-  void MarkWrappersInAllWorlds(const TraceWrapperBase*) const {
-    // TraceWrapperBase cannot point to V8 and thus doesn't need to
-    // mark wrappers.
-  }
-  template <typename T>
-  void MarkWrappersInAllWorlds(const Supplement<T>*) const {
-    // Supplement<T> which is not ScriptWrappable cannot point to V8 and thus
-    // doesn't need to mark wrappers.
-  }
-  // Catch all handlers needed because of mixins except for Supplement<T>.
-  void MarkWrappersInAllWorlds(const void*) const { CHECK(false); }
-
   // v8::EmbedderHeapTracer interface.
 
   void TracePrologue() override;
@@ -239,7 +224,8 @@
   // TODO(ulan): extract Visit methods to a general visitor interface.
   virtual void Visit(const TraceWrapperV8Reference<v8::Value>&) const;
   virtual void Visit(const WrapperDescriptor&) const;
-  virtual void Visit(DOMWrapperMap<ScriptWrappable>*, ScriptWrappable* key);
+  virtual void Visit(DOMWrapperMap<ScriptWrappable>*,
+                     const ScriptWrappable* key) const;
 
   v8::Isolate* isolate() const { return isolate_; }
 
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitorVerifier.h b/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitorVerifier.h
index 3ae510e..849f4ef 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitorVerifier.h
+++ b/third_party/WebKit/Source/platform/bindings/ScriptWrappableVisitorVerifier.h
@@ -19,8 +19,6 @@
       const WTF::Deque<WrapperMarkingData>* verifier_deque)
       : ScriptWrappableVisitor(isolate), verifier_deque_(verifier_deque) {}
 
-  void MarkWrappersInAllWorlds(const ScriptWrappable*) const final {}
-
   void Verify() {
     for (auto& marking_data : *verifier_deque_) {
       // Check that all children of this object are marked.
@@ -30,7 +28,7 @@
 
  protected:
   void Visit(const TraceWrapperV8Reference<v8::Value>&) const final {}
-  void Visit(const WrapperDescriptor& wrapper_descriptor) const override {
+  void Visit(const WrapperDescriptor& wrapper_descriptor) const final {
     HeapObjectHeader* header = wrapper_descriptor.heap_object_header_callback(
         wrapper_descriptor.traceable);
     if (!header->IsWrapperHeaderMarked()) {
@@ -48,6 +46,8 @@
       NOTREACHED();
     }
   }
+  void Visit(DOMWrapperMap<ScriptWrappable>*,
+             const ScriptWrappable* key) const final {}
 
  private:
   const WTF::Deque<WrapperMarkingData>* verifier_deque_;
diff --git a/third_party/WebKit/Source/platform/graphics/LoggingCanvas.cpp b/third_party/WebKit/Source/platform/graphics/LoggingCanvas.cpp
index 5655312..5a4b6c0e 100644
--- a/third_party/WebKit/Source/platform/graphics/LoggingCanvas.cpp
+++ b/third_party/WebKit/Source/platform/graphics/LoggingCanvas.cpp
@@ -483,6 +483,11 @@
   paint_item->SetString("hinting", HintingName(paint.getHinting()));
   if (paint.getBlendMode() != SkBlendMode::kSrcOver)
     paint_item->SetString("blendMode", SkBlendMode_Name(paint.getBlendMode()));
+  if (const auto* filter = paint.getImageFilter()) {
+    SkString str;
+    filter->toString(&str);
+    paint_item->SetString("imageFilter", str.c_str());
+  }
   return paint_item;
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
index 512fcc28..63512cf 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
@@ -24,12 +24,14 @@
                                           const IntRect& visual_rect_in_layer) {
   DCHECK(display_item.IsDrawing());
 
-  sk_sp<const PaintRecord> record =
-      static_cast<const DrawingDisplayItem&>(display_item).GetPaintRecord();
-  if (!record)
-    return;
   list.StartPaint();
-  list.push<cc::DrawRecordOp>(std::move(record));
+  if (auto record =
+          static_cast<const DrawingDisplayItem&>(display_item).GetPaintRecord())
+    list.push<cc::DrawRecordOp>(std::move(record));
+  // StartPaint() and EndPaintOfUnpaired() are called regardless of whether the
+  // record is null to ensure we'll set correct visual rects for the enclosing
+  // paired display items. This is especially important for filters that draw
+  // content by themselves but don't enclose any non-empty DrawingDisplayItem.
   list.EndPaintOfUnpaired(visual_rect_in_layer);
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index b8b715f..bc3c34db 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -847,11 +847,11 @@
 
     layer_->SetOpaque(!want_alpha_channel_);
     layer_->SetBlendBackgroundColor(want_alpha_channel_);
-    // If ShouldUseChromiumImage(), premultiplied_alpha_ has already been
-    // handled via CopySubTextureCHROMIUM, and does not need to be handled by
-    // the compositor.
+    // If premultiplied_alpha_false_texture_ exists, then premultiplied_alpha_
+    // has already been handled via CopySubTextureCHROMIUM, and does not need
+    // to be handled by the compositor.
     layer_->SetPremultipliedAlpha(premultiplied_alpha_ &&
-                                  !ShouldUseChromiumImage());
+                                  !premultiplied_alpha_false_texture_);
     layer_->SetNearestNeighbor(filter_quality_ == kNone_SkFilterQuality);
     GraphicsLayer::RegisterContentsLayer(layer_->Layer());
   }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
index 5e01b4308..01a4cf0 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
@@ -75,6 +75,7 @@
     DEBUG_STRING_CASE(DocumentBackground);
     DEBUG_STRING_CASE(DragImage);
     DEBUG_STRING_CASE(DragCaret);
+    DEBUG_STRING_CASE(EmptyContentForFilters);
     DEBUG_STRING_CASE(SVGImage);
     DEBUG_STRING_CASE(LinkHighlight);
     DEBUG_STRING_CASE(ImageAreaFocusRing);
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
index 13fe365..8f4bea091 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -77,6 +77,7 @@
     kDocumentBackground,
     kDragImage,
     kDragCaret,
+    kEmptyContentForFilters,
     kSVGImage,
     kLinkHighlight,
     kImageAreaFocusRing,
diff --git a/third_party/WebKit/Source/platform/heap/TraceTraits.h b/third_party/WebKit/Source/platform/heap/TraceTraits.h
index 5ae4d06..54875f47 100644
--- a/third_party/WebKit/Source/platform/heap/TraceTraits.h
+++ b/third_party/WebKit/Source/platform/heap/TraceTraits.h
@@ -114,7 +114,6 @@
     // API boundary, i.e., tell V8 that an object is alive. Actual marking
     // will be done in V8.
     visitor->DispatchTraceWrappers(self);
-    visitor->MarkWrappersInAllWorlds(self);
   }
 };
 
diff --git a/third_party/WebKit/Source/platform/memory_profiler/DEPS b/third_party/WebKit/Source/platform/memory_profiler/DEPS
new file mode 100644
index 0000000..70be7bf
--- /dev/null
+++ b/third_party/WebKit/Source/platform/memory_profiler/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+    "+base",
+]
+
diff --git a/third_party/WebKit/Source/platform/memory_profiler/OWNERS b/third_party/WebKit/Source/platform/memory_profiler/OWNERS
new file mode 100644
index 0000000..87c96616
--- /dev/null
+++ b/third_party/WebKit/Source/platform/memory_profiler/OWNERS
@@ -0,0 +1 @@
+alph@chromium.org
diff --git a/third_party/WebKit/Source/platform/memory_profiler/SamplingNativeHeapProfiler.cpp b/third_party/WebKit/Source/platform/memory_profiler/SamplingNativeHeapProfiler.cpp
new file mode 100644
index 0000000..f3f3cb5
--- /dev/null
+++ b/third_party/WebKit/Source/platform/memory_profiler/SamplingNativeHeapProfiler.cpp
@@ -0,0 +1,331 @@
+// 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 "platform/memory_profiler/SamplingNativeHeapProfiler.h"
+
+#include <cmath>
+
+#include "base/allocator/allocator_shim.h"
+#include "base/allocator/features.h"
+#include "base/atomicops.h"
+#include "base/bits.h"
+#include "base/debug/alias.h"
+#include "base/debug/stack_trace.h"
+#include "base/memory/singleton.h"
+#include "base/rand_util.h"
+#include "build/build_config.h"
+
+namespace blink {
+
+using base::allocator::AllocatorDispatch;
+using base::subtle::Atomic32;
+using base::subtle::AtomicWord;
+
+namespace {
+
+const unsigned kMagicSignature = 0x14690ca5;
+const unsigned kDefaultAlignment = 16;
+const unsigned kSkipAllocatorFrames = 4;
+
+Atomic32 g_running;
+Atomic32 g_deterministic;
+AtomicWord g_cumulative_counter = 0;
+AtomicWord g_threshold;
+AtomicWord g_sampling_interval = 128 * 1024;
+
+static void* AllocFn(const AllocatorDispatch* self,
+                     size_t size,
+                     void* context) {
+  SamplingNativeHeapProfiler::Sample sample;
+  if (LIKELY(!base::subtle::NoBarrier_Load(&g_running) ||
+             !SamplingNativeHeapProfiler::CreateAllocSample(size, &sample))) {
+    return self->next->alloc_function(self->next, size, context);
+  }
+  void* address =
+      self->next->alloc_function(self->next, size + kDefaultAlignment, context);
+  return SamplingNativeHeapProfiler::GetInstance()->RecordAlloc(
+      sample, address, kDefaultAlignment, kSkipAllocatorFrames);
+}
+
+static void* AllocZeroInitializedFn(const AllocatorDispatch* self,
+                                    size_t n,
+                                    size_t size,
+                                    void* context) {
+  SamplingNativeHeapProfiler::Sample sample;
+  if (LIKELY(
+          !base::subtle::NoBarrier_Load(&g_running) ||
+          !SamplingNativeHeapProfiler::CreateAllocSample(n * size, &sample))) {
+    return self->next->alloc_zero_initialized_function(self->next, n, size,
+                                                       context);
+  }
+  void* address = self->next->alloc_zero_initialized_function(
+      self->next, 1, n * size + kDefaultAlignment, context);
+  return SamplingNativeHeapProfiler::GetInstance()->RecordAlloc(
+      sample, address, kDefaultAlignment, kSkipAllocatorFrames);
+}
+
+static void* AllocAlignedFn(const AllocatorDispatch* self,
+                            size_t alignment,
+                            size_t size,
+                            void* context) {
+  SamplingNativeHeapProfiler::Sample sample;
+  if (LIKELY(!base::subtle::NoBarrier_Load(&g_running) ||
+             !SamplingNativeHeapProfiler::CreateAllocSample(size, &sample))) {
+    return self->next->alloc_aligned_function(self->next, alignment, size,
+                                              context);
+  }
+  size_t offset = base::bits::Align(sizeof(kMagicSignature), alignment);
+  void* address = self->next->alloc_aligned_function(self->next, alignment,
+                                                     size + offset, context);
+  return SamplingNativeHeapProfiler::GetInstance()->RecordAlloc(
+      sample, address, offset, kSkipAllocatorFrames);
+}
+
+static void* ReallocFn(const AllocatorDispatch* self,
+                       void* address,
+                       size_t size,
+                       void* context) {
+  // Note: size == 0 actually performs free.
+  SamplingNativeHeapProfiler::Sample sample;
+  bool will_sample =
+      base::subtle::NoBarrier_Load(&g_running) &&
+      SamplingNativeHeapProfiler::CreateAllocSample(size, &sample);
+  char* client_address = reinterpret_cast<char*>(address);
+  if (UNLIKELY(address &&
+               reinterpret_cast<unsigned*>(address)[-1] == kMagicSignature)) {
+    address = SamplingNativeHeapProfiler::GetInstance()->RecordFree(address);
+  }
+  intptr_t prev_offset = client_address - reinterpret_cast<char*>(address);
+  bool was_sampled = prev_offset;
+  if (LIKELY(!was_sampled && !will_sample))
+    return self->next->realloc_function(self->next, address, size, context);
+  size_t size_to_allocate = will_sample ? size + kDefaultAlignment : size;
+  address = self->next->realloc_function(self->next, address, size_to_allocate,
+                                         context);
+  if (will_sample) {
+    return SamplingNativeHeapProfiler::GetInstance()->RecordAlloc(
+        sample, address, kDefaultAlignment, kSkipAllocatorFrames,
+        client_address && prev_offset != kDefaultAlignment);
+  }
+  DCHECK(was_sampled && !will_sample);
+  memmove(address, reinterpret_cast<char*>(address) + prev_offset, size);
+  return address;
+}
+
+static void FreeFn(const AllocatorDispatch* self,
+                   void* address,
+                   void* context) {
+  if (UNLIKELY(address &&
+               reinterpret_cast<unsigned*>(address)[-1] == kMagicSignature)) {
+    address = SamplingNativeHeapProfiler::GetInstance()->RecordFree(address);
+  }
+  self->next->free_function(self->next, address, context);
+}
+
+static size_t GetSizeEstimateFn(const AllocatorDispatch* self,
+                                void* address,
+                                void* context) {
+  size_t ret =
+      self->next->get_size_estimate_function(self->next, address, context);
+  return ret;
+}
+
+static unsigned BatchMallocFn(const AllocatorDispatch* self,
+                              size_t size,
+                              void** results,
+                              unsigned num_requested,
+                              void* context) {
+  CHECK(false) << "Not implemented.";
+  return 0;
+}
+
+static void BatchFreeFn(const AllocatorDispatch* self,
+                        void** to_be_freed,
+                        unsigned num_to_be_freed,
+                        void* context) {
+  CHECK(false) << "Not implemented.";
+}
+
+static void FreeDefiniteSizeFn(const AllocatorDispatch* self,
+                               void* ptr,
+                               size_t size,
+                               void* context) {
+  CHECK(false) << "Not implemented.";
+}
+
+AllocatorDispatch g_allocator_dispatch = {&AllocFn,
+                                          &AllocZeroInitializedFn,
+                                          &AllocAlignedFn,
+                                          &ReallocFn,
+                                          &FreeFn,
+                                          &GetSizeEstimateFn,
+                                          &BatchMallocFn,
+                                          &BatchFreeFn,
+                                          &FreeDefiniteSizeFn,
+                                          nullptr};
+
+}  // namespace
+
+// static
+void SamplingNativeHeapProfiler::InstallAllocatorHooksOnce() {
+  static bool hook_installed = InstallAllocatorHooks();
+  base::debug::Alias(&hook_installed);
+}
+
+// static
+bool SamplingNativeHeapProfiler::InstallAllocatorHooks() {
+#if BUILDFLAG(USE_ALLOCATOR_SHIM)
+  base::allocator::InsertAllocatorDispatch(&g_allocator_dispatch);
+#else
+  base::debug::Alias(&g_allocator_dispatch);
+  CHECK(false)
+      << "Can't enable native sampling heap profiler without the shim.";
+#endif  // BUILDFLAG(USE_ALLOCATOR_SHIM)
+  return true;
+}
+
+void SamplingNativeHeapProfiler::Start() {
+  InstallAllocatorHooksOnce();
+  base::subtle::Release_Store(&g_threshold, g_sampling_interval);
+  base::subtle::Release_Store(&g_running, true);
+}
+
+void SamplingNativeHeapProfiler::Stop() {
+  base::subtle::Release_Store(&g_running, false);
+}
+
+void SamplingNativeHeapProfiler::SetSamplingInterval(
+    unsigned sampling_interval) {
+  // TODO(alph): Update the threshold. Make sure not to leave it in a state
+  // when the threshold is already crossed.
+  base::subtle::Release_Store(&g_sampling_interval, sampling_interval);
+}
+
+// static
+intptr_t SamplingNativeHeapProfiler::GetNextSampleInterval(uint64_t interval) {
+  if (base::subtle::NoBarrier_Load(&g_deterministic))
+    return static_cast<intptr_t>(interval);
+  // We sample with a Poisson process, with constant average sampling
+  // interval. This follows the exponential probability distribution with
+  // parameter λ = 1/interval where |interval| is the average number of bytes
+  // between samples.
+  // Let u be a uniformly distributed random number between 0 and 1, then
+  // next_sample = -ln(u) / λ
+  double uniform = base::RandDouble();
+  double value = -log(uniform) * interval;
+  intptr_t min_value = sizeof(intptr_t);
+  // We limit the upper bound of a sample interval to make sure we don't have
+  // huge gaps in the sampling stream. Probability of the upper bound gets hit
+  // is exp(-20) ~ 2e-9, so it should not skew the distibution.
+  intptr_t max_value = interval * 20;
+  if (UNLIKELY(value < min_value))
+    return min_value;
+  if (UNLIKELY(value > max_value))
+    return max_value;
+  return static_cast<intptr_t>(value);
+}
+
+// static
+bool SamplingNativeHeapProfiler::CreateAllocSample(size_t size,
+                                                   Sample* sample) {
+  // Lock-free algorithm that adds the allocation size to the cumulative
+  // counter. When the counter reaches threshold, it picks a single thread
+  // that will record the sample and reset the counter.
+  // The thread that records the sample returns true, others return false.
+  AtomicWord threshold = base::subtle::NoBarrier_Load(&g_threshold);
+  AtomicWord accumulated = base::subtle::NoBarrier_AtomicIncrement(
+      &g_cumulative_counter, static_cast<AtomicWord>(size));
+  if (LIKELY(accumulated < threshold))
+    return false;
+
+  // Return if it was another thread that in fact crossed the threshold.
+  // That other thread is responsible for recording the sample.
+  if (UNLIKELY(accumulated >= threshold + static_cast<AtomicWord>(size)))
+    return false;
+
+  intptr_t next_interval =
+      GetNextSampleInterval(base::subtle::NoBarrier_Load(&g_sampling_interval));
+  base::subtle::Release_Store(&g_threshold, next_interval);
+  accumulated =
+      base::subtle::NoBarrier_AtomicExchange(&g_cumulative_counter, 0);
+
+  DCHECK_NE(size, 0u);
+  sample->size = size;
+  sample->count = std::max<size_t>(1, (accumulated + size / 2) / size);
+  return true;
+}
+
+void SamplingNativeHeapProfiler::RecordStackTrace(Sample* sample,
+                                                  unsigned skip_frames) {
+  // TODO(alph): Consider using debug::TraceStackFramePointers. It should be
+  // somewhat faster than base::debug::StackTrace.
+  base::debug::StackTrace trace;
+  size_t count;
+  void* const* addresses = const_cast<void* const*>(trace.Addresses(&count));
+  // Skip SamplingNativeHeapProfiler frames.
+  sample->stack.insert(
+      sample->stack.end(), &addresses[skip_frames],
+      &addresses[std::max(count, static_cast<size_t>(skip_frames))]);
+}
+
+void* SamplingNativeHeapProfiler::RecordAlloc(Sample& sample,
+                                              void* address,
+                                              unsigned offset,
+                                              unsigned skip_frames,
+                                              bool preserve_data) {
+  // TODO(alph): It's better to use a recursive mutex and move the check
+  // inside the critical section. This way we won't skip the sample generation
+  // on one thread if another thread is recording a sample.
+  if (entered_.Get())
+    return address;
+  base::AutoLock lock(mutex_);
+  entered_.Set(true);
+  sample.offset = offset;
+  void* client_address = reinterpret_cast<char*>(address) + offset;
+  if (preserve_data)
+    memmove(client_address, address, sample.size);
+  RecordStackTrace(&sample, skip_frames);
+  samples_.insert(std::make_pair(client_address, sample));
+  if (offset)
+    reinterpret_cast<unsigned*>(client_address)[-1] = kMagicSignature;
+  entered_.Set(false);
+  return client_address;
+}
+
+void* SamplingNativeHeapProfiler::RecordFree(void* address) {
+  base::AutoLock lock(mutex_);
+  auto& samples = GetInstance()->samples_;
+  auto it = samples.find(address);
+  if (it == samples.end())
+    return address;
+  void* address_to_free = reinterpret_cast<char*>(address) - it->second.offset;
+  samples.erase(it);
+  if (it->second.offset)
+    reinterpret_cast<unsigned*>(address)[-1] = 0;
+  return address_to_free;
+}
+
+// static
+SamplingNativeHeapProfiler* SamplingNativeHeapProfiler::GetInstance() {
+  return base::Singleton<SamplingNativeHeapProfiler>::get();
+}
+
+// static
+void SamplingNativeHeapProfiler::SuppressRandomnessForTest() {
+  base::subtle::Release_Store(&g_deterministic, true);
+}
+
+std::vector<SamplingNativeHeapProfiler::Sample>
+SamplingNativeHeapProfiler::GetSamples() {
+  base::AutoLock lock(mutex_);
+  CHECK(!entered_.Get());
+  entered_.Set(true);
+  std::vector<Sample> samples;
+  for (auto it = samples_.begin(); it != samples_.end(); ++it)
+    samples.push_back(it->second);
+  entered_.Set(false);
+  return samples;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/memory_profiler/SamplingNativeHeapProfiler.h b/third_party/WebKit/Source/platform/memory_profiler/SamplingNativeHeapProfiler.h
new file mode 100644
index 0000000..21ad80e
--- /dev/null
+++ b/third_party/WebKit/Source/platform/memory_profiler/SamplingNativeHeapProfiler.h
@@ -0,0 +1,70 @@
+// 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 SamplingNativeHeapProfiler_h
+#define SamplingNativeHeapProfiler_h
+
+#include <unordered_map>
+#include <vector>
+
+#include "base/atomicops.h"
+#include "base/macros.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_local.h"
+#include "platform/PlatformExport.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+namespace blink {
+
+class PLATFORM_EXPORT SamplingNativeHeapProfiler {
+ public:
+  struct Sample {
+    size_t size;
+    size_t count;
+    unsigned offset;
+    std::vector<void*> stack;
+  };
+
+  SamplingNativeHeapProfiler() = default;
+
+  void Start();
+  void Stop();
+  void SetSamplingInterval(unsigned sampling_interval);
+  void SuppressRandomnessForTest();
+
+  std::vector<Sample> GetSamples();
+
+  static SamplingNativeHeapProfiler* GetInstance();
+
+  static inline bool CreateAllocSample(size_t, Sample*);
+  void* RecordAlloc(Sample&,
+                    void* address,
+                    unsigned offset,
+                    unsigned skip_frames,
+                    bool preserve_data = false);
+  void* RecordFree(void* address);
+
+ private:
+  static void InstallAllocatorHooksOnce();
+  static bool InstallAllocatorHooks();
+  static intptr_t GetNextSampleInterval(uint64_t base_interval);
+
+  void RecordStackTrace(Sample*, unsigned skip_frames);
+
+  base::ThreadLocalBoolean entered_;
+  base::Lock mutex_;
+  std::unordered_map<void*, Sample> samples_;
+
+  friend struct base::DefaultSingletonTraits<SamplingNativeHeapProfiler>;
+
+  DISALLOW_COPY_AND_ASSIGN(SamplingNativeHeapProfiler);
+};
+
+}  // namespace blink
+
+#endif  // SamplingNativeHeapProfiler_h
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
index 27b3b8d..453d6b7d 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
@@ -849,8 +849,9 @@
 }
 
 bool TaskQueueManager::ShouldRecordCPUTimeForTask() {
-  return uniform_distribution_(random_generator_) <
-         kSamplingRateForRecordingCPUTime;
+  return base::ThreadTicks::IsSupported() &&
+         uniform_distribution_(random_generator_) <
+             kSamplingRateForRecordingCPUTime;
 }
 
 void TaskQueueManager::SetRandomSeed(uint64_t value) {
diff --git a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
index 52aee356..361aff4 100644
--- a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
+++ b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
@@ -17,192 +17,44 @@
 // using the image corpii used to assess Blink image decode performance. Refer
 // to http://crbug.com/398235#c103 and http://crbug.com/258324#c5
 
-#include <memory>
+#include <fstream>
+
 #include "base/command_line.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/message_loop/message_loop.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "platform/SharedBuffer.h"
 #include "platform/image-decoders/ImageDecoder.h"
-#include "platform/wtf/PtrUtil.h"
+#include "platform/wtf/Time.h"
+#include "platform/wtf/Vector.h"
 #include "public/platform/Platform.h"
 #include "ui/gfx/test/icc_profiles.h"
 
-#if defined(_WIN32)
-#include <mmsystem.h>
-#include <sys/stat.h>
-#include <time.h>
-#define stat(x, y) _stat(x, y)
-typedef struct _stat sttype;
-#else
-#include <sys/stat.h>
-#include <sys/time.h>
-typedef struct stat sttype;
-#endif
-
 namespace blink {
 
 namespace {
 
-#if defined(_WIN32)
-
-// There is no real platform support herein, so adopt the WIN32 performance
-// counter from WTF
-// http://trac.webkit.org/browser/trunk/Source/WTF/wtf/CurrentTime.cpp?rev=152438
-
-static double LowResUTCTime() {
-  FILETIME file_time;
-  GetSystemTimeAsFileTime(&file_time);
-
-  // As per Windows documentation for FILETIME, copy the resulting FILETIME
-  // structure to a ULARGE_INTEGER structure using memcpy (using memcpy instead
-  // of direct assignment can prevent alignment faults on 64-bit Windows).
-  ULARGE_INTEGER date_time;
-  memcpy(&date_time, &file_time, sizeof(date_time));
-
-  // Number of 100 nanosecond between January 1, 1601 and January 1, 1970.
-  static const ULONGLONG kEpochBias = 116444736000000000ULL;
-  // Windows file times are in 100s of nanoseconds.
-  static const double kHundredsOfNanosecondsPerMillisecond = 10000;
-  return (date_time.QuadPart - kEpochBias) /
-         kHundredsOfNanosecondsPerMillisecond;
-}
-
-static LARGE_INTEGER g_qpc_frequency;
-static bool g_synced_time;
-
-static double HighResUpTime() {
-  // We use QPC, but only after sanity checking its result, due to bugs:
-  // http://support.microsoft.com/kb/274323
-  // http://support.microsoft.com/kb/895980
-  // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("you can get
-  // different results on different processors due to bugs in the basic
-  // input/output system (BIOS) or the hardware abstraction layer (HAL).").
-
-  static LARGE_INTEGER qpc_last;
-  static DWORD tick_count_last;
-  static bool inited;
-
-  LARGE_INTEGER qpc;
-  QueryPerformanceCounter(&qpc);
-  DWORD tick_count = GetTickCount();
-
-  if (inited) {
-    __int64 qpc_elapsed =
-        ((qpc.QuadPart - qpc_last.QuadPart) * 1000) / g_qpc_frequency.QuadPart;
-    __int64 tick_count_elapsed;
-    if (tick_count >= tick_count_last) {
-      tick_count_elapsed = (tick_count - tick_count_last);
-    } else {
-      __int64 tick_count_large = tick_count + 0x100000000I64;
-      tick_count_elapsed = tick_count_large - tick_count_last;
-    }
-
-    // Force a re-sync if QueryPerformanceCounter differs from GetTickCount() by
-    // more than 500ms. (The 500ms value is from
-    // http://support.microsoft.com/kb/274323).
-    __int64 diff = tick_count_elapsed - qpc_elapsed;
-    if (diff > 500 || diff < -500)
-      g_synced_time = false;
-  } else {
-    inited = true;
-  }
-
-  qpc_last = qpc;
-  tick_count_last = tick_count;
-
-  return (1000.0 * qpc.QuadPart) /
-         static_cast<double>(g_qpc_frequency.QuadPart);
-}
-
-static bool QpcAvailable() {
-  static bool available;
-  static bool checked;
-
-  if (checked)
-    return available;
-
-  available = QueryPerformanceFrequency(&g_qpc_frequency);
-  checked = true;
-  return available;
-}
-
-static double GetCurrentTime() {
-  // Use a combination of ftime and QueryPerformanceCounter.
-  // ftime returns the information we want, but doesn't have sufficient
-  // resolution.  QueryPerformanceCounter has high resolution, but is only
-  // usable to measure time intervals.  To combine them, we call ftime and
-  // QueryPerformanceCounter initially. Later calls will use
-  // QueryPerformanceCounter by itself, adding the delta to the saved ftime.  We
-  // periodically re-sync to correct for drift.
-  static double sync_low_res_utc_time;
-  static double sync_high_res_up_time;
-  static double last_utc_time;
-
-  double low_res_time = LowResUTCTime();
-  if (!QpcAvailable())
-    return low_res_time * (1.0 / 1000.0);
-
-  double high_res_time = HighResUpTime();
-  if (!g_synced_time) {
-    timeBeginPeriod(1);  // increase time resolution around low-res time getter
-    sync_low_res_utc_time = low_res_time = LowResUTCTime();
-    timeEndPeriod(1);  // restore time resolution
-    sync_high_res_up_time = high_res_time;
-    g_synced_time = true;
-  }
-
-  double high_res_elapsed = high_res_time - sync_high_res_up_time;
-  double utc = sync_low_res_utc_time + high_res_elapsed;
-
-  // Force a clock re-sync if we've drifted.
-  double low_res_elapsed = low_res_time - sync_low_res_utc_time;
-  const double kMaximumAllowedDriftMsec =
-      15.625 * 2.0;  // 2x the typical low-res accuracy
-  if (fabs(high_res_elapsed - low_res_elapsed) > kMaximumAllowedDriftMsec)
-    g_synced_time = false;
-
-  // Make sure time doesn't run backwards (only correct if the difference is < 2
-  // seconds, since DST or clock changes could occur).
-  const double kBackwardTimeLimit = 2000.0;
-  if (utc < last_utc_time && (last_utc_time - utc) < kBackwardTimeLimit)
-    return last_utc_time * (1.0 / 1000.0);
-
-  last_utc_time = utc;
-  return utc * (1.0 / 1000.0);
-}
-
-#else
-
-static double GetCurrentTime() {
-  struct timeval now;
-  gettimeofday(&now, nullptr);
-  return now.tv_sec + now.tv_usec * (1.0 / 1000000.0);
-}
-
-#endif
-
-scoped_refptr<SharedBuffer> ReadFile(const char* file_name) {
-  FILE* fp = fopen(file_name, "rb");
-  if (!fp) {
-    fprintf(stderr, "Can't open file %s\n", file_name);
+scoped_refptr<SharedBuffer> ReadFile(const char* name) {
+  std::ifstream file(name, std::ios::in | std::ios::binary);
+  if (!file) {
+    fprintf(stderr, "Can't open file %s\n", name);
     exit(2);
   }
 
-  sttype s;
-  stat(file_name, &s);
-  size_t file_size = s.st_size;
-  if (s.st_size <= 0)
+  file.seekg(0, std::ios::end);
+  size_t file_size = file.tellg();
+  file.seekg(0, std::ios::beg);
+
+  if (!file || !file_size)
     return SharedBuffer::Create();
 
-  auto buffer = std::make_unique<unsigned char[]>(file_size);
-  if (file_size != fread(buffer.get(), 1, file_size, fp)) {
-    fprintf(stderr, "Error reading file %s\n", file_name);
+  Vector<char> buffer(file_size);
+  if (!file.read(buffer.data(), file_size)) {
+    fprintf(stderr, "Error reading file %s\n", name);
     exit(2);
   }
 
-  fclose(fp);
-  return SharedBuffer::Create(buffer.get(), file_size);
+  return SharedBuffer::AdoptVector(buffer);
 }
 
 bool DecodeImageData(SharedBuffer* data,
@@ -333,10 +185,10 @@
   double total_time = 0.0;
 
   for (size_t i = 0; i < iterations; ++i) {
-    double start_time = GetCurrentTime();
+    auto start_time = CurrentTimeTicks();
     bool decoded =
         DecodeImageData(data.get(), apply_color_correction, packet_size);
-    double elapsed_time = GetCurrentTime() - start_time;
+    double elapsed_time = (CurrentTimeTicks() - start_time).InSecondsF();
     total_time += elapsed_time;
     if (!decoded) {
       fprintf(stderr, "Image decode failed [%s]\n", argv[1]);
diff --git a/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom b/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
index 1d1f8d64..23222fd0 100644
--- a/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
+++ b/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
@@ -82,23 +82,6 @@
   GetAudioInputCapabilities()
       => (array<AudioInputDeviceCapabilities> audio_input_device_capabilities);
 
-  // TODO(c.padhi): Remove below two methods once device change migration to
-  // blink is complete, see https://crbug.com/793297.
-  // Creates a subscription for device-change notifications for the calling
-  // frame/security origin. It is the responsibility of the caller to send
-  // |subscription_id| values that are unique per device type.
-  // Requests to create a subscription with an ID that already exists for type
-  // |type| are invalid and result in a renderer crash.
-  SubscribeDeviceChangeNotifications(MediaDeviceType type,
-                                     uint32 subscription_id);
-
-  // Removes a subscription to device-change notifications for the calling
-  // frame. The caller is responsible for sending |subscription_id| values that
-  // that refer to existing subscriptions for type |type|. Requests to remove
-  // a nonexisting subscription with are invalid and result in a renderer crash.
-  UnsubscribeDeviceChangeNotifications(MediaDeviceType type,
-                                       uint32 subscription_id);
-
   // Subscribes |listener| to device-change notifications for the calling
   // frame/security origin. |listener| will receive notifications only for
   // device types decided by the boolean fields. Closing the pipe will cancel
@@ -112,13 +95,10 @@
 // This object lives in the renderer process and is used by the browser process
 // to pass device-change notifications to the renderer.
 interface MediaDevicesListener {
-  // TODO(c.padhi): Remove |subscription_id| once device change migration to
-  // blink is complete, see https://crbug.com/793297.
-  // Called to notify a change in the set of devices of type |type| for
-  // subscription |subscription_id|. |device_infos| contains the new list of
-  // devices of type |type|, with device and group IDs obfuscated according to
-  // the subscription's security origin.
+  // Called to notify a change in the set of devices of type |type|.
+  // |device_infos| contains the new list of devices of type |type|, with
+  // device and group IDs obfuscated according to the subscription's security
+  // origin.
   OnDevicesChanged(MediaDeviceType type,
-                   uint32 subscription_id,
                    array<MediaDeviceInfo> device_infos);
 };
diff --git a/third_party/WebKit/public/platform/web_feature.mojom b/third_party/WebKit/public/platform/web_feature.mojom
index 09dd45d..334d1cc 100644
--- a/third_party/WebKit/public/platform/web_feature.mojom
+++ b/third_party/WebKit/public/platform/web_feature.mojom
@@ -487,10 +487,6 @@
   kV8Permissions_Query_Method = 750,
   // The above items are available in M43 branch.
 
-  kV8HTMLInputElement_Autocapitalize_AttributeGetter = 754,
-  kV8HTMLInputElement_Autocapitalize_AttributeSetter = 755,
-  kV8HTMLTextAreaElement_Autocapitalize_AttributeGetter = 756,
-  kV8HTMLTextAreaElement_Autocapitalize_AttributeSetter = 757,
   kSVGHrefBaseVal = 758,
   kSVGHrefAnimVal = 759,
   kV8CSSRuleList_Item_Method = 760,
@@ -1853,6 +1849,8 @@
   kRTCPeerConnectionWithActiveCsp = 2346,
   kImageDecodingAttribute = 2347,
   kImageDecodeAPI = 2348,
+  kV8HTMLElement_Autocapitalize_AttributeGetter = 2349,
+  kV8HTMLElement_Autocapitalize_AttributeSetter = 2350,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/tools/move_blink_source.py b/third_party/blink/tools/move_blink_source.py
index ac5122e..ba661ac 100755
--- a/third_party/blink/tools/move_blink_source.py
+++ b/third_party/blink/tools/move_blink_source.py
@@ -240,6 +240,35 @@
 Bug: 768828
 """)
 
+    def fix_branch(self):
+        git = Git(cwd=self._repo_root)
+        status = self._get_local_change_status(git)
+
+        # TODO(tkent): Apply "update" command only to files without "D" status.
+        # TODO(tkent): Apply "move" command only to them
+        # TODO(tkent): Show a message about "D" status files.
+
+    def _get_local_change_status(self, git):
+        """Returns a list of tuples representing local change summary.
+
+        Each tuple contains two strings. The first one is file change status
+        such as "M", "D".  See --diff-filter section of git-diff manual page.
+        The second one is file name relative to the repository top.
+        """
+
+        base_commit = git.run(['show-branch', '--merge-base', 'master', 'HEAD']).strip()
+        # Note that file names in the following command result are always
+        # slash-separated, even on Windows.
+        status_lines = git.run(['diff', '--name-status', '--no-renames', base_commit]).split('\n')
+        status_tuple_list = []
+        for l in status_lines:
+            items = l.split('\t')
+            if len(items) == 2:
+                status_tuple_list.append(tuple(items))
+            elif len(l) > 0:
+                _log.warning('Unrecognized diff output: "%s"', l)
+        return status_tuple_list
+
     def _get_checked_in_files(self, git):
         files_text = git.run(['ls-files',
                               'third_party/WebKit/Source',
@@ -533,12 +562,17 @@
     move_parser.add_argument('--git', dest='run_git', action='store_true',
                              help='Run |git mv| command instead of |mv|.')
 
+    fixbranch_parser = sub_parsers.add_parser('fixbranch')
+    fixbranch_parser.set_defaults(command='fixbranch', run=True, run_git=True)
+
     options = parser.parse_args()
     mover = MoveBlinkSource(FileSystem(), options, get_chromium_src_dir())
     if options.command == 'update':
         mover.update()
     elif options.command == 'move':
         mover.move()
+    elif options.command == 'fixbranch':
+        mover.fix_branch()
 
 
 if __name__ == '__main__':
diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
index e87d129..273e5f2 100644
--- a/third_party/zlib/BUILD.gn
+++ b/third_party/zlib/BUILD.gn
@@ -282,3 +282,24 @@
 
   public_configs = [ ":zlib_config" ]
 }
+
+executable("zlib_bench") {
+  include_dirs = [ "." ]
+
+  sources = [
+    "contrib/bench/zlib_bench.cc",
+  ]
+
+  if (!is_debug) {
+    configs -= [ "//build/config/compiler:default_optimization" ]
+    configs += [ "//build/config/compiler:optimize_speed" ]
+  }
+
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [ "//build/config/compiler:no_chromium_code" ]
+
+  deps = [
+    "//build/config:exe_and_shlib_deps",
+    ":zlib",
+  ]
+}
diff --git a/third_party/zlib/contrib/bench/zlib_bench.cc b/third_party/zlib/contrib/bench/zlib_bench.cc
new file mode 100644
index 0000000..300cf09
--- /dev/null
+++ b/third_party/zlib/contrib/bench/zlib_bench.cc
@@ -0,0 +1,299 @@
+/*
+ * 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 Chromium source repository LICENSE file.
+ *
+ * A benchmark test harness for measuring decoding performance of gzip or zlib
+ * (deflate) encoded compressed data. Given a file containing any data, encode
+ * (compress) it into gzip or zlib format and then decode (uncompress). Output
+ * the median and maximum encoding and decoding rates in MB/s.
+ *
+ * Raw deflate (no gzip or zlib stream wrapper) mode is also supported. Select
+ * it with the [raw] argument. Use the [gzip] [zlib] arguments to select those
+ * stream wrappers.
+ *
+ * Note this code can be compiled outside of the Chromium build system against
+ * the system zlib (-lz) with g++ or clang++ as follows:
+ *
+ *   g++|clang++ -O3 -Wall -std=c++11 -lstdc++ -lz zlib_bench.cc
+ */
+
+#include <algorithm>
+#include <chrono>
+#include <fstream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <memory.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "zlib.h"
+
+void error_exit(const char* error, int code) {
+  fprintf(stderr, "%s (%d)\n", error, code);
+  exit(code);
+}
+
+inline char* string_data(std::string* s) {
+  return s->empty() ? 0 : &*s->begin();
+}
+
+struct Data {
+  Data(size_t s) { data.reset(new (std::nothrow) char[size = s]); }
+  std::unique_ptr<char[]> data;
+  size_t size;
+};
+
+Data read_file_data_or_exit(const char* name) {
+  std::ifstream file;
+
+  file.open(name, std::ios::in | std::ios::binary);
+  if (!file) {
+    perror(name);
+    exit(1);
+  }
+
+  file.seekg(0, std::ios::end);
+  Data data(file.tellg());
+  file.seekg(0, std::ios::beg);
+
+  if (data.data)
+    file.read(data.data.get(), data.size);
+
+  if (file.bad() || !data.data) {
+    perror((std::string("error reading ") + name).c_str());
+    exit(1);
+  } else if (!data.size) {
+    fprintf(stderr, "%s is empty\n", name);
+    exit(1);
+  }
+
+  return data;
+}
+
+size_t zlib_estimate_compressed_size(size_t input_size) {
+  return compressBound(input_size);
+}
+
+enum zlib_wrapper {
+  kWrapperNONE,
+  kWrapperZLIB,
+  kWrapperGZIP,
+  kWrapperZRAW,
+};
+
+inline int zlib_stream_wrapper_type(zlib_wrapper type) {
+  if (type == kWrapperZLIB) // zlib DEFLATE stream wrapper
+    return MAX_WBITS;
+  if (type == kWrapperGZIP) // gzip DEFLATE stream wrapper
+    return MAX_WBITS + 16;
+  if (type == kWrapperZRAW) // no wrapper, use raw DEFLATE
+    return -MAX_WBITS;
+  error_exit("bad wrapper type", int(type));
+  return 0;
+}
+
+const char* zlib_wrapper_name(zlib_wrapper type) {
+  if (type == kWrapperZLIB)
+    return "ZLIB";
+  if (type == kWrapperGZIP)
+    return "GZIP";
+  if (type == kWrapperZRAW)
+    return "RAW";
+  error_exit("bad wrapper type", int(type));
+  return 0;
+}
+
+void zlib_compress(
+    const zlib_wrapper type,
+    const char* input,
+    const size_t input_size,
+    std::string* output,
+    bool resize_output = false)
+{
+  if (resize_output)
+    output->resize(zlib_estimate_compressed_size(input_size));
+  size_t output_size = output->size();
+
+  z_stream stream;
+  memset(&stream, 0, sizeof(stream));
+
+  int result = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
+      zlib_stream_wrapper_type(type), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+  if (result != Z_OK)
+    error_exit("deflateInit2 failed", result);
+
+  stream.next_out = (Bytef*)string_data(output);
+  stream.avail_out = (uInt)output_size;
+  stream.next_in = (z_const Bytef*)input;
+  stream.avail_in = (uInt)input_size;
+
+  result = deflate(&stream, Z_FINISH);
+  if (result == Z_STREAM_END)
+    output_size = stream.total_out;
+  result |= deflateEnd(&stream);
+  if (result != Z_STREAM_END)
+    error_exit("compress failed", result);
+
+  if (resize_output)
+    output->resize(output_size);
+}
+
+void zlib_uncompress(
+    const zlib_wrapper type,
+    const std::string& input,
+    const size_t output_size,
+    std::string* output)
+{
+  z_stream stream;
+  memset(&stream, 0, sizeof(stream));
+
+  int result = inflateInit2(&stream, zlib_stream_wrapper_type(type));
+  if (result != Z_OK)
+    error_exit("inflateInit2 failed", result);
+
+  stream.next_out = (Bytef*)string_data(output);
+  stream.avail_out = (uInt)output->size();
+  stream.next_in = (z_const Bytef*)input.data();
+  stream.avail_in = (uInt)input.size();
+
+  result = inflate(&stream, Z_FINISH);
+  if (stream.total_out != output_size)
+    result = Z_DATA_ERROR;
+  result |= inflateEnd(&stream);
+  if (result == Z_STREAM_END)
+    return;
+
+  std::string error("uncompress failed: ");
+  if (stream.msg)
+    error.append(stream.msg);
+  error_exit(error.c_str(), result);
+}
+
+void verify_equal(const char* input, size_t size, std::string* output) {
+  const char* data = string_data(output);
+  if (output->size() == size && !memcmp(data, input, size))
+    return;
+  fprintf(stderr, "uncompressed data does not match the input data\n");
+  exit(3);
+}
+
+void zlib_file(const char* name, const zlib_wrapper type) {
+  /*
+   * Read the file data.
+   */
+  const auto file = read_file_data_or_exit(name);
+  const int length = static_cast<int>(file.size);
+  const char* data = file.data.get();
+  printf("%-40s :\n", name);
+
+  /*
+   * Chop the data into blocks.
+   */
+  const int block_size = 1 << 20;
+  const int blocks = (length + block_size - 1) / block_size;
+
+  std::vector<const char*> input(blocks);
+  std::vector<size_t> input_length(blocks);
+  std::vector<std::string> compressed(blocks);
+  std::vector<std::string> output(blocks);
+
+  for (int b = 0; b < blocks; ++b) {
+    int input_start = b * block_size;
+    int input_limit = std::min<int>((b + 1) * block_size, length);
+    input[b] = data + input_start;
+    input_length[b] = input_limit - input_start;
+  }
+
+  /*
+   * Run the zlib compress/uncompress loop a few times with |repeats| to
+   * process about 10MB of data if the length is small relative to 10MB.
+   * If length is large relative to 10MB, process the data once.
+   */
+  const int mega_byte = 1024 * 1024;
+  const int repeats = (10 * mega_byte + length) / (length + 1);
+  const int runs = 5;
+  double ctime[runs];
+  double utime[runs];
+
+  for (int run = 0; run < runs; ++run) {
+    const auto now = [] { return std::chrono::steady_clock::now(); };
+
+    // Pre-grow the output buffer so we don't measure string resize time.
+    for (int b = 0; b < blocks; ++b)
+      compressed[b].resize(zlib_estimate_compressed_size(block_size));
+
+    auto start = now();
+    for (int b = 0; b < blocks; ++b)
+      for (int r = 0; r < repeats; ++r)
+        zlib_compress(type, input[b], input_length[b], &compressed[b]);
+    ctime[run] = std::chrono::duration<double>(now() - start).count();
+
+    // Compress again, resizing compressed, so we don't leave junk at the
+    // end of the compressed string that could confuse zlib_uncompress().
+    for (int b = 0; b < blocks; ++b)
+      zlib_compress(type, input[b], input_length[b], &compressed[b], true);
+
+    for (int b = 0; b < blocks; ++b)
+      output[b].resize(input_length[b]);
+
+    start = now();
+    for (int r = 0; r < repeats; ++r)
+      for (int b = 0; b < blocks; ++b)
+        zlib_uncompress(type, compressed[b], input_length[b], &output[b]);
+    utime[run] = std::chrono::duration<double>(now() - start).count();
+
+    for (int b = 0; b < blocks; ++b)
+      verify_equal(input[b], input_length[b], &output[b]);
+  }
+
+  /*
+   * Output the median/maximum compress/uncompress rates in MB/s.
+   */
+  size_t output_length = 0;
+  for (size_t i = 0; i < compressed.size(); ++i)
+    output_length += compressed[i].size();
+
+  std::sort(ctime, ctime + runs);
+  std::sort(utime, utime + runs);
+
+  double deflate_rate_med = length * repeats / mega_byte / ctime[runs / 2];
+  double inflate_rate_med = length * repeats / mega_byte / utime[runs / 2];
+  double deflate_rate_max = length * repeats / mega_byte / ctime[0];
+  double inflate_rate_max = length * repeats / mega_byte / utime[0];
+
+  // type, block size, compression ratio, etc
+  printf("%s: [b %dM] bytes %6d -> %6u %4.1f%%",
+    zlib_wrapper_name(type), block_size / (1 << 20), length,
+    static_cast<unsigned>(output_length), output_length * 100.0 / length);
+
+  // compress / uncompress median (max) rates
+  printf(" comp %5.1f (%5.1f) MB/s uncomp %5.1f (%5.1f) MB/s\n",
+    deflate_rate_med, deflate_rate_max, inflate_rate_med, inflate_rate_max);
+}
+
+int main(int argc, char* argv[]) {
+  zlib_wrapper type = kWrapperNONE;
+
+  if (argc > 1) {
+    if (!strcmp(argv[1], "zlib"))
+      type = kWrapperZLIB;
+    else if (!strcmp(argv[1], "gzip"))
+      type = kWrapperGZIP;
+    else if (!strcmp(argv[1], "raw"))
+      type = kWrapperZRAW;
+  }
+
+  if ((type != kWrapperNONE) && (argc > 2)) {
+    for (int file = 2; file < argc; ++file)
+      zlib_file(argv[file], type);
+    return 0;
+  }
+
+  printf("usage: %s gzip|zlib|raw files...\n", argv[0]);
+  return 1;
+}
diff --git a/tools/cygprofile/orderfile_generator_backend.py b/tools/cygprofile/orderfile_generator_backend.py
index 3827be7..45db9aae 100755
--- a/tools/cygprofile/orderfile_generator_backend.py
+++ b/tools/cygprofile/orderfile_generator_backend.py
@@ -539,8 +539,10 @@
       self._step_recorder.BeginStep('Process cyglog')
       if self._options.lightweight_instrumentation:
         assert os.path.exists(self._compiler.lib_chrome_so)
-        process_profiles.GetReachedSymbolsFromDumpsAndMaybeWriteOffsets(
-            files, self._compiler.lib_chrome_so, self._MERGED_CYGLOG_FILENAME)
+        offsets = process_profiles.GetReachedOffsetsFromDumpFiles(
+            files, self._compiler.lib_chrome_so)
+        with open(self._MERGED_CYGLOG_FILENAME, 'w') as f:
+          f.write('\n'.join(map(str, offsets)))
       else:
         with open(self._MERGED_CYGLOG_FILENAME, 'w') as merged_cyglog:
           self._step_recorder.RunCommand([self._MERGE_TRACES_SCRIPT] + files,
diff --git a/tools/cygprofile/process_profiles.py b/tools/cygprofile/process_profiles.py
index 22e66ca..12945cd 100755
--- a/tools/cygprofile/process_profiles.py
+++ b/tools/cygprofile/process_profiles.py
@@ -18,11 +18,160 @@
 import symbol_extractor
 
 
+class SymbolOffsetProcessor(object):
+  """Utility for processing symbols in binaries.
+
+  This class is used to translate between general offsets into a binary and the
+  starting offset of symbols in the binary. Because later phases in orderfile
+  generation have complicated strategies for resolving multiple symbols that map
+  to the same binary offset, this class is concerned with locating a symbol
+  containing a binary offset. If such a symbol exists, the start offset will be
+  unique, even when there are multiple symbol names at the same location in the
+  binary.
+
+  In the function names below, "dump" is used to refer to arbitrary offsets in a
+  binary (eg, from a profiling run), while "offset" refers to a symbol
+  offset. The dump offsets are relative to the start of text, as returned by
+  lightweight_cygprofile.cc.
+
+  This class manages expensive operations like extracting symbols, so that
+  higher-level operations can be done in different orders without the caller
+  managing all the state.
+  """
+
+  def __init__(self, binary_filename):
+    self._binary_filename = binary_filename
+    self._symbol_infos = None
+    self._name_to_symbol = None
+    self._offset_to_primary = None
+
+  def SymbolInfos(self):
+    """The symbols associated with this processor's binary.
+
+    The symbols are ordered by offset.
+
+    Returns:
+      [symbol_extractor.SymbolInfo]
+    """
+    if self._symbol_infos is None:
+      self._symbol_infos = symbol_extractor.SymbolInfosFromBinary(
+          self._binary_filename)
+      self._symbol_infos.sort(key=lambda s: s.offset)
+      logging.info('%d symbols from %s',
+                   len(self._symbol_infos), self._binary_filename)
+    return self._symbol_infos
+
+  def NameToSymbolMap(self):
+    """Map symbol names to their full information.
+
+    Returns:
+      {symbol name (str): symbol_extractor.SymbolInfo}
+    """
+    if self._name_to_symbol is None:
+      self._name_to_symbol = {s.name: s for s in self.SymbolInfos()}
+    return self._name_to_symbol
+
+  def OffsetToPrimaryMap(self):
+    """The map of a symbol offset in this binary to its primary symbol.
+
+    Several symbols can be aliased to the same address, through ICF. This
+    returns the first one. The order is consistent for a given binary, as it's
+    derived from the file layout. We assert that all aliased symbols are the
+    same size.
+
+    Returns:
+      {offset (int): primary (symbol_extractor.SymbolInfo)}
+    """
+    if self._offset_to_primary is None:
+      self._offset_to_primary = {}
+      for s in self.SymbolInfos():
+        if s.offset not in self._offset_to_primary:
+          self._offset_to_primary[s.offset] = s
+        else:
+          curr = self._offset_to_primary[s.offset]
+          if curr.size != s.size:
+            assert curr.size == 0 or s.size == 0, (
+                'Nonzero size mismatch between {} and {}'.format(
+                    curr.name, s.name))
+            # Upgrade to a symbol with nonzero size, otherwise don't change
+            # anything so that we use the earliest nonzero-size symbol.
+            if curr.size == 0 and s.size != 0:
+              self._offset_to_primary[s.offset] = s
+
+    return self._offset_to_primary
+
+  def GetReachedOffsetsFromDump(self, dump):
+    """Find the symbol offsets from a list of binary offsets.
+
+    The dump is a list offsets into a .text section. This finds the symbols
+    which contain the dump offsets, and returns their offsets. Note that while
+    usually a symbol offset corresponds to a single symbol, in some cases
+    several symbols will map to the same offset. For that reason this function
+    returns only the offset list. See cyglog_to_orderfile.py for computing more
+    information about symbols.
+
+    Args:
+     dump: (int iterable) Dump offsets, for example as returned by MergeDumps().
+
+    Returns:
+      [int] Reached symbol offsets.
+    """
+    dump_offset_to_symbol_info = self._GetDumpOffsetToSymbolInfo()
+    logging.info('Offset to Symbol size = %d', len(dump_offset_to_symbol_info))
+    assert max(dump) / 4 <= len(dump_offset_to_symbol_info)
+    already_seen = set()
+    reached_offsets = []
+    reached_return_addresses_not_found = 0
+    for dump_offset in dump:
+      symbol_info = dump_offset_to_symbol_info[dump_offset / 4]
+      if symbol_info is None:
+        reached_return_addresses_not_found += 1
+        continue
+      if symbol_info.offset in already_seen:
+        continue
+      reached_offsets.append(symbol_info.offset)
+      already_seen.add(symbol_info.offset)
+    if reached_return_addresses_not_found:
+      logging.warning('%d return addresses don\'t map to any symbol',
+                      reached_return_addresses_not_found)
+    return reached_offsets
+
+  def MatchSymbolNames(self, symbol_names):
+    """Find the symbols in this binary which match a list of symbols.
+
+    Args:
+      symbol_names (str iterable) List of symbol names.
+
+    Returns:
+      [symbol_extractor.SymbolInfo] Symbols in this binary matching the names.
+    """
+    our_symbol_names = set(s.name for s in self.SymbolInfos())
+    matched_names = our_symbol_names.intersection(set(symbol_names))
+    return [self.NameToSymbolMap()[n] for n in matched_names]
+
+  def _GetDumpOffsetToSymbolInfo(self):
+    """Computes an array mapping each word in .text to a symbol.
+
+    Returns:
+      [symbol_extractor.SymbolInfo or None] For every 4 bytes of the .text
+        section, maps it to a symbol, or None.
+    """
+    min_offset = min(s.offset for s in self.SymbolInfos())
+    max_offset = max(s.offset + s.size for s in self.SymbolInfos())
+    text_length_words = (max_offset - min_offset) / 4
+    offset_to_symbol_info = [None for _ in xrange(text_length_words)]
+    for s in self.SymbolInfos():
+      offset = s.offset - min_offset
+      for i in range(offset / 4, (offset + s.size) / 4):
+        offset_to_symbol_info[i] = s
+    return offset_to_symbol_info
+
+
 def _SortedFilenames(filenames):
   """Returns filenames in ascending timestamp order.
 
   Args:
-    filenames: ([str]) List of filenames, matching.  *-TIMESTAMP.*.
+    filenames: (str iterable) List of filenames, matching.  *-TIMESTAMP.*.
 
   Returns:
     [str] Ordered by ascending timestamp.
@@ -41,7 +190,7 @@
   """Merges several dumps.
 
   Args:
-    filenames: [str] List of dump filenames.
+    filenames: (str iterable) List of dump filenames.
 
   Returns:
     [int] Ordered list of reached offsets. Each offset only appears
@@ -58,147 +207,22 @@
   return result
 
 
-def GetOffsetToSymbolInfo(symbol_infos):
-  """From a list of symbol infos, returns a offset -> symbol info array.
+def GetReachedOffsetsFromDumpFiles(dump_filenames, library_filename):
+  """Produces a list of symbol offsets reached by the dumps.
 
   Args:
-    symbol_infos: ([symbol_extractor.SymbolInfo]) List of sumbols extracted from
-                  the native library.
+    dump_filenames (str iterable) A list of dump filenames.
+    library_filename (str) The library file which the dumps refer to.
 
   Returns:
-    [symbol_extractor.SymbolInfo or None] For every 4 bytes of the .text
-    section, maps it to a symbol, or None.
+    [int] A list of symbol offsets. This order of symbol offsets produced is
+      given by the deduplicated order of offsets found in dump_filenames (see
+      also MergeDumps().
   """
-  min_offset = min(s.offset for s in symbol_infos)
-  max_offset = max(s.offset + s.size for s in symbol_infos)
-  text_length_words = (max_offset - min_offset) / 4
-  offset_to_symbol_info = [None for _ in xrange(text_length_words)]
-  for s in symbol_infos:
-    offset = s.offset - min_offset
-    for i in range(offset / 4, (offset + s.size) / 4):
-      offset_to_symbol_info[i] = s
-  return offset_to_symbol_info
-
-
-def GetOffsetToSymbolArray(instrumented_native_lib_filename):
-  """From the native library, maps .text offsets to symbols.
-
-  Args:
-    instrumented_native_lib_filename: (str) Native library filename.
-                                      Has to be the instrumented version.
-
-  Returns:
-    [symbol_extractor.SymbolInfo or None] For every 4 bytes of the .text
-    section, maps it to a symbol, or None.
-  """
-  symbol_infos = symbol_extractor.SymbolInfosFromBinary(
-      instrumented_native_lib_filename)
-  logging.info('%d Symbols', len(symbol_infos))
-  return GetOffsetToSymbolInfo(symbol_infos)
-
-
-def GetReachedSymbolsFromDump(offsets, offset_to_symbol_info):
-  """From a dump and an offset->symbol array, returns reached symbols.
-
-  Args:
-   offsets: ([int]) As returned by MergeDumps()
-   offset_to_symbol_info: As returned by GetOffsetToSymbolArray()
-
-  Returns:
-    [symbol_extractor.SymbolInfo] Reached symbols.
-  """
-  logging.info('Reached offsets = %d', len(offsets))
-  logging.info('Offset to Symbol size = %d', len(offset_to_symbol_info))
-  assert max(offsets) / 4 <= len(offset_to_symbol_info)
-  already_seen = set()
-  reached_symbols = []
-  reached_return_addresses_not_found = 0
-  for offset in offsets:
-    symbol_info = offset_to_symbol_info[offset / 4]
-    if symbol_info is None:
-      reached_return_addresses_not_found += 1
-      continue
-    if symbol_info in already_seen:
-      continue
-    reached_symbols.append(symbol_info)
-    already_seen.add(symbol_info)
-  if reached_return_addresses_not_found:
-    logging.warning('%d return addresses don\'t map to any symbol',
-                    reached_return_addresses_not_found)
-  return reached_symbols
-
-
-def SymbolNameToPrimary(symbol_infos):
-  """Maps a symbol names to a "primary" symbol.
-
-  Several symbols can be aliased to the same address, through ICF. This returns
-  the first one. The order is consistent for a given binary, as it's derived
-  from the file layout.
-
-  Args:
-    symbol_infos: ([symbol_extractor.SymbolInfo])
-
-  Returns:
-    {name (str): primary (symbol_extractor.SymbolInfo)}
-  """
-  symbol_name_to_primary = {}
-  offset_to_symbol_info = {}
-  for s in symbol_infos:
-    if s.offset not in offset_to_symbol_info:
-      offset_to_symbol_info[s.offset] = s
-  for s in symbol_infos:
-    symbol_name_to_primary[s.name] = offset_to_symbol_info[s.offset]
-  return symbol_name_to_primary
-
-
-def MatchSymbolsInRegularBuild(reached_symbol_infos,
-                               regular_native_lib_filename):
-  """Match a list of symbols to canonical ones on the regular build.
-
-  Args:
-    reached_symbol_infos: ([symbol_extractor.SymbolInfo]) Reached symbol
-      in the instrumented build.
-    regular_native_lib_filename: (str) regular build filename.
-
-  Returns:
-    [symbol_extractor.SymbolInfo] list of matched canonical symbols.
-  """
-  regular_build_symbol_infos = symbol_extractor.SymbolInfosFromBinary(
-      regular_native_lib_filename)
-  regular_build_symbol_names = set(s.name for s in regular_build_symbol_infos)
-  reached_symbol_names = set(s.name for s in reached_symbol_infos)
-  logging.info('Reached symbols = %d', len(reached_symbol_names))
-  matched_names = reached_symbol_names.intersection(regular_build_symbol_names)
-  logging.info('Matched symbols = %d', len(matched_names))
-
-  symbol_name_to_primary = SymbolNameToPrimary(regular_build_symbol_infos)
-  matched_primary_symbols = []
-  for symbol in reached_symbol_names:
-    if symbol in matched_names:
-      matched_primary_symbols.append(symbol_name_to_primary[symbol])
-  return matched_primary_symbols
-
-
-def GetReachedSymbolsFromDumpsAndMaybeWriteOffsets(
-    dump_filenames, native_lib_filename, output_filename):
-  """Merges a list of dumps, returns reached symbols and maybe writes offsets.
-
-  Args:
-    dump_filenames: ([str]) List of dump filenames.
-    native_lib_filename: (str) Path to the native library.
-    output_filename: (str or None) Offset output path, if not None.
-
-  Returns:
-    [symbol_extractor.SymbolInfo] Reached symbols.
-  """
-  offsets = MergeDumps(dump_filenames)
-  offset_to_symbol_info = GetOffsetToSymbolArray(native_lib_filename)
-  reached_symbols = GetReachedSymbolsFromDump(offsets, offset_to_symbol_info)
-  if output_filename:
-    offsets = [s.offset for s in reached_symbols]
-    with open(output_filename, 'w') as f:
-      f.write('\n'.join('%d' % offset for offset in offsets))
-  return reached_symbols
+  dump = MergeDumps(dump_filenames)
+  logging.info('Reached offsets = %d', len(dump))
+  processor = SymbolOffsetProcessor(library_filename)
+  return processor.GetReachedOffsetsFromDump(dump)
 
 
 def CreateArgumentParser():
@@ -215,6 +239,9 @@
   parser.add_argument('--offsets-output', type=str,
                       help='Output filename for the symbol offsets',
                       required=False, default=None)
+  parser.add_argument('--library-name', default='libchrome.so',
+                      help=('Chrome shared library name (usually libchrome.so '
+                            'or libmonochrome.so'))
   return parser
 
 
@@ -223,19 +250,31 @@
   parser = CreateArgumentParser()
   args = parser.parse_args()
   logging.info('Merging dumps')
-  dumps = args.dumps.split(',')
-  sorted_dumps = _SortedFilenames(dumps)
+  dump_files = args.dumps.split(',')
+  dumps = MergeDumps(_SortedFilenames(dump_files))
 
   instrumented_native_lib = os.path.join(args.instrumented_build_dir,
-                                         'lib.unstripped', 'libchrome.so')
+                                         'lib.unstripped', args.library_name)
   regular_native_lib = os.path.join(args.build_dir,
-                                    'lib.unstripped', 'libchrome.so')
+                                    'lib.unstripped', args.library_name)
 
-  reached_symbols = GetReachedSymbolsFromDumpsAndMaybeWriteOffsets(
-      sorted_dumps, instrumented_native_lib, args.offsets_output)
-  logging.info('Reached Symbols = %d', len(reached_symbols))
-  matched_in_regular_build = MatchSymbolsInRegularBuild(reached_symbols,
-                                                        regular_native_lib)
+  instrumented_processor = SymbolOffsetProcessor(instrumented_native_lib)
+
+  reached_offsets = instrumented_processor.GetReachedOffsetsFromDumps(dumps)
+  if args.offsets_output:
+    with file(args.offsets_output, 'w') as f:
+      f.write('\n'.join(map(str, reached_offsets)))
+  logging.info('Reached Offsets = %d', len(reached_offsets))
+
+  primary_map = instrumented_processor.OffsetToPrimaryMap()
+  reached_primary_symbols = set(
+      primary_map[offset] for offset in reached_offsets)
+  logging.info('Reached symbol names = %d', len(reached_primary_symbols))
+
+  regular_processor = SymbolOffsetProcessor(regular_native_lib)
+  matched_in_regular_build = regular_processor.MatchSymbolNames(
+      s.name for s in reached_primary_symbols)
+  logging.info('Matched symbols = %d', len(matched_in_regular_build))
   total_size = sum(s.size for s in matched_in_regular_build)
   logging.info('Total reached size = %d', total_size)
 
diff --git a/tools/cygprofile/process_profiles_unittest.py b/tools/cygprofile/process_profiles_unittest.py
index 352643e4..37db2ad 100644
--- a/tools/cygprofile/process_profiles_unittest.py
+++ b/tools/cygprofile/process_profiles_unittest.py
@@ -13,6 +13,12 @@
 SymbolInfo = collections.namedtuple('SymbolInfo', ['name', 'offset', 'size'])
 
 
+class TestSymbolOffsetProcessor(process_profiles.SymbolOffsetProcessor):
+  def __init__(self, symbol_infos):
+    super(TestSymbolOffsetProcessor, self).__init__(None)
+    self._symbol_infos = symbol_infos
+
+
 class ProcessProfilesTestCase(unittest.TestCase):
 
   def setUp(self):
@@ -23,32 +29,53 @@
     self.offset_to_symbol_info = (
         [None, None] + [self.symbol_1] * 4 + [None] * 2 + [self.symbol_2] * 2
         + [self.symbol_3] * 3)
+    self.symbol_infos = [self.symbol_0, self.symbol_1,
+                         self.symbol_2, self.symbol_3]
 
   def testGetOffsetToSymbolInfo(self):
-    symbol_infos = [self.symbol_0, self.symbol_1, self.symbol_2, self.symbol_3]
-    offset_to_symbol_info = process_profiles.GetOffsetToSymbolInfo(symbol_infos)
+    processor = TestSymbolOffsetProcessor(self.symbol_infos)
+    offset_to_symbol_info = processor._GetDumpOffsetToSymbolInfo()
     self.assertListEqual(self.offset_to_symbol_info, offset_to_symbol_info)
 
   def testGetReachedSymbolsFromDump(self):
+    processor = TestSymbolOffsetProcessor(self.symbol_infos)
     # 2 hits for symbol_1, 0 for symbol_2, 1 for symbol_3
     dump = [8, 12, 48]
-    reached = process_profiles.GetReachedSymbolsFromDump(
-        dump, self.offset_to_symbol_info)
-    self.assertListEqual([self.symbol_1, self.symbol_3], reached)
+    reached = processor.GetReachedOffsetsFromDump(dump)
+    self.assertListEqual([self.symbol_1.offset, self.symbol_3.offset], reached)
     # Ordering matters, no repetitions
     dump = [48, 12, 8, 12, 8, 16]
-    reached = process_profiles.GetReachedSymbolsFromDump(
-        dump, self.offset_to_symbol_info)
-    self.assertListEqual([self.symbol_3, self.symbol_1], reached)
+    reached = processor.GetReachedOffsetsFromDump(dump)
+    self.assertListEqual([self.symbol_3.offset, self.symbol_1.offset], reached)
 
   def testSymbolNameToPrimary(self):
     symbol_infos = [SymbolInfo('1', 8, 16),
                     SymbolInfo('AnAlias', 8, 16),
                     SymbolInfo('Another', 40, 16)]
-    symbol_name_to_primary = process_profiles.SymbolNameToPrimary(symbol_infos)
-    self.assertDictEqual({'1': symbol_infos[0],
-                          'AnAlias': symbol_infos[0],
-                          'Another': symbol_infos[2]}, symbol_name_to_primary)
+    processor = TestSymbolOffsetProcessor(symbol_infos)
+    self.assertDictEqual({8: symbol_infos[0],
+                          40: symbol_infos[2]}, processor.OffsetToPrimaryMap())
+
+  def testPrimarySizeMismatch(self):
+    symbol_infos = [SymbolInfo('1', 8, 16),
+                    SymbolInfo('AnAlias', 8, 32)]
+    processor = TestSymbolOffsetProcessor(symbol_infos)
+    self.assertRaises(AssertionError, processor.OffsetToPrimaryMap)
+    symbol_infos = [SymbolInfo('1', 8, 0),
+                    SymbolInfo('2', 8, 32),
+                    SymbolInfo('3', 8, 32),
+                    SymbolInfo('4', 8, 0),]
+    processor = TestSymbolOffsetProcessor(symbol_infos)
+    self.assertDictEqual({8: symbol_infos[1]}, processor.OffsetToPrimaryMap())
+
+
+  def testMatchSymbols(self):
+    symbols_b = [SymbolInfo('W', 30, 10),
+                 SymbolInfo('Y', 60, 5),
+                 SymbolInfo('X', 100, 10)]
+    processor_b = TestSymbolOffsetProcessor(symbols_b)
+    self.assertListEqual(symbols_b[1:3],
+                         processor_b.MatchSymbolNames(['Y', 'X']))
 
   def testSortedFilenames(self):
     filenames = ['second-1234-456.txt', 'first-345345-123.txt',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index cf1a580..3183b45f 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -1175,6 +1175,9 @@
 </enum>
 
 <enum name="AppListDoodleAction">
+  <obsolete>
+    App list doesn't support doodles anymore.
+  </obsolete>
   <int value="0" label="DOODLE_SHOWN"/>
   <int value="1" label="DOODLE_CLICKED"/>
 </enum>
@@ -17682,6 +17685,8 @@
   <int value="2346" label="RTCPeerConnectionWithActiveCsp"/>
   <int value="2347" label="ImageDecodingAttribute"/>
   <int value="2348" label="ImageDecodeAPI"/>
+  <int value="2349" label="V8HTMLElement_Autocapitalize_AttributeGetter"/>
+  <int value="2350" label="V8HTMLElement_Autocapitalize_AttributeSetter"/>
 </enum>
 
 <enum name="FeedbackSource">
@@ -25030,7 +25035,7 @@
 <enum name="LoadRulesetResult">
   <int value="0" label="Load succeeded"/>
   <int value="1" label="Load failed - Invalid path"/>
-  <int value="2" label="Load failed - Memory Map error"/>
+  <int value="2" label="Load failed - File read error"/>
   <int value="3" label="Load failed - Ruleset verification error"/>
 </enum>
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b07ce83..1b0bf91 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -2062,6 +2062,9 @@
 </histogram>
 
 <histogram name="Apps.AppListDoodleAction" enum="AppListDoodleAction">
+  <obsolete>
+    App list doesn't support doodles anymore.
+  </obsolete>
   <owner>calamity@chromium.org</owner>
   <summary>
     The number of user interactions with the app list doodle. This is logged
@@ -13591,6 +13594,9 @@
 
 <histogram name="DataReductionProxy.Quic.OnAlternativeProxyBroken"
     units="count">
+  <obsolete>
+    As of M66 this has been superceded by Net.AlternativeProxyFailed.
+  </obsolete>
   <owner>tbansal@chromium.org</owner>
   <summary>
     Number of times an alternative QUIC proxy was marked as broken.
@@ -41304,6 +41310,17 @@
   </summary>
 </histogram>
 
+<histogram name="Net.AlternativeProxyFailed" enum="NetErrorCodes">
+  <owner>tbansal@chromium.org</owner>
+  <summary>
+    Positive net error codes that failed alternative proxy requests end with.
+    Recorded when an alternative job fails, whether or not the main job
+    succeeds.
+
+    As of M66 this superceded DataReductionProxy.Quic.OnAlternativeProxyBroken.
+  </summary>
+</histogram>
+
 <histogram name="Net.AlternativeServiceServers.MoreOrEqualCacheEntries">
   <owner>rch@chromium.org</owner>
   <summary>
@@ -94999,8 +95016,9 @@
 <histogram name="Variations.LoadSeedSignature" enum="VariationSeedSignature">
   <owner>asvitkine@chromium.org</owner>
   <summary>
-    The result of verifying the variations seed signature, recorded when the
-    variations seed is loaded from Local State.
+    The result of verifying the latest variations seed's signature, recorded
+    when the seed is loaded from Local State.  Not recorded when running in safe
+    mode.
   </summary>
 </histogram>
 
@@ -95043,6 +95061,26 @@
   </summary>
 </histogram>
 
+<histogram name="Variations.SafeMode.LoadSafeSeed.Result"
+    enum="VariationsSeedLoadResult">
+  <owner>isherman@chromium.org</owner>
+  <summary>
+    Records whether the safe variations seed was successfully read from local
+    state on startup. Records a detailed reason on read failure. Only recorded
+    when attempting to run in safe mode.
+  </summary>
+</histogram>
+
+<histogram name="Variations.SafeMode.LoadSafeSeed.SignatureValidity"
+    enum="VariationSeedSignature">
+  <owner>isherman@chromium.org</owner>
+  <summary>
+    The result of verifying the safe variations seed's signature, recorded when
+    the seed is loaded from Local State. Only recorded when attempting to run in
+    safe mode.
+  </summary>
+</histogram>
+
 <histogram name="Variations.SafeMode.StoreSafeSeed.Result"
     enum="VariationsSeedStoreResult">
   <owner>isherman@chromium.org</owner>
@@ -95197,8 +95235,9 @@
 <histogram name="Variations.SeedLoadResult" enum="VariationsSeedLoadResult">
   <owner>asvitkine@chromium.org</owner>
   <summary>
-    Records whether the variations seed was successfully read from local state
-    on startup. Records a detailed reason on read failure.
+    Records whether the latest variations seed was successfully read from local
+    state on startup. Records a detailed reason on read failure. Not recorded
+    when running in safe mode.
   </summary>
 </histogram>
 
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 85f62d4..ed3ee46f 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -164,7 +164,7 @@
  <item id="privet_http_impl" hash_code="71251498" type="0" content_hash_code="107348604" os_list="linux,windows" file_path="chrome/browser/printing/cloud_print/privet_http_impl.cc"/>
  <item id="profile_avatar" hash_code="51164680" type="0" content_hash_code="113550845" os_list="linux,windows" file_path="chrome/browser/profiles/profile_avatar_downloader.cc"/>
  <item id="profile_resetter_upload" hash_code="105330607" type="0" content_hash_code="129329171" os_list="linux,windows" file_path="chrome/browser/profile_resetter/reset_report_uploader.cc"/>
- <item id="proxy_script_fetcher" hash_code="37531401" type="0" content_hash_code="31866133" os_list="linux,windows" file_path="net/proxy/proxy_script_fetcher_impl.cc"/>
+ <item id="proxy_script_fetcher" hash_code="37531401" type="0" content_hash_code="31866133" os_list="linux,windows" file_path="net/proxy/pac_file_fetcher_impl.cc"/>
  <item id="ranker_url_fetcher" hash_code="95682324" type="0" content_hash_code="45958626" os_list="linux,windows" file_path="components/assist_ranker/ranker_url_fetcher.cc"/>
  <item id="rappor_report" hash_code="44606780" type="0" content_hash_code="111287826" os_list="linux,windows" file_path="components/rappor/log_uploader.cc"/>
  <item id="refresh_token_annotation_request" hash_code="7433837" type="1" second_id="29188932" deprecated="2018-01-17" content_hash_code="137103383" file_path=""/>
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn
index 37b5eac84..53bce0f 100644
--- a/ui/app_list/BUILD.gn
+++ b/ui/app_list/BUILD.gn
@@ -178,7 +178,6 @@
     "//ui/resources",
     "//ui/resources:ui_test_pak",
     "//ui/views",
-    "//ui/views/controls/webview",
     "//ui/views_content_client",
     "//url",
   ]
diff --git a/ui/app_list/app_list_view_delegate.h b/ui/app_list/app_list_view_delegate.h
index 9c87b1b..ef8d98b3 100644
--- a/ui/app_list/app_list_view_delegate.h
+++ b/ui/app_list/app_list_view_delegate.h
@@ -60,9 +60,6 @@
                                         int action_index,
                                         int event_flags) = 0;
 
-  // Invoked when the app list UI is created.
-  virtual void ViewInitialized() = 0;
-
   // Invoked when the app list is shown.
   virtual void ViewShown() = 0;
 
@@ -73,10 +70,6 @@
   // Invoked when the app list is closing.
   virtual void ViewClosing() = 0;
 
-  // Creates the web view for the start page. The caller takes the ownership of
-  // the returned view.
-  virtual views::View* CreateStartPageWebView(const gfx::Size& size) = 0;
-
   // Gets the wallpaper prominent colors.
   virtual void GetWallpaperProminentColors(std::vector<SkColor>* colors) = 0;
 
diff --git a/ui/app_list/demo/app_list_demo_views.cc b/ui/app_list/demo/app_list_demo_views.cc
index 0546e3e2..121d8f0 100644
--- a/ui/app_list/demo/app_list_demo_views.cc
+++ b/ui/app_list/demo/app_list_demo_views.cc
@@ -13,14 +13,11 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "build/build_config.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_switches.h"
 #include "ui/app_list/test/app_list_test_model.h"
 #include "ui/app_list/test/app_list_test_view_delegate.h"
 #include "ui/app_list/views/app_list_view.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/resources/grit/ui_resources.h"
-#include "ui/views/controls/webview/webview.h"
 #include "ui/views_content_client/views_content_client.h"
 
 namespace {
@@ -34,8 +31,7 @@
 // window is closed, and to close the window if it is simply dismissed.
 class DemoAppListViewDelegate : public app_list::test::AppListTestViewDelegate {
  public:
-  explicit DemoAppListViewDelegate(content::BrowserContext* browser_context)
-      : view_(NULL), browser_context_(browser_context) {}
+  DemoAppListViewDelegate() : view_(NULL) {}
   ~DemoAppListViewDelegate() override {}
 
   app_list::AppListView* InitView(gfx::NativeWindow window_context);
@@ -43,12 +39,9 @@
   // Overridden from AppListViewDelegate:
   void Dismiss() override;
   void ViewClosing() override;
-  views::View* CreateStartPageWebView(const gfx::Size& size) override;
 
  private:
   app_list::AppListView* view_;  // Weak. Owns this.
-  content::BrowserContext* browser_context_;
-  std::unique_ptr<content::WebContents> web_contents_;
 
   DISALLOW_COPY_AND_ASSIGN(DemoAppListViewDelegate);
 };
@@ -89,25 +82,8 @@
   base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
-views::View* DemoAppListViewDelegate::CreateStartPageWebView(
-    const gfx::Size& size) {
-  web_contents_.reset(content::WebContents::Create(
-      content::WebContents::CreateParams(browser_context_)));
-  web_contents_->GetController().LoadURL(GURL("http://www.google.com/"),
-                                         content::Referrer(),
-                                         ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
-                                         std::string());
-  views::WebView* web_view = new views::WebView(
-      web_contents_->GetBrowserContext());
-  web_view->SetPreferredSize(size);
-  web_view->SetWebContents(web_contents_.get());
-  return web_view;
-}
-
-void ShowAppList(content::BrowserContext* browser_context,
-                 gfx::NativeWindow window_context) {
-  DemoAppListViewDelegate* delegate =
-      new DemoAppListViewDelegate(browser_context);
+void ShowAppList(gfx::NativeWindow window_context) {
+  DemoAppListViewDelegate* delegate = new DemoAppListViewDelegate;
   app_list::AppListView* view = delegate->InitView(window_context);
   view->GetWidget()->Show();
   view->GetWidget()->Activate();
diff --git a/ui/app_list/test/app_list_test_view_delegate.cc b/ui/app_list/test/app_list_test_view_delegate.cc
index 2b9d50f..414078a1 100644
--- a/ui/app_list/test/app_list_test_view_delegate.cc
+++ b/ui/app_list/test/app_list_test_view_delegate.cc
@@ -47,11 +47,6 @@
   ++dismiss_count_;
 }
 
-views::View* AppListTestViewDelegate::CreateStartPageWebView(
-    const gfx::Size& size) {
-  return NULL;
-}
-
 void AppListTestViewDelegate::ReplaceTestModel(int item_count) {
   model_ = std::make_unique<AppListTestModel>();
   model_->PopulateApps(item_count);
diff --git a/ui/app_list/test/app_list_test_view_delegate.h b/ui/app_list/test/app_list_test_view_delegate.h
index 1b1b745..bc16b49 100644
--- a/ui/app_list/test/app_list_test_view_delegate.h
+++ b/ui/app_list/test/app_list_test_view_delegate.h
@@ -52,11 +52,9 @@
   void InvokeSearchResultAction(SearchResult* result,
                                 int action_index,
                                 int event_flags) override {}
-  void ViewInitialized() override {}
   void ViewShown() override {}
   void Dismiss() override;
   void ViewClosing() override {}
-  views::View* CreateStartPageWebView(const gfx::Size& size) override;
   void GetWallpaperProminentColors(std::vector<SkColor>* colors) override {}
   void ActivateItem(const std::string& id, int event_flags) override;
   ui::MenuModel* GetContextMenuModel(const std::string& id) override;
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc
index 2086744..9b33e43 100644
--- a/ui/app_list/views/app_list_view.cc
+++ b/ui/app_list/views/app_list_view.cc
@@ -280,8 +280,6 @@
 
   SetState(app_list_state_);
 
-  delegate_->ViewInitialized();
-
   UMA_HISTOGRAM_TIMES(kAppListCreationTimeHistogram,
                       base::Time::Now() - start_time);
   RecordFolderMetrics();
diff --git a/ui/gl/gl_image_io_surface.mm b/ui/gl/gl_image_io_surface.mm
index d2af129..b3a2342 100644
--- a/ui/gl/gl_image_io_surface.mm
+++ b/ui/gl/gl_image_io_surface.mm
@@ -188,7 +188,7 @@
 // When an IOSurface is bound to a texture with internalformat "GL_RGB", many
 // OpenGL operations are broken. Therefore, don't allow an IOSurface to be bound
 // with GL_RGB unless overridden via BindTexImageWithInternalformat.
-// crbug.com/595948, crbug.com/699566.
+// https://crbug.com/595948, https://crbug.com/699566.
 GLenum ConvertRequestedInternalFormat(GLenum internalformat) {
   if (internalformat == GL_RGB)
     return GL_RGBA;
diff --git a/ui/gl/gl_image_io_surface_unittest.cc b/ui/gl/gl_image_io_surface_unittest.cc
index 6884e4d09..3c10926 100644
--- a/ui/gl/gl_image_io_surface_unittest.cc
+++ b/ui/gl/gl_image_io_surface_unittest.cc
@@ -40,8 +40,8 @@
     uint8_t corrected_color[4];
     if (format == gfx::BufferFormat::RGBA_8888) {
       // GL_RGBA is not supported by CGLTexImageIOSurface2D(), so we pretend it
-      // is GL_BGRA, (see https://crbug.com/533677) swizzle the channels for the
-      // purpose of this test.
+      // is GL_BGRA, (see https://crbug.com/533677#c6) swizzle the channels for
+      // the purpose of this test.
       corrected_color[0] = color[2];
       corrected_color[1] = color[1];
       corrected_color[2] = color[0];
@@ -69,7 +69,18 @@
 
   unsigned GetTextureTarget() const { return GL_TEXTURE_RECTANGLE_ARB; }
 
-  const uint8_t* GetImageColor() { return kImageColor; }
+  const uint8_t* GetImageColor() {
+    if (format != gfx::BufferFormat::BGRX_8888)
+      return kImageColor;
+
+    // BGRX_8888 is actually treated as BGRA because many operations are broken
+    // when binding an IOSurface as GL_RGB, see https://crbug.com/595948. This
+    // makes the alpha value comparison fail, because we expect 0xFF but are
+    // actually writing something (0xAA). Correct the alpha value for the test.
+    static uint8_t bgrx_image_color[] = {kImageColor[0], kImageColor[1],
+                                         kImageColor[2], 0xAA};
+    return bgrx_image_color;
+  }
 
   int GetAdmissibleError() const {
     return format == gfx::BufferFormat::YUV_420_BIPLANAR ? 1 : 0;
@@ -98,9 +109,10 @@
                               GLImageRGBTestTypes);
 
 using GLImageBindTestTypes = testing::Types<
-    // TODO(mcasas): enable BGRX_1010102, BGRX_8888, https://crbug.com/803473.
+    // TODO(mcasas): enable BGRX_1010102, https://crbug.com/803473.
     GLImageIOSurfaceTestDelegate<gfx::BufferFormat::BGRA_8888>,
     GLImageIOSurfaceTestDelegate<gfx::BufferFormat::RGBA_8888>,
+    GLImageIOSurfaceTestDelegate<gfx::BufferFormat::BGRX_8888>,
     GLImageIOSurfaceTestDelegate<gfx::BufferFormat::RGBA_F16>>;
 
 INSTANTIATE_TYPED_TEST_CASE_P(GLImageIOSurface,
diff --git a/ui/gl/test/gl_image_test_support.cc b/ui/gl/test/gl_image_test_support.cc
index fb4dcf42..675d383 100644
--- a/ui/gl/test/gl_image_test_support.cc
+++ b/ui/gl/test/gl_image_test_support.cc
@@ -24,7 +24,6 @@
 #if defined(USE_OZONE)
   ui::OzonePlatform::InitParams params;
   params.single_process = true;
-  params.using_mojo = true;
   ui::OzonePlatform::InitializeForGPU(params);
 #endif
 
diff --git a/ui/gl/test/gl_surface_test_support.cc b/ui/gl/test/gl_surface_test_support.cc
index a1cab69..e4039b6 100644
--- a/ui/gl/test/gl_surface_test_support.cc
+++ b/ui/gl/test/gl_surface_test_support.cc
@@ -37,7 +37,6 @@
   ui::OzonePlatform::InitParams params;
   params.single_process = true;
   ui::OzonePlatform::InitializeForGPU(params);
-  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
 #endif
 
   ui::test::EnableTestConfigForPlatformWindows();
@@ -117,7 +116,6 @@
   ui::OzonePlatform::InitParams params;
   params.single_process = true;
   ui::OzonePlatform::InitializeForGPU(params);
-  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
 #endif
 
   InitializeOneOffImplementation(kGLImplementationMockGL, false);
@@ -128,7 +126,6 @@
   ui::OzonePlatform::InitParams params;
   params.single_process = true;
   ui::OzonePlatform::InitializeForGPU(params);
-  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
 #endif
 
   InitializeOneOffImplementation(kGLImplementationStubGL, false);
diff --git a/ui/ozone/demo/ozone_demo.cc b/ui/ozone/demo/ozone_demo.cc
index 9598ed8..38d3c919 100644
--- a/ui/ozone/demo/ozone_demo.cc
+++ b/ui/ozone/demo/ozone_demo.cc
@@ -206,7 +206,6 @@
   ui::OzonePlatform::InitParams params;
   params.single_process = true;
   ui::OzonePlatform::InitializeForGPU(params);
-  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (!command_line->HasSwitch(kDisableGpu) && gl::init::InitializeGLOneOff() &&
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn
index 99fc0d66..3eee627 100644
--- a/ui/ozone/platform/drm/BUILD.gn
+++ b/ui/ozone/platform/drm/BUILD.gn
@@ -81,8 +81,6 @@
     "gpu/screen_manager.h",
     "host/drm_cursor.cc",
     "host/drm_cursor.h",
-    "host/drm_device_connector.cc",
-    "host/drm_device_connector.h",
     "host/drm_device_handle.cc",
     "host/drm_device_handle.h",
     "host/drm_display_host.cc",
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.cc b/ui/ozone/platform/drm/gpu/drm_thread.cc
index eb840a7..a00011f 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -78,18 +78,16 @@
 }  // namespace
 
 DrmThread::DrmThread()
-    : base::Thread("DrmThread"), drm_binding_(this), weak_ptr_factory_(this) {}
+    : base::Thread("DrmThread"), binding_(this), weak_ptr_factory_(this) {}
 
 DrmThread::~DrmThread() {
   Stop();
 }
 
-void DrmThread::Start(base::OnceClosure binding_completer) {
-  complete_early_binding_requests_ = std::move(binding_completer);
+void DrmThread::Start() {
   base::Thread::Options thread_options;
   thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
   thread_options.priority = base::ThreadPriority::DISPLAY;
-
   if (!StartWithOptions(thread_options))
     LOG(FATAL) << "Failed to create DRM thread";
 }
@@ -106,13 +104,6 @@
 
   display_manager_.reset(
       new DrmGpuDisplayManager(screen_manager_.get(), device_manager_.get()));
-
-  DCHECK(task_runner())
-      << "DrmThread::Init -- thread doesn't have a task_runner";
-
-  // DRM thread is running now so can safely handle binding requests. So drain
-  // the queue of as-yet unhandled binding requests if there are any.
-  std::move(complete_early_binding_requests_).Run();
 }
 
 void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
@@ -352,12 +343,12 @@
 // be used from multiple threads in multiple processes.
 void DrmThread::AddBindingCursorDevice(
     ozone::mojom::DeviceCursorRequest request) {
-  cursor_bindings_.AddBinding(this, std::move(request));
+  bindings_.AddBinding(this, std::move(request));
 }
 
 void DrmThread::AddBindingDrmDevice(ozone::mojom::DrmDeviceRequest request) {
   TRACE_EVENT0("drm", "DrmThread::AddBindingDrmDevice");
-  drm_binding_.Bind(std::move(request));
+  binding_.Bind(std::move(request));
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.h b/ui/ozone/platform/drm/gpu/drm_thread.h
index ea944803..5c0dcad 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread.h
+++ b/ui/ozone/platform/drm/gpu/drm_thread.h
@@ -62,7 +62,7 @@
   DrmThread();
   ~DrmThread() override;
 
-  void Start(base::OnceClosure binding_completer);
+  void Start();
 
   // Must be called on the DRM thread. All methods for use from the GPU thread.
   // DrmThreadProxy (on GPU)thread) is the client for these methods.
@@ -150,14 +150,12 @@
   std::unique_ptr<ScreenManager> screen_manager_;
   std::unique_ptr<DrmGpuDisplayManager> display_manager_;
 
-  base::OnceClosure complete_early_binding_requests_;
-
   // The mojo implementation requires a BindingSet because the DrmThread serves
   // requests from two different client threads.
-  mojo::BindingSet<ozone::mojom::DeviceCursor> cursor_bindings_;
+  mojo::BindingSet<ozone::mojom::DeviceCursor> bindings_;
 
   // The mojo implementation of DrmDevice can use a simple binding.
-  mojo::Binding<ozone::mojom::DrmDevice> drm_binding_;
+  mojo::Binding<ozone::mojom::DrmDevice> binding_;
 
   base::WeakPtrFactory<DrmThread> weak_ptr_factory_;
 
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc b/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc
index 6e1d4a74..24a88ec 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc
@@ -26,6 +26,10 @@
 
 void DrmThreadMessageProxy::OnFilterAdded(IPC::Channel* channel) {
   sender_ = channel;
+
+  // The DRM thread needs to be started late since we need to wait for the
+  // sandbox to start.
+  drm_thread_->Start();
 }
 
 bool DrmThreadMessageProxy::OnMessageReceived(const IPC::Message& message) {
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
index 2bad52d..bdc798c 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
@@ -17,15 +17,13 @@
 
 DrmThreadProxy::~DrmThreadProxy() {}
 
-// Used only with the paramtraits implementation.
 void DrmThreadProxy::BindThreadIntoMessagingProxy(
     InterThreadMessagingProxy* messaging_proxy) {
   messaging_proxy->SetDrmThread(&drm_thread_);
 }
 
-// Used only for the mojo implementation.
-void DrmThreadProxy::StartDrmThread(base::OnceClosure binding_drainer) {
-  drm_thread_.Start(std::move(binding_drainer));
+void DrmThreadProxy::StartDrmThread() {
+  drm_thread_.Start();
 }
 
 std::unique_ptr<DrmWindowProxy> DrmThreadProxy::CreateDrmWindowProxy(
@@ -38,10 +36,7 @@
     const gfx::Size& size,
     gfx::BufferFormat format,
     gfx::BufferUsage usage) {
-  DCHECK(drm_thread_.task_runner())
-      << "no task runner! in DrmThreadProxy::CreateBuffer";
   scoped_refptr<GbmBuffer> buffer;
-
   PostSyncTask(
       drm_thread_.task_runner(),
       base::Bind(&DrmThread::CreateBuffer, base::Unretained(&drm_thread_),
@@ -82,9 +77,6 @@
 
 void DrmThreadProxy::AddBindingDrmDevice(
     ozone::mojom::DrmDeviceRequest request) {
-  DCHECK(drm_thread_.task_runner()) << "DrmThreadProxy::AddBindingDrmDevice "
-                                       "drm_thread_ task runner missing";
-
   drm_thread_.task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&DrmThread::AddBindingDrmDevice,
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_proxy.h b/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
index d46de5a..c8a0b4b 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
+++ b/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
@@ -27,7 +27,7 @@
 
   void BindThreadIntoMessagingProxy(InterThreadMessagingProxy* messaging_proxy);
 
-  void StartDrmThread(base::OnceClosure binding_drainer);
+  void StartDrmThread();
 
   std::unique_ptr<DrmWindowProxy> CreateDrmWindowProxy(
       gfx::AcceleratedWidget widget);
diff --git a/ui/ozone/platform/drm/host/drm_device_connector.cc b/ui/ozone/platform/drm/host/drm_device_connector.cc
deleted file mode 100644
index c0468196..0000000
--- a/ui/ozone/platform/drm/host/drm_device_connector.cc
+++ /dev/null
@@ -1,101 +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 "ui/ozone/platform/drm/host/drm_device_connector.h"
-
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/ui/public/interfaces/constants.mojom.h"
-#include "ui/ozone/platform/drm/host/host_drm_device.h"
-#include "ui/ozone/public/gpu_platform_support_host.h"
-
-namespace {
-// TODO(rjkroege): In the future when ozone/drm is always mojo-based, remove
-// this utility code.
-using BinderCallback = ui::GpuPlatformSupportHost::GpuHostBindInterfaceCallback;
-
-void BindInterfaceInGpuProcess(const std::string& interface_name,
-                               mojo::ScopedMessagePipeHandle interface_pipe,
-                               const BinderCallback& binder_callback) {
-  return binder_callback.Run(interface_name, std::move(interface_pipe));
-}
-
-template <typename Interface>
-void BindInterfaceInGpuProcess(mojo::InterfaceRequest<Interface> request,
-                               const BinderCallback& binder_callback) {
-  BindInterfaceInGpuProcess(
-      Interface::Name_, std::move(request.PassMessagePipe()), binder_callback);
-}
-
-}  // namespace
-
-namespace ui {
-
-DrmDeviceConnector::DrmDeviceConnector(
-    service_manager::Connector* connector,
-    scoped_refptr<HostDrmDevice> host_drm_device_)
-    : connector_(connector), host_drm_device_(host_drm_device_) {}
-
-DrmDeviceConnector::~DrmDeviceConnector() {}
-
-void DrmDeviceConnector::OnGpuProcessLaunched(
-    int host_id,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> send_runner,
-    const base::RepeatingCallback<void(IPC::Message*)>& send_callback) {
-  NOTREACHED();
-}
-
-void DrmDeviceConnector::OnChannelDestroyed(int host_id) {
-  // TODO(rjkroege): Handle Viz restarting.
-  NOTIMPLEMENTED();
-}
-
-void DrmDeviceConnector::OnGpuServiceLaunched(
-    scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> io_runner,
-    GpuHostBindInterfaceCallback binder) {
-  // We need to preserve |binder| to let us bind interfaces later.
-  binder_callback_ = std::move(binder);
-
-  ui::ozone::mojom::DrmDevicePtr drm_device_ptr;
-  BindInterfaceDrmDevice(&drm_device_ptr);
-  ui::ozone::mojom::DeviceCursorPtr cursor_ptr_ui, cursor_ptr_io;
-  BindInterfaceDeviceCursor(&cursor_ptr_ui);
-  BindInterfaceDeviceCursor(&cursor_ptr_io);
-
-  ui_runner->PostTask(
-      FROM_HERE,
-      base::BindOnce(&HostDrmDevice::OnGpuServiceLaunched, host_drm_device_,
-                     std::move(drm_device_ptr), std::move(cursor_ptr_ui),
-                     std::move(cursor_ptr_io)));
-}
-
-void DrmDeviceConnector::OnMessageReceived(const IPC::Message& message) {
-  NOTREACHED() << "This class should only be used with mojo transport but here "
-                  "we're wrongly getting invoked to handle IPC communication.";
-}
-
-void DrmDeviceConnector::BindInterfaceDrmDevice(
-    ui::ozone::mojom::DrmDevicePtr* drm_device_ptr) const {
-  if (connector_) {
-    connector_->BindInterface(ui::mojom::kServiceName, drm_device_ptr);
-  } else {
-    auto request = mojo::MakeRequest(drm_device_ptr);
-    BindInterfaceInGpuProcess(std::move(request), binder_callback_);
-  }
-}
-
-void DrmDeviceConnector::BindInterfaceDeviceCursor(
-    ui::ozone::mojom::DeviceCursorPtr* cursor_ptr) const {
-  if (connector_) {
-    connector_->BindInterface(ui::mojom::kServiceName, cursor_ptr);
-  } else {
-    auto request = mojo::MakeRequest(cursor_ptr);
-    BindInterfaceInGpuProcess(std::move(request), binder_callback_);
-  }
-}
-
-}  // namespace ui
\ No newline at end of file
diff --git a/ui/ozone/platform/drm/host/drm_device_connector.h b/ui/ozone/platform/drm/host/drm_device_connector.h
deleted file mode 100644
index c717662..0000000
--- a/ui/ozone/platform/drm/host/drm_device_connector.h
+++ /dev/null
@@ -1,70 +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 UI_OZONE_PLATFORM_DRM_HOST_DRM_DEVICE_CONNECTOR_H_
-#define UI_OZONE_PLATFORM_DRM_HOST_DRM_DEVICE_CONNECTOR_H_
-
-#include "ui/ozone/public/gpu_platform_support_host.h"
-#include "ui/ozone/public/interfaces/device_cursor.mojom.h"
-#include "ui/ozone/public/interfaces/drm_device.mojom.h"
-
-namespace service_manager {
-class Connector;
-}
-
-namespace ui {
-class HostDrmDevice;
-
-// DrmDeviceConnector sets up mojo pipes connecting the Viz host to the DRM
-// service. It operates in two modes: running on the I/O thread when invoked
-// from content and running on the VizHost main thread when operating with a
-// service_manager.
-class DrmDeviceConnector : public GpuPlatformSupportHost {
- public:
-  DrmDeviceConnector(service_manager::Connector* connector,
-                     scoped_refptr<HostDrmDevice> host_drm_device_);
-  ~DrmDeviceConnector() override;
-
-  // GpuPlatformSupportHost:
-  void OnGpuProcessLaunched(
-      int host_id,
-      scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> send_runner,
-      const base::RepeatingCallback<void(IPC::Message*)>& send_callback)
-      override;
-  void OnChannelDestroyed(int host_id) override;
-  void OnMessageReceived(const IPC::Message& message) override;
-  void OnGpuServiceLaunched(
-      scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> io_runner,
-      GpuHostBindInterfaceCallback binder) override;
-
-  // BindInterface arranges for the drm_device_ptr to be connected.
-  void BindInterfaceDrmDevice(
-      ui::ozone::mojom::DrmDevicePtr* drm_device_ptr) const;
-
-  // BindInterface arranges for the cursor_ptr to be wired up.
-  void BindInterfaceDeviceCursor(
-      ui::ozone::mojom::DeviceCursorPtr* cursor_ptr) const;
-
-  // BindableNow returns true if this DrmDeviceConnector is capable of binding a
-  // mojo endpoint for the DrmDevice service.
-  bool BindableNow() const { return !!connector_; }
-
- private:
-  // This will be present if the Viz host has a service manager.
-  service_manager::Connector* connector_;
-
-  // This will be used if we are operating under content/gpu without a service
-  // manager.
-  GpuHostBindInterfaceCallback binder_callback_;
-
-  scoped_refptr<HostDrmDevice> host_drm_device_;
-
-  DISALLOW_COPY_AND_ASSIGN(DrmDeviceConnector);
-};
-
-}  // namespace ui
-
-#endif  // UI_OZONE_PLATFORM_DRM_HOST_DRM_DEVICE_CONNECTOR_H_
\ No newline at end of file
diff --git a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
index df8585d..c8267a2 100644
--- a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
+++ b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
@@ -117,14 +117,6 @@
   return host_id_ >= 0 && channel_established_;
 }
 
-void DrmGpuPlatformSupportHost::OnGpuServiceLaunched(
-    scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> io_runner,
-    GpuHostBindInterfaceCallback binder) {
-  NOTREACHED() << "DrmGpuPlatformSupportHost::OnGpuServiceLaunched shouldn't "
-                  "be used with pre-mojo IPC";
-}
-
 void DrmGpuPlatformSupportHost::OnGpuProcessLaunched(
     int host_id,
     scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
diff --git a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
index ebcb9d5e..1de15ce 100644
--- a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
+++ b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
@@ -41,10 +41,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> send_runner,
       const base::Callback<void(IPC::Message*)>& send_callback) override;
   void OnChannelDestroyed(int host_id) override;
-  void OnGpuServiceLaunched(
-      scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> io_runner,
-      GpuHostBindInterfaceCallback binder) override;
 
   void OnMessageReceived(const IPC::Message& message) override;
 
diff --git a/ui/ozone/platform/drm/host/host_cursor_proxy.cc b/ui/ozone/platform/drm/host/host_cursor_proxy.cc
index fa2880d..ba5baeec 100644
--- a/ui/ozone/platform/drm/host/host_cursor_proxy.cc
+++ b/ui/ozone/platform/drm/host/host_cursor_proxy.cc
@@ -6,17 +6,15 @@
 
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/ui/public/interfaces/constants.mojom.h"
-#include "ui/ozone/public/gpu_platform_support_host.h"
 
 namespace ui {
 
-// We assume that this is invoked only on the Mus/UI thread.
-HostCursorProxy::HostCursorProxy(
-    ui::ozone::mojom::DeviceCursorPtr main_cursor_ptr,
-    ui::ozone::mojom::DeviceCursorPtr evdev_cursor_ptr)
-    : main_cursor_ptr_(std::move(main_cursor_ptr)),
-      evdev_cursor_ptr_(std::move(evdev_cursor_ptr)),
-      ui_thread_ref_(base::PlatformThread::CurrentRef()) {}
+// We assume that this is invoked only on the UI thread.
+HostCursorProxy::HostCursorProxy(service_manager::Connector* connector)
+    : connector_(connector->Clone()) {
+  ui_thread_ref_ = base::PlatformThread::CurrentRef();
+  connector->BindInterface(ui::mojom::kServiceName, &main_cursor_ptr_);
+}
 
 HostCursorProxy::~HostCursorProxy() {}
 
@@ -48,14 +46,8 @@
 // when the GpuThread/DrmThread pair are once again running), we need to run it
 // on cursor motions.
 void HostCursorProxy::InitializeOnEvdevIfNecessary() {
-  // TODO(rjkroege): Rebind on Viz process restart.
-  if (evdev_bound_)
-    return;
-
   if (ui_thread_ref_ != base::PlatformThread::CurrentRef()) {
-    // Rebind the mojo pipe on the current thread. We expect this to be the
-    // thread running EVDEV.
-    evdev_cursor_ptr_.Bind(evdev_cursor_ptr_.PassInterface());
+    connector_->BindInterface(ui::mojom::kServiceName, &evdev_cursor_ptr_);
   }
 }
 
diff --git a/ui/ozone/platform/drm/host/host_cursor_proxy.h b/ui/ozone/platform/drm/host/host_cursor_proxy.h
index 87115dd..42feece 100644
--- a/ui/ozone/platform/drm/host/host_cursor_proxy.h
+++ b/ui/ozone/platform/drm/host/host_cursor_proxy.h
@@ -9,6 +9,10 @@
 #include "ui/ozone/platform/drm/host/drm_cursor.h"
 #include "ui/ozone/public/interfaces/device_cursor.mojom.h"
 
+namespace service_manager {
+class Connector;
+}
+
 namespace ui {
 
 // Ozone requires a IPC from the browser (or mus-ws) process to the gpu (or
@@ -18,8 +22,7 @@
 // priviledged process.
 class HostCursorProxy : public DrmCursorProxy {
  public:
-  HostCursorProxy(ui::ozone::mojom::DeviceCursorPtr main_cursor_ptr,
-                  ui::ozone::mojom::DeviceCursorPtr evdev_cursor_ptr);
+  explicit HostCursorProxy(service_manager::Connector* connector);
   ~HostCursorProxy() override;
 
  private:
@@ -31,13 +34,13 @@
   void Move(gfx::AcceleratedWidget window, const gfx::Point& point) override;
   void InitializeOnEvdevIfNecessary() override;
 
+  std::unique_ptr<service_manager::Connector> connector_;
+
   // Mojo implementation of the DrmCursorProxy.
-  ui::ozone::mojom::DeviceCursorPtr main_cursor_ptr_ = nullptr;
-  ui::ozone::mojom::DeviceCursorPtr evdev_cursor_ptr_ = nullptr;
+  ui::ozone::mojom::DeviceCursorPtr main_cursor_ptr_;
+  ui::ozone::mojom::DeviceCursorPtr evdev_cursor_ptr_;
 
   base::PlatformThreadRef ui_thread_ref_;
-  bool evdev_bound_ = false;
-
   DISALLOW_COPY_AND_ASSIGN(HostCursorProxy);
 };
 
diff --git a/ui/ozone/platform/drm/host/host_drm_device.cc b/ui/ozone/platform/drm/host/host_drm_device.cc
index 682942ae..9d1311b 100644
--- a/ui/ozone/platform/drm/host/host_drm_device.cc
+++ b/ui/ozone/platform/drm/host/host_drm_device.cc
@@ -13,15 +13,19 @@
 #include "services/ui/public/interfaces/constants.mojom.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/ozone/platform/drm/common/drm_util.h"
-#include "ui/ozone/platform/drm/host/drm_device_connector.h"
 #include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
 #include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
 #include "ui/ozone/platform/drm/host/host_cursor_proxy.h"
 
 namespace ui {
 
-HostDrmDevice::HostDrmDevice(DrmCursor* cursor) : cursor_(cursor) {
-  DETACH_FROM_THREAD(on_io_thread_);
+HostDrmDevice::HostDrmDevice(DrmCursor* cursor,
+                             service_manager::Connector* connector)
+    : cursor_(cursor), connector_(connector), weak_ptr_factory_(this) {
+  // Bind the viz process pointer here.
+  // TODO(rjkroege): Reconnect on error as that would indicate that the Viz
+  // process has failed.
+  connector->BindInterface(ui::mojom::kServiceName, &drm_device_ptr_);
 }
 
 HostDrmDevice::~HostDrmDevice() {
@@ -30,39 +34,15 @@
     observer.OnGpuThreadRetired();
 }
 
-// Setup the DRM device if we are using the ServiceManager.
-void HostDrmDevice::AsyncStartDrmDevice(const DrmDeviceConnector& connector) {
-  DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
-
-  // We bind here using the provided connector object.
-  if (!connector.BindableNow())
-    return;
-
-  connector.BindInterfaceDrmDevice(&drm_device_ptr_);
-
-  // Launch the DRM thread.
-  auto callback =
-      base::BindOnce(&HostDrmDevice::OnDrmServiceStartedCallback, this);
+void HostDrmDevice::AsyncStartDrmDevice() {
+  auto callback = base::BindOnce(&HostDrmDevice::OnDrmServiceStartedCallback,
+                                 weak_ptr_factory_.GetWeakPtr());
   drm_device_ptr_->StartDrmDevice(std::move(callback));
-
-  // Bind the cursor interface pointers.
-  ui::ozone::mojom::DeviceCursorPtr cursor_ptr_ui, cursor_ptr_io;
-  connector.BindInterfaceDeviceCursor(&cursor_ptr_ui);
-
-  // This interface pointer is bound on the wrong thread. But that's OK because
-  // we'll re-bind it the first time that it's used from the I/O thread in
-  // HostCursorProxy.
-  connector.BindInterfaceDeviceCursor(&cursor_ptr_io);
-
-  // Stash the cursor_proxy so that we can install it in the callback.
-  cursor_proxy_ = std::make_unique<HostCursorProxy>(std::move(cursor_ptr_ui),
-                                                    std::move(cursor_ptr_io));
 }
 
-// TODO(rjkroege): Remove the need for this entry point.
 void HostDrmDevice::BlockingStartDrmDevice() {
   // Wait until startup related tasks posted to this thread that must precede
-  // blocking.
+  // blocking on
   base::RunLoop().RunUntilIdle();
 
   bool success;
@@ -74,20 +54,15 @@
   return;
 }
 
-// The callback is executed in response to getting back a message from a
-// DrmDevice service that we launched earlier via ServiceManager.
 void HostDrmDevice::OnDrmServiceStartedCallback(bool success) {
   // This can be called multiple times in the course of single-threaded startup.
-  // Ignore invocations after we've started.
   if (connected_)
     return;
-
   if (success == true) {
     connected_ = true;
     RunObservers();
   }
-  // TODO(rjkroege): Handle failure of launching a viz process with the
-  // ServiceManager.
+  // TODO(rjkroege): Handle failure of launching a viz process.
 }
 
 void HostDrmDevice::ProvideManagers(DrmDisplayHostManager* display_manager,
@@ -103,9 +78,10 @@
     observer.OnGpuThreadReady();
   }
 
-  DCHECK(cursor_proxy_)
-      << "We should have already created a cursor proxy previously";
-  cursor_->SetDrmCursorProxy(std::move(cursor_proxy_));
+  // The cursor is special since it will process input events on the IO thread
+  // and can by-pass the UI thread. This means that we need to special case it
+  // and notify it after all other observers/handlers are notified.
+  cursor_->SetDrmCursorProxy(std::make_unique<HostCursorProxy>(connector_));
 
   // TODO(rjkroege): Call ResetDrmCursorProxy when the mojo connection to the
   // DRM thread is broken.
@@ -170,15 +146,14 @@
     return false;
 
   drm_device_ptr_->SetWindowBounds(widget, bounds);
-
   return true;
 }
 
 // Services needed for DrmOverlayManager.
 void HostDrmDevice::RegisterHandlerForDrmOverlayManager(
     DrmOverlayManager* handler) {
-  // TODO(rjkroege): Permit overlay manager to run in Viz when the display
-  // compositor runs in Viz.
+  // TODO(rjkroege): Permit overlay manager to run in viz when the display
+  // compositor runs in viz.
   DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
   overlay_manager_ = handler;
 }
@@ -196,11 +171,11 @@
     return false;
 
   auto callback =
-      base::BindOnce(&HostDrmDevice::GpuCheckOverlayCapabilitiesCallback, this);
+      base::BindOnce(&HostDrmDevice::GpuCheckOverlayCapabilitiesCallback,
+                     weak_ptr_factory_.GetWeakPtr());
 
   drm_device_ptr_->CheckOverlayCapabilities(widget, overlays,
                                             std::move(callback));
-
   return true;
 }
 
@@ -208,11 +183,10 @@
   DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
   if (!IsConnected())
     return false;
-
   auto callback =
-      base::BindOnce(&HostDrmDevice::GpuRefreshNativeDisplaysCallback, this);
+      base::BindOnce(&HostDrmDevice::GpuRefreshNativeDisplaysCallback,
+                     weak_ptr_factory_.GetWeakPtr());
   drm_device_ptr_->RefreshNativeDisplays(std::move(callback));
-
   return true;
 }
 
@@ -226,11 +200,11 @@
   // TODO(rjkroege): Remove the use of mode here.
   auto mode = CreateDisplayModeFromParams(pmode);
   auto callback =
-      base::BindOnce(&HostDrmDevice::GpuConfigureNativeDisplayCallback, this);
+      base::BindOnce(&HostDrmDevice::GpuConfigureNativeDisplayCallback,
+                     weak_ptr_factory_.GetWeakPtr());
 
   drm_device_ptr_->ConfigureNativeDisplay(id, std::move(mode), origin,
                                           std::move(callback));
-
   return true;
 }
 
@@ -239,10 +213,9 @@
   if (!IsConnected())
     return false;
   auto callback =
-      base::BindOnce(&HostDrmDevice::GpuDisableNativeDisplayCallback, this);
-
+      base::BindOnce(&HostDrmDevice::GpuDisableNativeDisplayCallback,
+                     weak_ptr_factory_.GetWeakPtr());
   drm_device_ptr_->DisableNativeDisplay(id, std::move(callback));
-
   return true;
 }
 
@@ -250,11 +223,9 @@
   DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
   if (!IsConnected())
     return false;
-  auto callback =
-      base::BindOnce(&HostDrmDevice::GpuTakeDisplayControlCallback, this);
-
+  auto callback = base::BindOnce(&HostDrmDevice::GpuTakeDisplayControlCallback,
+                                 weak_ptr_factory_.GetWeakPtr());
   drm_device_ptr_->TakeDisplayControl(std::move(callback));
-
   return true;
 }
 
@@ -263,10 +234,9 @@
   if (!IsConnected())
     return false;
   auto callback =
-      base::BindOnce(&HostDrmDevice::GpuRelinquishDisplayControlCallback, this);
-
+      base::BindOnce(&HostDrmDevice::GpuRelinquishDisplayControlCallback,
+                     weak_ptr_factory_.GetWeakPtr());
   drm_device_ptr_->RelinquishDisplayControl(std::move(callback));
-
   return true;
 }
 
@@ -276,9 +246,7 @@
   if (!IsConnected())
     return false;
   base::File file(fd.release());
-
   drm_device_ptr_->AddGraphicsDevice(path, std::move(file));
-
   return true;
 }
 
@@ -286,9 +254,7 @@
   DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
   if (!IsConnected())
     return false;
-
   drm_device_ptr_->RemoveGraphicsDevice(std::move(path));
-
   return true;
 }
 
@@ -296,10 +262,9 @@
   DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
   if (!IsConnected())
     return false;
-  auto callback = base::BindOnce(&HostDrmDevice::GpuGetHDCPStateCallback, this);
-
+  auto callback = base::BindOnce(&HostDrmDevice::GpuGetHDCPStateCallback,
+                                 weak_ptr_factory_.GetWeakPtr());
   drm_device_ptr_->GetHDCPState(display_id, std::move(callback));
-
   return true;
 }
 
@@ -308,10 +273,9 @@
   DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
   if (!IsConnected())
     return false;
-  auto callback = base::BindOnce(&HostDrmDevice::GpuSetHDCPStateCallback, this);
-
+  auto callback = base::BindOnce(&HostDrmDevice::GpuSetHDCPStateCallback,
+                                 weak_ptr_factory_.GetWeakPtr());
   drm_device_ptr_->SetHDCPState(display_id, state, std::move(callback));
-
   return true;
 }
 
@@ -381,30 +345,4 @@
   display_manager_->GpuUpdatedHDCPState(display_id, success);
 }
 
-// Invoked in response to the successful launching of the GPU service.
-void HostDrmDevice::OnGpuServiceLaunched(
-    ui::ozone::mojom::DrmDevicePtr drm_device_ptr,
-    ui::ozone::mojom::DeviceCursorPtr cursor_ptr_ui,
-    ui::ozone::mojom::DeviceCursorPtr cursor_ptr_io) {
-  DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
-
-  // Rebind InterfacePtrs to the window server thread.
-  cursor_ptr_ui.Bind(cursor_ptr_ui.PassInterface());
-  drm_device_ptr.Bind(drm_device_ptr.PassInterface());
-
-  drm_device_ptr_ = std::move(drm_device_ptr);
-
-  // Make sure that we've launched the DRM device service in the Viz process.
-  auto callback =
-      base::BindOnce(&HostDrmDevice::OnDrmServiceStartedCallback, this);
-  drm_device_ptr_->StartDrmDevice(std::move(callback));
-
-  // The cursor is special since it will process input events on the IO thread
-  // and can by-pass the UI thread. As a result, it has an InterfacePtr for both
-  // the window server and I/O thread.  cursor_ptr_io is already bound correctly
-  // to an I/O thread by GpuProcessHost.
-  cursor_proxy_ = std::make_unique<HostCursorProxy>(std::move(cursor_ptr_ui),
-                                                    std::move(cursor_ptr_io));
-}
-
 }  // namespace ui
diff --git a/ui/ozone/platform/drm/host/host_drm_device.h b/ui/ozone/platform/drm/host/host_drm_device.h
index 4562cc5f..47c5b18 100644
--- a/ui/ozone/platform/drm/host/host_drm_device.h
+++ b/ui/ozone/platform/drm/host/host_drm_device.h
@@ -14,7 +14,6 @@
 #include "ui/gfx/native_widget_types.h"
 #include "ui/ozone/platform/drm/host/drm_cursor.h"
 #include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
-#include "ui/ozone/public/gpu_platform_support_host.h"
 #include "ui/ozone/public/interfaces/device_cursor.mojom.h"
 #include "ui/ozone/public/interfaces/drm_device.mojom.h"
 
@@ -22,23 +21,25 @@
 class DisplaySnapshot;
 }
 
+namespace service_manager {
+class Connector;
+}
+
 namespace ui {
 class DrmDisplayHostManager;
 class DrmOverlayManager;
 class GpuThreadObserver;
-class DrmDeviceConnector;
-class HostCursorProxy;
 
 // This is the Viz host-side library for the DRM device service provided by the
 // viz process.
-class HostDrmDevice : public base::RefCountedThreadSafe<HostDrmDevice>,
-                      public GpuThreadAdapter {
+class HostDrmDevice : public GpuThreadAdapter {
  public:
-  explicit HostDrmDevice(DrmCursor* cursor);
+  HostDrmDevice(DrmCursor* cursor, service_manager::Connector* connector);
+  ~HostDrmDevice() override;
 
   // Start the DRM service. Runs the |OnDrmServiceStartedCallback| when the
   // service has launched and initiates the remaining startup.
-  void AsyncStartDrmDevice(const DrmDeviceConnector& connector);
+  void AsyncStartDrmDevice();
 
   // Blocks until the DRM service has come up. Use this entry point only when
   // supporting launch of the service where the ozone UI and GPU
@@ -48,10 +49,6 @@
   void ProvideManagers(DrmDisplayHostManager* display_manager,
                        DrmOverlayManager* overlay_manager);
 
-  void OnGpuServiceLaunched(ui::ozone::mojom::DrmDevicePtr drm_device_ptr,
-                            ui::ozone::mojom::DeviceCursorPtr cursor_ptr_ui,
-                            ui::ozone::mojom::DeviceCursorPtr cursor_ptr_io);
-
   // GpuThreadAdapter
   void AddGpuThreadObserver(GpuThreadObserver* observer) override;
   void RemoveGpuThreadObserver(GpuThreadObserver* observer) override;
@@ -96,24 +93,8 @@
                               const gfx::Rect& bounds) override;
 
  private:
-  friend class base::RefCountedThreadSafe<HostDrmDevice>;
-  ~HostDrmDevice() override;
-
-  void HostOnGpuServiceLaunched();
-
-  // BindInterface arranges for the drm_device_ptr to be wired up.
-  void BindInterfaceDrmDevice(
-      ui::ozone::mojom::DrmDevicePtr* drm_device_ptr) const;
-
-  // BindInterface arranges for the cursor_ptr to be wired up.
-  void BindInterfaceDeviceCursor(
-      ui::ozone::mojom::DeviceCursorPtr* cursor_ptr) const;
-
   void OnDrmServiceStartedCallback(bool success);
-
-  // TODO(rjkroege): Get rid of the need for this method in a subsequent CL.
   void PollForSingleThreadReady(int previous_delay);
-
   void RunObservers();
 
   void GpuCheckOverlayCapabilitiesCallback(
@@ -134,25 +115,21 @@
                                display::HDCPState state) const;
   void GpuSetHDCPStateCallback(int64_t display_id, bool success) const;
 
-  // Mojo implementation of the DrmDevice. Will be bound on the "main" thread.
+  // Mojo implementation of the DrmDevice.
   ui::ozone::mojom::DrmDevicePtr drm_device_ptr_;
 
   DrmDisplayHostManager* display_manager_;  // Not owned.
   DrmOverlayManager* overlay_manager_;      // Not owned.
   DrmCursor* cursor_;                       // Not owned.
 
-  std::unique_ptr<HostCursorProxy> cursor_proxy_;
-
-  scoped_refptr<base::SingleThreadTaskRunner> ws_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
-
-  THREAD_CHECKER(on_io_thread_);  // Needs to be rebound as is allocated on the
-                                  // window server  thread.
+  service_manager::Connector* connector_;
   THREAD_CHECKER(on_window_server_thread_);
 
   bool connected_ = false;
   base::ObserverList<GpuThreadObserver> gpu_thread_observers_;
 
+  base::WeakPtrFactory<HostDrmDevice> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(HostDrmDevice);
 };
 
diff --git a/ui/ozone/platform/drm/ozone_platform_gbm.cc b/ui/ozone/platform/drm/ozone_platform_gbm.cc
index bd56715d..3ad0de48 100644
--- a/ui/ozone/platform/drm/ozone_platform_gbm.cc
+++ b/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -37,7 +37,6 @@
 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
 #include "ui/ozone/platform/drm/gpu/screen_manager.h"
 #include "ui/ozone/platform/drm/host/drm_cursor.h"
-#include "ui/ozone/platform/drm/host/drm_device_connector.h"
 #include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
 #include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h"
 #include "ui/ozone/platform/drm/host/drm_native_display_delegate.h"
@@ -101,85 +100,47 @@
     return event_factory_ozone_->input_controller();
   }
   IPC::MessageFilter* GetGpuMessageFilter() override {
-    if (using_mojo_) {
-      return nullptr;
-    } else {
-      return gpu_message_filter_.get();
-    }
+    return gpu_message_filter_.get();
   }
-
   GpuPlatformSupportHost* GetGpuPlatformSupportHost() override {
-    if (using_mojo_) {
-      return drm_device_connector_.get();
-    } else {
-      return gpu_platform_support_host_.get();
-    }
+    return gpu_platform_support_host_.get();
   }
-
   std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
     return event_factory_ozone_->CreateSystemInputInjector();
   }
 
-  // In multi-process mode, this function must be executed in Viz as it sets up
-  // the callbacks needed  for Mojo bindings.  In single process mode, it may be
-  // called on any thread.  It must follow one of |InitializeUI| or
-  // |InitializeGPU|. Invocations of this method when not using mojo will be
-  // ignored. While the caller may choose to invoke this method before entering
-  // the sandbox, the actual interface adding has to happen on the DRM Device
-  // thread and so will be deferred until the DRM thread is running.
   void AddInterfaces(
       service_manager::BinderRegistryWithArgs<
           const service_manager::BindSourceInfo&>* registry) override {
-    if (!using_mojo_)
-      return;
-
     registry->AddInterface<ozone::mojom::DeviceCursor>(
         base::Bind(&OzonePlatformGbm::CreateDeviceCursorBinding,
                    weak_factory_.GetWeakPtr()),
-        base::ThreadTaskRunnerHandle::Get());
+        gpu_task_runner_);
 
     registry->AddInterface<ozone::mojom::DrmDevice>(
         base::Bind(&OzonePlatformGbm::CreateDrmDeviceBinding,
                    weak_factory_.GetWeakPtr()),
-        base::ThreadTaskRunnerHandle::Get());
+        gpu_task_runner_);
   }
-
-  // Runs on the thread where AddInterfaces was invoked. But the endpoint is
-  // always bound on the DRM thread.
   void CreateDeviceCursorBinding(
       ozone::mojom::DeviceCursorRequest request,
       const service_manager::BindSourceInfo& source_info) {
-    if (drm_thread_started_)
+    if (drm_thread_proxy_)
       drm_thread_proxy_->AddBindingCursorDevice(std::move(request));
     else
       pending_cursor_requests_.push_back(std::move(request));
   }
-  // Runs on the thread where AddInterfaces was invoked. But the endpoint is
-  // always bound on the DRM thread.
+
   // service_manager::InterfaceFactory<ozone::mojom::DrmDevice>:
   void CreateDrmDeviceBinding(
       ozone::mojom::DrmDeviceRequest request,
       const service_manager::BindSourceInfo& source_info) {
-    if (drm_thread_started_)
+    if (drm_thread_proxy_)
       drm_thread_proxy_->AddBindingDrmDevice(std::move(request));
     else
       pending_gpu_adapter_requests_.push_back(std::move(request));
   }
 
-  // Runs on the thread that invoked |AddInterfaces| to drain the queue of
-  // binding requests that could not be satisfied until the DRM thread is
-  // available (i.e. if waiting until the sandbox has been entered.)
-  void DrainBindingRequests() {
-    for (auto& request : pending_cursor_requests_)
-      drm_thread_proxy_->AddBindingCursorDevice(std::move(request));
-    pending_cursor_requests_.clear();
-    for (auto& request : pending_gpu_adapter_requests_)
-      drm_thread_proxy_->AddBindingDrmDevice(std::move(request));
-    pending_gpu_adapter_requests_.clear();
-
-    drm_thread_started_ = true;
-  }
-
   std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       const gfx::Rect& bounds) override {
@@ -198,31 +159,21 @@
       override {
     return std::make_unique<DrmNativeDisplayDelegate>(display_manager_.get());
   }
-
   void InitializeUI(const InitParams& args) override {
-    // Ozone drm can operate in four modes configured at
-    // runtime. Three process modes:
+    // Ozone drm can operate in three modes configured at runtime:
     //   1. legacy mode where host and viz components communicate
     //      via param traits IPC.
     //   2. single-process mode where host and viz components
-    //      communicate via in-process mojo. Single-process mode can be single
-    //      or multi-threaded.
+    //      communicate via in-process mojo.
     //   3. multi-process mode where host and viz components communicate
     //      via mojo IPC.
-    //
-    // and 2 connection modes
-    //   a. Viz is launched via content::GpuProcessHost and it notifies the
-    //   ozone host when Viz becomes available. b. The ozone host uses a service
-    //   manager to launch and connect to Viz.
-    //
-    // Combinations 1a, 2b, and 3a, and 3b are supported and expected to work.
-    // Combination 1a will hopefully be deprecated and replaced with 3a.
-    // Combination 2b adds undesirable code-debt and the intent is to remove it.
-
     single_process_ = args.single_process;
-    using_mojo_ = args.using_mojo || args.connector != nullptr;
+    using_mojo_ = args.connector != nullptr;
     host_thread_ = base::PlatformThread::CurrentRef();
 
+    DCHECK(!(using_mojo_ && !single_process_))
+        << "Multiprocess Mojo is not supported yet.";
+
     device_manager_ = CreateDeviceManager();
     window_manager_.reset(new DrmWindowHostManager());
     cursor_.reset(new DrmCursor(window_manager_.get()));
@@ -244,9 +195,8 @@
       gl_api_loader_.reset(new GlApiLoader());
 
     if (using_mojo_) {
-      host_drm_device_ = base::MakeRefCounted<HostDrmDevice>(cursor_.get());
-      drm_device_connector_ = std::make_unique<DrmDeviceConnector>(
-          args.connector, host_drm_device_);
+      host_drm_device_ =
+          std::make_unique<HostDrmDevice>(cursor_.get(), args.connector);
       adapter = host_drm_device_.get();
     } else {
       gpu_platform_support_host_.reset(
@@ -264,12 +214,17 @@
     if (using_mojo_) {
       host_drm_device_->ProvideManagers(display_manager_.get(),
                                         overlay_manager_.get());
-      host_drm_device_->AsyncStartDrmDevice(*drm_device_connector_);
+      host_drm_device_->AsyncStartDrmDevice();
     }
   }
 
   void InitializeGPU(const InitParams& args) override {
-    using_mojo_ = args.using_mojo;
+    // TODO(rjkroege): services/ui should initialize this with a connector.
+    // However, in-progress refactorings in services/ui make it difficult to
+    // require this at present. Set using_mojo_ like below once this is
+    // complete.
+    // TODO(rjk): Make it possible to turn this on.
+    // using_mojo_ = args.connector != nullptr;
     gpu_task_runner_ = base::ThreadTaskRunnerHandle::Get();
 
     if (!single_process_)
@@ -284,50 +239,48 @@
     }
 
     // NOTE: Can't start the thread here since this is called before sandbox
-    // initialization in multi-process Chrome.
+    // initialization in multi-process Chrome. In mus, we start the DRM thread.
     drm_thread_proxy_.reset(new DrmThreadProxy());
 
     surface_factory_.reset(new GbmSurfaceFactory(drm_thread_proxy_.get()));
     if (!using_mojo_) {
       drm_thread_proxy_->BindThreadIntoMessagingProxy(itmp);
+    } else {
+      drm_thread_proxy_->StartDrmThread();
     }
 
+    // When the viz process (and hence the gpu portion of ozone/gbm) is
+    // operating in a single process, the AddInterfaces method is best
+    // invoked before the GPU thread launches.  As a result, requests to add
+    // mojom bindings to the as yet un-launched service will fail so we queue
+    // incoming binding requests until the GPU thread is running and play them
+    // back here.
+    for (auto& request : pending_cursor_requests_)
+      drm_thread_proxy_->AddBindingCursorDevice(std::move(request));
+    pending_cursor_requests_.clear();
+    for (auto& request : pending_gpu_adapter_requests_)
+      drm_thread_proxy_->AddBindingDrmDevice(std::move(request));
+    pending_gpu_adapter_requests_.clear();
+
     // If InitializeGPU and InitializeUI are invoked on the same thread, startup
     // sequencing is complicated because tasks are queued on the unbound mojo
     // pipe connecting the UI (the host) to the DRM thread before the DRM thread
-    // is launched above. Special case this sequence via the
+    // is launched above. Special case this sequence vis the
     // BlockingStartDrmDevice API.
     // TODO(rjkroege): In a future when we have completed splitting Viz, it will
     // be possible to simplify this logic.
-    if (using_mojo_ && single_process_) {
+    if (using_mojo_ && single_process_ &&
+        host_thread_ == base::PlatformThread::CurrentRef()) {
       CHECK(host_drm_device_)
           << "Mojo single-process mode requires a HostDrmDevice.";
-
-      // Wait here if host and gpu are one and the same thread.
-      if (host_thread_ == base::PlatformThread::CurrentRef()) {
-        // One-thread exection does not permit use of the sandbox.
-        AfterSandboxEntry();
-        host_drm_device_->BlockingStartDrmDevice();
-      }
+      host_drm_device_->BlockingStartDrmDevice();
     }
   }
 
-  // The DRM thread needs to be started late because we need to wait for the
-  // sandbox to start. This entry point in the Ozne API gives platforms
-  // flexibility in handing this requirement.
-  void AfterSandboxEntry() override {
-    CHECK(drm_thread_proxy_) << "AfterSandboxEntry before InitializeForGPU is "
-                                "invalid startup order.\n";
-    // Defer the actual startup of the DRM thread to here.
-    auto safe_binding_resquest_drainer = CreateSafeOnceCallback(base::BindOnce(
-        &OzonePlatformGbm::DrainBindingRequests, weak_factory_.GetWeakPtr()));
-
-    drm_thread_proxy_->StartDrmThread(std::move(safe_binding_resquest_drainer));
-  }
-
  private:
   bool using_mojo_;
   bool single_process_;
+  base::PlatformThreadRef host_thread_;
 
   // Objects in the GPU process.
   std::unique_ptr<DrmThreadProxy> drm_thread_proxy_;
@@ -340,7 +293,6 @@
   // running in single process mode.
   std::vector<ozone::mojom::DeviceCursorRequest> pending_cursor_requests_;
   std::vector<ozone::mojom::DrmDeviceRequest> pending_gpu_adapter_requests_;
-  bool drm_thread_started_;
 
   // gpu_platform_support_host_ is the IPC bridge to the GPU process while
   // host_drm_device_ is the mojo bridge to the Viz process. Only one can be in
@@ -352,11 +304,9 @@
   // To avoid a use after free, the following two members should be declared
   // before the two managers, so that they're deleted after them.
   std::unique_ptr<DrmGpuPlatformSupportHost> gpu_platform_support_host_;
+  std::unique_ptr<HostDrmDevice> host_drm_device_;
 
-  // Objects in the host process.
-  std::unique_ptr<DrmDeviceConnector> drm_device_connector_;
-  scoped_refptr<HostDrmDevice> host_drm_device_;
-  base::PlatformThreadRef host_thread_;
+  // Objects in the Browser process.
   std::unique_ptr<DeviceManager> device_manager_;
   std::unique_ptr<BitmapCursorFactoryOzone> cursor_factory_ozone_;
   std::unique_ptr<DrmWindowHostManager> window_manager_;
diff --git a/ui/ozone/public/gpu_platform_support_host.cc b/ui/ozone/public/gpu_platform_support_host.cc
index 586186c..98a23b1 100644
--- a/ui/ozone/public/gpu_platform_support_host.cc
+++ b/ui/ozone/public/gpu_platform_support_host.cc
@@ -23,10 +23,6 @@
 
   void OnChannelDestroyed(int host_id) override {}
   void OnMessageReceived(const IPC::Message&) override {}
-  void OnGpuServiceLaunched(
-      scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> io_runner,
-      GpuHostBindInterfaceCallback binder) override {}
 };
 
 }  // namespace
diff --git a/ui/ozone/public/gpu_platform_support_host.h b/ui/ozone/public/gpu_platform_support_host.h
index f1120e74..50db642 100644
--- a/ui/ozone/public/gpu_platform_support_host.h
+++ b/ui/ozone/public/gpu_platform_support_host.h
@@ -5,13 +5,10 @@
 #ifndef UI_OZONE_PUBLIC_GPU_PLATFORM_SUPPORT_HOST_H_
 #define UI_OZONE_PUBLIC_GPU_PLATFORM_SUPPORT_HOST_H_
 
-#include <string>
-
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_sender.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "ui/ozone/ozone_base_export.h"
 
 namespace ui {
@@ -27,10 +24,6 @@
 // to support additional messages needed by specific platforms.
 class OZONE_BASE_EXPORT GpuPlatformSupportHost {
  public:
-  using GpuHostBindInterfaceCallback =
-      base::RepeatingCallback<void(const std::string&,
-                                   mojo::ScopedMessagePipeHandle)>;
-
   GpuPlatformSupportHost();
   virtual ~GpuPlatformSupportHost();
 
@@ -49,13 +42,6 @@
   // Called to handle an IPC message. Note that this can be called from any
   // thread.
   virtual void OnMessageReceived(const IPC::Message& message) = 0;
-
-  // Called when the GPU service is launched.
-  // Called from the browser IO thread.
-  virtual void OnGpuServiceLaunched(
-      scoped_refptr<base::SingleThreadTaskRunner> host_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> io_runner,
-      GpuHostBindInterfaceCallback binder) = 0;
 };
 
 // create a stub implementation.
diff --git a/ui/ozone/public/DEPS b/ui/ozone/public/interfaces/DEPS
similarity index 100%
rename from ui/ozone/public/DEPS
rename to ui/ozone/public/interfaces/DEPS
diff --git a/ui/ozone/public/ozone_platform.cc b/ui/ozone/public/ozone_platform.cc
index 58c114b..8b41780 100644
--- a/ui/ozone/public/ozone_platform.cc
+++ b/ui/ozone/public/ozone_platform.cc
@@ -125,6 +125,4 @@
     service_manager::BinderRegistryWithArgs<
         const service_manager::BindSourceInfo&>* registry) {}
 
-void OzonePlatform::AfterSandboxEntry() {}
-
 }  // namespace ui
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index f715a6af..b6335ea 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -13,7 +13,6 @@
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "ui/events/system_input_injector.h"
 #include "ui/ozone/ozone_export.h"
-//#include "ui/ozone/public/interfaces/drm_device.mojom.h"
 
 namespace display {
 class NativeDisplayDelegate;
@@ -65,23 +64,14 @@
   // retain a reference to this structure.
   struct InitParams {
     // Ozone may retain this pointer for later use. An Ozone platform embedder
-    // may set this value if operating in the idiomatic mojo fashion with a
-    // service manager. Mojo transport does not require a service manager but in
-    // that case ozone will not be able to connect to the DRM and cursor
-    // services. Instead the host must invoke |OnGpuServiceLaunched| as
-    // described in ui/ozone/public/gpu_platform_support_host.h to inform the
-    // ozone host that a process containing these services is running.
+    // must set this parameter in order for the Ozone platform implementation to
+    // be able to use Mojo.
     service_manager::Connector* connector = nullptr;
 
     // Setting this to true indicates that the platform implementation should
     // operate as a single process for platforms (i.e. drm) that are usually
-    // split between a host and viz specific portion.
+    // split between a main and gpu specific portion.
     bool single_process = false;
-
-    //  Setting this to true indicates that the platform implementation should
-    //  use mojo. Setting this to true requires calling |AddInterfaces|
-    //  afterwards in the Viz process and providing a connector as part
-    bool using_mojo = false;
   };
 
   // Ensures the OzonePlatform instance without doing any initialization.
@@ -141,23 +131,11 @@
   // service_manager::BinderRegistry* pointer to export all Mojo interfaces
   // defined within Ozone.
   //
-  // Requests arriving before they can be immediately handled will be queued and
-  // executed later.
-  //
   // A default do-nothing implementation is provided to permit platform
   // implementations to opt out of implementing any Mojo interfaces.
   virtual void AddInterfaces(service_manager::BinderRegistryWithArgs<
                              const service_manager::BindSourceInfo&>* registry);
 
-  // The GPU-specific portion of Ozone would typically run in a sandboxed
-  // process for additional security. Some startup might need to wait until
-  // after the sandbox has been configured. The embedder should use this method
-  // to specify that the sandbox is configured and that GPU-side setup should
-  // complete. A default do-nothing implementation is provided to permit
-  // platform implementations to ignore sandboxing and any associated launch
-  // ordering issues.
-  virtual void AfterSandboxEntry();
-
  private:
   virtual void InitializeUI(const InitParams& params) = 0;
   virtual void InitializeGPU(const InitParams& params) = 0;
diff --git a/ui/ozone/public/ozone_switches.cc b/ui/ozone/public/ozone_switches.cc
index 4669cfa..f7a772a5 100644
--- a/ui/ozone/public/ozone_switches.cc
+++ b/ui/ozone/public/ozone_switches.cc
@@ -15,9 +15,4 @@
 // Try to enable drm atomic. This works only with drm platform.
 const char kEnableDrmAtomic[] = "enable-drm-atomic";
 
-// Use mojo communication in the drm platform instead of paramtraits. Remove
-// this switch (and associated code) when the drm platform always uses mojo
-// communication.
-const char kEnableDrmMojo[] = "enable-drm-mojo";
-
 }  // namespace switches
diff --git a/ui/ozone/public/ozone_switches.h b/ui/ozone/public/ozone_switches.h
index b8360e80..e53912bf 100644
--- a/ui/ozone/public/ozone_switches.h
+++ b/ui/ozone/public/ozone_switches.h
@@ -16,8 +16,6 @@
 
 OZONE_BASE_EXPORT extern const char kEnableDrmAtomic[];
 
-OZONE_BASE_EXPORT extern const char kEnableDrmMojo[];
-
 }  // namespace switches
 
 #endif  // UI_OZONE_PUBLIC_OZONE_SWITCHES_H_
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.cc b/ui/views/controls/tabbed_pane/tabbed_pane.cc
index bff1a9c4..45d82493 100644
--- a/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -45,6 +45,8 @@
 const gfx::Font::Weight kInactiveWeight = gfx::Font::Weight::NORMAL;
 
 const int kHarmonyTabStripTabHeight = 32;
+constexpr int kBorderThickness = 2;
+constexpr int kBorderThicknessHorizontal = 16;
 
 // The View containing the text for each tab in the tab strip.
 class TabLabel : public Label {
@@ -91,7 +93,7 @@
 // class uses a BoxLayout to position tabs.
 class MdTabStrip : public TabStrip, public gfx::AnimationDelegate {
  public:
-  MdTabStrip();
+  explicit MdTabStrip(TabbedPane::Orientation orientation);
   ~MdTabStrip() override;
 
   // Overridden from TabStrip:
@@ -134,6 +136,8 @@
   const int kTabVerticalPadding = 5;
   const int kTabHorizontalPadding = 10;
 
+  if (!tabbed_pane_->IsHorizontal())
+    title_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
   SetBorder(CreateEmptyBorder(
       gfx::Insets(kTabVerticalPadding, kTabHorizontalPadding)));
   SetLayoutManager(std::make_unique<FillLayout>());
@@ -271,8 +275,13 @@
              const base::string16& title,
              View* contents)
     : Tab(tabbed_pane, title, contents) {
-  const int kBorderThickness = 2;
-  SetBorder(CreateEmptyBorder(gfx::Insets(kBorderThickness)));
+  if (tabbed_pane->IsHorizontal()) {
+    SetBorder(CreateEmptyBorder(gfx::Insets(kBorderThickness)));
+  } else {
+    SetBorder(CreateEmptyBorder(
+        gfx::Insets(kBorderThickness, kBorderThicknessHorizontal)));
+  }
+
   OnStateChanged();
 }
 
@@ -321,12 +330,20 @@
 // static
 const char TabStrip::kViewClassName[] = "TabStrip";
 
-TabStrip::TabStrip() {
+TabStrip::TabStrip(TabbedPane::Orientation orientation)
+    : orientation_(orientation) {
   const int kTabStripLeadingEdgePadding = 9;
-  auto layout = std::make_unique<BoxLayout>(
-      BoxLayout::kHorizontal, gfx::Insets(0, kTabStripLeadingEdgePadding));
+  std::unique_ptr<BoxLayout> layout;
+  if (IsHorizontal()) {
+    layout = std::make_unique<BoxLayout>(
+        BoxLayout::kHorizontal, gfx::Insets(0, kTabStripLeadingEdgePadding));
+    layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_END);
+  } else {
+    layout = std::make_unique<BoxLayout>(
+        BoxLayout::kVertical, gfx::Insets(kTabStripLeadingEdgePadding, 0));
+    layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_START);
+  }
   layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_START);
-  layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_END);
   layout->SetDefaultFlex(0);
   SetLayoutManager(std::move(layout));
 }
@@ -343,31 +360,59 @@
   cc::PaintFlags fill_flags;
   fill_flags.setColor(kTabBorderColor);
   fill_flags.setStrokeWidth(kTabBorderThickness);
-  SkScalar line_y = SkIntToScalar(height()) - (kTabBorderThickness / 2);
-  SkScalar line_end = SkIntToScalar(width());
+  SkScalar line_center_cross_axis;
+  SkScalar line_end_main_axis;
+
+  if (IsHorizontal()) {
+    line_center_cross_axis =
+        SkIntToScalar(height()) - (kTabBorderThickness / 2);
+    line_end_main_axis = SkIntToScalar(width());
+  } else {
+    line_center_cross_axis = SkIntToScalar(width()) - (kTabBorderThickness / 2);
+    line_end_main_axis = SkIntToScalar(height());
+  }
+
   int selected_tab_index = GetSelectedTabIndex();
   if (selected_tab_index >= 0) {
     Tab* selected_tab = GetTabAtIndex(selected_tab_index);
     SkPath path;
     SkScalar tab_height =
         SkIntToScalar(selected_tab->height()) - kTabBorderThickness;
-    SkScalar tab_width =
-        SkIntToScalar(selected_tab->width()) - kTabBorderThickness;
-    SkScalar tab_start = SkIntToScalar(selected_tab->GetMirroredX());
-    path.moveTo(0, line_y);
-    path.rLineTo(tab_start, 0);
-    path.rLineTo(0, -tab_height);
-    path.rLineTo(tab_width, 0);
-    path.rLineTo(0, tab_height);
-    path.lineTo(line_end, line_y);
+    SkScalar tab_width;
 
-    cc::PaintFlags fill_flags;
+    SkScalar tab_start_x = SkIntToScalar(selected_tab->GetMirroredX());
+    SkScalar tab_start_y = SkIntToScalar(selected_tab->bounds().y());
+    if (IsHorizontal()) {
+      tab_width = SkIntToScalar(selected_tab->width()) - kTabBorderThickness;
+      path.moveTo(0, line_center_cross_axis);
+      path.rLineTo(tab_start_x, 0);
+      path.rLineTo(0, -tab_height);
+      path.rLineTo(tab_width, 0);
+      path.rLineTo(0, tab_height);
+      path.lineTo(line_end_main_axis, line_center_cross_axis);
+    } else {
+      tab_width =
+          SkIntToScalar(width() - selected_tab->GetInsets().left() / 2) -
+          kTabBorderThickness;
+      path.moveTo(line_center_cross_axis, 0);
+      path.rLineTo(0, tab_start_y);
+      path.rLineTo(-tab_width, 0);
+      path.rLineTo(0, tab_height);
+      path.rLineTo(tab_width, 0);
+      path.lineTo(line_center_cross_axis, line_end_main_axis);
+    }
+
     fill_flags.setStyle(cc::PaintFlags::kStroke_Style);
-    fill_flags.setColor(kTabBorderColor);
-    fill_flags.setStrokeWidth(kTabBorderThickness);
     canvas->DrawPath(path, fill_flags);
   } else {
-    canvas->sk_canvas()->drawLine(0, line_y, line_end, line_y, fill_flags);
+    if (IsHorizontal())
+      canvas->sk_canvas()->drawLine(0, line_center_cross_axis,
+                                    line_end_main_axis, line_center_cross_axis,
+                                    fill_flags);
+    else
+      canvas->sk_canvas()->drawLine(line_center_cross_axis, 0,
+                                    line_center_cross_axis, line_end_main_axis,
+                                    fill_flags);
   }
 }
 
@@ -394,8 +439,10 @@
   return GetTabAtIndex(index);
 }
 
-MdTabStrip::MdTabStrip() {
-  auto layout = std::make_unique<BoxLayout>(BoxLayout::kHorizontal);
+MdTabStrip::MdTabStrip(TabbedPane::Orientation orientation)
+    : TabStrip(orientation) {
+  auto layout = std::make_unique<BoxLayout>(
+      IsHorizontal() ? BoxLayout::kHorizontal : BoxLayout::kVertical);
   layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
   layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
   layout->SetDefaultFlex(1);
@@ -417,29 +464,46 @@
   DCHECK(!from_tab->selected());
   DCHECK(to_tab->selected());
 
-  animating_from_ = gfx::Range(from_tab->GetMirroredX(),
-                               from_tab->GetMirroredX() + from_tab->width());
-  animating_to_ = gfx::Range(to_tab->GetMirroredX(),
-                             to_tab->GetMirroredX() + to_tab->width());
+  if (IsHorizontal()) {
+    animating_from_ = gfx::Range(from_tab->GetMirroredX(),
+                                 from_tab->GetMirroredX() + from_tab->width());
+    animating_to_ = gfx::Range(to_tab->GetMirroredX(),
+                               to_tab->GetMirroredX() + to_tab->width());
+  } else {
+    animating_from_ = gfx::Range(from_tab->bounds().y(),
+                                 from_tab->bounds().y() + from_tab->height());
+    animating_to_ = gfx::Range(to_tab->bounds().y(),
+                               to_tab->bounds().y() + to_tab->height());
+  }
 
   contract_animation_->Stop();
   expand_animation_->Start();
 }
 
 void MdTabStrip::OnPaintBorder(gfx::Canvas* canvas) {
-  int max_y = child_at(0)->y() + child_at(0)->height();
   const int kUnselectedBorderThickness = 1;
   const int kSelectedBorderThickness = 2;
 
-  // First, draw the unselected border across the TabStrip's entire width. The
-  // area underneath the selected tab will be overdrawn later.
-  canvas->FillRect(gfx::Rect(0, max_y - kUnselectedBorderThickness, width(),
-                             kUnselectedBorderThickness),
-                   GetNativeTheme()->GetSystemColor(
-                       ui::NativeTheme::kColorId_TabBottomBorder));
+  int max_cross_axis;
 
-  int min_x = 0;
-  int max_x = 0;
+  // First, draw the unselected border across the TabStrip's entire width or
+  // height, depending on the orientation of the tab alignment. The area
+  // underneath or on the right of the selected tab will be overdrawn later.
+  gfx::Rect rect;
+  if (IsHorizontal()) {
+    max_cross_axis = child_at(0)->y() + child_at(0)->height();
+    rect = gfx::Rect(0, max_cross_axis - kUnselectedBorderThickness, width(),
+                     kUnselectedBorderThickness);
+  } else {
+    max_cross_axis = child_at(0)->x() + child_at(0)->width();
+    rect = gfx::Rect(max_cross_axis - kUnselectedBorderThickness, 0,
+                     kUnselectedBorderThickness, height());
+  }
+  canvas->FillRect(rect, GetNativeTheme()->GetSystemColor(
+                             ui::NativeTheme::kColorId_TabBottomBorder));
+
+  int min_main_axis = 0;
+  int max_main_axis = 0;
 
   // Now, figure out the range to draw the selection marker underneath. There
   // are three states here:
@@ -454,43 +518,53 @@
   if (!tab)
     return;
   if (expand_animation_->is_animating()) {
-    bool animating_left = animating_to_.start() < animating_from_.start();
+    bool animating_leading = animating_to_.start() < animating_from_.start();
     double anim_value = gfx::Tween::CalculateValue(
         gfx::Tween::FAST_OUT_LINEAR_IN, expand_animation_->GetCurrentValue());
 
-    if (animating_left) {
-      min_x = gfx::Tween::IntValueBetween(anim_value, animating_from_.start(),
-                                          animating_to_.start());
-      max_x = animating_from_.end();
+    if (animating_leading) {
+      min_main_axis = gfx::Tween::IntValueBetween(
+          anim_value, animating_from_.start(), animating_to_.start());
+      max_main_axis = animating_from_.end();
     } else {
-      min_x = animating_from_.start();
-      max_x = gfx::Tween::IntValueBetween(anim_value, animating_from_.end(),
-                                          animating_to_.end());
+      min_main_axis = animating_from_.start();
+      max_main_axis = gfx::Tween::IntValueBetween(
+          anim_value, animating_from_.end(), animating_to_.end());
     }
   } else if (contract_animation_->is_animating()) {
-    bool animating_left = animating_to_.start() < animating_from_.start();
+    bool animating_leading = animating_to_.start() < animating_from_.start();
     double anim_value = gfx::Tween::CalculateValue(
         gfx::Tween::LINEAR_OUT_SLOW_IN, contract_animation_->GetCurrentValue());
-    if (animating_left) {
-      min_x = animating_to_.start();
-      max_x = gfx::Tween::IntValueBetween(anim_value, animating_from_.end(),
-                                          animating_to_.end());
+    if (animating_leading) {
+      min_main_axis = animating_to_.start();
+      max_main_axis = gfx::Tween::IntValueBetween(
+          anim_value, animating_from_.end(), animating_to_.end());
     } else {
-      min_x = gfx::Tween::IntValueBetween(anim_value, animating_from_.start(),
-                                          animating_to_.start());
-      max_x = animating_to_.end();
+      min_main_axis = gfx::Tween::IntValueBetween(
+          anim_value, animating_from_.start(), animating_to_.start());
+      max_main_axis = animating_to_.end();
     }
   } else if (tab) {
-    min_x = tab->GetMirroredX();
-    max_x = tab->GetMirroredX() + tab->width();
+    if (IsHorizontal()) {
+      min_main_axis = tab->GetMirroredX();
+      max_main_axis = tab->GetMirroredX() + tab->width();
+    } else {
+      min_main_axis = tab->bounds().y();
+      max_main_axis = tab->bounds().y() + tab->height();
+    }
   }
 
-  DCHECK(min_x != max_x);
+  DCHECK(min_main_axis != max_main_axis);
   // Draw over the unselected border from above.
-  canvas->FillRect(gfx::Rect(min_x, max_y - kSelectedBorderThickness,
-                             max_x - min_x, kSelectedBorderThickness),
-                   GetNativeTheme()->GetSystemColor(
-                       ui::NativeTheme::kColorId_FocusedBorderColor));
+  if (IsHorizontal()) {
+    rect = gfx::Rect(min_main_axis, max_cross_axis - kSelectedBorderThickness,
+                     max_main_axis - min_main_axis, kSelectedBorderThickness);
+  } else {
+    rect = gfx::Rect(max_cross_axis - kSelectedBorderThickness, min_main_axis,
+                     kSelectedBorderThickness, max_main_axis - min_main_axis);
+  }
+  canvas->FillRect(rect, GetNativeTheme()->GetSystemColor(
+                             ui::NativeTheme::kColorId_FocusedBorderColor));
 }
 
 void MdTabStrip::AnimationProgressed(const gfx::Animation* animation) {
@@ -502,12 +576,11 @@
     contract_animation_->Start();
 }
 
-TabbedPane::TabbedPane()
-    : listener_(NULL),
-      tab_strip_(ui::MaterialDesignController::IsSecondaryUiMaterial()
-                     ? new MdTabStrip
-                     : new TabStrip),
-      contents_(new View()) {
+TabbedPane::TabbedPane(TabbedPane::Orientation orientation)
+    : listener_(NULL), contents_(new View()) {
+  tab_strip_ = ui::MaterialDesignController::IsSecondaryUiMaterial()
+                   ? new MdTabStrip(orientation)
+                   : new TabStrip(orientation);
   AddChildView(tab_strip_);
   AddChildView(contents_);
 }
@@ -581,14 +654,25 @@
   gfx::Size size;
   for (int i = 0; i < contents_->child_count(); ++i)
     size.SetToMax(contents_->child_at(i)->GetPreferredSize());
-  size.Enlarge(0, tab_strip_->GetPreferredSize().height());
+  if (IsHorizontal())
+    size.Enlarge(0, tab_strip_->GetPreferredSize().height());
+  else
+    size.Enlarge(tab_strip_->GetPreferredSize().width(), 0);
   return size;
 }
 
+bool TabbedPane::IsHorizontal() const {
+  return tab_strip_->IsHorizontal();
+}
+
 Tab* TabbedPane::GetSelectedTab() {
   return tab_strip_->GetSelectedTab();
 }
 
+View* TabbedPane::GetSelectedTabContentView() {
+  return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr;
+}
+
 bool TabbedPane::MoveSelectionBy(int delta) {
   if (contents_->child_count() <= 1)
     return false;
@@ -598,9 +682,15 @@
 
 void TabbedPane::Layout() {
   const gfx::Size size = tab_strip_->GetPreferredSize();
-  tab_strip_->SetBounds(0, 0, width(), size.height());
-  contents_->SetBounds(0, tab_strip_->bounds().bottom(), width(),
-                       std::max(0, height() - size.height()));
+  if (IsHorizontal()) {
+    tab_strip_->SetBounds(0, 0, width(), size.height());
+    contents_->SetBounds(0, tab_strip_->bounds().bottom(), width(),
+                         std::max(0, height() - size.height()));
+  } else {
+    tab_strip_->SetBounds(0, 0, size.width(), height());
+    contents_->SetBounds(tab_strip_->bounds().width(), 0,
+                         std::max(0, width() - size.width()), height());
+  }
   for (int i = 0; i < contents_->child_count(); ++i)
     contents_->child_at(i)->SetSize(contents_->size());
 }
@@ -625,10 +715,6 @@
   return kViewClassName;
 }
 
-View* TabbedPane::GetSelectedTabContentView() {
-  return GetSelectedTab() ? GetSelectedTab()->contents() : nullptr;
-}
-
 void TabbedPane::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   node_data->role = ui::AX_ROLE_TAB_LIST;
 }
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.h b/ui/views/controls/tabbed_pane/tabbed_pane.h
index 2397828..8fe7dbcf 100644
--- a/ui/views/controls/tabbed_pane/tabbed_pane.h
+++ b/ui/views/controls/tabbed_pane/tabbed_pane.h
@@ -29,7 +29,13 @@
   // Internal class name.
   static const char kViewClassName[];
 
-  TabbedPane();
+  // The orientation of the tab alignment.
+  enum class Orientation {
+    kHorizontal,
+    kVertical,
+  };
+
+  explicit TabbedPane(Orientation orientation = Orientation::kHorizontal);
   ~TabbedPane() override;
 
   TabbedPaneListener* listener() const { return listener_; }
@@ -62,6 +68,9 @@
   gfx::Size CalculatePreferredSize() const override;
   const char* GetClassName() const override;
 
+  // Returns true if the tab alignment is horizontal.
+  bool IsHorizontal() const;
+
  private:
   friend class FocusTraversalTest;
   friend class Tab;
@@ -154,13 +163,13 @@
   DISALLOW_COPY_AND_ASSIGN(Tab);
 };
 
-// The tab strip shown above the tab contents.
+// The tab strip shown above/left of the tab contents.
 class TabStrip : public View {
  public:
   // Internal class name.
   static const char kViewClassName[];
 
-  TabStrip();
+  explicit TabStrip(TabbedPane::Orientation orientation);
   ~TabStrip() override;
 
   // Called by TabStrip when the selected tab changes. This function is only
@@ -177,7 +186,15 @@
   Tab* GetTabAtIndex(int index) const;
   int GetSelectedTabIndex() const;
 
+  // Returns true if the tab alignment is horizontal.
+  bool IsHorizontal() const {
+    return orientation_ == TabbedPane::Orientation::kHorizontal;
+  }
+
  private:
+  // The orientation of the tab alignment.
+  const TabbedPane::Orientation orientation_;
+
   DISALLOW_COPY_AND_ASSIGN(TabStrip);
 };
 
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc b/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
index c6b243d..43f65a9 100644
--- a/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
+++ b/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
@@ -38,6 +38,11 @@
   }
 
  protected:
+  void MakeTabbedPaneForOrientation(TabbedPane::Orientation orientation) {
+    tabbed_pane_ = std::make_unique<TabbedPane>(orientation);
+    tabbed_pane_->set_owned_by_client();
+  }
+
   Tab* GetTabAt(int index) {
     return static_cast<Tab*>(tabbed_pane_->tab_strip_->child_at(index));
   }
@@ -58,7 +63,19 @@
   DISALLOW_COPY_AND_ASSIGN(TabbedPaneTest);
 };
 
-// Tests TabbedPane::GetPreferredSize() and TabbedPane::Layout().
+// Tests tab orientation.
+TEST_F(TabbedPaneTest, HorizontalOrientation) {
+  EXPECT_EQ(tabbed_pane_->IsHorizontal(), true);
+}
+
+// Tests tab orientation.
+TEST_F(TabbedPaneTest, VerticalOrientation) {
+  MakeTabbedPaneForOrientation(TabbedPane::Orientation::kVertical);
+  EXPECT_EQ(tabbed_pane_->IsHorizontal(), false);
+}
+
+// Tests TabbedPane::GetPreferredSize() and TabbedPane::Layout() when tabs
+// aligned in horizontal orientation.
 TEST_F(TabbedPaneTest, SizeAndLayout) {
   View* child1 = new StaticSizedView(gfx::Size(20, 10));
   tabbed_pane_->AddTab(ASCIIToUTF16("tab1"), child1);
@@ -90,6 +107,40 @@
   EXPECT_EQ(bounds, child2->bounds());
 }
 
+// Tests TabbedPane::GetPreferredSize() and TabbedPane::Layout() when tabs
+// aligned in vertical orientation.
+TEST_F(TabbedPaneTest, SizeAndLayoutInVerticalOrientation) {
+  MakeTabbedPaneForOrientation(TabbedPane::Orientation::kVertical);
+  View* child1 = new StaticSizedView(gfx::Size(20, 10));
+  tabbed_pane_->AddTab(ASCIIToUTF16("tab1"), child1);
+  View* child2 = new StaticSizedView(gfx::Size(5, 5));
+  tabbed_pane_->AddTab(ASCIIToUTF16("tab2"), child2);
+  tabbed_pane_->SelectTabAt(0);
+
+  // The |tabbed_pane_| implementation of Views has no border by default.
+  // Therefore it should be as high as the highest tab. The native Windows
+  // tabbed pane has a border that used up extra space. Therefore the preferred
+  // height is larger than the largest child.
+  gfx::Size pref(tabbed_pane_->GetPreferredSize());
+  EXPECT_GT(pref.width(), 20);
+  EXPECT_GE(pref.height(), 10);
+
+  // The bounds of our children should be smaller than the tabbed pane's bounds.
+  tabbed_pane_->SetBounds(0, 0, 100, 200);
+  RunPendingMessages();
+  gfx::Rect bounds(child1->bounds());
+  EXPECT_GT(bounds.width(), 0);
+  EXPECT_LT(bounds.width(), 100);
+  EXPECT_GT(bounds.height(), 0);
+  // The |tabbed_pane_| has no border. Therefore the children should be as high
+  // as the |tabbed_pane_|.
+  EXPECT_LE(bounds.height(), 200);
+
+  // If we switch to the other tab, it should get assigned the same bounds.
+  tabbed_pane_->SelectTabAt(1);
+  EXPECT_EQ(bounds, child2->bounds());
+}
+
 TEST_F(TabbedPaneTest, AddAndSelect) {
   // Add several tabs; only the first should be selected automatically.
   for (int i = 0; i < 3; ++i) {